3

I would like all of the physical interfaces on my system to live within a specific network namespace called "physical". It's easy enough to move devices over manually using commands like ip link set enp2s0 netns physical and iw phy phy0 set netns name physical, but I would like this to happen automatically both at boot and for any devices connected at runtime.

It seems like the best way to accomplish this would be via udev rules, or possibly some systemd magic.

My first thought was just to write a udev rule that runs the appropriate command, but I ran into a couple of questions I haven't been able to answer via my searches:

  1. How do I distinguish physical interfaces from virtual interfaces?
  2. How do I tell WLAN interfaces apart so I can issue the iw command instead of the ip command?
  3. How do I get the name of a WLAN phy so I can pass it to the iw command?

I was hoping the above would be relatively straightforward, but I don't see any obvious distinguishing factors in udevadm info.

3

Most of these informations are retrievable from /sys:

1a. /sys/class/net/ : list of network devices, all types included

1b. /sys/devices/virtual/net/ : list of virtual network devices: includes lo, tunnels, veth, bridges ... so if it's in the former but not this one, it should be physical.

  1. if a device is a modern wireless device (driver), it will have the entry /sys/class/net/<device>/phy82011/name, eg:

    $ grep -s --with-filename ''  /sys/class/net/*/phy80211/name
    /sys/class/net/wlan0/phy80211/name:phy0
    /sys/class/net/wlan1/phy80211/name:phy1
    /sys/class/net/wlan2/phy80211/name:phy2
    

So by running the adequate script from udev environment and comparing with those directories and files from /sys, you should have all the needed informations to do it.

Just as a side note, if later, to work on those devices, you change only the network namespace (eg using nsenter --net=/var/run/netns/physical), /sys will still be in the host's mount namespace, and won't reflect the arrival of those devices but will instead show them missing. Using ip netns exec physical command is fine, it does change mount namespace and remounts /sys for you.

  • In other words, have udev call an external script for all new net devices, and make it the script's responsibility to determine whether/how to move the interface? I suppose if udev doesn't expose the needed attributes itself, that's probably my best bet. Thanks! – rkjnsn Aug 3 '18 at 8:04
4

Based on A.B's answer, I came up with the following rule:

SUBSYSTEM=="net", ACTION=="add", DEVPATH!="/devices/virtual/*", TAG+="systemd", ENV{SYSTEMD_WANTS}="physical-namespace@.service"

DEVPATH!="/devices/virtual/* is the key to only grabbing physical devices. physical-namespace@.service is a oneshot service that moves the interface to the desired namespace (physical):

[Unit]
Description=Move interface to physical namespace
Requires=netns@physical.service
After=netns@physical.service

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/move-netif %I physical

(netns@.service just creates a network namespace of the given name.)

Finally, move-netif is responsible for figuring out how to move the interface:

#!/bin/bash

devpath="$1"
target_ns="$2"

if [[ -e "$devpath/phy80211" ]]; then
  phy="$(basename "$(readlink "$devpath/phy80211")")"
  iw phy "$phy" set netns name "$target_ns"
else
  ifname="$(basename "$devpath")"
  ip link set "$ifname" netns "$target_ns"
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.