Автоматически перемещать физические сетевые интерфейсы в пространство имен

Я хотел бы, чтобы все физические интерфейсы в моей системе жили в определенном пространстве имен сети, называемом «физическим». Достаточно просто переместить устройства вручную, используя такие команды, как ip link set enp2s0 netns physical и iw phy phy0 set netns name physical , но я бы хотел, чтобы это происходило автоматически как при загрузке, так и для любых устройств, подключенных во время выполнения.

Похоже, что лучший способ сделать это – использовать правила udev или, возможно, некоторую системную магию.

Моей первой мыслью было просто написать правило udev, которое запускает соответствующую команду, но я столкнулся с парой вопросов, на которые я не смог ответить с помощью моих поисков:

  1. Как отличить физические интерфейсы от виртуальных интерфейсов?
  2. Как отличить интерфейсы WLAN, чтобы можно было использовать команду iw вместо команды ip ?
  3. Как я могу получить имя WLAN phy, чтобы я мог передать его команде iw ?

Я надеялся, что вышесказанное будет относительно простым, но я не вижу очевидных отличительных факторов в udevadm info .

Большая часть этой информации извлекается из /sys :

1a. /sys/class/net/ : список сетевых устройств, включая все типы

1б. /sys/devices/virtual/net/ : список виртуальных сетевых устройств: включает в себя lo , туннели, veth, мосты … так что, если он в первом, но не в этом, он должен быть физическим.

  1. если устройство является современным беспроводным устройством (драйвером), оно будет иметь имя /sys/class/net//phy82011/name , например:

     $ 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 

Поэтому, запустив соответствующий сценарий из среды udev и сравнив эти каталоги и файлы из /sys , вы получите всю необходимую информацию для этого.

Как примечание, если позже, для работы на этих устройствах, вы изменяете только пространство имен сети ( например, используя nsenter --net=/var/run/netns/physical ), /sys прежнему будет в пространстве имен монтирования хоста, и не будет отражать прибытие этих устройств, но вместо этого покажет, что они отсутствуют. Использование ip netns exec physical command прекрасно, она меняет пространство имен монтирования и remounts /sys для вас.

Основываясь на ответе AB, я придумал следующее правило:

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

DEVPATH!="/devices/virtual/* – это ключ для захвата только физических устройств. physical-namespace@.service – это сервис с одним выстрелом, который перемещает интерфейс в желаемое пространство имен ( 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 просто создает пространство имен сети с заданным именем.)

Наконец, move-netif отвечает за выяснение того, как перемещать интерфейс:

 #!/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