Дата и время публикации:
Проблемы и решение
1. Суть проблем
1.1 Несколько слов об наследование опции -net и -nic
Qemu ранее использовал опцию -net nic вместо -device DEVNAME и -net TYPE взамен -netdev TYPE. Хотя, использование опций -net nic и -net TYPE считается устаревшим, начиная с версии Qemu 0.12 [3.1], поэтому для реализации поддержки мультисетевых устройств в Qemu/KVM, реализуемых согласно схеме, показанной на рисунке 1.1, используются их более современные аналоги -device DEVNAME и -netdev TYPE
Рисунок 1.1
1.2 Проблема "IP-Config: Auto-configuration of network failed"
Показана в дампе 1.2.1
Дамп 1.2.1
... [ 7.215993] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/amba/amba:fpga/10007000.kmi/serio1/input/input2 [ 7.380255] usb 1-2: new full-speed USB device number 3 using ohci-pci [ 7.656654] ftdi_sio 1-2:1.0: FTDI USB Serial Device converter detected [ 7.663882] usb 1-2: Detected FT232BM [ 7.674369] usb 1-2: FTDI USB Serial Device converter now attached to ttyUSB0 [ 9.439977] ..... timed out! [ 90.298166] IP-Config: Reopening network devices... [ 90.330664] Sending DHCP and RARP requests ...... timed out! [ 177.651921] IP-Config: Auto-configuration of network failed ...
Которая заключалась в указанных неверно и переданных в опции ядра ip= статического IP-адреса (Static IP Address) , который изначально рассчитан на использование с одним сетевым устройством.
1.3 Переменные QB_TAP_OPT и QB_NETWORK_DEVICE
Определяемые в описании, файла конфигурации -conf/machine/qemuarm5te.conf , к реализуемой эмулируемой виртуальной платформы "qemuarm5te" в сборочной машине Yocto/poky, интерисующий фрагмент показаны в дампе 1.3.1
Дамп 1.3.1
#@TYPE: Machine #@NAME: QEMU ARM9 machine #@DESCRIPTION: Machine configuration for running an ARMv5te system on QEMU require conf/machine/include/qemu.inc require conf/machine/include/tune-arm926ejs.inc ... # network device to be access from host machine QB_NETWORK_DEVICE = "-device virtio-net-pci,netdev=net0,mac=@MAC@" QB_NETWORK_DEVICE += " -device virtio-net-pci,netdev=net1" # network option for 'tap' mode QB_TAP_OPT = "-netdev tap,id=net0,ifname=tap0,script=no,downscript=no" QB_TAP_OPT += " -netdev tap,id=net1,ifname=tap1,script=no,downscript=no" ... KMACHINE_qemuarmv5 = "qemuarm5te"
Далее, переменные будут использованы в скрипте runqemu, который нужно модифицировать, потому что значения сетевого устройства tap0 прописаны жестко и не учитывают возможность одновременного использования с другими запущенными копиями Qemu/KVM , например в проекте gnome-boxes
2. Решение
2.1 Реализация схемы мультисетевых устройств
Как показано на рисунке 1.1, главной проблемой реализации поддержки мультисетевых устройств является идентификация -device DEVNAME и -netdev TYPE, потому что отсутствие явного сопоставления этих функций приводит к появлению поперечной связи внутри пар сетевых интерфейсов tap0 / eth0 и tap1 / eth0
Для устранения этой связи в обоих опциях вводится параметр id=, который устанавливает данное сопоставление внутри пар tap0 / eth0 и tap1 / eth0, как показано в дампе 2.1.1
Дамп 2.1.1
... QB_NETWORK_DEVICE = "-device virtio-net-pci,netdev=net0,mac=@MAC@" QB_NETWORK_DEVICE += "-device virtio-net-pci,netdev=net1" QB_TAP_OPT = "-netdev tap,id=net0,ifname=tap0,script=no,downscript=no" QB_TAP_OPT = "-netdev tap,id=net1,ifname=tap1,script=no,downscript=no" ...
Таким образом, -netdev tap,id=net0,ifname=tap0 будет связан -device virtio-net-pci,netdev=net0 , а -netdev tap,id=net1,ifname=tap1 с -device virtio-net-pci,netdev=net1
В результате чего, как показано на рисунке 1.1, поперечная связь исчезнет, а вертикальные связи пар tap0 / eth0, tap1 / eth0 будут обрамлены соответствующими цветами — красным и зеленым.
2.2 Устранение проблемы "IP-Config: Auto-configuration of network failed"
Как было показано ранее в дампе 1.2.1, вывод данного сообщения сопровождался с внушительной задержкой, примерно равной 1.5 минуты, между выдаваемыми диагностическими сообщениями ядра Linux на консоль "..... timed out!" и "IP-Config: Reopening network devices..."
Как показал ручной статический анализ в редакторе исходного кода скрипта runqemu сборочной машине Yocto/poky, в основе данной ошибки лежала таже проблема, что и с сопоставлением интерфейсов вычислительного узла эмулятора Qemu/KVM (host) и виртуального узла в режиме роутер (Route-VM), а именно установка статической конфигурации IP адресов и таблицы IP-маршрутизации в ядре Linux[3.2], которая показана в листинге 2.2.1
Листинг 2.2.1
...
129 class BaseConfig(object):
130 def __init__(self):
…
220 self.cmdline_ip_tap = "ip=192.168.7.@CLIENT@::192.168.7.@GATEWAY@:255.255.255.0"
…
1099 def setup_tap(self,tapdev,subnet):
…
1168 self.tap = tap
1169 tapnum = int(tap[3:])
1170 gateway = tapnum * 2 + 1
1171 client = gateway + 1
1172 if self.fstype == 'nfs':
1173 self.setup_nfs()
1174 netconf = " " + self.cmdline_ip_tap
1175 netconf = netconf.replace('@CLIENT@', str(client))
1176 netconf = netconf.replace('@GATEWAY@', str(gateway))
1177 logger.info("Network configuration:%s", netconf)
...
Как показано в строках 220,1174-1177 листинга 2.2.2, статическая конфигурация IP адресов и инициализация таблицы IP-маршрутизации в ядре Linux устанавливается путем передачи ему параметра "ip=", полный формат значения которого показан в листинге 2.2.2
Листинг 2.2.2
ip=<client-ip>:<srv-ip>:<gw-ip>:<netmask>:<host>:<device>:<autoconf>
Как показано в листинге 2.2.2, в первой, во второй и в третьей позиции передаются IP-адреса клиента, NFS-сервера и шлюза, т.е. в client-ip — IP-адрес сетевого узла и gw-ip — щлюза через который будет осуществляться доступ к NFS серверу, указанному в srv-ip
Кроме того, в значениях параметра <netmask> — маска подсети, в <host> — имя узла, <device> — сетевое устройство с которым идентифицируется данная подсеть, а также какой протокол rarp или bootp будет указан в настройках автоконфигурации – <autoconf> . Также в <autoconf> может быть указано both (автоопределение включено) , off (автоопределение выключено), последний, как мне показалось, предпочтителен.
Результат использования параметра ip= показан в листинге 2.2.3
Листинг 2.2.3
...
1099 def setup_tap(self,tapdev,subnet):
...
1168 self.tap = tap
1169 tapnum = int(tap[3:])
1170 gateway = tapnum * 2 + 1
1171 client = gateway + 1
1172 if self.fstype == 'nfs':
1173 self.setup_nfs()
1174 if subnet = "192.168.7" :
1175 netconf = "192.168.7.%s::192.168.2.%s:255.255.255.0::tap%d:off" % (client, gateway,tapnum)
1176 logger.info("Network configuration:%s", netconf)
...
1191 def setup_network(self):
...
1204 self.setup_tap("tap0", "192.168.7")
1205 self.setup_tap("tap1", "192.168.8")
Как показано в строках 1174-1176 листинга 2.2.3, при двойной настройке в setup_tap() нужно обязательно указывать адрес подсети "192.168.7", значения для которой указываются в параметре ip= : в первой, и третьей позиции передаются IP-адреса клиента и шлюза, в четвертой маска подсети (mask). И самое главное устраняющее ошибку "IP-Config: Auto-configuration of network failed" имя сетевого устройство (device), в данном случае это будет значение tap0 в шестой позиции, и отключающее автоконфигурацию (autoconf) значение off в седьмой позиции. При этом имя узла в пятой позиции (host) не указывается, т.е. остается пустым.
2.3 Использование переменных QB_TAP_OPT и QB_NETWORK_DEVICE
Осуществляется чтением их значений в скрипте runqemu сборочной машины Yocto/poky, как показано в листинге 2.3.1
Листинг 2.3.1
1099 def setup_tap(self):
...
1180 qb_tap_opt = self.get('QB_TAP_OPT')
...
1189 self.set('NETWORK_CMD', '%s %s' % (self.network_device.replace('@MAC@', mac), qemu_tap_opt))
...
1191 def setup_network(self):
...
1196 self.network_device = self.get('QB_NETWORK_DEVICE') or self.network_device
...
Как показано в листинге 2.3.1, фрагменте скрипта runqemu сборочной машинеYocto/poky чтение переменных QB_TAP_OPT и QB_NETWORK_DEVICE происходит до запуска эмулятора Qemu/KVM при получении соответствующих значений опций -device DEVNAME и -netdev TYPE
3. Библиография
3.1 Qemu.Documentation/Networking.The legacy -net option
3.2 Setting a Static IP Address Using the Kernel Command Line