[OE-core] [PATCHv4 2/3] runqemu: Add support for multiple tap devices
Anibal Limon
anibal.limon at linaro.org
Wed Jul 3 17:05:08 UTC 2019
On Wed, 3 Jul 2019 at 12:01, Aníbal Limón <anibal.limon at linaro.org> wrote:
> Add the ability to set more than one tap devices into the
> same qemu instance,
>
> The code was modified to detect multiple @TAP@ and @MAC@ in the
> QA_TAP_OPT and QA_NETWORK_DEVICE respectively, it handles the
> attach/creation of multiple tap devices and stores into a list
> for lock/unlock.
>
> Configure the first interface because Kernel IP Configuration
> only takes care of the first device.
>
> This patch was tested using qemux86, kvm-vhost and NFS rootfs.
>
> Example of the configuration:
>
> QB_TAP_OPT = "-netdev tap,id=net0,ifname=@TAP@,script=no,downscript=no \
> -netdev tap,id=net1,ifname=@TAP@,script=no,downscript=no"
> QB_NETWORK_DEVICE = "-device virtio-net-pci,netdev=net0,mac=@MAC@ \
> -device virtio-net-pci,netdev=net1,mac=@MAC@"
>
> Signed-off-by: Aníbal Limón <anibal.limon at linaro.org>
> ---
> scripts/runqemu | 141 ++++++++++++++++++++++++++++--------------------
> 1 file changed, 83 insertions(+), 58 deletions(-)
>
> diff --git a/scripts/runqemu b/scripts/runqemu
> index 38dd1c30d9..0134f86b4c 100755
> --- a/scripts/runqemu
> +++ b/scripts/runqemu
> @@ -1006,64 +1006,88 @@ class BaseConfig(object):
> except FileExistsError:
> pass
>
> - cmd = (ip, 'link')
> - logger.debug('Running %s...' % str(cmd))
> - ip_link = subprocess.check_output(cmd).decode('utf-8')
> - # Matches line like: 6: tap0: <foo>
> - possibles = re.findall('^[0-9]+: +(tap[0-9]+): <.*', ip_link,
> re.M)
> - tap = ""
> - for p in possibles:
> - lockfile = os.path.join(lockdir, p)
> - if os.path.exists('%s.skip' % lockfile):
> - logger.info('Found %s.skip, skipping %s' % (lockfile, p))
> - continue
> - lock = lockfile + '.lock'
> - if self.acquire_lock(lock, error=False):
> - tap = p
> - logger.info("Using preconfigured tap device %s" % tap)
> - logger.info("If this is not intended, touch %s.skip to
> make runqemu skip %s." %(lockfile, tap))
> - break
> -
> - if not tap:
> - if os.path.exists(nosudo_flag):
> - logger.error("Error: There are no available tap devices
> to use for networking,")
> - logger.error("and I see %s exists, so I am not going to
> try creating" % nosudo_flag)
> - raise RunQemuError("a new one with sudo.")
> -
> - gid = os.getgid()
> - uid = os.getuid()
> - logger.info("Setting up tap interface under sudo")
> - cmd = ('sudo', self.qemuifup, str(uid), str(gid),
> self.bindir_native)
> - tap = subprocess.check_output(cmd).decode('utf-8').strip()
> - lockfile = os.path.join(lockdir, tap)
> - lock = lockfile + '.lock'
> - self.acquire_lock(lock)
> - self.cleantap = True
> - logger.debug('Created tap: %s' % tap)
> -
> - if not tap:
> - logger.error("Failed to setup tap device. Run
> runqemu-gen-tapdevs to manually create.")
> - return 1
> - self.tap = tap
> - tapnum = int(tap[3:])
> - gateway = tapnum * 2 + 1
> - client = gateway + 1
> - if self.fstype == 'nfs':
> - self.setup_nfs()
> - netconf = "192.168.7.%s::192.168.7.%s:255.255.255.0" % (client,
> gateway)
> - logger.info("Network configuration: %s", netconf)
> - self.kernel_cmdline_script += " ip=%s" % netconf
> - mac = "%s%02x" % (self.mac_tap, client)
> - qb_tap_opt = self.get('QB_TAP_OPT')
> - if qb_tap_opt:
> - qemu_tap_opt = qb_tap_opt.replace('@TAP@', tap)
> - else:
> - qemu_tap_opt = "-netdev
> tap,id=net0,ifname=%s,script=no,downscript=no" % (self.tap)
> + self.taps = []
> + qemu_tap_opt = self.get('QB_TAP_OPT')
> + if not qemu_tap_opt:
> + qemu_tap_opt = '-netdev tap,id=net0,ifname=@TAP@
> ,script=no,downscript=no'
>
> if self.vhost_enabled:
> - qemu_tap_opt += ',vhost=on'
> + opts = []
> + for tap_opt in qemu_tap_opt.split():
> + if 'tap' in tap_opt:
> + tap_opt += ',vhost=on'
> + opts.append(tap_opt)
> + else:
> + opts.append(tap_opt)
> + qemu_tap_opt = ' '.join(opts)
> +
> + tap_no = qemu_tap_opt.count('@TAP@')
> + for tap_idx in range(tap_no):
> + cmd = (ip, 'link')
> + logger.debug('Running %s...' % str(cmd))
> + ip_link = subprocess.check_output(cmd).decode('utf-8')
> + # Matches line like: 6: tap0: <foo>
> + possibles = re.findall('^[0-9]+: +(tap[0-9]+): <.*', ip_link,
> re.M)
> + tap = ""
> + for p in possibles:
> + if p in self.taps:
> + continue
> +
> + lockfile = os.path.join(lockdir, p)
> + if os.path.exists('%s.skip' % lockfile):
> + logger.info('Found %s.skip, skipping %s' %
> (lockfile, p))
> + continue
> + lock = lockfile + '.lock'
> + if self.acquire_lock(lock, error=False):
> + tap = p
> + logger.info("Using preconfigured tap device %s" %
> tap)
> + logger.info("If this is not intended, touch %s.skip
> to make runqemu skip %s." %(lockfile, tap))
> + break
>
> - self.set('NETWORK_CMD', '%s %s' %
> (self.network_device.replace('@MAC@', mac), qemu_tap_opt))
> + if not tap:
> + if os.path.exists(nosudo_flag):
> + logger.error("Error: There are no available tap
> devices to use for networking,")
> + logger.error("and I see %s exists, so I am not going
> to try creating" % nosudo_flag)
> + raise RunQemuError("a new one with sudo.")
> +
> + gid = os.getgid()
> + uid = os.getuid()
> + logger.info("Setting up tap interface under sudo")
> + cmd = ('sudo', self.qemuifup, str(uid), str(gid),
> self.bindir_native)
> + tap = subprocess.check_output(cmd).decode('utf-8').strip()
> + lockfile = os.path.join(lockdir, tap)
> + lock = lockfile + '.lock'
> + self.acquire_lock(lock)
> + self.cleantap = True
> + logger.info('Created tap: %s' % tap)
> +
> + if not tap:
> + logger.error("Failed to setup tap device. Run
> runqemu-gen-tapdevs to manually create.")
> + return 1
> + self.taps.append(tap)
> + tapnum = int(tap[3:])
> + gateway = tapnum * 2 + 1
> + client = gateway + 1
> +
>
Hi Chen,
For some reason Linux isn't not configuring the NIC when eth0 is specified
in the cmdline for qemuppc and qemuarm, I added this workaround
that not pass ethN to ip= in kernel cmdline when only one tap device is
requested.
Regards,
Anibal
> + # XXX: Linux qemuarm and qemuppc dosen't configure the
> interface
> + # if device is specified in ip (ethN), so if only one tap
> device is
> + # requested don't specify ethN.
> + if tap_no == 1:
> + netconf = "192.168.7.%s::192.168.7.%s:255.255.255.0" %
> (client, gateway)
> + logger.info("Network configuration: %s", netconf)
> + self.kernel_cmdline_script += " ip=%s" % netconf
> + elif tap_idx == 0:
> + netconf = "192.168.7.%s::192.168.7.%s:255.255.255.0::eth%d"
> % (client, gateway, tap_idx)
> + logger.info("Network configuration: %s", netconf)
> + self.kernel_cmdline_script += " ip=%s" % netconf
> +
> + mac = "%s%02x" % (self.mac_tap, client)
> + qemu_tap_opt = qemu_tap_opt.replace('@TAP@', tap, 1)
> + self.network_device = self.network_device.replace('@MAC@',
> mac, 1)
> +
> + self.set('NETWORK_CMD', '%s %s' % (self.network_device,
> qemu_tap_opt))
> + if self.fstype == 'nfs':
> + self.setup_nfs()
>
> def setup_network(self):
> if self.get('QB_NET') == 'none':
> @@ -1289,9 +1313,10 @@ class BaseConfig(object):
>
> logger.info("Cleaning up")
> if self.cleantap:
> - cmd = ('sudo', self.qemuifdown, self.tap, self.bindir_native)
> - logger.debug('Running %s' % str(cmd))
> - subprocess.check_call(cmd)
> + for tap in self.taps:
> + cmd = ('sudo', self.qemuifdown, tap, self.bindir_native)
> + logger.debug('Running %s' % str(cmd))
> + subprocess.check_call(cmd)
> for lock in self.lock_descriptors.keys():
> self.release_lock(lock)
>
> --
> 2.20.1
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openembedded.org/pipermail/openembedded-core/attachments/20190703/532965a9/attachment-0001.html>
More information about the Openembedded-core
mailing list