← Documents Documentation/virt/uml/user_mode_linux_howto_v2.rst GitHub 원문 ↗

Linux 6.18.37 · 가상화 / User Mode Linux

UML HowTo

User Mode Linux의 실행 모델, image와 network 구축, management console, COW·hostfs, 성능 tuning, tracing·driver 개발과 production 보안 조건을 설명합니다.

Source pathDocumentation/virt/uml/user_mode_linux_howto_v2.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

user_mode_linux_howto_v2.rst:1-1240

UML kernel은 host의 일반 process로 실행되며 실제 hardware emulation 대신 file·socket·pipe에 대응하는 paravirtual device를 사용합니다. Image 생성, UBD root와 COW, vector network transport, console과 mconsole 운영 절차를 명령 단위로 정리했습니다.

후반부는 hostfs 노출 위험, CPU·NUMA locality, strace·GDB debugging, user/kernel driver 분할과 DTB test를 다룹니다. Production에서는 host 영향 parameter를 startup에서 고정하고 boot 후 module loading을 막아야 한다는 보안 경계를 강조합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 #########
4 UML HowTo
5 #########
6
7 .. contents:: :local:
8
9 ************
10 Introduction
11 ************
12
13 Welcome to User Mode Linux
14
15 User Mode Linux is the first Open Source virtualization platform (first
16 release date 1991) and second virtualization platform for an x86 PC.
17
18 How is UML Different from a VM using Virtualization package X?
19 ==============================================================
20
21 We have come to assume that virtualization also means some level of
22 hardware emulation. In fact, it does not. As long as a virtualization
23 package provides the OS with devices which the OS can recognize and
24 has a driver for, the devices do not need to emulate real hardware.
25 Most OSes today have built-in support for a number of "fake"
26 devices used only under virtualization.
27 User Mode Linux takes this concept to the ultimate extreme - there
28 is not a single real device in sight. It is 100% artificial or if
29 we use the correct term 100% paravirtual. All UML devices are abstract
30 concepts which map onto something provided by the host - files, sockets,
31 pipes, etc.
32
33 The other major difference between UML and various virtualization
34 packages is that there is a distinct difference between the way the UML
35 kernel and the UML programs operate.
36 The UML kernel is just a process running on Linux - same as any other
37 program. It can be run by an unprivileged user and it does not require
38 anything in terms of special CPU features.
39 The UML userspace, however, is a bit different. The Linux kernel on the
40 host machine assists UML in intercepting everything the program running
41 on a UML instance is trying to do and making the UML kernel handle all
42 of its requests.
43 This is different from other virtualization packages which do not make any
44 difference between the guest kernel and guest programs. This difference
45 results in a number of advantages and disadvantages of UML over let's say
46 QEMU which we will cover later in this document.
47
48
49 Why Would I Want User Mode Linux?
50 =================================
51
52
53 * If User Mode Linux kernel crashes, your host kernel is still fine. It
54 is not accelerated in any way (vhost, kvm, etc) and it is not trying to
55 access any devices directly. It is, in fact, a process like any other.
56
57 * You can run a usermode kernel as a non-root user (you may need to
58 arrange appropriate permissions for some devices).
59
60 * You can run a very small VM with a minimal footprint for a specific
61 task (for example 32M or less).
62
63 * You can get extremely high performance for anything which is a "kernel
64 specific task" such as forwarding, firewalling, etc while still being
65 isolated from the host kernel.
66
67 * You can play with kernel concepts without breaking things.
68
69 * You are not bound by "emulating" hardware, so you can try weird and
70 wonderful concepts which are very difficult to support when emulating
71 real hardware such as time travel and making your system clock
72 dependent on what UML does (very useful for things like tests).
73
74 * It's fun.
75
76 Why not to run UML
77 ==================
78
79 * The syscall interception technique used by UML makes it inherently
80 slower for any userspace applications. While it can do kernel tasks
81 on par with most other virtualization packages, its userspace is
82 **slow**. The root cause is that UML has a very high cost of creating
83 new processes and threads (something most Unix/Linux applications
84 take for granted).
85
86 * UML is strictly uniprocessor at present. If you want to run an
87 application which needs many CPUs to function, it is clearly the
88 wrong choice.
89
90 ***********************
91 Building a UML instance
92 ***********************
93
94 There is no UML installer in any distribution. While you can use off
95 the shelf install media to install into a blank VM using a virtualization
96 package, there is no UML equivalent. You have to use appropriate tools on
97 your host to build a viable filesystem image.
98
99 This is extremely easy on Debian - you can do it using debootstrap. It is
100 also easy on OpenWRT - the build process can build UML images. All other
101 distros - YMMV.
102
103 Creating an image
104 =================
105
106 Create a sparse raw disk image::
107
108 # dd if=/dev/zero of=disk_image_name bs=1 count=1 seek=16G
109
110 This will create a 16G disk image. The OS will initially allocate only one
111 block and will allocate more as they are written by UML. As of kernel
112 version 4.19 UML fully supports TRIM (as usually used by flash drives).
113 Using TRIM inside the UML image by specifying discard as a mount option
114 or by running ``tune2fs -o discard /dev/ubdXX`` will request UML to
115 return any unused blocks to the OS.
116
117 Create a filesystem on the disk image and mount it::
118
119 # mkfs.ext4 ./disk_image_name && mount ./disk_image_name /mnt
120
121 This example uses ext4, any other filesystem such as ext3, btrfs, xfs,
122 jfs, etc will work too.
123
124 Create a minimal OS installation on the mounted filesystem::
125
126 # debootstrap buster /mnt http://deb.debian.org/debian
127
128 debootstrap does not set up the root password, fstab, hostname or
129 anything related to networking. It is up to the user to do that.
130
131 Set the root password - the easiest way to do that is to chroot into the
132 mounted image::
133
134 # chroot /mnt
135 # passwd
136 # exit
137
138 Edit key system files
139 =====================
140
141 UML block devices are called ubds. The fstab created by debootstrap
142 will be empty and it needs an entry for the root file system::
143
144 /dev/ubd0 ext4 discard,errors=remount-ro 0 1
145
146 The image hostname will be set to the same as the host on which you
147 are creating its image. It is a good idea to change that to avoid
148 "Oh, bummer, I rebooted the wrong machine".
149
150 UML supports vector I/O high performance network devices which have
151 support for some standard virtual network encapsulations like
152 Ethernet over GRE and Ethernet over L2TPv3. These are called vecX.
153
154 When vector network devices are in use, ``/etc/network/interfaces``
155 will need entries like::
156
157 # vector UML network devices
158 auto vec0
159 iface vec0 inet dhcp
160
161 We now have a UML image which is nearly ready to run, all we need is a
162 UML kernel and modules for it.
163
164 Most distributions have a UML package. Even if you intend to use your own
165 kernel, testing the image with a stock one is always a good start. These
166 packages come with a set of modules which should be copied to the target
167 filesystem. The location is distribution dependent. For Debian these
168 reside under /usr/lib/uml/modules. Copy recursively the content of this
169 directory to the mounted UML filesystem::
170
171 # cp -rax /usr/lib/uml/modules /mnt/lib/modules
172
173 If you have compiled your own kernel, you need to use the usual "install
174 modules to a location" procedure by running::
175
176 # make INSTALL_MOD_PATH=/mnt/lib/modules modules_install
177
178 This will install modules into /mnt/lib/modules/$(KERNELRELEASE).
179 To specify the full module installation path, use::
180
181 # make MODLIB=/mnt/lib/modules modules_install
182
183 At this point the image is ready to be brought up.
184
185 *************************
186 Setting Up UML Networking
187 *************************
188
189 UML networking is designed to emulate an Ethernet connection. This
190 connection may be either point-to-point (similar to a connection
191 between machines using a back-to-back cable) or a connection to a
192 switch. UML supports a wide variety of means to build these
193 connections to all of: local machine, remote machine(s), local and
194 remote UML and other VM instances.
195
196
197 +-----------+--------+------------------------------------+------------+
198 | Transport | Type | Capabilities | Throughput |
199 +===========+========+====================================+============+
200 | tap | vector | checksum, tso | > 8Gbit |
201 +-----------+--------+------------------------------------+------------+
202 | hybrid | vector | checksum, tso, multipacket rx | > 6GBit |
203 +-----------+--------+------------------------------------+------------+
204 | raw | vector | checksum, tso, multipacket rx, tx" | > 6GBit |
205 +-----------+--------+------------------------------------+------------+
206 | EoGRE | vector | multipacket rx, tx | > 3Gbit |
207 +-----------+--------+------------------------------------+------------+
208 | Eol2tpv3 | vector | multipacket rx, tx | > 3Gbit |
209 +-----------+--------+------------------------------------+------------+
210 | bess | vector | multipacket rx, tx | > 3Gbit |
211 +-----------+--------+------------------------------------+------------+
212 | fd | vector | dependent on fd type | varies |
213 +-----------+--------+------------------------------------+------------+
214 | vde | vector | dep. on VDE VPN: Virt.Net Locator | varies |
215 +-----------+--------+------------------------------------+------------+
216
217 * All transports which have tso and checksum offloads can deliver speeds
218 approaching 10G on TCP streams.
219
220 * All transports which have multi-packet rx and/or tx can deliver pps
221 rates of up to 1Mps or more.
222
223 * GRE and L2TPv3 allow connections to all of: local machine, remote
224 machines, remote network devices and remote UML instances.
225
226
227 Network configuration privileges
228 ================================
229
230 The majority of the supported networking modes need ``root`` privileges.
231 For example, for vector transports, ``root`` privilege is required to fire
232 an ioctl to setup the tun interface and/or use raw sockets where needed.
233
234 This can be achieved by granting the user a particular capability instead
235 of running UML as root. In case of vector transport, a user can add the
236 capability ``CAP_NET_ADMIN`` or ``CAP_NET_RAW`` to the uml binary.
237 Thenceforth, UML can be run with normal user privilges, along with
238 full networking.
239
240 For example::
241
242 # sudo setcap cap_net_raw,cap_net_admin+ep linux
243
244 Configuring vector transports
245 ===============================
246
247 All vector transports support a similar syntax:
248
249 If X is the interface number as in vec0, vec1, vec2, etc, the general
250 syntax for options is::
251
252 vecX:transport="Transport Name",option=value,option=value,...,option=value
253
254 Common options
255 --------------
256
257 These options are common for all transports:
258
259 * ``depth=int`` - sets the queue depth for vector IO. This is the
260 amount of packets UML will attempt to read or write in a single
261 system call. The default number is 64 and is generally sufficient
262 for most applications that need throughput in the 2-4 Gbit range.
263 Higher speeds may require larger values.
264
265 * ``mac=XX:XX:XX:XX:XX`` - sets the interface MAC address value.
266
267 * ``gro=[0,1]`` - sets GRO off or on. Enables receive/transmit offloads.
268 The effect of this option depends on the host side support in the transport
269 which is being configured. In most cases it will enable TCP segmentation and
270 RX/TX checksumming offloads. The setting must be identical on the host side
271 and the UML side. The UML kernel will produce warnings if it is not.
272 For example, GRO is enabled by default on local machine interfaces
273 (e.g. veth pairs, bridge, etc), so it should be enabled in UML in the
274 corresponding UML transports (raw, tap, hybrid) in order for networking to
275 operate correctly.
276
277 * ``mtu=int`` - sets the interface MTU
278
279 * ``headroom=int`` - adjusts the default headroom (32 bytes) reserved
280 if a packet will need to be re-encapsulated into for instance VXLAN.
281
282 * ``vec=0`` - disable multipacket IO and fall back to packet at a
283 time mode
284
285 Shared Options
286 --------------
287
288 * ``ifname=str`` Transports which bind to a local network interface
289 have a shared option - the name of the interface to bind to.
290
291 * ``src, dst, src_port, dst_port`` - all transports which use sockets
292 which have the notion of source and destination and/or source port
293 and destination port use these to specify them.
294
295 * ``v6=[0,1]`` to specify if a v6 connection is desired for all
296 transports which operate over IP. Additionally, for transports that
297 have some differences in the way they operate over v4 and v6 (for example
298 EoL2TPv3), sets the correct mode of operation. In the absence of this
299 option, the socket type is determined based on what do the src and dst
300 arguments resolve/parse to.
301
302 tap transport
303 -------------
304
305 Example::
306
307 vecX:transport=tap,ifname=tap0,depth=128,gro=1
308
309 This will connect vec0 to tap0 on the host. Tap0 must already exist (for example
310 created using tunctl) and UP.
311
312 tap0 can be configured as a point-to-point interface and given an IP
313 address so that UML can talk to the host. Alternatively, it is possible
314 to connect UML to a tap interface which is connected to a bridge.
315
316 While tap relies on the vector infrastructure, it is not a true vector
317 transport at this point, because Linux does not support multi-packet
318 IO on tap file descriptors for normal userspace apps like UML. This
319 is a privilege which is offered only to something which can hook up
320 to it at kernel level via specialized interfaces like vhost-net. A
321 vhost-net like helper for UML is planned at some point in the future.
322
323 Privileges required: tap transport requires either:
324
325 * tap interface to exist and be created persistent and owned by the
326 UML user using tunctl. Example ``tunctl -u uml-user -t tap0``
327
328 * binary to have ``CAP_NET_ADMIN`` privilege
329
330 hybrid transport
331 ----------------
332
333 Example::
334
335 vecX:transport=hybrid,ifname=tap0,depth=128,gro=1
336
337 This is an experimental/demo transport which couples tap for transmit
338 and a raw socket for receive. The raw socket allows multi-packet
339 receive resulting in significantly higher packet rates than normal tap.
340
341 Privileges required: hybrid requires ``CAP_NET_RAW`` capability by
342 the UML user as well as the requirements for the tap transport.
343
344 raw socket transport
345 --------------------
346
347 Example::
348
349 vecX:transport=raw,ifname=p-veth0,depth=128,gro=1
350
351
352 This transport uses vector IO on raw sockets. While you can bind to any
353 interface including a physical one, the most common use it to bind to
354 the "peer" side of a veth pair with the other side configured on the
355 host.
356
357 Example host configuration for Debian:
358
359 **/etc/network/interfaces**::
360
361 auto veth0
362 iface veth0 inet static
363 address 192.168.4.1
364 netmask 255.255.255.252
365 broadcast 192.168.4.3
366 pre-up ip link add veth0 type veth peer name p-veth0 && \
367 ifconfig p-veth0 up
368
369 UML can now bind to p-veth0 like this::
370
371 vec0:transport=raw,ifname=p-veth0,depth=128,gro=1
372
373
374 If the UML guest is configured with 192.168.4.2 and netmask 255.255.255.0
375 it can talk to the host on 192.168.4.1
376
377 The raw transport also provides some support for offloading some of the
378 filtering to the host. The two options to control it are:
379
380 * ``bpffile=str`` filename of raw bpf code to be loaded as a socket filter
381
382 * ``bpfflash=int`` 0/1 allow loading of bpf from inside User Mode Linux.
383 This option allows the use of the ethtool load firmware command to
384 load bpf code.
385
386 In either case the bpf code is loaded into the host kernel. While this is
387 presently limited to legacy bpf syntax (not ebpf), it is still a security
388 risk. It is not recommended to allow this unless the User Mode Linux
389 instance is considered trusted.
390
391 Privileges required: raw socket transport requires `CAP_NET_RAW`
392 capability.
393
394 GRE socket transport
395 --------------------
396
397 Example::
398
399 vecX:transport=gre,src=$src_host,dst=$dst_host
400
401
402 This will configure an Ethernet over ``GRE`` (aka ``GRETAP`` or
403 ``GREIRB``) tunnel which will connect the UML instance to a ``GRE``
404 endpoint at host dst_host. ``GRE`` supports the following additional
405 options:
406
407 * ``rx_key=int`` - GRE 32-bit integer key for rx packets, if set,
408 ``txkey`` must be set too
409
410 * ``tx_key=int`` - GRE 32-bit integer key for tx packets, if set
411 ``rx_key`` must be set too
412
413 * ``sequence=[0,1]`` - enable GRE sequence
414
415 * ``pin_sequence=[0,1]`` - pretend that the sequence is always reset
416 on each packet (needed to interoperate with some really broken
417 implementations)
418
419 * ``v6=[0,1]`` - force IPv4 or IPv6 sockets respectively
420
421 * GRE checksum is not presently supported
422
423 GRE has a number of caveats:
424
425 * You can use only one GRE connection per IP address. There is no way to
426 multiplex connections as each GRE tunnel is terminated directly on
427 the UML instance.
428
429 * The key is not really a security feature. While it was intended as such
430 its "security" is laughable. It is, however, a useful feature to
431 ensure that the tunnel is not misconfigured.
432
433 An example configuration for a Linux host with a local address of
434 192.168.128.1 to connect to a UML instance at 192.168.129.1
435
436 **/etc/network/interfaces**::
437
438 auto gt0
439 iface gt0 inet static
440 address 10.0.0.1
441 netmask 255.255.255.0
442 broadcast 10.0.0.255
443 mtu 1500
444 pre-up ip link add gt0 type gretap local 192.168.128.1 \
445 remote 192.168.129.1 || true
446 down ip link del gt0 || true
447
448 Additionally, GRE has been tested versus a variety of network equipment.
449
450 Privileges required: GRE requires ``CAP_NET_RAW``
451
452 l2tpv3 socket transport
453 -----------------------
454
455 _Warning_. L2TPv3 has a "bug". It is the "bug" known as "has more
456 options than GNU ls". While it has some advantages, there are usually
457 easier (and less verbose) ways to connect a UML instance to something.
458 For example, most devices which support L2TPv3 also support GRE.
459
460 Example::
461
462 vec0:transport=l2tpv3,udp=1,src=$src_host,dst=$dst_host,srcport=$src_port,dstport=$dst_port,depth=128,rx_session=0xffffffff,tx_session=0xffff
463
464 This will configure an Ethernet over L2TPv3 fixed tunnel which will
465 connect the UML instance to a L2TPv3 endpoint at host $dst_host using
466 the L2TPv3 UDP flavour and UDP destination port $dst_port.
467
468 L2TPv3 always requires the following additional options:
469
470 * ``rx_session=int`` - l2tpv3 32-bit integer session for rx packets
471
472 * ``tx_session=int`` - l2tpv3 32-bit integer session for tx packets
473
474 As the tunnel is fixed these are not negotiated and they are
475 preconfigured on both ends.
476
477 Additionally, L2TPv3 supports the following optional parameters.
478
479 * ``rx_cookie=int`` - l2tpv3 32-bit integer cookie for rx packets - same
480 functionality as GRE key, more to prevent misconfiguration than provide
481 actual security
482
483 * ``tx_cookie=int`` - l2tpv3 32-bit integer cookie for tx packets
484
485 * ``cookie64=[0,1]`` - use 64-bit cookies instead of 32-bit.
486
487 * ``counter=[0,1]`` - enable l2tpv3 counter
488
489 * ``pin_counter=[0,1]`` - pretend that the counter is always reset on
490 each packet (needed to interoperate with some really broken
491 implementations)
492
493 * ``v6=[0,1]`` - force v6 sockets
494
495 * ``udp=[0,1]`` - use raw sockets (0) or UDP (1) version of the protocol
496
497 L2TPv3 has a number of caveats:
498
499 * you can use only one connection per IP address in raw mode. There is
500 no way to multiplex connections as each L2TPv3 tunnel is terminated
501 directly on the UML instance. UDP mode can use different ports for
502 this purpose.
503
504 Here is an example of how to configure a Linux host to connect to UML
505 via L2TPv3:
506
507 **/etc/network/interfaces**::
508
509 auto l2tp1
510 iface l2tp1 inet static
511 address 192.168.126.1
512 netmask 255.255.255.0
513 broadcast 192.168.126.255
514 mtu 1500
515 pre-up ip l2tp add tunnel remote 127.0.0.1 \
516 local 127.0.0.1 encap udp tunnel_id 2 \
517 peer_tunnel_id 2 udp_sport 1706 udp_dport 1707 && \
518 ip l2tp add session name l2tp1 tunnel_id 2 \
519 session_id 0xffffffff peer_session_id 0xffffffff
520 down ip l2tp del session tunnel_id 2 session_id 0xffffffff && \
521 ip l2tp del tunnel tunnel_id 2
522
523
524 Privileges required: L2TPv3 requires ``CAP_NET_RAW`` for raw IP mode and
525 no special privileges for the UDP mode.
526
527 BESS socket transport
528 ---------------------
529
530 BESS is a high performance modular network switch.
531
532 https://github.com/NetSys/bess
533
534 It has support for a simple sequential packet socket mode which in the
535 more recent versions is using vector IO for high performance.
536
537 Example::
538
539 vecX:transport=bess,src=$unix_src,dst=$unix_dst
540
541 This will configure a BESS transport using the unix_src Unix domain
542 socket address as source and unix_dst socket address as destination.
543
544 For BESS configuration and how to allocate a BESS Unix domain socket port
545 please see the BESS documentation.
546
547 https://github.com/NetSys/bess/wiki/Built-In-Modules-and-Ports
548
549 BESS transport does not require any special privileges.
550
551 VDE vector transport
552 --------------------
553
554 Virtual Distributed Ethernet (VDE) is a project whose main goal is to provide a
555 highly flexible support for virtual networking.
556
557 http://wiki.virtualsquare.org/#/tutorials/vdebasics
558
559 Common usages of VDE include fast prototyping and teaching.
560
561 Examples:
562
563 ``vecX:transport=vde,vnl=tap://tap0``
564
565 use tap0
566
567 ``vecX:transport=vde,vnl=slirp://``
568
569 use slirp
570
571 ``vec0:transport=vde,vnl=vde:///tmp/switch``
572
573 connect to a vde switch
574
575 ``vecX:transport=\"vde,vnl=cmd://ssh remote.host //tmp/sshlirp\"``
576
577 connect to a remote slirp (instant VPN: convert ssh to VPN, it uses sshlirp)
578 https://github.com/virtualsquare/sshlirp
579
580 ``vec0:transport=vde,vnl=vxvde://234.0.0.1``
581
582 connect to a local area cloud (all the UML nodes using the same
583 multicast address running on hosts in the same multicast domain (LAN)
584 will be automagically connected together to a virtual LAN.
585
586 ***********
587 Running UML
588 ***********
589
590 This section assumes that either the user-mode-linux package from the
591 distribution or a custom built kernel has been installed on the host.
592
593 These add an executable called linux to the system. This is the UML
594 kernel. It can be run just like any other executable.
595 It will take most normal linux kernel arguments as command line
596 arguments. Additionally, it will need some UML-specific arguments
597 in order to do something useful.
598
599 Arguments
600 =========
601
602 Mandatory Arguments:
603 --------------------
604
605 * ``mem=int[K,M,G]`` - amount of memory. By default in bytes. It will
606 also accept K, M or G qualifiers.
607
608 * ``ubdX[s,d,c,t]=`` virtual disk specification. This is not really
609 mandatory, but it is likely to be needed in nearly all cases so we can
610 specify a root file system.
611 The simplest possible image specification is the name of the image
612 file for the filesystem (created using one of the methods described
613 in `Creating an image`_).
614
615 * UBD devices support copy on write (COW). The changes are kept in
616 a separate file which can be discarded allowing a rollback to the
617 original pristine image. If COW is desired, the UBD image is
618 specified as: ``cow_file,master_image``.
619 Example:``ubd0=Filesystem.cow,Filesystem.img``
620
621 * UBD devices can be set to use synchronous IO. Any writes are
622 immediately flushed to disk. This is done by adding ``s`` after
623 the ``ubdX`` specification.
624
625 * UBD performs some heuristics on devices specified as a single
626 filename to make sure that a COW file has not been specified as
627 the image. To turn them off, use the ``d`` flag after ``ubdX``.
628
629 * UBD supports TRIM - asking the Host OS to reclaim any unused
630 blocks in the image. To turn it off, specify the ``t`` flag after
631 ``ubdX``.
632
633 * ``root=`` root device - most likely ``/dev/ubd0`` (this is a Linux
634 filesystem image)
635
636 Important Optional Arguments
637 ----------------------------
638
639 If UML is run as "linux" with no extra arguments, it will try to start an
640 xterm for every console configured inside the image (up to 6 in most
641 Linux distributions). Each console is started inside an
642 xterm. This makes it nice and easy to use UML on a host with a GUI. It is,
643 however, the wrong approach if UML is to be used as a testing harness or run
644 in a text-only environment.
645
646 In order to change this behaviour we need to specify an alternative console
647 and wire it to one of the supported "line" channels. For this we need to map a
648 console to use something different from the default xterm.
649
650 Example which will divert console number 1 to stdin/stdout::
651
652 con1=fd:0,fd:1
653
654 UML supports a wide variety of serial line channels which are specified using
655 the following syntax
656
657 conX=channel_type:options[,channel_type:options]
658
659
660 If the channel specification contains two parts separated by comma, the first
661 one is input, the second one output.
662
663 * The null channel - Discard all input or output. Example ``con=null`` will set
664 all consoles to null by default.
665
666 * The fd channel - use file descriptor numbers for input/output. Example:
667 ``con1=fd:0,fd:1.``
668
669 * The port channel - start a telnet server on TCP port number. Example:
670 ``con1=port:4321``. The host must have /usr/sbin/in.telnetd (usually part of
671 a telnetd package) and the port-helper from the UML utilities (see the
672 information for the xterm channel below). UML will not boot until a client
673 connects.
674
675 * The pty and pts channels - use system pty/pts.
676
677 * The tty channel - bind to an existing system tty. Example: ``con1=/dev/tty8``
678 will make UML use the host 8th console (usually unused).
679
680 * The xterm channel - this is the default - bring up an xterm on this channel
681 and direct IO to it. Note that in order for xterm to work, the host must
682 have the UML distribution package installed. This usually contains the
683 port-helper and other utilities needed for UML to communicate with the xterm.
684 Alternatively, these need to be complied and installed from source. All
685 options applicable to consoles also apply to UML serial lines which are
686 presented as ttyS inside UML.
687
688 Starting UML
689 ============
690
691 We can now run UML.
692 ::
693
694 # linux mem=2048M umid=TEST \
695 ubd0=Filesystem.img \
696 vec0:transport=tap,ifname=tap0,depth=128,gro=1 \
697 root=/dev/ubda con=null con0=null,fd:2 con1=fd:0,fd:1
698
699 This will run an instance with ``2048M RAM`` and try to use the image file
700 called ``Filesystem.img`` as root. It will connect to the host using tap0.
701 All consoles except ``con1`` will be disabled and console 1 will
702 use standard input/output making it appear in the same terminal it was started.
703
704 Logging in
705 ============
706
707 If you have not set up a password when generating the image, you will have to
708 shut down the UML instance, mount the image, chroot into it and set it - as
709 described in the Generating an Image section. If the password is already set,
710 you can just log in.
711
712 The UML Management Console
713 ============================
714
715 In addition to managing the image from "the inside" using normal sysadmin tools,
716 it is possible to perform a number of low-level operations using the UML
717 management console. The UML management console is a low-level interface to the
718 kernel on a running UML instance, somewhat like the i386 SysRq interface. Since
719 there is a full-blown operating system under UML, there is much greater
720 flexibility possible than with the SysRq mechanism.
721
722 There are a number of things you can do with the mconsole interface:
723
724 * get the kernel version
725 * add and remove devices
726 * halt or reboot the machine
727 * Send SysRq commands
728 * Pause and resume the UML
729 * Inspect processes running inside UML
730 * Inspect UML internal /proc state
731
732 You need the mconsole client (uml\_mconsole) which is a part of the UML
733 tools package available in most Linux distritions.
734
735 You also need ``CONFIG_MCONSOLE`` (under 'General Setup') enabled in the UML
736 kernel. When you boot UML, you'll see a line like::
737
738 mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole
739
740 If you specify a unique machine id on the UML command line, i.e.
741 ``umid=debian``, you'll see this::
742
743 mconsole initialized on /home/jdike/.uml/debian/mconsole
744
745
746 That file is the socket that uml_mconsole will use to communicate with
747 UML. Run it with either the umid or the full path as its argument::
748
749 # uml_mconsole debian
750
751 or
752
753 # uml_mconsole /home/jdike/.uml/debian/mconsole
754
755
756 You'll get a prompt, at which you can run one of these commands:
757
758 * version
759 * help
760 * halt
761 * reboot
762 * config
763 * remove
764 * sysrq
765 * help
766 * cad
767 * stop
768 * go
769 * proc
770 * stack
771
772 version
773 -------
774
775 This command takes no arguments. It prints the UML version::
776
777 (mconsole) version
778 OK Linux OpenWrt 4.14.106 #0 Tue Mar 19 08:19:41 2019 x86_64
779
780
781 There are a couple actual uses for this. It's a simple no-op which
782 can be used to check that a UML is running. It's also a way of
783 sending a device interrupt to the UML. UML mconsole is treated internally as
784 a UML device.
785
786 help
787 ----
788
789 This command takes no arguments. It prints a short help screen with the
790 supported mconsole commands.
791
792
793 halt and reboot
794 ---------------
795
796 These commands take no arguments. They shut the machine down immediately, with
797 no syncing of disks and no clean shutdown of userspace. So, they are
798 pretty close to crashing the machine::
799
800 (mconsole) halt
801 OK
802
803 config
804 ------
805
806 "config" adds a new device to the virtual machine. This is supported
807 by most UML device drivers. It takes one argument, which is the
808 device to add, with the same syntax as the kernel command line::
809
810 (mconsole) config ubd3=/home/jdike/incoming/roots/root_fs_debian22
811
812 remove
813 ------
814
815 "remove" deletes a device from the system. Its argument is just the
816 name of the device to be removed. The device must be idle in whatever
817 sense the driver considers necessary. In the case of the ubd driver,
818 the removed block device must not be mounted, swapped on, or otherwise
819 open, and in the case of the network driver, the device must be down::
820
821 (mconsole) remove ubd3
822
823 sysrq
824 -----
825
826 This command takes one argument, which is a single letter. It calls the
827 generic kernel's SysRq driver, which does whatever is called for by
828 that argument. See the SysRq documentation in
829 Documentation/admin-guide/sysrq.rst in your favorite kernel tree to
830 see what letters are valid and what they do.
831
832 cad
833 ---
834
835 This invokes the ``Ctl-Alt-Del`` action in the running image. What exactly
836 this ends up doing is up to init, systemd, etc. Normally, it reboots the
837 machine.
838
839 stop
840 ----
841
842 This puts the UML in a loop reading mconsole requests until a 'go'
843 mconsole command is received. This is very useful as a
844 debugging/snapshotting tool.
845
846 go
847 --
848
849 This resumes a UML after being paused by a 'stop' command. Note that
850 when the UML has resumed, TCP connections may have timed out and if
851 the UML is paused for a long period of time, crond might go a little
852 crazy, running all the jobs it didn't do earlier.
853
854 proc
855 ----
856
857 This takes one argument - the name of a file in /proc which is printed
858 to the mconsole standard output
859
860 stack
861 -----
862
863 This takes one argument - the pid number of a process. Its stack is
864 printed to a standard output.
865
866 *******************
867 Advanced UML Topics
868 *******************
869
870 Sharing Filesystems between Virtual Machines
871 ============================================
872
873 Don't attempt to share filesystems simply by booting two UMLs from the
874 same file. That's the same thing as booting two physical machines
875 from a shared disk. It will result in filesystem corruption.
876
877 Using layered block devices
878 ---------------------------
879
880 The way to share a filesystem between two virtual machines is to use
881 the copy-on-write (COW) layering capability of the ubd block driver.
882 Any changed blocks are stored in the private COW file, while reads come
883 from either device - the private one if the requested block is valid in
884 it, the shared one if not. Using this scheme, the majority of data
885 which is unchanged is shared between an arbitrary number of virtual
886 machines, each of which has a much smaller file containing the changes
887 that it has made. With a large number of UMLs booting from a large root
888 filesystem, this leads to a huge disk space saving.
889
890 Sharing file system data will also help performance, since the host will
891 be able to cache the shared data using a much smaller amount of memory,
892 so UML disk requests will be served from the host's memory rather than
893 its disks. There is a major caveat in doing this on multisocket NUMA
894 machines. On such hardware, running many UML instances with a shared
895 master image and COW changes may cause issues like NMIs from excess of
896 inter-socket traffic.
897
898 If you are running UML on high-end hardware like this, make sure to
899 bind UML to a set of logical CPUs residing on the same socket using the
900 ``taskset`` command or have a look at the "tuning" section.
901
902 To add a copy-on-write layer to an existing block device file, simply
903 add the name of the COW file to the appropriate ubd switch::
904
905 ubd0=root_fs_cow,root_fs_debian_22
906
907 where ``root_fs_cow`` is the private COW file and ``root_fs_debian_22`` is
908 the existing shared filesystem. The COW file need not exist. If it
909 doesn't, the driver will create and initialize it.
910
911 Disk Usage
912 ----------
913
914 UML has TRIM support which will release any unused space in its disk
915 image files to the underlying OS. It is important to use either ls -ls
916 or du to verify the actual file size.
917
918 COW validity.
919 -------------
920
921 Any changes to the master image will invalidate all COW files. If this
922 happens, UML will *NOT* automatically delete any of the COW files and
923 will refuse to boot. In this case the only solution is to either
924 restore the old image (including its last modified timestamp) or remove
925 all COW files which will result in their recreation. Any changes in
926 the COW files will be lost.
927
928 Cows can moo - uml_moo : Merging a COW file with its backing file
929 -----------------------------------------------------------------
930
931 Depending on how you use UML and COW devices, it may be advisable to
932 merge the changes in the COW file into the backing file every once in
933 a while.
934
935 The utility that does this is uml_moo. Its usage is::
936
937 uml_moo COW_file new_backing_file
938
939
940 There's no need to specify the backing file since that information is
941 already in the COW file header. If you're paranoid, boot the new
942 merged file, and if you're happy with it, move it over the old backing
943 file.
944
945 ``uml_moo`` creates a new backing file by default as a safety measure.
946 It also has a destructive merge option which will merge the COW file
947 directly into its current backing file. This is really only usable
948 when the backing file only has one COW file associated with it. If
949 there are multiple COWs associated with a backing file, a -d merge of
950 one of them will invalidate all of the others. However, it is
951 convenient if you're short of disk space, and it should also be
952 noticeably faster than a non-destructive merge.
953
954 ``uml_moo`` is installed with the UML distribution packages and is
955 available as a part of UML utilities.
956
957 Host file access
958 ==================
959
960 If you want to access files on the host machine from inside UML, you
961 can treat it as a separate machine and either nfs mount directories
962 from the host or copy files into the virtual machine with scp.
963 However, since UML is running on the host, it can access those
964 files just like any other process and make them available inside the
965 virtual machine without the need to use the network.
966 This is possible with the hostfs virtual filesystem. With it, you
967 can mount a host directory into the UML filesystem and access the
968 files contained in it just as you would on the host.
969
970 *SECURITY WARNING*
971
972 Hostfs without any parameters to the UML Image will allow the image
973 to mount any part of the host filesystem and write to it. Always
974 confine hostfs to a specific "harmless" directory (for example ``/var/tmp``)
975 if running UML. This is especially important if UML is being run as root.
976
977 Using hostfs
978 ------------
979
980 To begin with, make sure that hostfs is available inside the virtual
981 machine with::
982
983 # cat /proc/filesystems
984
985 ``hostfs`` should be listed. If it's not, either rebuild the kernel
986 with hostfs configured into it or make sure that hostfs is built as a
987 module and available inside the virtual machine, and insmod it.
988
989
990 Now all you need to do is run mount::
991
992 # mount none /mnt/host -t hostfs
993
994 will mount the host's ``/`` on the virtual machine's ``/mnt/host``.
995 If you don't want to mount the host root directory, then you can
996 specify a subdirectory to mount with the -o switch to mount::
997
998 # mount none /mnt/home -t hostfs -o /home
999
1000 will mount the host's /home on the virtual machine's /mnt/home.
1002 hostfs as the root filesystem
1003 -----------------------------
1005 It's possible to boot from a directory hierarchy on the host using
1006 hostfs rather than using the standard filesystem in a file.
1007 To start, you need that hierarchy. The easiest way is to loop mount
1008 an existing root_fs file::
1010 # mount root_fs uml_root_dir -o loop
1013 You need to change the filesystem type of ``/`` in ``etc/fstab`` to be
1014 'hostfs', so that line looks like this::
1016 /dev/ubd/0 / hostfs defaults 1 1
1018 Then you need to chown to yourself all the files in that directory
1019 that are owned by root. This worked for me::
1021 # find . -uid 0 -exec chown jdike {} \;
1023 Next, make sure that your UML kernel has hostfs compiled in, not as a
1024 module. Then run UML with the boot device pointing at that directory::
1026 ubd0=/path/to/uml/root/directory
1028 UML should then boot as it does normally.
1030 Hostfs Caveats
1031 --------------
1033 Hostfs does not support keeping track of host filesystem changes on the
1034 host (outside UML). As a result, if a file is changed without UML's
1035 knowledge, UML will not know about it and its own in-memory cache of
1036 the file may be corrupt. While it is possible to fix this, it is not
1037 something which is being worked on at present.
1039 Tuning UML
1040 ============
1042 UML at present is strictly uniprocessor. It will, however spin up a
1043 number of threads to handle various functions.
1045 The UBD driver, SIGIO and the MMU emulation do that. If the system is
1046 idle, these threads will be migrated to other processors on a SMP host.
1047 This, unfortunately, will usually result in LOWER performance because of
1048 all of the cache/memory synchronization traffic between cores. As a
1049 result, UML will usually benefit from being pinned on a single CPU,
1050 especially on a large system. This can result in performance differences
1051 of 5 times or higher on some benchmarks.
1053 Similarly, on large multi-node NUMA systems UML will benefit if all of
1054 its memory is allocated from the same NUMA node it will run on. The
1055 OS will *NOT* do that by default. In order to do that, the sysadmin
1056 needs to create a suitable tmpfs ramdisk bound to a particular node
1057 and use that as the source for UML RAM allocation by specifying it
1058 in the TMP or TEMP environment variables. UML will look at the values
1059 of ``TMPDIR``, ``TMP`` or ``TEMP`` for that. If that fails, it will
1060 look for shmfs mounted under ``/dev/shm``. If everything else fails use
1061 ``/tmp/`` regardless of the filesystem type used for it::
1063 mount -t tmpfs -ompol=bind:X none /mnt/tmpfs-nodeX
1064 TEMP=/mnt/tmpfs-nodeX taskset -cX linux options options options..
1066 *******************************************
1067 Contributing to UML and Developing with UML
1068 *******************************************
1070 UML is an excellent platform to develop new Linux kernel concepts -
1071 filesystems, devices, virtualization, etc. It provides unrivalled
1072 opportunities to create and test them without being constrained to
1073 emulating specific hardware.
1075 Example - want to try how Linux will work with 4096 "proper" network
1076 devices?
1078 Not an issue with UML. At the same time, this is something which
1079 is difficult with other virtualization packages - they are
1080 constrained by the number of devices allowed on the hardware bus
1081 they are trying to emulate (for example 16 on a PCI bus in qemu).
1083 If you have something to contribute such as a patch, a bugfix, a
1084 new feature, please send it to ``linux-um@lists.infradead.org``.
1086 Please follow all standard Linux patch guidelines such as cc-ing
1087 relevant maintainers and run ``./scripts/checkpatch.pl`` on your patch.
1088 For more details see ``Documentation/process/submitting-patches.rst``
1090 Note - the list does not accept HTML or attachments, all emails must
1091 be formatted as plain text.
1093 Developing always goes hand in hand with debugging. First of all,
1094 you can always run UML under gdb and there will be a whole section
1095 later on on how to do that. That, however, is not the only way to
1096 debug a Linux kernel. Quite often adding tracing statements and/or
1097 using UML specific approaches such as ptracing the UML kernel process
1098 are significantly more informative.
1100 Tracing UML
1101 =============
1103 When running, UML consists of a main kernel thread and a number of
1104 helper threads. The ones of interest for tracing are NOT the ones
1105 that are already ptraced by UML as a part of its MMU emulation.
1107 These are usually the first three threads visible in a ps display.
1108 The one with the lowest PID number and using most CPU is usually the
1109 kernel thread. The other threads are the disk
1110 (ubd) device helper thread and the SIGIO helper thread.
1111 Running ptrace on this thread usually results in the following picture::
1113 host$ strace -p 16566
1114 --- SIGIO {si_signo=SIGIO, si_code=POLL_IN, si_band=65} ---
1115 epoll_wait(4, [{EPOLLIN, {u32=3721159424, u64=3721159424}}], 64, 0) = 1
1116 epoll_wait(4, [], 64, 0) = 0
1117 rt_sigreturn({mask=[PIPE]}) = 16967
1118 ptrace(PTRACE_GETREGS, 16967, NULL, 0xd5f34f38) = 0
1119 ptrace(PTRACE_GETREGSET, 16967, NT_X86_XSTATE, [{iov_base=0xd5f35010, iov_len=832}]) = 0
1120 ptrace(PTRACE_GETSIGINFO, 16967, NULL, {si_signo=SIGTRAP, si_code=0x85, si_pid=16967, si_uid=0}) = 0
1121 ptrace(PTRACE_SETREGS, 16967, NULL, 0xd5f34f38) = 0
1122 ptrace(PTRACE_SETREGSET, 16967, NT_X86_XSTATE, [{iov_base=0xd5f35010, iov_len=2696}]) = 0
1123 ptrace(PTRACE_SYSEMU, 16967, NULL, 0) = 0
1124 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=16967, si_uid=0, si_status=SIGTRAP, si_utime=65, si_stime=89} ---
1125 wait4(16967, [{WIFSTOPPED(s) && WSTOPSIG(s) == SIGTRAP | 0x80}], WSTOPPED|__WALL, NULL) = 16967
1126 ptrace(PTRACE_GETREGS, 16967, NULL, 0xd5f34f38) = 0
1127 ptrace(PTRACE_GETREGSET, 16967, NT_X86_XSTATE, [{iov_base=0xd5f35010, iov_len=832}]) = 0
1128 ptrace(PTRACE_GETSIGINFO, 16967, NULL, {si_signo=SIGTRAP, si_code=0x85, si_pid=16967, si_uid=0}) = 0
1129 timer_settime(0, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=0, tv_nsec=2830912}}, NULL) = 0
1130 getpid() = 16566
1131 clock_nanosleep(CLOCK_MONOTONIC, 0, {tv_sec=1, tv_nsec=0}, NULL) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
1132 --- SIGALRM {si_signo=SIGALRM, si_code=SI_TIMER, si_timerid=0, si_overrun=0, si_value={int=1631716592, ptr=0x614204f0}} ---
1133 rt_sigreturn({mask=[PIPE]}) = -1 EINTR (Interrupted system call)
1135 This is a typical picture from a mostly idle UML instance.
1137 * UML interrupt controller uses epoll - this is UML waiting for IO
1138 interrupts:
1140 epoll_wait(4, [{EPOLLIN, {u32=3721159424, u64=3721159424}}], 64, 0) = 1
1142 * The sequence of ptrace calls is part of MMU emulation and running the
1143 UML userspace.
1144 * ``timer_settime`` is part of the UML high res timer subsystem mapping
1145 timer requests from inside UML onto the host high resolution timers.
1146 * ``clock_nanosleep`` is UML going into idle (similar to the way a PC
1147 will execute an ACPI idle).
1149 As you can see UML will generate quite a bit of output even in idle. The output
1150 can be very informative when observing IO. It shows the actual IO calls, their
1151 arguments and returns values.
1153 Kernel debugging
1154 ================
1156 You can run UML under gdb now, though it will not necessarily agree to
1157 be started under it. If you are trying to track a runtime bug, it is
1158 much better to attach gdb to a running UML instance and let UML run.
1160 Assuming the same PID number as in the previous example, this would be::
1162 # gdb -p 16566
1164 This will STOP the UML instance, so you must enter `cont` at the GDB
1165 command line to request it to continue. It may be a good idea to make
1166 this into a gdb script and pass it to gdb as an argument.
1168 Developing Device Drivers
1169 =========================
1171 Nearly all UML drivers are monolithic. While it is possible to build a
1172 UML driver as a kernel module, that limits the possible functionality
1173 to in-kernel only and non-UML specific. The reason for this is that
1174 in order to really leverage UML, one needs to write a piece of
1175 userspace code which maps driver concepts onto actual userspace host
1176 calls.
1178 This forms the so-called "user" portion of the driver. While it can
1179 reuse a lot of kernel concepts, it is generally just another piece of
1180 userspace code. This portion needs some matching "kernel" code which
1181 resides inside the UML image and which implements the Linux kernel part.
1183 *Note: There are very few limitations in the way "kernel" and "user" interact*.
1185 UML does not have a strictly defined kernel-to-host API. It does not
1186 try to emulate a specific architecture or bus. UML's "kernel" and
1187 "user" can share memory, code and interact as needed to implement
1188 whatever design the software developer has in mind. The only
1189 limitations are purely technical. Due to a lot of functions and
1190 variables having the same names, the developer should be careful
1191 which includes and libraries they are trying to refer to.
1193 As a result a lot of userspace code consists of simple wrappers.
1194 E.g. ``os_close_file()`` is just a wrapper around ``close()``
1195 which ensures that the userspace function close does not clash
1196 with similarly named function(s) in the kernel part.
1198 Using UML as a Test Platform
1199 ============================
1201 UML is an excellent test platform for device driver development. As
1202 with most things UML, "some user assembly may be required". It is
1203 up to the user to build their emulation environment. UML at present
1204 provides only the kernel infrastructure.
1206 Part of this infrastructure is the ability to load and parse fdt
1207 device tree blobs as used in Arm or Open Firmware platforms. These
1208 are supplied as an optional extra argument to the kernel command
1209 line::
1211 dtb=filename
1213 The device tree is loaded and parsed at boottime and is accessible by
1214 drivers which query it. At this moment in time this facility is
1215 intended solely for development purposes. UML's own devices do not
1216 query the device tree.
1218 Security Considerations
1219 -----------------------
1221 Drivers or any new functionality should default to not
1222 accepting arbitrary filename, bpf code or other parameters
1223 which can affect the host from inside the UML instance.
1224 For example, specifying the socket used for IPC communication
1225 between a driver and the host at the UML command line is OK
1226 security-wise. Allowing it as a loadable module parameter
1227 isn't.
1229 If such functionality is desirable for a particular application
1230 (e.g. loading BPF "firmware" for raw socket network transports),
1231 it should be off by default and should be explicitly turned on
1232 as a command line parameter at startup.
1234 Even with this in mind, the level of isolation between UML
1235 and the host is relatively weak. If the UML userspace is
1236 allowed to load arbitrary kernel drivers, an attacker can
1237 use this to break out of UML. Thus, if UML is used in
1238 a production application, it is recommended that all modules
1239 are loaded at boot and kernel module loading is disabled
1240 afterwards.

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

UML HowTo 소개

1-17

이 문서는 User Mode Linux(UML)의 사용법을 설명하는 HowTo입니다. UML은 최초 공개가 1991년인 첫 번째 Open Source virtualization platform이며, x86 PC용으로 등장한 두 번째 virtualization platform이라고 소개됩니다.

이후 절에서는 UML이 일반적인 hardware emulation 기반 VM과 어떻게 다른지, UML instance와 filesystem image를 어떻게 만들고 networking을 구성하는지 단계별로 설명합니다.

문서 출발점
항목내용
이름User Mode Linux, UML
분류Open Source virtualization platform
첫 공개1991년
초기 대상x86 PC

첫 문단에서 밝히는 UML의 정체성과 범위입니다.

.. SPDX-License-Identifier: GPL-2.0

#########
UML HowTo
#########

.. contents:: :local:

************
Introduction
************

Welcome to User Mode Linux

User Mode Linux is the first Open Source virtualization platform (first
release date 1991) and second virtualization platform for an x86 PC.

일반 가상화 패키지와 UML의 차이

18-48

가상화가 반드시 어느 정도의 hardware emulation을 뜻하는 것은 아닙니다. 가상화 패키지가 운영체제가 인식할 수 있고 driver를 가진 device를 제공한다면, 그 device가 실제 hardware를 모사할 필요는 없습니다.

오늘날 대부분의 운영체제에는 가상화 환경에서만 쓰는 여러 'fake' device 지원이 내장돼 있습니다. UML은 이 개념을 극단까지 밀어붙여 실제 device를 하나도 노출하지 않고, 올바른 용어로는 100% paravirtual인 환경을 구성합니다.

모든 UML device는 host가 제공하는 file, socket, pipe 같은 자원에 대응하는 추상 개념입니다. 따라서 guest가 보는 device contract와 host에서 실제로 이용하는 객체를 분리합니다.

또 하나의 큰 차이는 UML kernel과 UML program의 실행 방식이 명확히 다르다는 점입니다. UML kernel은 다른 program과 마찬가지로 Linux host에서 실행되는 하나의 process이며, unprivileged user로 실행할 수 있고 특별한 CPU feature도 요구하지 않습니다.

반면 UML userspace가 수행하려는 모든 동작은 host Linux kernel의 도움으로 가로채지고 UML kernel이 그 요청을 처리합니다. Guest kernel과 guest program을 같은 방식으로 취급하는 QEMU 같은 다른 가상화 패키지와 달라, 뒤에서 설명할 UML 고유의 장점과 단점이 생깁니다.

UML과 일반 VM의 실행 모델
항목UML일반적인 가상화 패키지
Devicefile·socket·pipe에 매핑된 추상 device실제 hardware를 모사하는 device가 흔함
가상화 방식100% paravirtualEmulation 또는 혼합 방식
Guest kernelHost의 일반 processVM 전체와 함께 취급
Guest programHost kernel이 syscall 동작을 가로채 UML kernel에 전달Guest kernel과 같은 VM 경계 안에서 실행
CPU 요구특별한 feature 불필요패키지에 따라 virtualization feature 사용
권한UML kernel을 unprivileged user로 실행 가능구성에 따라 높은 권한 필요

실제 hardware emulation 여부와 kernel/userspace 처리 차이를 비교합니다.

UML userspace 요청 처리
UML instance 안의 program이 system operation 요청Host Linux kernel이 요청을 intercept요청을 UML kernel process가 처리UML kernel이 추상 device를 host file·socket·pipe에 매핑결과를 UML userspace program에 반환

Guest program의 요청이 UML kernel로 전달되는 경로입니다.

How is UML Different from a VM using Virtualization package X?
==============================================================

We have come to assume that virtualization also means some level of
hardware emulation. In fact, it does not. As long as a virtualization
package provides the OS with devices which the OS can recognize and
has a driver for, the devices do not need to emulate real hardware.
Most OSes today have built-in support for a number of "fake"
devices used only under virtualization.
User Mode Linux takes this concept to the ultimate extreme - there
is not a single real device in sight. It is 100% artificial or if
we use the correct term 100% paravirtual. All UML devices are abstract
concepts which map onto something provided by the host - files, sockets,
pipes, etc.

The other major difference between UML and various virtualization
packages is that there is a distinct difference between the way the UML
kernel and the UML programs operate.
The UML kernel is just a process running on Linux - same as any other
program. It can be run by an unprivileged user and it does not require
anything in terms of special CPU features.
The UML userspace, however, is a bit different. The Linux kernel on the
host machine assists UML in intercepting everything the program running
on a UML instance is trying to do and making the UML kernel handle all
of its requests.
This is different from other virtualization packages which do not make any
difference between the guest kernel and guest programs. This difference
results in a number of advantages and disadvantages of UML over let's say
QEMU which we will cover later in this document.

User Mode Linux를 선택할 이유

49-75

UML kernel이 crash해도 host kernel은 안전합니다. UML은 `vhost`, `kvm` 같은 방식으로 가속되지 않고 device에 직접 접근하지 않으며, 실제로 다른 application과 같은 하나의 process이기 때문입니다.

일부 device에 적절한 permission을 마련해야 할 수 있지만, usermode kernel 자체는 non-root user로 실행할 수 있습니다.

특정 작업만 수행하는 footprint가 매우 작은 VM을 만들 수 있습니다. 원문은 32M 이하의 memory로도 실행할 수 있는 예를 듭니다.

Forwarding이나 firewalling처럼 kernel specific task는 host kernel과 격리된 상태에서도 매우 높은 성능을 낼 수 있습니다.

Host를 망가뜨리지 않고 kernel concept를 실험할 수 있습니다. 실제 hardware emulation에 묶이지 않으므로 time travel이나 UML 동작에 따라 system clock이 달라지는 구성처럼, 실제 hardware를 흉내 내는 VM에서는 구현하기 어려운 아이디어도 시험할 수 있습니다.

UML 동작에 종속된 clock은 재현 가능한 test 같은 용도에 특히 유용합니다.

마지막 장점으로 원문은 간결하게 '재미있다'고 덧붙입니다.

UML의 장점
관점장점근거 또는 예
Crash 격리Host kernel 유지UML kernel은 일반 process
권한non-root 실행 가능필요 device permission만 별도 구성
Footprint작은 전용 VM32M 이하 예시
Kernel task높은 성능Forwarding, firewalling
Kernel 실험Host 손상 없이 개념 검증격리된 UML kernel
가상 device실제 hardware 제약 없음100% paravirtual model
시간 실험Time travel·동작 종속 clockTest 재현성에 활용

안전성·권한·규모·성능·실험성 관점으로 정리했습니다.

UML에 잘 맞는 용도
Host kernel과 분리해 kernel code를 실험작은 memory로 단일 목적 instance 실행Forwarding·firewalling 같은 kernel 중심 작업 처리실제 hardware로 만들기 어려운 가상 device·시간 모델 시험non-root 환경에서 반복 가능한 test 수행

원문이 제시하는 선택 기준을 작업 유형으로 묶었습니다.

Why Would I Want User Mode Linux?
=================================


* If User Mode Linux kernel crashes, your host kernel is still fine. It
  is not accelerated in any way (vhost, kvm, etc) and it is not trying to
  access any devices directly.  It is, in fact, a process like any other.

* You can run a usermode kernel as a non-root user (you may need to
  arrange appropriate permissions for some devices).

* You can run a very small VM with a minimal footprint for a specific
  task (for example 32M or less).

* You can get extremely high performance for anything which is a "kernel
  specific task" such as forwarding, firewalling, etc while still being
  isolated from the host kernel.

* You can play with kernel concepts without breaking things.

* You are not bound by "emulating" hardware, so you can try weird and
  wonderful concepts which are very difficult to support when emulating
  real hardware such as time travel and making your system clock
  dependent on what UML does (very useful for things like tests).

* It's fun.

UML을 선택하지 말아야 할 경우

76-88

UML의 syscall interception 기법은 userspace application을 본질적으로 느리게 만듭니다. Kernel task 성능은 다른 가상화 패키지와 비슷할 수 있지만, 새 process와 thread를 만드는 비용이 매우 높아 일반 Unix/Linux application이 당연하게 사용하는 동작에서 userspace가 느립니다.

현재 UML은 엄격한 uniprocessor 환경입니다. 정상 동작에 여러 CPU가 필요한 application이라면 UML은 분명히 적합하지 않습니다.

UML의 제약
제약원인영향
느린 userspaceSyscall interceptionApplication system call 비용 증가
비싼 process/thread 생성UML 실행 모델Unix/Linux 일반 workload에 불리
Uniprocessor현재 SMP 미지원다중 CPU 필수 application 실행 부적합

작업 부하 특성에 따라 UML 사용을 피해야 하는 이유입니다.

Why not to run UML
==================

* The syscall interception technique used by UML makes it inherently
  slower for any userspace applications. While it can do kernel tasks
  on par with most other virtualization packages, its userspace is
  **slow**. The root cause is that UML has a very high cost of creating
  new processes and threads (something most Unix/Linux applications
  take for granted).

* UML is strictly uniprocessor at present. If you want to run an
  application which needs many CPUs to function, it is clearly the
  wrong choice.

UML instance 구축 준비

89-102

어떤 distribution에도 UML installer는 없습니다. 일반 가상화 패키지처럼 기성 installation media로 빈 VM에 OS를 설치하는 동등한 절차가 없으므로, host의 적절한 도구를 사용해 실행 가능한 filesystem image를 직접 만들어야 합니다.

Debian에서는 `debootstrap`으로 매우 쉽게 만들 수 있고, OpenWRT는 build process가 UML image를 생성할 수 있습니다. 다른 distribution의 난이도는 환경마다 다를 수 있다는 의미로 원문은 YMMV라고 표현합니다.

Distribution별 image 준비
환경방법비고
Debiandebootstrap간단한 최소 설치
OpenWRTBuild processUML image 생성 지원
그 밖의 distributionHost 도구로 직접 구성YMMV

문서가 언급한 구축 경로입니다.


***********************
Building a UML instance
***********************

There is no UML installer in any distribution. While you can use off
the shelf install media to install into a blank VM using a virtualization
package, there is no UML equivalent. You have to use appropriate tools on
your host to build a viable filesystem image.

This is extremely easy on Debian - you can do it using debootstrap. It is
also easy on OpenWRT - the build process can build UML images. All other
distros - YMMV.

Sparse disk image와 최소 OS 설치

103-137

먼저 `dd if=/dev/zero of=disk_image_name bs=1 count=1 seek=16G`로 sparse raw disk image를 만듭니다. 논리 크기는 16G지만 OS는 처음에 block 하나만 할당하고, UML이 실제로 기록할 때 추가 block을 할당합니다.

Kernel 4.19부터 UML은 flash drive에서 흔히 쓰는 TRIM을 완전히 지원합니다. UML image 안에서 mount option에 `discard`를 지정하거나 `tune2fs -o discard /dev/ubdXX`를 실행하면, 사용하지 않는 block을 host OS에 돌려주도록 UML에 요청합니다.

`mkfs.ext4 ./disk_image_name && mount ./disk_image_name /mnt`로 image에 ext4 filesystem을 만들고 `/mnt`에 mount합니다. 예시는 ext4지만 ext3, btrfs, xfs, jfs 같은 다른 filesystem도 사용할 수 있습니다.

Mount한 filesystem에 `debootstrap buster /mnt http://deb.debian.org/debian`을 실행해 최소 Debian OS를 설치합니다.

`debootstrap`은 root password, `fstab`, hostname, network 설정을 만들지 않으므로 사용자가 직접 구성해야 합니다.

Root password는 mount한 image에 `chroot /mnt`로 들어가 `passwd`를 실행한 뒤 `exit`하는 방법이 가장 간단합니다.

UML image 생성 명령
단계명령결과
Sparse image`dd ... count=1 seek=16G`논리 16G, 초기 한 block 할당
Filesystem`mkfs.ext4 ./disk_image_name`ext4 생성
Mount`mount ./disk_image_name /mnt`Image 내용을 host에서 편집 가능
최소 OS`debootstrap buster /mnt ...`Debian buster root filesystem
Root 진입`chroot /mnt`Image 내부 환경으로 전환
Password`passwd`Root password 설정
종료`exit`Chroot에서 복귀

명령과 생성되는 상태를 순서대로 정리합니다.

Sparse image 구축
16G sparse raw image 생성Filesystem을 만들고 /mnt에 mountdebootstrap으로 최소 OS 설치fstab·hostname·network 수동 구성 준비chroot에서 root password 설정

빈 image에서 로그인 가능한 최소 OS까지의 흐름입니다.

Creating an image
=================

Create a sparse raw disk image::

   # dd if=/dev/zero of=disk_image_name bs=1 count=1 seek=16G

This will create a 16G disk image. The OS will initially allocate only one
block and will allocate more as they are written by UML. As of kernel
version 4.19 UML fully supports TRIM (as usually used by flash drives).
Using TRIM inside the UML image by specifying discard as a mount option
or by running ``tune2fs -o discard /dev/ubdXX`` will request UML to
return any unused blocks to the OS.

Create a filesystem on the disk image and mount it::

   # mkfs.ext4 ./disk_image_name && mount ./disk_image_name /mnt

This example uses ext4, any other filesystem such as ext3, btrfs, xfs,
jfs, etc will work too.

Create a minimal OS installation on the mounted filesystem::

   # debootstrap buster /mnt http://deb.debian.org/debian

debootstrap does not set up the root password, fstab, hostname or
anything related to networking. It is up to the user to do that.

Set the root password - the easiest way to do that is to chroot into the
mounted image::

   # chroot /mnt
   # passwd
   # exit

핵심 system file과 kernel module 구성

138-184

UML block device 이름은 `ubd` 계열입니다. `debootstrap`이 만든 빈 `fstab`에는 root filesystem 항목으로 `/dev/ubd0 ext4 discard,errors=remount-ro 0 1`을 추가합니다.

Image hostname은 기본적으로 image를 만든 host와 같으므로, 잘못된 machine을 reboot하는 사고를 피하려면 다른 이름으로 바꾸는 것이 좋습니다.

UML은 Ethernet over GRE와 Ethernet over L2TPv3 같은 표준 virtual network encapsulation을 지원하는 고성능 vector I/O network device를 제공합니다. Interface 이름은 `vecX` 형식입니다.

Vector network device를 사용한다면 `/etc/network/interfaces`에 `auto vec0`과 `iface vec0 inet dhcp` 같은 항목을 추가합니다.

이 단계가 끝나면 image를 실행하기 위해 UML kernel과 module만 더 필요합니다. 대부분의 distribution은 UML package를 제공하며, 자체 kernel을 쓸 예정이어도 먼저 stock kernel로 image를 시험하는 것이 좋습니다.

Distribution package의 module은 target filesystem으로 복사해야 합니다. Debian에서는 `/usr/lib/uml/modules` 아래 내용을 `cp -rax /usr/lib/uml/modules /mnt/lib/modules`로 재귀 복사합니다.

직접 compile한 kernel은 `make INSTALL_MOD_PATH=/mnt/lib/modules modules_install`로 설치하며 결과는 `/mnt/lib/modules/$(KERNELRELEASE)`에 놓입니다. 전체 module 설치 경로를 직접 지정하려면 `make MODLIB=/mnt/lib/modules modules_install`을 사용합니다. 이제 image를 기동할 준비가 끝났습니다.

Image 내부 필수 설정
항목설정목적
Root device`/dev/ubd0`UML root block device
fstab option`discard,errors=remount-ro`TRIM과 오류 시 read-only remount
HostnameHost와 다른 이름운영 대상 혼동 방지
Vector interface`vec0`고성능 virtual network
Network method`iface vec0 inet dhcp`DHCP 주소 설정
Package module`cp -rax /usr/lib/uml/modules ...`Stock UML module 복사
직접 build module`INSTALL_MOD_PATH=... modules_install`KERNELRELEASE 하위에 설치
고정 module 경로`MODLIB=/mnt/lib/modules`전체 설치 경로 직접 지정

Boot와 network, module에 필요한 file과 명령입니다.

Image 실행 준비 완료
fstab에 /dev/ubd0 root 항목 추가Hostname 변경필요하면 vec0 DHCP 설정Stock UML package로 image 우선 시험Package 또는 자체 build module 설치UML kernel로 image 기동 준비

Filesystem 편집 이후 kernel과 module을 갖추는 순서입니다.

Edit key system files
=====================

UML block devices are called ubds. The fstab created by debootstrap
will be empty and it needs an entry for the root file system::

   /dev/ubd0   ext4    discard,errors=remount-ro  0       1

The image hostname will be set to the same as the host on which you
are creating its image. It is a good idea to change that to avoid
"Oh, bummer, I rebooted the wrong machine".

UML supports vector I/O high performance network devices which have
support for some standard virtual network encapsulations like
Ethernet over GRE and Ethernet over L2TPv3. These are called vecX.

When vector network devices are in use, ``/etc/network/interfaces``
will need entries like::

   # vector UML network devices
   auto vec0
   iface vec0 inet dhcp

We now have a UML image which is nearly ready to run, all we need is a
UML kernel and modules for it.

Most distributions have a UML package. Even if you intend to use your own
kernel, testing the image with a stock one is always a good start. These
packages come with a set of modules which should be copied to the target
filesystem. The location is distribution dependent. For Debian these
reside under /usr/lib/uml/modules. Copy recursively the content of this
directory to the mounted UML filesystem::

   # cp -rax /usr/lib/uml/modules /mnt/lib/modules

If you have compiled your own kernel, you need to use the usual "install
modules to a location" procedure by running::

  # make INSTALL_MOD_PATH=/mnt/lib/modules modules_install

This will install modules into /mnt/lib/modules/$(KERNELRELEASE).
To specify the full module installation path, use::

  # make MODLIB=/mnt/lib/modules modules_install

At this point the image is ready to be brought up.

UML networking 모델과 transport

185-226

UML networking은 Ethernet connection을 모사하도록 설계되었습니다. Back-to-back cable로 두 machine을 연결한 것과 비슷한 point-to-point 방식 또는 switch 연결 방식을 사용할 수 있습니다.

연결 대상은 local machine, remote machine, local·remote UML instance, 다른 VM instance까지 폭넓게 지원합니다.

`tap` vector transport는 checksum과 TSO를 지원하며 8Gbit를 넘는 throughput을 제시합니다. `hybrid`는 checksum, TSO, multipacket RX로 6Gbit를 넘고, `raw`는 checksum, TSO, multipacket RX/TX로 6Gbit를 넘습니다. 원문 표의 `raw` capability 끝 따옴표는 그대로 보존합니다.

EoGRE, Eol2tpv3, `bess`는 multipacket RX/TX를 지원하며 각각 3Gbit를 넘는 throughput을 제시합니다. `fd` 성능은 file descriptor 종류에 따라, `vde` 성능은 VDE VPN 또는 Virtual Network Locator에 따라 달라집니다.

TSO와 checksum offload를 모두 갖춘 transport는 TCP stream에서 10G에 가까운 속도를 낼 수 있습니다. Multipacket RX 또는 TX를 지원하면 초당 1M packet 이상 처리할 수 있습니다. GRE와 L2TPv3는 local·remote machine, remote network device, remote UML instance를 모두 연결할 수 있습니다.

UML vector transport 성능
TransportTypeCapabilitiesThroughput
tapvectorchecksum, tso> 8Gbit
hybridvectorchecksum, tso, multipacket rx> 6GBit
rawvectorchecksum, tso, multipacket rx, tx"> 6GBit
EoGREvectormultipacket rx, tx> 3Gbit
Eol2tpv3vectormultipacket rx, tx> 3Gbit
bessvectormultipacket rx, tx> 3Gbit
fdvectordependent on fd typevaries
vdevectorVDE VPN: Virt.Net Locator에 종속varies

원문 ASCII 표를 동일한 항목의 구조화 표로 다시 그렸습니다.

UML Ethernet 연결 범위
UML vecX interfacePoint-to-point 또는 switch 방식 선택Local host·local UML·다른 local VM 연결GRE/L2TPv3로 remote machine·network device 연결Remote UML instance까지 Ethernet traffic 전달

Transport가 연결할 수 있는 endpoint를 구조화했습니다.

*************************
Setting Up UML Networking
*************************

UML networking is designed to emulate an Ethernet connection. This
connection may be either point-to-point (similar to a connection
between machines using a back-to-back cable) or a connection to a
switch. UML supports a wide variety of means to build these
connections to all of: local machine, remote machine(s), local and
remote UML and other VM instances.


+-----------+--------+------------------------------------+------------+
| Transport |  Type  |        Capabilities                | Throughput |
+===========+========+====================================+============+
| tap       | vector | checksum, tso                      | > 8Gbit    |
+-----------+--------+------------------------------------+------------+
| hybrid    | vector | checksum, tso, multipacket rx      | > 6GBit    |
+-----------+--------+------------------------------------+------------+
| raw       | vector | checksum, tso, multipacket rx, tx" | > 6GBit    |
+-----------+--------+------------------------------------+------------+
| EoGRE     | vector | multipacket rx, tx                 | > 3Gbit    |
+-----------+--------+------------------------------------+------------+
| Eol2tpv3  | vector | multipacket rx, tx                 | > 3Gbit    |
+-----------+--------+------------------------------------+------------+
| bess      | vector | multipacket rx, tx                 | > 3Gbit    |
+-----------+--------+------------------------------------+------------+
| fd        | vector | dependent on fd type               | varies     |
+-----------+--------+------------------------------------+------------+
| vde       | vector | dep. on VDE VPN: Virt.Net Locator  | varies     |
+-----------+--------+------------------------------------+------------+

* All transports which have tso and checksum offloads can deliver speeds
  approaching 10G on TCP streams.

* All transports which have multi-packet rx and/or tx can deliver pps
  rates of up to 1Mps or more.

* GRE and L2TPv3 allow connections to all of: local machine, remote
  machines, remote network devices and remote UML instances.

Network 구성 권한

227-243

지원되는 networking mode 대부분은 `root` 권한이 필요합니다. 예를 들어 vector transport는 TUN interface를 설정하는 ioctl을 실행하거나 필요한 raw socket을 사용하기 위해 높은 권한이 필요합니다.

UML 전체를 root로 실행하는 대신 특정 capability만 UML binary에 부여할 수 있습니다. Vector transport에서는 `CAP_NET_ADMIN` 또는 `CAP_NET_RAW`를 추가하면 일반 user privilege로 UML을 실행하면서 전체 networking 기능을 사용할 수 있습니다.

예제 명령은 `sudo setcap cap_net_raw,cap_net_admin+ep linux`이며, `linux` UML binary에 두 capability의 effective·permitted bit를 설정합니다.

Vector networking 권한
작업필요 권한대안
TUN interface setup ioctlrootCAP_NET_ADMIN
Raw socket 사용rootCAP_NET_RAW
UML 전체 networkingroot 실행 가능Binary에 필요한 capability만 설정
예제 binary`linux``setcap ...+ep linux`

필요 작업과 최소 capability를 구분합니다.

Root 대신 capability 사용
사용할 vector transport가 TUN·raw socket을 요구하는지 확인UML binary에 CAP_NET_ADMIN·CAP_NET_RAW 설정일반 user로 UML 실행Kernel이 capability에 허용된 network operation만 승인

권한 범위를 networking에 필요한 기능으로 제한합니다.

Network configuration privileges
================================

The majority of the supported networking modes need ``root`` privileges.
For example, for vector transports, ``root`` privilege is required to fire
an ioctl to setup the tun interface and/or use raw sockets where needed.

This can be achieved by granting the user a particular capability instead
of running UML as root.  In case of vector transport, a user can add the
capability ``CAP_NET_ADMIN`` or ``CAP_NET_RAW`` to the uml binary.
Thenceforth, UML can be run with normal user privilges, along with
full networking.

For example::

   # sudo setcap cap_net_raw,cap_net_admin+ep linux

Vector transport 설정 문법

244-253

모든 vector transport는 비슷한 option 문법을 사용합니다. Interface 번호 X는 `vec0`, `vec1`, `vec2`처럼 `vecX` 이름에 들어갑니다.

일반 형식은 `vecX:transport="Transport Name",option=value,...`입니다. 먼저 transport 이름을 지정하고 쉼표로 `option=value` 쌍을 이어 붙입니다.

Vector option 형식
요소의미
InterfacevecXX는 interface 번호
Transporttransport="Transport Name"사용할 backend transport
Optionoption=valueTransport 또는 공통 parameter
구분쉼표여러 option 연결

Interface, transport, option의 위치를 설명합니다.

Configuring vector transports
===============================

All vector transports support a similar syntax:

If X is the interface number as in vec0, vec1, vec2, etc, the general
syntax for options is::

   vecX:transport="Transport Name",option=value,option=value,...,option=value

Vector transport 공통 option

254-284

`depth=int`는 vector I/O queue depth, 즉 UML이 한 system call에서 읽거나 쓰려는 packet 수를 정합니다. 기본값 64는 대체로 2–4Gbit throughput이 필요한 application에 충분하며, 더 높은 속도에는 더 큰 값이 필요할 수 있습니다.

`mac=XX:XX:XX:XX:XX`는 interface MAC address를 설정합니다.

`gro=[0,1]`은 GRO를 끄거나 켜 receive/transmit offload를 제어합니다. 실제 효과는 transport의 host-side 지원에 따라 달라지지만, 대체로 TCP segmentation과 RX/TX checksum offload를 활성화합니다.

GRO 설정은 host와 UML 쪽이 같아야 하며 다르면 UML kernel이 warning을 출력합니다. Local interface, 예를 들어 veth pair나 bridge에서는 GRO가 기본 활성화되므로 대응하는 UML `raw`, `tap`, `hybrid` transport에서도 올바른 networking을 위해 GRO를 켜야 합니다.

`mtu=int`는 interface MTU를 설정합니다. `headroom=int`는 packet을 VXLAN 같은 형식으로 다시 encapsulate할 때 쓸 공간으로 예약되는 기본 32 bytes headroom을 조정합니다.

`vec=0`은 multipacket I/O를 비활성화하고 한 번에 packet 하나를 처리하는 mode로 되돌립니다.

공통 vector option
Option값·기본값효과 또는 주의점
depthint, 기본 64한 syscall의 packet 수; 2–4Gbit에 일반적으로 충분
macXX:XX:XX:XX:XXInterface MAC address
gro0 또는 1GRO와 RX/TX offload 제어
gro 일치Host와 UML 동일불일치 시 kernel warning
gro local 권장raw, tap, hybrid에서 1veth·bridge의 기본 GRO와 일치
mtuintInterface MTU
headroom기본 32 bytesVXLAN 등 재encapsulation 공간
vec0Multipacket I/O를 끄고 packet-at-a-time mode

줄 254–284의 option 이름, 기본값, 제약을 보존했습니다.

공통 option 점검
목표 throughput에 맞춰 depth 선택필요한 MAC·MTU 설정Host interface의 GRO 상태 확인UML transport의 gro 값을 host와 일치재encapsulation이면 headroom 조정문제 진단 시 vec=0으로 단일 packet mode 시험

성능과 host 호환성을 함께 맞추는 순서입니다.

Common options
--------------

These options are common for all transports:

* ``depth=int`` - sets the queue depth for vector IO. This is the
  amount of packets UML will attempt to read or write in a single
  system call. The default number is 64 and is generally sufficient
  for most applications that need throughput in the 2-4 Gbit range.
  Higher speeds may require larger values.

* ``mac=XX:XX:XX:XX:XX`` - sets the interface MAC address value.

* ``gro=[0,1]`` - sets GRO off or on. Enables receive/transmit offloads.
  The effect of this option depends on the host side support in the transport
  which is being configured. In most cases it will enable TCP segmentation and
  RX/TX checksumming offloads. The setting must be identical on the host side
  and the UML side. The UML kernel will produce warnings if it is not.
  For example, GRO is enabled by default on local machine interfaces
  (e.g. veth pairs, bridge, etc), so it should be enabled in UML in the
  corresponding UML transports (raw, tap, hybrid) in order for networking to
  operate correctly.

* ``mtu=int`` - sets the interface MTU

* ``headroom=int`` - adjusts the default headroom (32 bytes) reserved
  if a packet will need to be re-encapsulated into for instance VXLAN.

* ``vec=0`` - disable multipacket IO and fall back to packet at a
  time mode

Socket·interface transport 공유 option

285-301

Local network interface에 bind하는 transport는 `ifname=str` 공유 option으로 연결할 interface 이름을 지정합니다.

Source와 destination 또는 각 port 개념이 있는 socket transport는 `src`, `dst`, `src_port`, `dst_port`로 endpoint를 지정합니다.

IP 위에서 동작하는 transport는 `v6=[0,1]`로 IPv6 connection 사용 여부를 지정합니다. EoL2TPv3처럼 IPv4와 IPv6에서 동작 방식이 다른 transport에서는 올바른 mode까지 선택합니다. 이 option이 없으면 `src`와 `dst`가 해석되는 주소 형식을 보고 socket type을 결정합니다.

Transport 공유 option
Option대상의미
ifnameLocal interface bind transportBind할 interface 이름
src, dstSource/destination socket양 끝 IP 또는 address
src_port, dst_portPort를 쓰는 socket양 끝 port
v6IP transportIPv4/IPv6 mode 선택 또는 주소 자동 판별

Local interface와 socket endpoint에 공통으로 쓰이는 값입니다.

Socket mode 결정
Transport가 local interface 또는 socket을 사용하는지 확인필요하면 ifname과 src·dst·port 지정v6 option이 있으면 IPv4/IPv6 mode 강제v6가 없으면 src·dst parse 결과로 socket type 결정

명시 option과 address 해석 결과의 우선순위입니다.

Shared Options
--------------

* ``ifname=str`` Transports which bind to a local network interface
  have a shared option - the name of the interface to bind to.

* ``src, dst, src_port, dst_port`` - all transports which use sockets
  which have the notion of source and destination and/or source port
  and destination port use these to specify them.

* ``v6=[0,1]`` to specify if a v6 connection is desired for all
  transports which operate over IP. Additionally, for transports that
  have some differences in the way they operate over v4 and v6 (for example
  EoL2TPv3), sets the correct mode of operation. In the absence of this
  option, the socket type is determined based on what do the src and dst
  arguments resolve/parse to.

tap transport

302-329

예제 `vecX:transport=tap,ifname=tap0,depth=128,gro=1`은 UML의 vector interface를 host `tap0`에 연결합니다. 원문의 설명은 `vec0` 연결이라고 표현하며, `tap0`은 `tunctl` 등으로 미리 만들어져 있고 UP 상태여야 합니다.

`tap0`에 IP address를 부여해 point-to-point interface로 구성하면 UML과 host가 직접 통신할 수 있습니다. 또는 bridge에 연결된 tap interface에 UML을 붙여 switch 형태의 network를 만들 수 있습니다.

Tap은 vector infrastructure를 사용하지만 현재 시점에는 진정한 vector transport가 아닙니다. Linux가 UML 같은 일반 userspace application에 tap file descriptor의 multipacket I/O를 허용하지 않기 때문입니다.

이 권한은 `vhost-net`처럼 kernel-level specialized interface에 연결할 수 있는 구성에만 제공됩니다. 문서는 향후 UML용 vhost-net 유사 helper를 계획하고 있다고 밝힙니다.

권한은 두 방법 중 하나로 충족합니다. `tunctl -u uml-user -t tap0`처럼 UML user가 소유한 persistent tap interface를 미리 만들거나, UML binary에 `CAP_NET_ADMIN`을 부여합니다.

tap 구성 조건
항목설정결과
예제`transport=tap,ifname=tap0,depth=128,gro=1`vecX를 tap0에 연결
사전 상태tap0 존재·UPUML 시작 전에 준비
Point-to-pointtap0에 IP addressUML과 host 직접 통신
Bridgetap0을 bridge에 연결Switch형 network
권한Persistent user-owned tap 또는 CAP_NET_ADMINUML user의 tap 사용 허용

Interface 준비, 연결 방식, 권한 요구를 분리했습니다.

tap 연결
tunctl로 user-owned persistent tap0 생성 또는 capability 준비tap0을 UP 상태로 전환Point-to-point IP 또는 bridge 연결 구성vecX transport=tap으로 tap0 지정UML이 tap file descriptor를 통해 frame 송수신

Host tap 준비부터 UML 연결까지의 순서입니다.

tap transport
-------------

Example::

   vecX:transport=tap,ifname=tap0,depth=128,gro=1

This will connect vec0 to tap0 on the host. Tap0 must already exist (for example
created using tunctl) and UP.

tap0 can be configured as a point-to-point interface and given an IP
address so that UML can talk to the host. Alternatively, it is possible
to connect UML to a tap interface which is connected to a bridge.

While tap relies on the vector infrastructure, it is not a true vector
transport at this point, because Linux does not support multi-packet
IO on tap file descriptors for normal userspace apps like UML. This
is a privilege which is offered only to something which can hook up
to it at kernel level via specialized interfaces like vhost-net. A
vhost-net like helper for UML is planned at some point in the future.

Privileges required: tap transport requires either:

* tap interface to exist and be created persistent and owned by the
  UML user using tunctl. Example ``tunctl -u uml-user -t tap0``

* binary to have ``CAP_NET_ADMIN`` privilege

hybrid transport

330-343

예제 `vecX:transport=hybrid,ifname=tap0,depth=128,gro=1`은 hybrid transport를 `tap0`에 연결합니다.

Hybrid는 송신에 tap을, 수신에 raw socket을 결합한 experimental/demo transport입니다. Raw socket이 multipacket receive를 허용하므로 일반 tap보다 packet rate가 크게 높아집니다.

Hybrid를 쓰려면 UML user가 `CAP_NET_RAW` capability를 가져야 하며, 여기에 persistent tap 또는 `CAP_NET_ADMIN` 같은 tap transport의 요구사항도 모두 충족해야 합니다.

hybrid data path
방향Backend특성
TXtaptap interface로 frame 송신
RXraw socketMultipacket receive
효과혼합일반 tap보다 높은 packet rate
권한CAP_NET_RAW + tap 요구사항Raw socket과 tap 모두 허용

송신과 수신이 서로 다른 backend를 사용합니다.

hybrid packet 경로
UML TX packet → tap0Host network로 송신Host RX packet → raw socket multipacket queueUML vector RX가 packet batch 처리

방향별 backend 선택을 나타냅니다.

hybrid transport
----------------

Example::

   vecX:transport=hybrid,ifname=tap0,depth=128,gro=1

This is an experimental/demo transport which couples tap for transmit
and a raw socket for receive. The raw socket allows multi-packet
receive resulting in significantly higher packet rates than normal tap.

Privileges required: hybrid requires ``CAP_NET_RAW`` capability by
the UML user as well as the requirements for the tap transport.

raw socket transport

344-393

예제 `vecX:transport=raw,ifname=p-veth0,depth=128,gro=1`은 raw socket에서 vector I/O를 사용하고 `p-veth0`에 bind합니다. Physical interface에도 bind할 수 있지만, 일반적으로 veth pair의 peer 쪽에 bind하고 다른 쪽을 host에서 설정합니다.

Debian 예제의 `/etc/network/interfaces`는 `veth0`을 static으로 올려 `192.168.4.1`, netmask `255.255.255.252`, broadcast `192.168.4.3`을 설정합니다. `pre-up`에서는 `ip link add veth0 type veth peer name p-veth0`로 pair를 만들고 `p-veth0`을 UP 상태로 전환합니다.

UML은 `vec0:transport=raw,ifname=p-veth0,depth=128,gro=1`로 peer interface에 bind합니다. Guest 주소를 `192.168.4.2`, netmask를 원문 그대로 `255.255.255.0`으로 구성하면 host `192.168.4.1`과 통신할 수 있습니다.

Raw transport는 filtering 일부를 host로 offload할 수 있습니다. `bpffile=str`은 socket filter로 load할 raw BPF code file을 지정합니다.

`bpfflash=int`의 0/1 값은 User Mode Linux 안에서 BPF를 load할 수 있는지 정합니다. 활성화하면 `ethtool load firmware` command로 BPF code를 load할 수 있습니다.

두 방식 모두 BPF code가 host kernel에 load됩니다. 현재 legacy BPF syntax만 지원하고 eBPF는 지원하지 않지만 여전히 security risk가 있으므로, UML instance를 trusted로 간주할 수 있을 때만 허용해야 합니다.

Raw socket transport에는 `CAP_NET_RAW` capability가 필요합니다.

raw transport 설정
항목설명
UML interfacep-veth0veth pair의 peer 쪽에 bind
Host interfaceveth0 / 192.168.4.1Host static endpoint
Guest address192.168.4.2Host와 통신하는 UML endpoint
depth·gro128·1Vector queue와 offload
bpffileRaw BPF filenameHost socket filter load
bpfflash0 또는 1Guest 내부 ethtool load 허용
BPF dialectLegacy BPF, eBPF 아님Host kernel에 load
권한CAP_NET_RAWRaw socket 사용

Veth 연결과 BPF option, 권한을 정리합니다.

veth 기반 raw 연결
Host가 veth0 ↔ p-veth0 pair 생성veth0에 192.168.4.1 설정p-veth0을 UP 상태로 전환UML vec0 raw transport를 p-veth0에 bindGuest에 192.168.4.2 설정필요한 경우 trusted instance에서만 BPF offload 사용

Host veth pair와 UML endpoint를 연결합니다.

raw socket transport
--------------------

Example::

   vecX:transport=raw,ifname=p-veth0,depth=128,gro=1


This transport uses vector IO on raw sockets. While you can bind to any
interface including a physical one, the most common use it to bind to
the "peer" side of a veth pair with the other side configured on the
host.

Example host configuration for Debian:

**/etc/network/interfaces**::

   auto veth0
   iface veth0 inet static
        address 192.168.4.1
        netmask 255.255.255.252
        broadcast 192.168.4.3
        pre-up ip link add veth0 type veth peer name p-veth0 && \
          ifconfig p-veth0 up

UML can now bind to p-veth0 like this::

   vec0:transport=raw,ifname=p-veth0,depth=128,gro=1


If the UML guest is configured with 192.168.4.2 and netmask 255.255.255.0
it can talk to the host on 192.168.4.1

The raw transport also provides some support for offloading some of the
filtering to the host. The two options to control it are:

* ``bpffile=str`` filename of raw bpf code to be loaded as a socket filter

* ``bpfflash=int`` 0/1 allow loading of bpf from inside User Mode Linux.
  This option allows the use of the ethtool load firmware command to
  load bpf code.

In either case the bpf code is loaded into the host kernel. While this is
presently limited to legacy bpf syntax (not ebpf), it is still a security
risk. It is not recommended to allow this unless the User Mode Linux
instance is considered trusted.

Privileges required: raw socket transport requires `CAP_NET_RAW`
capability.

GRE socket transport

394-451

예제 `vecX:transport=gre,src=$src_host,dst=$dst_host`는 Ethernet over GRE tunnel을 구성해 UML instance를 `dst_host`의 GRE endpoint에 연결합니다. 이 방식은 `GRETAP` 또는 `GREIRB`라고도 합니다.

`rx_key=int`와 `tx_key=int`는 수신·송신 packet용 32-bit GRE key입니다. 한쪽 key를 설정하면 반대쪽 key도 반드시 설정해야 합니다.

`sequence=[0,1]`은 GRE sequence를 활성화합니다. `pin_sequence=[0,1]`은 매 packet마다 sequence가 reset된 것처럼 처리해, 동작이 잘못된 일부 구현과 상호 운용할 때 사용합니다.

`v6=[0,1]`은 각각 IPv4 또는 IPv6 socket을 강제합니다. 현재 GRE checksum은 지원하지 않습니다.

GRE는 IP address 하나당 connection 하나만 사용할 수 있습니다. 각 tunnel이 UML instance에서 직접 끝나기 때문에 여러 connection을 multiplex할 방법이 없습니다.

GRE key는 실제 security 기능으로 신뢰할 수 없지만 tunnel misconfiguration을 발견하거나 방지하는 식별값으로는 유용합니다.

Host `192.168.128.1`과 UML `192.168.129.1`을 연결하는 예제는 `gt0`에 `10.0.0.1/24`, broadcast `10.0.0.255`, MTU 1500을 설정하고 `ip link add ... type gretap local ... remote ...`로 tunnel을 만듭니다. GRE는 여러 network equipment와의 상호 운용 시험을 거쳤으며, `CAP_NET_RAW`이 필요합니다.

GRE 추가 option
Option규칙
rx_key32-bit int설정하면 tx_key도 필요
tx_key32-bit int설정하면 rx_key도 필요
sequence0 또는 1GRE sequence 활성화
pin_sequence0 또는 1Packet마다 sequence reset으로 간주
v6=0IPv4IPv4 socket 강제
v6=1IPv6IPv6 socket 강제
checksum미지원현재 GRE checksum 없음

Key, sequence, address family 지원을 보존했습니다.

GRE caveat
항목제약운영 의미
ConnectionIP당 하나UML endpoint에서 직접 tunnel 종료
Multiplex불가능IP를 추가하거나 다른 transport 고려
Key security신뢰 불가Misconfiguration 확인 용도
권한CAP_NET_RAWRaw GRE socket 사용

연결 수, key 의미, 권한 제약입니다.

GRETAP host 연결
Host outer address 192.168.128.1 확인UML outer endpoint 192.168.129.1 지정gt0 GRETAP link 생성gt0에 10.0.0.1/24와 MTU 1500 설정UML GRE transport의 src·dst를 양 endpoint에 맞춤CAP_NET_RAW으로 tunnel packet 송수신

예제 주소로 tunnel을 구성하는 흐름입니다.

GRE socket transport
--------------------

Example::

   vecX:transport=gre,src=$src_host,dst=$dst_host


This will configure an Ethernet over ``GRE`` (aka ``GRETAP`` or
``GREIRB``) tunnel which will connect the UML instance to a ``GRE``
endpoint at host dst_host. ``GRE`` supports the following additional
options:

* ``rx_key=int`` - GRE 32-bit integer key for rx packets, if set,
  ``txkey`` must be set too

* ``tx_key=int`` - GRE 32-bit integer key for tx packets, if set
  ``rx_key`` must be set too

* ``sequence=[0,1]`` - enable GRE sequence

* ``pin_sequence=[0,1]`` - pretend that the sequence is always reset
  on each packet (needed to interoperate with some really broken
  implementations)

* ``v6=[0,1]`` - force IPv4 or IPv6 sockets respectively

* GRE checksum is not presently supported

GRE has a number of caveats:

* You can use only one GRE connection per IP address. There is no way to
  multiplex connections as each GRE tunnel is terminated directly on
  the UML instance.

* The key is not really a security feature. While it was intended as such
  its "security" is laughable. It is, however, a useful feature to
  ensure that the tunnel is not misconfigured.

An example configuration for a Linux host with a local address of
192.168.128.1 to connect to a UML instance at 192.168.129.1

**/etc/network/interfaces**::

   auto gt0
   iface gt0 inet static
    address 10.0.0.1
    netmask 255.255.255.0
    broadcast 10.0.0.255
    mtu 1500
    pre-up ip link add gt0 type gretap local 192.168.128.1 \
           remote 192.168.129.1 || true
    down ip link del gt0 || true

Additionally, GRE has been tested versus a variety of network equipment.

Privileges required: GRE requires ``CAP_NET_RAW``

L2TPv3 socket transport

452-526

원문은 L2TPv3가 'GNU ls보다 option이 많다'는 농담으로 복잡성을 경고합니다. 장점은 있지만 UML instance를 연결하는 더 쉽고 간결한 방법이 흔하며, L2TPv3를 지원하는 device 대부분은 GRE도 지원합니다.

예제는 UDP mode, source·destination host와 port, depth 128, RX session `0xffffffff`, TX session `0xffff`를 지정합니다. 이렇게 하면 UML instance와 `$dst_host`의 L2TPv3 endpoint 사이에 Ethernet over L2TPv3 fixed tunnel을 만들고 UDP destination port `$dst_port`를 사용합니다.

L2TPv3는 항상 `rx_session=int`와 `tx_session=int` 32-bit session ID를 요구합니다. Fixed tunnel이므로 이 값들은 협상되지 않고 양 endpoint에 미리 같은 관계로 구성해야 합니다.

`rx_cookie=int`와 `tx_cookie=int`는 각 방향의 32-bit cookie입니다. GRE key와 마찬가지로 실제 보안보다는 misconfiguration 방지에 가깝습니다. `cookie64=[0,1]`을 켜면 64-bit cookie를 사용합니다.

`counter=[0,1]`은 L2TPv3 counter를 켭니다. `pin_counter=[0,1]`은 매 packet에서 counter가 reset된 것처럼 처리해 잘못된 일부 구현과 상호 운용할 때 씁니다.

`v6=[0,1]`은 IPv6 socket을 강제하고, `udp=[0,1]`은 raw socket mode 0과 UDP mode 1 사이를 선택합니다.

Raw mode에서는 IP address당 connection 하나만 사용할 수 있고 tunnel이 UML instance에서 직접 끝나므로 multiplex할 수 없습니다. UDP mode는 서로 다른 port를 사용해 여러 connection을 구분할 수 있습니다.

Linux host 예제는 loopback `127.0.0.1` 사이에 UDP tunnel ID 2를 만들고 source port 1706, destination port 1707을 사용합니다. 이어서 `l2tp1` session ID와 peer session ID를 모두 `0xffffffff`로 만들고, interface에는 `192.168.126.1/24`, broadcast `192.168.126.255`, MTU 1500을 설정합니다.

Raw IP mode에는 `CAP_NET_RAW`이 필요하지만 UDP mode에는 특별한 privilege가 필요하지 않습니다.

L2TPv3 option
Option필수 여부의미
rx_session필수32-bit RX session ID
tx_session필수32-bit TX session ID
rx_cookie선택32-bit RX cookie
tx_cookie선택32-bit TX cookie
cookie64선택64-bit cookie 사용
counter선택L2TPv3 counter 활성화
pin_counter선택Packet마다 counter reset으로 간주
v6선택IPv6 socket 강제
udp선택0 raw socket, 1 UDP

필수 session과 선택 cookie·counter·transport mode입니다.

L2TPv3 caveat와 권한
ModeMultiplex권한구분 수단
Raw IPIP당 하나CAP_NET_RAWIP endpoint
UDP가능특별 권한 없음서로 다른 port
Fixed tunnelSession 협상 없음양 끝 사전 구성rx_session·tx_session
Cookie보안 수단 아님선택Misconfiguration 방지

Raw와 UDP mode의 multiplex·권한 차이입니다.

L2TPv3 UDP tunnel
UDP tunnel ID 2와 peer tunnel ID 2 생성Local port 1706·remote port 1707 설정l2tp1 session ID 0xffffffff 생성l2tp1에 192.168.126.1/24와 MTU 1500 설정UML transport에 같은 host·port·session 관계 지정종료 시 session을 먼저 지우고 tunnel 삭제

원문의 Linux host 예제를 단계로 정리했습니다.

l2tpv3 socket transport
-----------------------

_Warning_. L2TPv3 has a "bug". It is the "bug" known as "has more
options than GNU ls". While it has some advantages, there are usually
easier (and less verbose) ways to connect a UML instance to something.
For example, most devices which support L2TPv3 also support GRE.

Example::

    vec0:transport=l2tpv3,udp=1,src=$src_host,dst=$dst_host,srcport=$src_port,dstport=$dst_port,depth=128,rx_session=0xffffffff,tx_session=0xffff

This will configure an Ethernet over L2TPv3 fixed tunnel which will
connect the UML instance to a L2TPv3 endpoint at host $dst_host using
the L2TPv3 UDP flavour and UDP destination port $dst_port.

L2TPv3 always requires the following additional options:

* ``rx_session=int`` - l2tpv3 32-bit integer session for rx packets

* ``tx_session=int`` - l2tpv3 32-bit integer session for tx packets

As the tunnel is fixed these are not negotiated and they are
preconfigured on both ends.

Additionally, L2TPv3 supports the following optional parameters.

* ``rx_cookie=int`` - l2tpv3 32-bit integer cookie for rx packets - same
  functionality as GRE key, more to prevent misconfiguration than provide
  actual security

* ``tx_cookie=int`` - l2tpv3 32-bit integer cookie for tx packets

* ``cookie64=[0,1]`` - use 64-bit cookies instead of 32-bit.

* ``counter=[0,1]`` - enable l2tpv3 counter

* ``pin_counter=[0,1]`` - pretend that the counter is always reset on
  each packet (needed to interoperate with some really broken
  implementations)

* ``v6=[0,1]`` - force v6 sockets

* ``udp=[0,1]`` - use raw sockets (0) or UDP (1) version of the protocol

L2TPv3 has a number of caveats:

* you can use only one connection per IP address in raw mode. There is
  no way to multiplex connections as each L2TPv3 tunnel is terminated
  directly on the UML instance. UDP mode can use different ports for
  this purpose.

Here is an example of how to configure a Linux host to connect to UML
via L2TPv3:

**/etc/network/interfaces**::

   auto l2tp1
   iface l2tp1 inet static
    address 192.168.126.1
    netmask 255.255.255.0
    broadcast 192.168.126.255
    mtu 1500
    pre-up ip l2tp add tunnel remote 127.0.0.1 \
           local 127.0.0.1 encap udp tunnel_id 2 \
           peer_tunnel_id 2 udp_sport 1706 udp_dport 1707 && \
           ip l2tp add session name l2tp1 tunnel_id 2 \
           session_id 0xffffffff peer_session_id 0xffffffff
    down ip l2tp del session tunnel_id 2 session_id 0xffffffff && \
           ip l2tp del tunnel tunnel_id 2


Privileges required: L2TPv3 requires ``CAP_NET_RAW`` for raw IP mode and
no special privileges for the UDP mode.

BESS socket transport

527-550

BESS는 high-performance modular network switch입니다. 프로젝트와 구성 방법은 원문에 제시된 `https://github.com/NetSys/bess` 및 BESS built-in module·port 문서를 참고합니다.

BESS는 단순한 sequential packet socket mode를 지원하며, 최신 version에서는 고성능을 위해 vector I/O를 사용합니다.

예제 `vecX:transport=bess,src=$unix_src,dst=$unix_dst`는 source로 `unix_src`, destination으로 `unix_dst` Unix domain socket address를 사용하는 BESS transport를 구성합니다.

BESS 설정과 Unix domain socket port 할당 방법은 BESS documentation을 따라야 하며, 이 transport에는 특별한 privilege가 필요하지 않습니다.

BESS transport
항목내용
SwitchBESS high-performance modular network switch
I/OSequential packet socket, 최신 version은 vector I/O
EndpointUnix domain socket src·dst
권한특별한 privilege 없음

Endpoint, packet mode, 권한 특성입니다.

BESS 연결
BESS에서 Unix domain socket port 할당Source socket address를 unix_src에 지정Destination socket address를 unix_dst에 지정vecX transport=bess로 UML 시작BESS vector I/O path로 packet 전달

BESS port 할당과 UML endpoint 연결 순서입니다.

BESS socket transport
---------------------

BESS is a high performance modular network switch.

https://github.com/NetSys/bess

It has support for a simple sequential packet socket mode which in the
more recent versions is using vector IO for high performance.

Example::

   vecX:transport=bess,src=$unix_src,dst=$unix_dst

This will configure a BESS transport using the unix_src Unix domain
socket address as source and unix_dst socket address as destination.

For BESS configuration and how to allocate a BESS Unix domain socket port
please see the BESS documentation.

https://github.com/NetSys/bess/wiki/Built-In-Modules-and-Ports

BESS transport does not require any special privileges.

VDE vector transport

551-585

Virtual Distributed Ethernet(VDE)은 매우 유연한 virtual networking 지원을 목표로 하는 프로젝트입니다. Fast prototyping과 교육이 흔한 활용 사례입니다.

`vecX:transport=vde,vnl=tap://tap0`은 `tap0`을 사용하고, `vecX:transport=vde,vnl=slirp://`은 slirp를 사용합니다.

`vec0:transport=vde,vnl=vde:///tmp/switch`는 `/tmp/switch`의 VDE switch에 연결합니다.

`vecX:transport="vde,vnl=cmd://ssh remote.host //tmp/sshlirp"`는 remote slirp에 연결합니다. `sshlirp`를 사용해 SSH connection을 즉석 VPN으로 바꾸는 방식이며 원문은 `https://github.com/virtualsquare/sshlirp`를 참조합니다.

`vec0:transport=vde,vnl=vxvde://234.0.0.1`은 local area cloud에 연결합니다.

같은 multicast domain, 즉 LAN의 host에서 같은 multicast address를 사용하는 모든 UML node는 자동으로 하나의 virtual LAN에 연결됩니다.

VDE locator 예제
VNL연결 대상용도
tap://tap0Local tap0Host tap network
slirp://Local slirpUserspace network
vde:///tmp/switchVDE switchLocal switch
cmd://ssh remote.host //tmp/sshlirpRemote slirpSSH를 instant VPN으로 변환
vxvde://234.0.0.1Multicast local area cloud같은 LAN의 UML node 자동 연결

VNL scheme에 따라 연결 대상이 달라집니다.

VDE 연결 선택
Local tap이면 tap:// scheme 선택간단한 userspace NAT는 slirp:// 선택Local VDE switch는 vde:// path 지정Remote VPN은 cmd://ssh와 sshlirp 사용LAN 전체 UML cloud는 같은 vxvde multicast address 사용

원하는 network 범위에 맞는 locator를 고릅니다.

VDE vector transport
--------------------

Virtual Distributed Ethernet (VDE) is a project whose main goal is to provide a
highly flexible support for virtual networking.

http://wiki.virtualsquare.org/#/tutorials/vdebasics

Common usages of VDE include fast prototyping and teaching.

Examples:

   ``vecX:transport=vde,vnl=tap://tap0``

use tap0

   ``vecX:transport=vde,vnl=slirp://``

use slirp

   ``vec0:transport=vde,vnl=vde:///tmp/switch``

connect to a vde switch

   ``vecX:transport=\"vde,vnl=cmd://ssh remote.host //tmp/sshlirp\"``

connect to a remote slirp (instant VPN: convert ssh to VPN, it uses sshlirp)
https://github.com/virtualsquare/sshlirp

   ``vec0:transport=vde,vnl=vxvde://234.0.0.1``

connect to a local area cloud (all the UML nodes using the same
multicast address running on hosts in the same multicast domain (LAN)
will be automagically connected together to a virtual LAN.

UML kernel 실행 준비

586-598

이 절은 distribution의 `user-mode-linux` package 또는 직접 build한 UML kernel이 host에 설치돼 있다고 가정합니다.

설치 결과 생기는 `linux` executable이 UML kernel입니다. 일반 executable처럼 실행하며 대부분의 일반 Linux kernel argument를 command line으로 받을 수 있지만, 유용한 instance를 만들려면 UML-specific argument도 지정해야 합니다.

UML 실행 전제
항목내용
설치 경로Distribution package 또는 custom build
Executablelinux
실행 형태Host의 일반 process
Argument일반 kernel argument + UML-specific argument

Host에 준비해야 할 executable과 argument 종류입니다.

***********
Running UML
***********

This section assumes that either the user-mode-linux package from the
distribution or a custom built kernel has been installed on the host.

These add an executable called linux to the system. This is the UML
kernel. It can be run just like any other executable.
It will take most normal linux kernel arguments as command line
arguments.  Additionally, it will need some UML-specific arguments
in order to do something useful.

Memory·UBD·root 필수 인자

599-635

`mem=int[K,M,G]`는 UML instance에 줄 memory 양을 지정합니다. 단위가 없으면 byte이며 K, M, G suffix를 사용할 수 있습니다.

`ubdX[s,d,c,t]=`는 virtual disk를 정의합니다. 문법상 완전한 필수 인자는 아니지만 root filesystem을 지정해야 하는 거의 모든 경우에 필요합니다. 가장 단순한 값은 앞 절에서 만든 filesystem image file 이름입니다.

UBD는 copy on write(COW)를 지원합니다. 변경분을 버릴 수 있는 별도 file에 보관해 pristine master image로 rollback할 수 있으며, `cow_file,master_image` 형식을 사용합니다. 예제는 `ubd0=Filesystem.cow,Filesystem.img`입니다.

`ubdX` 뒤의 `s` flag는 synchronous I/O를 켜 모든 write를 즉시 disk로 flush합니다.

Single filename이 실제 image가 아니라 COW file인지 점검하는 UBD heuristic을 끄려면 `d` flag를 사용합니다. 문법 표제의 `c`도 원문에 포함되지만 이 구간에는 별도 설명이 없습니다.

UBD는 image의 unused block을 host OS가 회수하도록 요청하는 TRIM을 기본 지원합니다. 이를 끄려면 `t` flag를 붙입니다. Root device는 일반적으로 Linux filesystem image가 연결된 `/dev/ubd0`을 `root=`에 지정합니다.

UML 기본 boot 인자
인자·flag형식효과
memint[K,M,G]Instance memory 크기
ubdXimage filenameVirtual disk 연결
COWcow_file,master_image변경분 분리·rollback
subdXsSynchronous write·즉시 flush
dubdXdCOW image heuristic 비활성화
tubdXtTRIM 비활성화
root/dev/ubd0Root filesystem device

Memory, disk image, UBD flag, root device를 정리합니다.

UBD root 구성
Memory 크기를 mem=으로 지정직접 image 또는 COW pair 선택필요하면 s·d·t flag 적용ubd0에 image 연결root=/dev/ubd0 지정

Master image를 instance root로 연결하는 순서입니다.

Arguments
=========

Mandatory Arguments:
--------------------

* ``mem=int[K,M,G]`` - amount of memory. By default in bytes. It will
  also accept K, M or G qualifiers.

* ``ubdX[s,d,c,t]=`` virtual disk specification. This is not really
  mandatory, but it is likely to be needed in nearly all cases so we can
  specify a root file system.
  The simplest possible image specification is the name of the image
  file for the filesystem (created using one of the methods described
  in `Creating an image`_).

  * UBD devices support copy on write (COW). The changes are kept in
    a separate file which can be discarded allowing a rollback to the
    original pristine image.  If COW is desired, the UBD image is
    specified as: ``cow_file,master_image``.
    Example:``ubd0=Filesystem.cow,Filesystem.img``

  * UBD devices can be set to use synchronous IO. Any writes are
    immediately flushed to disk. This is done by adding ``s`` after
    the ``ubdX`` specification.

  * UBD performs some heuristics on devices specified as a single
    filename to make sure that a COW file has not been specified as
    the image. To turn them off, use the ``d`` flag after ``ubdX``.

  * UBD supports TRIM - asking the Host OS to reclaim any unused
    blocks in the image. To turn it off, specify the ``t`` flag after
    ``ubdX``.

* ``root=`` root device - most likely ``/dev/ubd0`` (this is a Linux
  filesystem image)

Console과 serial line channel

636-687

`linux`를 추가 인자 없이 실행하면 image 안에 구성된 console마다 xterm을 시작하려고 합니다. 대부분의 Linux distribution에서는 최대 6개이며, GUI host에서는 편리하지만 test harness나 text-only 환경에는 적합하지 않습니다.

동작을 바꾸려면 console을 기본 xterm이 아닌 지원 line channel에 연결합니다. `con1=fd:0,fd:1`은 console 1의 input을 stdin file descriptor 0, output을 stdout file descriptor 1로 보냅니다.

일반 문법은 `conX=channel_type:options[,channel_type:options]`입니다. 쉼표로 두 부분을 쓰면 첫 번째가 input, 두 번째가 output channel입니다.

`null` channel은 input 또는 output을 모두 버립니다. `con=null`은 모든 console의 기본 channel을 null로 만듭니다.

`fd` channel은 input/output에 file descriptor 번호를 사용합니다. 예제는 `con1=fd:0,fd:1`입니다.

`port` channel은 지정한 TCP port에서 telnet server를 시작합니다. `con1=port:4321`을 쓰려면 host에 `/usr/sbin/in.telnetd`와 UML utility의 `port-helper`가 있어야 하며, client가 연결할 때까지 UML은 boot하지 않습니다.

`pty`와 `pts` channel은 system pty/pts를 사용합니다. `tty` channel은 기존 system tty에 bind하며 `con1=/dev/tty8`은 보통 비어 있는 host 8번째 console을 사용합니다.

기본값인 `xterm` channel은 xterm을 띄워 I/O를 연결합니다. Host에 `port-helper` 등 utility가 든 UML distribution package가 설치돼 있거나 source에서 직접 compile·install돼 있어야 합니다. Console option은 UML 안에서 `ttyS`로 보이는 serial line에도 그대로 적용됩니다.

UML line channel
Channel동작·조건
nullcon=null모든 input/output 폐기
fdcon1=fd:0,fd:1File descriptor로 stdin/stdout 연결
portcon1=port:4321Telnet client 연결 전까지 boot 대기
ptyconX=ptySystem pty 사용
ptsconX=ptsSystem pts 사용
ttycon1=/dev/tty8기존 host tty에 bind
xterm기본값xterm과 port-helper 필요
serialttyS inside UML같은 console option 적용

Console input/output backend와 사전 조건입니다.

Console I/O 선택
Interactive GUI이면 기본 xterm 사용Terminal foreground면 fd:0,fd:1 연결Remote 접속이면 port channel과 telnetd 준비자동 test에서 불필요한 console은 null 처리Input·output을 다르게 쓰면 쉼표로 두 channel 지정

GUI와 자동화 환경에 맞춰 channel을 고릅니다.

Important Optional Arguments
----------------------------

If UML is run as "linux" with no extra arguments, it will try to start an
xterm for every console configured inside the image (up to 6 in most
Linux distributions). Each console is started inside an
xterm. This makes it nice and easy to use UML on a host with a GUI. It is,
however, the wrong approach if UML is to be used as a testing harness or run
in a text-only environment.

In order to change this behaviour we need to specify an alternative console
and wire it to one of the supported "line" channels. For this we need to map a
console to use something different from the default xterm.

Example which will divert console number 1 to stdin/stdout::

   con1=fd:0,fd:1

UML supports a wide variety of serial line channels which are specified using
the following syntax

   conX=channel_type:options[,channel_type:options]


If the channel specification contains two parts separated by comma, the first
one is input, the second one output.

* The null channel - Discard all input or output. Example ``con=null`` will set
  all consoles to null by default.

* The fd channel - use file descriptor numbers for input/output. Example:
  ``con1=fd:0,fd:1.``

* The port channel - start a telnet server on TCP port number. Example:
  ``con1=port:4321``.  The host must have /usr/sbin/in.telnetd (usually part of
  a telnetd package) and the port-helper from the UML utilities (see the
  information for the xterm channel below).  UML will not boot until a client
  connects.

* The pty and pts channels - use system pty/pts.

* The tty channel - bind to an existing system tty. Example: ``con1=/dev/tty8``
  will make UML use the host 8th console (usually unused).

* The xterm channel - this is the default - bring up an xterm on this channel
  and direct IO to it. Note that in order for xterm to work, the host must
  have the UML distribution package installed. This usually contains the
  port-helper and other utilities needed for UML to communicate with the xterm.
  Alternatively, these need to be complied and installed from source. All
  options applicable to consoles also apply to UML serial lines which are
  presented as ttyS inside UML.

UML instance 시작 예제

688-703

예제 command는 `mem=2048M`, `umid=TEST`, `ubd0=Filesystem.img`, tap vector transport, `root=/dev/ubda`와 console mapping을 한 번에 지정합니다.

Instance에는 2048M RAM이 주어지고 `Filesystem.img`가 root image로 연결됩니다. Networking은 host `tap0`에 연결된 `vec0`을 사용하며 queue depth 128과 GRO를 활성화합니다.

`con=null con0=null,fd:2 con1=fd:0,fd:1`은 console 1을 제외한 console을 비활성화하고, console 1을 시작한 terminal의 standard input/output에 연결합니다. `con0`은 input을 null로 두고 output을 file descriptor 2로 보냅니다.

실행 예제 해석
인자결과
mem2048M2GiB급 RAM
umidTEST고유 machine ID
ubd0Filesystem.imgRoot image 연결
vec0tap0, depth=128, gro=1Host tap network
consolecon1=fd:0,fd:1현재 terminal에서 로그인

Command line의 각 설정과 결과입니다.

UML boot command
linux executable 실행Memory와 umid 설정UBD image와 root device 연결vec0을 host tap0에 연결Console channel을 현재 terminal로 배선UML userspace boot

Image·network·console을 조합해 instance를 시작합니다.

Starting UML
============

We can now run UML.
::

   # linux mem=2048M umid=TEST \
    ubd0=Filesystem.img \
    vec0:transport=tap,ifname=tap0,depth=128,gro=1 \
    root=/dev/ubda con=null con0=null,fd:2 con1=fd:0,fd:1

This will run an instance with ``2048M RAM`` and try to use the image file
called ``Filesystem.img`` as root. It will connect to the host using tap0.
All consoles except ``con1`` will be disabled and console 1 will
use standard input/output making it appear in the same terminal it was started.

UML 로그인

704-711

Image 생성 단계에서 password를 설정하지 않았다면 UML instance를 shutdown하고 image를 mount한 뒤 chroot로 들어가 password를 설정해야 합니다.

이미 password가 설정돼 있다면 연결한 console에서 바로 로그인할 수 있습니다.

Login 준비 상태
상태조치결과
Password 없음Shutdown → mount → chroot → passwd로그인 credential 생성
Password 있음Console에서 loginUML userspace 접근
수정 중UML instance 정지Image 동시 write 방지

Password 유무에 따른 조치입니다.

Logging in
============

If you have not set up a password when generating the image, you will have to
shut down the UML instance, mount the image, chroot into it and set it - as
described in the Generating an Image section.  If the password is already set,
you can just log in.

UML management console

712-771

Image 내부에서는 일반 sysadmin tool을 쓰지만, UML management console은 실행 중인 UML kernel에 low-level operation을 수행하는 별도 interface입니다.

i386 SysRq와 비슷하지만 UML 아래에는 완전한 operating system이 있으므로 SysRq보다 훨씬 유연합니다.

`mconsole`로 kernel version 조회, device 추가·제거, halt·reboot, SysRq command 전송, UML pause·resume, 내부 process 검사, UML 내부 `/proc` state 검사를 할 수 있습니다.

Client는 대부분의 Linux distribution UML tools package에 포함된 `uml_mconsole`입니다. UML kernel에는 General Setup 아래의 `CONFIG_MCONSOLE`을 활성화해야 합니다.

UML을 boot하면 `~/.uml/<자동-id>/mconsole` socket path가 출력됩니다. Command line에 `umid=debian`처럼 고유 machine ID를 주면 path는 `/home/jdike/.uml/debian/mconsole`처럼 예측 가능해집니다.

이 file은 `uml_mconsole`이 UML과 통신하는 socket입니다. Client에는 `uml_mconsole debian`처럼 umid를 주거나 `uml_mconsole /home/jdike/.uml/debian/mconsole`처럼 전체 path를 전달합니다.

연결 후 prompt에서 `version`, `help`, `halt`, `reboot`, `config`, `remove`, `sysrq`, `cad`, `stop`, `go`, `proc`, `stack` command를 실행할 수 있습니다. 원문 목록에는 `help`가 두 번 나오며 원문 자체는 그대로 보존합니다.

Management console은 running UML의 device로 내부 처리되므로 command request 자체가 UML에 device interrupt를 전달할 수 있습니다.

mconsole 기능
기능Command효과
상태 확인version, proc, stackVersion·proc file·process stack 조회
도움말help지원 command 표시
전원halt, reboot, cad즉시 종료·재부팅·Ctl-Alt-Del
Deviceconfig, removeRuntime hot-add·remove
Kernel actionsysrqGeneric SysRq 호출
Pausestop, goUML 실행 정지·재개
Clientuml_mconsoleumid 또는 socket path로 연결
Kernel configCONFIG_MCONSOLEManagement console 활성화

Low-level 관리 범위를 command group별로 정리합니다.

mconsole 연결
UML kernel에서 CONFIG_MCONSOLE 활성화Command line에 고유 umid 지정Boot log에서 mconsole socket path 확인uml_mconsole에 umid 또는 full path 전달Prompt에서 management command 실행

Kernel option부터 command prompt까지의 흐름입니다.

The UML Management Console
============================

In addition to managing the image from "the inside" using normal sysadmin tools,
it is possible to perform a number of low-level operations using the UML
management console. The UML management console is a low-level interface to the
kernel on a running UML instance, somewhat like the i386 SysRq interface. Since
there is a full-blown operating system under UML, there is much greater
flexibility possible than with the SysRq mechanism.

There are a number of things you can do with the mconsole interface:

* get the kernel version
* add and remove devices
* halt or reboot the machine
* Send SysRq commands
* Pause and resume the UML
* Inspect processes running inside UML
* Inspect UML internal /proc state

You need the mconsole client (uml\_mconsole) which is a part of the UML
tools package available in most Linux distritions.

You also need ``CONFIG_MCONSOLE`` (under 'General Setup') enabled in the UML
kernel.  When you boot UML, you'll see a line like::

   mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole

If you specify a unique machine id on the UML command line, i.e.
``umid=debian``, you'll see this::

   mconsole initialized on /home/jdike/.uml/debian/mconsole


That file is the socket that uml_mconsole will use to communicate with
UML.  Run it with either the umid or the full path as its argument::

   # uml_mconsole debian

or

   # uml_mconsole /home/jdike/.uml/debian/mconsole


You'll get a prompt, at which you can run one of these commands:

* version
* help
* halt
* reboot
* config
* remove
* sysrq
* help
* cad
* stop
* go
* proc
* stack

version command

772-785

`version` command는 인자를 받지 않고 UML version string을 출력합니다. 예제 결과는 OpenWrt Linux 4.14.106 x86_64 build 정보를 보여 줍니다.

이 command는 side effect가 거의 없는 no-op으로 running UML이 응답하는지 점검하는 health check에 사용할 수 있습니다.

또한 mconsole 자체가 UML device로 취급되므로 `version` request는 UML에 device interrupt를 보내는 간단한 방법이기도 합니다.

version 사용
용도결과
Version 조회Kernel release·build·architecture 출력
Liveness checkUML 응답 여부 확인
Device interruptmconsole device event 전달

조회 이상의 두 가지 진단 용도입니다.

version
-------

This command takes no arguments.  It prints the UML version::

   (mconsole)  version
   OK Linux OpenWrt 4.14.106 #0 Tue Mar 19 08:19:41 2019 x86_64


There are a couple actual uses for this.  It's a simple no-op which
can be used to check that a UML is running.  It's also a way of
sending a device interrupt to the UML. UML mconsole is treated internally as
a UML device.

help command

786-792

`help` command는 인자를 받지 않습니다.

현재 UML management console이 지원하는 command의 짧은 help screen을 출력합니다.

help 특성
항목내용
인자없음
출력지원 mconsole command 목록
용도현재 build의 command 확인

입력과 출력을 간단히 정리합니다.

help
----

This command takes no arguments. It prints a short help screen with the
supported mconsole commands.

halt·reboot command

793-802

`halt`와 `reboot`는 인자를 받지 않고 machine을 즉시 종료하거나 재부팅합니다.

Disk sync와 userspace clean shutdown을 수행하지 않으므로 정상 shutdown이라기보다 machine crash에 가깝습니다.

예제 `(mconsole) halt`는 `OK`를 반환하지만, 중요한 data가 있다면 내부 userspace에서 먼저 정상 shutdown 절차를 수행해야 합니다.

halt·reboot 위험
Command수행생략
halt즉시 정지Disk sync·userspace shutdown
reboot즉시 재부팅Disk sync·userspace shutdown
운영 판단Crash와 유사Data consistency 보장 없음

즉시 동작이 생략하는 절차입니다.

halt and reboot
---------------

These commands take no arguments.  They shut the machine down immediately, with
no syncing of disks and no clean shutdown of userspace.  So, they are
pretty close to crashing the machine::

   (mconsole)  halt
   OK

config command

803-811

`config`는 virtual machine에 새 device를 추가하며 대부분의 UML device driver가 지원합니다.

인자는 kernel command line과 같은 device specification 하나입니다. 예제는 `config ubd3=/home/jdike/incoming/roots/root_fs_debian22`로 새 UBD block device를 runtime에 연결합니다.

config hot-add
요소내용
Commandconfig
인자추가할 device specification 하나
문법Kernel command line과 동일

Command line device 문법을 runtime에 재사용합니다.

config
------

"config" adds a new device to the virtual machine. This is supported
by most UML device drivers. It takes one argument, which is the
device to add, with the same syntax as the kernel command line::

   (mconsole) config ubd3=/home/jdike/incoming/roots/root_fs_debian22

remove command

812-822

`remove`는 system에서 device를 삭제하며 인자로 제거할 device name만 받습니다.

Device는 driver가 요구하는 의미에서 idle이어야 합니다. UBD block device는 mount, swap, open 상태가 아니어야 합니다.

Network device는 DOWN 상태여야 합니다. 예제 `(mconsole) remove ubd3`는 조건을 충족한 `ubd3`를 분리합니다.

Device remove 조건
Device제거 전 조건인자
UBDUnmounted·not swap·not openubd3 같은 device name
NetworkInterface DOWNNetwork device name
기타각 driver가 정의한 idleDevice name
실패 방지사용 중 resource 해제remove 실행 전 확인

Driver별 idle 의미를 구분합니다.

remove
------

"remove" deletes a device from the system.  Its argument is just the
name of the device to be removed. The device must be idle in whatever
sense the driver considers necessary.  In the case of the ubd driver,
the removed block device must not be mounted, swapped on, or otherwise
open, and in the case of the network driver, the device must be down::

   (mconsole)  remove ubd3

sysrq command

823-831

`sysrq`는 한 글자 인자 하나를 받습니다.

Generic kernel SysRq driver를 호출하고 글자에 대응하는 operation을 수행합니다. 유효한 글자와 동작은 `Documentation/admin-guide/sysrq.rst`를 따라야 합니다.

sysrq 전달
항목내용
인자단일 문자
처리Generic kernel SysRq driver
참조Documentation/admin-guide/sysrq.rst

mconsole 입력이 generic SysRq로 이어집니다.

sysrq
-----

This command takes one argument, which is a single letter.  It calls the
generic kernel's SysRq driver, which does whatever is called for by
that argument.  See the SysRq documentation in
Documentation/admin-guide/sysrq.rst in your favorite kernel tree to
see what letters are valid and what they do.

cad command

832-838

`cad`는 running image에서 `Ctl-Alt-Del` action을 호출합니다.

실제 결과는 init, systemd 등 userspace 설정에 달려 있으며 보통 machine을 reboot합니다.

cad 처리
단계동작
mconsolecad command 수신
KernelCtl-Alt-Del action 발생
Userspaceinit/systemd policy에 따라 보통 reboot

Key sequence와 userspace policy의 관계입니다.

cad
---

This invokes the ``Ctl-Alt-Del`` action in the running image.  What exactly
this ends up doing is up to init, systemd, etc.  Normally, it reboots the
machine.

stop·go command

839-853

`stop`은 UML을 mconsole request만 읽는 loop에 넣고 `go` command가 올 때까지 일반 실행을 멈춥니다. Debugging과 snapshotting에 매우 유용합니다.

`go`는 `stop`으로 pause한 UML을 다시 실행합니다.

Pause 중에는 guest time과 외부 network 시간이 계속 어긋날 수 있어 resume 후 TCP connection이 timeout됐을 수 있습니다.

오랫동안 pause하면 `crond`가 그동안 실행하지 못한 job을 한꺼번에 처리할 수 있으므로 재개 직후 workload를 주의해야 합니다.

Pause·resume 영향
상태동작주의
stopmconsole request loop만 유지Guest 일반 실행 정지
pausedDebug·snapshot 가능TCP timeout 가능
goUML 실행 재개외부 상태와 재동기화 필요
long pause예약 job 누적crond가 job을 집중 실행 가능

정지 중 유지되는 관리 경로와 재개 위험입니다.

Snapshot pause
mconsole stop 실행UML이 management request loop에 진입Debugging 또는 snapshot 수행mconsole go 실행TCP session과 scheduled job 상태 확인

정지와 재개 전후의 운영 점검입니다.

stop
----

This puts the UML in a loop reading mconsole requests until a 'go'
mconsole command is received. This is very useful as a
debugging/snapshotting tool.

go
--

This resumes a UML after being paused by a 'stop' command. Note that
when the UML has resumed, TCP connections may have timed out and if
the UML is paused for a long period of time, crond might go a little
crazy, running all the jobs it didn't do earlier.

proc command

854-859

`proc`는 `/proc` 아래에서 읽을 file name 하나를 인자로 받습니다.

해당 UML 내부 proc file 내용을 mconsole standard output에 출력합니다.

proc 조회
입력대상출력
File nameUML 내부 /procmconsole stdout
용도Kernel·process stateHost에서 low-level inspection
범위지정한 file 하나Text 내용

UML 내부 proc state를 외부 console로 가져옵니다.

proc
----

This takes one argument - the name of a file in /proc which is printed
to the mconsole standard output

stack command

860-865

`stack`은 process ID, 즉 PID 하나를 인자로 받습니다.

선택한 UML process의 stack을 standard output에 출력해 hang이나 실행 위치를 진단할 수 있게 합니다.

stack 조회
입력대상출력
PIDUML 내부 process해당 process stack
출력 channelmconsole standard outputHost에서 확인
용도Hang·실행 위치 진단Low-level debugging

Process 선택과 출력입니다.

stack
-----

This takes one argument - the pid number of a process. Its stack is
printed to a standard output.

Advanced UML과 filesystem 공유 경고

866-876

Advanced UML Topics의 첫 주제는 virtual machine 사이의 filesystem 공유입니다.

같은 image file에서 UML 두 개를 단순히 boot해 filesystem을 공유해서는 안 됩니다. 이는 물리 machine 두 대를 하나의 shared disk에서 동시에 boot하는 것과 같아 filesystem corruption을 일으킵니다.

공유가 필요하다면 master image를 직접 write하는 대신 각 instance가 별도 변경 계층을 갖는 UBD copy-on-write 방식을 사용해야 합니다.

Filesystem 공유 방식
방식결과판정
두 UML이 같은 image를 직접 boot동시 metadata updateFilesystem corruption
물리 machine의 shared disk 동시 boot같은 위험사용 금지
Shared master + per-UML COW변경분 분리권장
Read-only master공통 block 공유COW와 함께 사용
Private change fileInstance별 write 격리Rollback 가능

동시 write 방식의 안전성을 비교합니다.

안전한 공유 선택
공통 root filesystem을 master image로 준비Master를 여러 UML이 직접 write하지 않음Instance마다 private COW file 생성Read는 COW 또는 master에서 수행Write는 private COW에만 저장

공통 데이터와 instance 변경분을 분리합니다.

*******************
Advanced UML Topics
*******************

Sharing Filesystems between Virtual Machines
============================================

Don't attempt to share filesystems simply by booting two UMLs from the
same file.  That's the same thing as booting two physical machines
from a shared disk.  It will result in filesystem corruption.

UBD layered block device

877-910

두 virtual machine이 filesystem 데이터를 공유하는 올바른 방법은 UBD block driver의 COW layering 기능을 사용하는 것입니다.

변경된 block은 private COW file에 저장합니다. Read할 block이 COW에 유효하면 private file에서, 아니면 shared master에서 읽습니다.

변하지 않은 대부분의 데이터는 임의 개수의 VM이 공유하고, 각 VM은 자신이 만든 변경분만 담은 훨씬 작은 file을 갖습니다. 큰 root filesystem에서 많은 UML을 boot할 때 disk 공간을 크게 절약합니다.

Shared data는 host page cache가 같은 block을 적은 memory로 재사용하게 하므로 disk request가 host disk 대신 memory에서 처리될 가능성이 높아져 성능에도 도움이 됩니다.

다만 multisocket NUMA machine에서는 shared master와 여러 COW 변경분을 쓰는 UML을 많이 실행할 때 inter-socket traffic이 과도해져 NMI 같은 문제가 생길 수 있습니다.

고성능 NUMA hardware에서는 `taskset`으로 UML을 같은 socket의 logical CPU 집합에 bind하거나 뒤의 tuning 절을 적용해야 합니다.

기존 block image에 COW layer를 붙이는 형식은 `ubd0=root_fs_cow,root_fs_debian_22`입니다. `root_fs_cow`가 private file, `root_fs_debian_22`가 shared filesystem이며 COW file이 없으면 driver가 생성하고 초기화합니다.

COW read·write 경로
상황접근 위치효과
변경 block writePrivate COWInstance 변경 격리
COW에 유효한 block readPrivate COW최신 변경 사용
COW에 없는 block readShared master공통 data 재사용
다수 UMLMaster 하나 + COW 여러 개Disk 공간 절약
Host cacheShared master blockMemory cache 효율 향상
Multisocket NUMAInter-socket trafficNMI·성능 문제 가능
완화taskset으로 same-socket CPU bindTraffic locality 개선

Block 위치와 NUMA 운영 조건을 정리합니다.

Layered UBD read
UML이 block read 요청Private COW validity map 확인유효하면 COW block 반환없으면 shared master block 반환Write는 항상 private COW에 기록

요청 block의 유효 위치를 선택합니다.

Using layered block devices
---------------------------

The way to share a filesystem between two virtual machines is to use
the copy-on-write (COW) layering capability of the ubd block driver.
Any changed blocks are stored in the private COW file, while reads come
from either device - the private one if the requested block is valid in
it, the shared one if not.  Using this scheme, the majority of data
which is unchanged is shared between an arbitrary number of virtual
machines, each of which has a much smaller file containing the changes
that it has made.  With a large number of UMLs booting from a large root
filesystem, this leads to a huge disk space saving.

Sharing file system data will also help performance, since the host will
be able to cache the shared data using a much smaller amount of memory,
so UML disk requests will be served from the host's memory rather than
its disks.  There is a major caveat in doing this on multisocket NUMA
machines.  On such hardware, running many UML instances with a shared
master image and COW changes may cause issues like NMIs from excess of
inter-socket traffic.

If you are running UML on high-end hardware like this, make sure to
bind UML to a set of logical CPUs residing on the same socket using the
``taskset`` command or have a look at the "tuning" section.

To add a copy-on-write layer to an existing block device file, simply
add the name of the COW file to the appropriate ubd switch::

   ubd0=root_fs_cow,root_fs_debian_22

where ``root_fs_cow`` is the private COW file and ``root_fs_debian_22`` is
the existing shared filesystem.  The COW file need not exist.  If it
doesn't, the driver will create and initialize it.

COW disk 사용량 확인

911-917

UML은 disk image의 unused space를 underlying OS에 돌려주는 TRIM을 지원합니다.

Sparse image의 논리 크기와 실제 할당량은 다르므로 실제 file size는 `ls -ls` 또는 `du`로 확인하는 것이 중요합니다.

Disk usage 확인
항목방법의미
Unused blockTRIMUnderlying OS에 반환
논리 크기일반 file sizeAddressable image 크기
실제 할당ls -lsAllocated block 확인
실제 사용duFilesystem 소비량 확인

Sparse·TRIM image에서 적절한 측정 방법입니다.

Disk Usage
----------

UML has TRIM support which will release any unused space in its disk
image files to the underlying OS. It is important to use either ls -ls
or du to verify the actual file size.

Master image 변경과 COW validity

918-927

Master image를 변경하면 연결된 모든 COW file이 invalid해집니다.

UML은 invalid COW file을 자동 삭제하지 않고 boot를 거부합니다. 잘못된 master와 기존 change map을 섞어 data corruption을 만드는 것을 막기 위한 동작입니다.

해결책은 old master image를 last-modified timestamp까지 포함해 복원하거나, 모든 COW file을 제거해 새로 생성하게 하는 두 가지뿐입니다.

COW file을 제거하면 그 안의 모든 변경분을 잃으므로 master 수정과 COW 정리는 명시적인 backup 계획 아래 수행해야 합니다.

COW invalid 복구
선택필요 조건결과
Old master 복원내용 + timestamp 일치기존 COW 계속 사용
COW 모두 삭제Master를 새 기준으로 채택COW 재생성
COW 일부 유지지원되지 않음Boot 거부 지속
자동 삭제 기대수행되지 않음관리자가 직접 판단
변경분COW 삭제 시모두 손실

Master 변경 후 가능한 선택과 손실을 비교합니다.

Master 변경 사고 대응
UML boot가 invalid COW를 감지기존 변경분을 보존할지 결정보존: timestamp까지 old master 복원포기: 모든 COW를 backup 후 삭제새 COW 생성 후 boot 검증

Validity를 회복하는 두 경로입니다.

COW validity.
-------------

Any changes to the master image will invalidate all COW files. If this
happens, UML will *NOT* automatically delete any of the COW files and
will refuse to boot. In this case the only solution is to either
restore the old image (including its last modified timestamp) or remove
all COW files which will result in their recreation. Any changes in
the COW files will be lost.

uml_moo로 COW merge

928-956

UML과 COW device의 사용 패턴에 따라 COW 변경분을 backing file에 주기적으로 merge하는 것이 유용할 수 있습니다.

Utility는 `uml_moo`이며 기본 문법은 `uml_moo COW_file new_backing_file`입니다.

현재 backing file 정보는 COW header에 들어 있으므로 command에 따로 지정할 필요가 없습니다. 안전을 중시한다면 새 merged file을 먼저 boot해 검증한 뒤 old backing file을 교체합니다.

기본 동작은 안전을 위해 새 backing file을 만듭니다.

Destructive merge option은 COW를 현재 backing file에 직접 합칩니다. Disk 공간이 부족할 때 편리하고 non-destructive merge보다 빠르지만 backing file에 COW가 하나만 연결된 경우에만 안전합니다.

여러 COW가 같은 backing file을 쓰는 상태에서 하나를 `-d` merge하면 다른 COW가 모두 invalid해집니다. `uml_moo`는 UML distribution package의 UML utilities에 포함됩니다.

uml_moo merge 방식
방식출력장점위험
기본new_backing_file원본 유지·검증 가능추가 disk 공간 필요
Destructive -d현재 backing file 수정빠르고 공간 절약다른 COW invalid
단일 COW-d 사용 가능연결 관계 단순Backup 권장
여러 COW기본 merge 권장다른 instance 보호-d 금지
Header현재 backing path 포함Command에 old backing 생략Header validity 필요
검증새 merged image boot교체 전 상태 확인검증 전 overwrite 금지

새 file 생성과 destructive merge의 trade-off입니다.

안전한 COW merge
UML과 COW 사용 중지uml_moo COW_file new_backing_file 실행새 merged file로 UML 시험 bootFilesystem과 application 상태 검증정상일 때 old backing 교체

새 backing file을 검증한 뒤 교체합니다.

Cows can moo - uml_moo : Merging a COW file with its backing file
-----------------------------------------------------------------

Depending on how you use UML and COW devices, it may be advisable to
merge the changes in the COW file into the backing file every once in
a while.

The utility that does this is uml_moo.  Its usage is::

   uml_moo COW_file new_backing_file


There's no need to specify the backing file since that information is
already in the COW file header.  If you're paranoid, boot the new
merged file, and if you're happy with it, move it over the old backing
file.

``uml_moo`` creates a new backing file by default as a safety measure.
It also has a destructive merge option which will merge the COW file
directly into its current backing file.  This is really only usable
when the backing file only has one COW file associated with it.  If
there are multiple COWs associated with a backing file, a -d merge of
one of them will invalidate all of the others.  However, it is
convenient if you're short of disk space, and it should also be
noticeably faster than a non-destructive merge.

``uml_moo`` is installed with the UML distribution packages and is
available as a part of UML utilities.

Host file access와 보안 경고

957-976

UML 안에서 host file에 접근하려면 별도 machine처럼 NFS로 directory를 mount하거나 `scp`로 file을 복사할 수 있습니다.

그러나 UML 자체가 host process이므로 network 없이도 host file에 접근할 수 있습니다. `hostfs` virtual filesystem은 host directory를 UML filesystem에 mount해 host에서처럼 file을 사용하게 합니다.

중요한 security warning이 있습니다. UML image에 parameter 제한 없이 hostfs를 허용하면 guest가 host filesystem의 어느 부분이든 mount하고 write할 수 있습니다.

UML을 실행할 때 hostfs는 `/var/tmp` 같은 특정 harmless directory에 항상 제한해야 합니다.

특히 UML을 root로 실행하면 hostfs write가 host 전체에 미치는 영향이 커지므로 제한이 필수입니다.

Host file 전달 방식
방식경로장점주의
NFSHost export → UML mount표준 network 공유Network 설정 필요
scpHost ↔ UML copy명시적 file 전달복사본 관리
hostfsHost directory 직접 mountNetwork 불필요Host write 노출
무제한 hostfsHost / 전체 가능편리하지만 위험사용 금지
제한 hostfs/var/tmp 등피해 범위 축소Startup parameter로 고정
Root UMLHost privilege 큼일부 관리 가능특히 강한 격리 필요

Network 방식과 hostfs의 편의·위험을 비교합니다.

안전한 hostfs 노출
Guest가 필요한 file 범위 식별Harmless 전용 host directory 생성UML startup에서 hostfs root를 그 directory로 제한필요 최소 user permission 적용Host root나 민감 path mount 차단

Guest에 필요한 host directory만 제공합니다.

Host file access
==================

If you want to access files on the host machine from inside UML, you
can treat it as a separate machine and either nfs mount directories
from the host or copy files into the virtual machine with scp.
However, since UML is running on the host, it can access those
files just like any other process and make them available inside the
virtual machine without the need to use the network.
This is possible with the hostfs virtual filesystem.  With it, you
can mount a host directory into the UML filesystem and access the
files contained in it just as you would on the host.

*SECURITY WARNING*

Hostfs without any parameters to the UML Image will allow the image
to mount any part of the host filesystem and write to it. Always
confine hostfs to a specific "harmless" directory (for example ``/var/tmp``)
if running UML. This is especially important if UML is being run as root.

hostfs 사용

977-1001

먼저 UML 안에서 `cat /proc/filesystems`를 실행해 `hostfs`가 사용 가능한지 확인합니다.

목록에 없다면 hostfs를 built-in으로 포함해 kernel을 다시 build하거나, module로 build된 hostfs가 VM 안에 존재하는지 확인하고 `insmod`로 load합니다.

`mount none /mnt/host -t hostfs`는 host의 `/`를 UML의 `/mnt/host`에 mount합니다.

Host root 전체가 필요하지 않다면 `-o` option으로 subdirectory를 지정합니다.

예제 `mount none /mnt/home -t hostfs -o /home`은 host `/home`을 UML `/mnt/home`에 mount합니다.

hostfs mount
단계Command결과
지원 확인cat /proc/filesystemshostfs 목록 확인
Built-inKernel rebuildBoot부터 hostfs 사용
Moduleinsmod hostfsRuntime load
Host rootmount none /mnt/host -t hostfs/ → /mnt/host
Subdirectorymount ... -o /home/home → /mnt/home

Availability 확인과 mount 범위를 정리합니다.

hostfs subdirectory mount
/proc/filesystems에서 hostfs 확인필요하면 built-in 또는 module loadUML mount point 생성-o에 제한된 host path 지정Mount 후 permission과 write 범위 확인

전체 root 대신 필요한 path만 연결합니다.

Using hostfs
------------

To begin with, make sure that hostfs is available inside the virtual
machine with::

   # cat /proc/filesystems

``hostfs`` should be listed.  If it's not, either rebuild the kernel
with hostfs configured into it or make sure that hostfs is built as a
module and available inside the virtual machine, and insmod it.


Now all you need to do is run mount::

   # mount none /mnt/host -t hostfs

will mount the host's ``/`` on the virtual machine's ``/mnt/host``.
If you don't want to mount the host root directory, then you can
specify a subdirectory to mount with the -o switch to mount::

   # mount none /mnt/home -t hostfs -o /home

will mount the host's /home on the virtual machine's /mnt/home.

hostfs를 root filesystem으로 사용

1002-1029

Standard image file 대신 host directory hierarchy를 hostfs root로 사용해 boot할 수 있습니다.

먼저 root hierarchy가 필요합니다. 가장 쉬운 방법은 `mount root_fs uml_root_dir -o loop`로 기존 `root_fs` image를 loop mount하는 것입니다.

Hierarchy의 `etc/fstab`에서 `/` filesystem type을 `hostfs`로 바꾸고 `/dev/ubd/0 / hostfs defaults 1 1` 형태로 설정합니다.

그 directory에서 root 소유 file을 UML 실행 user 소유로 바꿔야 합니다. 예제는 `find . -uid 0 -exec chown jdike {} ;`입니다.

UML kernel에는 hostfs가 module이 아니라 built-in으로 compile돼 있어야 합니다. `ubd0=/path/to/uml/root/directory`로 boot device를 directory에 지정하면 일반 image처럼 UML이 boot합니다.

hostfs root 준비
단계설정이유
Hierarchyroot_fs를 loop mount기존 image 내용 재사용
fstab/ type=hostfsRoot filesystem driver 선택
OwnershipRoot-owned file을 실행 user로 chownHost process 권한 일치
Kernelhostfs built-inRoot mount 전에 module load 불가
Boot argumentubd0=/path/to/directoryDirectory를 root source로 지정
검증일반 boot 확인fstab·permission 점검

Directory hierarchy에서 boot하기 위한 조건입니다.

Directory root boot
기존 root_fs를 uml_root_dir에 loop mountetc/fstab의 root type을 hostfs로 변경Root-owned file ownership 조정hostfs built-in UML kernel 준비ubd0에 directory path를 지정해 boot

Image 내용을 host directory로 노출해 UML root로 사용합니다.

hostfs as the root filesystem
-----------------------------

It's possible to boot from a directory hierarchy on the host using
hostfs rather than using the standard filesystem in a file.
To start, you need that hierarchy.  The easiest way is to loop mount
an existing root_fs file::

   #  mount root_fs uml_root_dir -o loop


You need to change the filesystem type of ``/`` in ``etc/fstab`` to be
'hostfs', so that line looks like this::

   /dev/ubd/0       /        hostfs      defaults          1   1

Then you need to chown to yourself all the files in that directory
that are owned by root.  This worked for me::

   #  find . -uid 0 -exec chown jdike {} \;

Next, make sure that your UML kernel has hostfs compiled in, not as a
module.  Then run UML with the boot device pointing at that directory::

   ubd0=/path/to/uml/root/directory

UML should then boot as it does normally.

hostfs cache caveat

1030-1038

hostfs는 UML 밖의 host에서 발생한 filesystem 변경을 추적하지 못합니다.

UML이 모르는 상태에서 host file이 바뀌면 UML의 in-memory file cache가 stale하거나 corrupt한 상태가 될 수 있습니다.

기술적으로 고칠 수는 있지만 현재 이 개선은 진행 중인 작업이 아니므로, mounted hostfs path를 host와 UML이 동시에 수정하지 않도록 운영해야 합니다.

hostfs coherence
변경 주체UML 인지위험완화
UML 내부인지일반 cache 동작정상 사용
Host 외부 process미인지Stale cache동시 수정 금지
동일 file 양쪽 write불일치Data corruption 가능Single writer 원칙
현재 상태자동 coherence 없음Known caveatOperational isolation

외부 변경이 UML cache에 미치는 영향입니다.

Hostfs Caveats
--------------

Hostfs does not support keeping track of host filesystem changes on the
host (outside UML). As a result, if a file is changed without UML's
knowledge, UML will not know about it and its own in-memory cache of
the file may be corrupt. While it is possible to fix this, it is not
something which is being worked on at present.

CPU·NUMA locality tuning

1039-1065

현재 UML은 strict uniprocessor이지만 UBD driver, SIGIO, MMU emulation 등 여러 기능을 위한 helper thread를 만듭니다.

SMP host가 idle하면 OS가 이 thread들을 다른 processor로 migrate할 수 있습니다. 그 결과 core 사이 cache와 memory synchronization traffic이 늘어 오히려 성능이 낮아지는 경우가 많습니다.

특히 큰 system에서는 UML thread 전체를 CPU 하나에 pin하는 것이 유리하며 일부 benchmark에서는 5배 이상의 성능 차이가 날 수 있습니다.

큰 multi-node NUMA system에서는 UML이 실행될 node와 같은 NUMA node에서 모든 memory를 할당해야 유리하지만 OS는 기본적으로 그렇게 하지 않습니다.

관리자는 특정 node에 bind한 tmpfs ramdisk를 만들고 `TMPDIR`, `TMP`, `TEMP` 중 하나로 지정해 UML RAM allocation source로 사용해야 합니다. UML은 이 순서의 environment value를 확인하고 실패하면 `/dev/shm`의 shmfs, 마지막에는 filesystem type과 관계없이 `/tmp/`를 사용합니다.

예제는 `mount -t tmpfs -ompol=bind:X none /mnt/tmpfs-nodeX`로 node X tmpfs를 만들고 `TEMP=/mnt/tmpfs-nodeX taskset -cX linux ...`로 memory와 CPU를 같은 node에 맞춥니다.

UML locality tuning
대상기본 동작조정효과
UML vCPUUniprocessorCPU X에 pinExecution locality
Helper threadsSMP core로 migratetaskset -cXCache traffic 감소
NUMA memory여러 node 가능Node X tmpfsRemote memory 감소
Allocation envTMPDIR/TMP/TEMPBound tmpfs pathUML RAM source 지정
Fallback 1/dev/shm shmfsEnv 실패 시Shared memory 사용
Fallback 2/tmp/최종 fallbackFilesystem type 무관
BenchmarkMigration 상태CPU·memory 결합5배 이상 차이 가능

Thread migration과 memory allocation 경로입니다.

NUMA-local UML 시작
실행할 CPU X와 NUMA node 확인Node X에 bind한 tmpfs mountTEMP 또는 TMPDIR을 tmpfs path로 지정taskset -cX로 UML thread를 CPU X에 pinBenchmark와 inter-socket traffic 확인

CPU와 backing memory를 같은 node에 둡니다.

Tuning UML
============

UML at present is strictly uniprocessor. It will, however spin up a
number of threads to handle various functions.

The UBD driver, SIGIO and the MMU emulation do that. If the system is
idle, these threads will be migrated to other processors on a SMP host.
This, unfortunately, will usually result in LOWER performance because of
all of the cache/memory synchronization traffic between cores. As a
result, UML will usually benefit from being pinned on a single CPU,
especially on a large system. This can result in performance differences
of 5 times or higher on some benchmarks.

Similarly, on large multi-node NUMA systems UML will benefit if all of
its memory is allocated from the same NUMA node it will run on. The
OS will *NOT* do that by default. In order to do that, the sysadmin
needs to create a suitable tmpfs ramdisk bound to a particular node
and use that as the source for UML RAM allocation by specifying it
in the TMP or TEMP environment variables. UML will look at the values
of ``TMPDIR``, ``TMP`` or ``TEMP`` for that. If that fails, it will
look for shmfs mounted under ``/dev/shm``. If everything else fails use
``/tmp/`` regardless of the filesystem type used for it::

   mount -t tmpfs -ompol=bind:X none /mnt/tmpfs-nodeX
   TEMP=/mnt/tmpfs-nodeX taskset -cX linux options options options..

UML 개발과 기여

1066-1099

UML은 filesystem, device, virtualization 같은 새로운 Linux kernel concept를 개발하기 좋은 platform입니다. 특정 hardware emulation에 묶이지 않고 구현하고 시험할 수 있습니다.

예를 들어 4,096개의 'proper' network device를 가진 Linux를 시험할 수 있습니다. QEMU의 PCI bus당 16개 같은 emulated hardware bus limit 때문에 다른 virtualization package에서는 어려운 실험입니다.

Patch, bugfix, new feature는 `linux-um@lists.infradead.org` mailing list로 보냅니다.

관련 maintainer를 CC하고 `./scripts/checkpatch.pl`을 실행하는 등 표준 Linux patch guideline을 따라야 하며 자세한 내용은 `Documentation/process/submitting-patches.rst`를 참조합니다.

Mailing list는 HTML이나 attachment를 받지 않으므로 모든 email을 plain text로 작성해야 합니다.

개발에는 debugging이 따릅니다. UML을 GDB 아래에서 실행할 수 있지만 tracing statement를 추가하거나 UML kernel process를 ptrace하는 UML-specific 방식이 더 많은 정보를 주는 경우가 흔합니다.

UML 기여 절차
항목내용
실험 대상Filesystem·device·virtualization concept
확장성 예4,096 network devices
제약 회피Emulated bus device limit 없음
Mailing listlinux-um@lists.infradead.org
검사./scripts/checkpatch.pl
Mail 형식Plain text, HTML·attachment 금지

실험 장점과 patch 제출 요건입니다.

Patch 제출
UML에서 concept 구현·시험관련 test와 tracing 수행checkpatch.pl 실행Relevant maintainer CCPlain-text patch를 linux-um list에 전송

표준 kernel contribution 절차를 UML list에 적용합니다.

*******************************************
Contributing to UML and Developing with UML
*******************************************

UML is an excellent platform to develop new Linux kernel concepts -
filesystems, devices, virtualization, etc. It provides unrivalled
opportunities to create and test them without being constrained to
emulating specific hardware.

Example - want to try how Linux will work with 4096 "proper" network
devices?

Not an issue with UML. At the same time, this is something which
is difficult with other virtualization packages - they are
constrained by the number of devices allowed on the hardware bus
they are trying to emulate (for example 16 on a PCI bus in qemu).

If you have something to contribute such as a patch, a bugfix, a
new feature, please send it to ``linux-um@lists.infradead.org``.

Please follow all standard Linux patch guidelines such as cc-ing
relevant maintainers and run ``./scripts/checkpatch.pl`` on your patch.
For more details see ``Documentation/process/submitting-patches.rst``

Note - the list does not accept HTML or attachments, all emails must
be formatted as plain text.

Developing always goes hand in hand with debugging. First of all,
you can always run UML under gdb and there will be a whole section
later on on how to do that. That, however, is not the only way to
debug a Linux kernel. Quite often adding tracing statements and/or
using UML specific approaches such as ptracing the UML kernel process
are significantly more informative.

Running UML tracing

1100-1152

실행 중인 UML은 main kernel thread와 여러 helper thread로 구성됩니다. Tracing 대상은 MMU emulation 때문에 UML이 이미 ptrace 중인 thread가 아닙니다.

`ps`에 처음 보이는 세 thread가 보통 주요 대상입니다. PID가 가장 낮고 CPU를 가장 많이 쓰는 것이 kernel thread이며, 나머지는 disk(UBD) helper와 SIGIO helper입니다.

`strace -p 16566` 예제는 idle UML에서도 SIGIO, `epoll_wait`, 여러 `ptrace` request, `timer_settime`, `clock_nanosleep`, SIGALRM이 반복되는 모습을 보여 줍니다. 원문 syscall trace 전체는 해당 줄 좌표에 그대로 보존됩니다.

UML interrupt controller는 `epoll`을 사용하므로 `epoll_wait`는 I/O interrupt를 기다리는 동작입니다.

연속된 `ptrace` call은 MMU emulation과 UML userspace 실행의 일부입니다. `timer_settime`은 UML 내부 high-resolution timer 요청을 host high-resolution timer에 매핑합니다.

`clock_nanosleep`은 physical PC의 ACPI idle과 비슷하게 UML이 idle 상태로 들어가는 동작입니다.

따라서 idle에서도 trace output이 많지만 I/O를 관찰할 때 실제 syscall, argument, return value를 모두 보여 주어 매우 유용합니다.

Idle UML trace 해석
TraceUML 의미관찰 대상
SIGIOI/O event signalDevice activity
epoll_waitInterrupt controller 대기I/O interrupt
PTRACE_GET/SETREGSMMU·userspace 제어Guest execution
PTRACE_SYSEMUSystem call emulationGuest syscall
timer_settimeHigh-res timer mappingTimer request
clock_nanosleepUML idleIdle transition

대표 syscall과 UML subsystem의 대응입니다.

Tracing thread 선택
ps로 UML의 초기 helper thread 확인가장 낮은 PID·높은 CPU의 kernel thread 선택strace -p PID attachepoll·ptrace·timer·sleep sequence 관찰I/O syscall argument와 return value 분석

Main kernel thread를 찾아 syscall을 해석합니다.

Tracing UML
=============

When running, UML consists of a main kernel thread and a number of
helper threads. The ones of interest for tracing are NOT the ones
that are already ptraced by UML as a part of its MMU emulation.

These are usually the first three threads visible in a ps display.
The one with the lowest PID number and using most CPU is usually the
kernel thread. The other threads are the disk
(ubd) device helper thread and the SIGIO helper thread.
Running ptrace on this thread usually results in the following picture::

   host$ strace -p 16566
   --- SIGIO {si_signo=SIGIO, si_code=POLL_IN, si_band=65} ---
   epoll_wait(4, [{EPOLLIN, {u32=3721159424, u64=3721159424}}], 64, 0) = 1
   epoll_wait(4, [], 64, 0)                = 0
   rt_sigreturn({mask=[PIPE]})             = 16967
   ptrace(PTRACE_GETREGS, 16967, NULL, 0xd5f34f38) = 0
   ptrace(PTRACE_GETREGSET, 16967, NT_X86_XSTATE, [{iov_base=0xd5f35010, iov_len=832}]) = 0
   ptrace(PTRACE_GETSIGINFO, 16967, NULL, {si_signo=SIGTRAP, si_code=0x85, si_pid=16967, si_uid=0}) = 0
   ptrace(PTRACE_SETREGS, 16967, NULL, 0xd5f34f38) = 0
   ptrace(PTRACE_SETREGSET, 16967, NT_X86_XSTATE, [{iov_base=0xd5f35010, iov_len=2696}]) = 0
   ptrace(PTRACE_SYSEMU, 16967, NULL, 0)   = 0
   --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=16967, si_uid=0, si_status=SIGTRAP, si_utime=65, si_stime=89} ---
   wait4(16967, [{WIFSTOPPED(s) && WSTOPSIG(s) == SIGTRAP | 0x80}], WSTOPPED|__WALL, NULL) = 16967
   ptrace(PTRACE_GETREGS, 16967, NULL, 0xd5f34f38) = 0
   ptrace(PTRACE_GETREGSET, 16967, NT_X86_XSTATE, [{iov_base=0xd5f35010, iov_len=832}]) = 0
   ptrace(PTRACE_GETSIGINFO, 16967, NULL, {si_signo=SIGTRAP, si_code=0x85, si_pid=16967, si_uid=0}) = 0
   timer_settime(0, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=0, tv_nsec=2830912}}, NULL) = 0
   getpid()                                = 16566
   clock_nanosleep(CLOCK_MONOTONIC, 0, {tv_sec=1, tv_nsec=0}, NULL) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
   --- SIGALRM {si_signo=SIGALRM, si_code=SI_TIMER, si_timerid=0, si_overrun=0, si_value={int=1631716592, ptr=0x614204f0}} ---
   rt_sigreturn({mask=[PIPE]})             = -1 EINTR (Interrupted system call)

This is a typical picture from a mostly idle UML instance.

* UML interrupt controller uses epoll - this is UML waiting for IO
  interrupts:

   epoll_wait(4, [{EPOLLIN, {u32=3721159424, u64=3721159424}}], 64, 0) = 1

* The sequence of ptrace calls is part of MMU emulation and running the
  UML userspace.
* ``timer_settime`` is part of the UML high res timer subsystem mapping
  timer requests from inside UML onto the host high resolution timers.
* ``clock_nanosleep`` is UML going into idle (similar to the way a PC
  will execute an ACPI idle).

As you can see UML will generate quite a bit of output even in idle. The output
can be very informative when observing IO. It shows the actual IO calls, their
arguments and returns values.

GDB kernel debugging

1153-1167

UML을 GDB 아래에서 시작할 수 있지만 항상 debugger 시작을 순순히 허용하지는 않습니다.

Runtime bug를 추적할 때는 실행 중인 UML에 GDB를 attach한 뒤 계속 실행하게 하는 편이 좋습니다.

앞 trace와 같은 PID라면 `gdb -p 16566`으로 attach합니다.

Attach 즉시 UML instance가 STOP되므로 GDB prompt에서 `cont`를 입력해야 합니다. 이 동작을 GDB script로 만들고 argument로 전달하면 반복 debugging을 자동화할 수 있습니다.

GDB attach
단계Command상태
PID 확인ps/straceMain UML kernel thread 식별
Attachgdb -p 16566UML STOP
Breakpoint·검사GDB commandPaused state 분석
재개contUML 실행 계속

Runtime UML을 멈추고 재개하는 절차입니다.

Runtime GDB
재현 가능한 runtime bug 준비Main UML PID 확인gdb -p PID 실행State·stack·variable 검사cont로 UML 재개

실행 중 instance에 안전하게 attach합니다.

Kernel debugging
================

You can run UML under gdb now, though it will not necessarily agree to
be started under it. If you are trying to track a runtime bug, it is
much better to attach gdb to a running UML instance and let UML run.

Assuming the same PID number as in the previous example, this would be::

   # gdb -p 16566

This will STOP the UML instance, so you must enter `cont` at the GDB
command line to request it to continue. It may be a good idea to make
this into a gdb script and pass it to gdb as an argument.

UML device driver 개발

1168-1197

거의 모든 UML driver는 monolithic입니다. Kernel module로 만들 수는 있지만 in-kernel 기능과 non-UML-specific 기능으로 범위가 제한됩니다.

UML의 강점을 제대로 활용하려면 driver concept를 실제 host userspace call에 매핑하는 userspace code를 작성해야 하기 때문입니다.

이 부분을 driver의 `user` portion이라고 하며 kernel concept을 많이 재사용할 수 있어도 본질적으로 userspace code입니다.

이에 대응하는 `kernel` code는 UML image 안에 있고 Linux kernel 측 기능을 구현합니다.

`kernel`과 `user`가 상호 작용하는 방식에는 제한이 거의 없습니다. UML은 엄격한 kernel-to-host API를 정의하지 않고 특정 architecture나 bus를 emulation하지도 않습니다.

두 부분은 developer 설계에 따라 memory와 code를 공유하고 필요한 방식으로 상호 작용할 수 있습니다. 다만 같은 이름의 function과 variable이 많아 include와 library가 어느 쪽 symbol을 뜻하는지 주의해야 합니다.

그래서 userspace code에는 단순 wrapper가 많습니다. `os_close_file()`은 userspace `close()`가 kernel 쪽의 같은 이름 function과 충돌하지 않도록 감싼 예입니다.

UML driver 양쪽 구조
부분실행 위치역할
userHost userspaceDriver concept를 host syscall에 매핑
kernelUML image kernelLinux kernel interface 구현
공유Memory·codeDesign에 맞춘 자유로운 상호 작용
APIStrict kernel-to-host API 없음Architecture·bus emulation 제약 없음
위험동일 symbol nameInclude·library namespace 주의
Wrapperos_close_file() → close()Kernel/user name 충돌 방지

User portion과 kernel portion의 책임입니다.

UML-specific driver
UML image 안에 kernel-side driver 작성Host call을 수행할 user-side code 작성공유 memory·message·code 경계 설계Namespace 충돌을 wrapper로 격리양쪽 lifecycle과 error path 시험

Kernel interface와 host 구현을 연결합니다.

Developing Device Drivers
=========================

Nearly all UML drivers are monolithic. While it is possible to build a
UML driver as a kernel module, that limits the possible functionality
to in-kernel only and non-UML specific.  The reason for this is that
in order to really leverage UML, one needs to write a piece of
userspace code which maps driver concepts onto actual userspace host
calls.

This forms the so-called "user" portion of the driver. While it can
reuse a lot of kernel concepts, it is generally just another piece of
userspace code. This portion needs some matching "kernel" code which
resides inside the UML image and which implements the Linux kernel part.

*Note: There are very few limitations in the way "kernel" and "user" interact*.

UML does not have a strictly defined kernel-to-host API. It does not
try to emulate a specific architecture or bus. UML's "kernel" and
"user" can share memory, code and interact as needed to implement
whatever design the software developer has in mind. The only
limitations are purely technical. Due to a lot of functions and
variables having the same names, the developer should be careful
which includes and libraries they are trying to refer to.

As a result a lot of userspace code consists of simple wrappers.
E.g. ``os_close_file()`` is just a wrapper around ``close()``
which ensures that the userspace function close does not clash
with similarly named function(s) in the kernel part.

Device driver test platform

1198-1217

UML은 device driver 개발을 위한 훌륭한 test platform입니다.

다만 원문 표현대로 'some user assembly may be required'하므로 사용자가 자신의 emulation environment를 구축해야 합니다. 현재 UML은 kernel infrastructure만 제공합니다.

Infrastructure에는 Arm이나 Open Firmware platform에서 쓰는 FDT device tree blob을 load하고 parse하는 기능이 포함됩니다.

DTB는 kernel command line의 optional argument `dtb=filename`으로 전달합니다.

Device tree는 boot time에 load·parse되고 이를 query하는 driver에서 접근할 수 있습니다. 현재는 development 전용이며 UML 자체 device는 device tree를 query하지 않습니다.

UML device-tree test
항목내용
Emulation사용자가 environment 구축
UML 제공Kernel infrastructure
입력dtb=filename
처리 시점Boot time load·parse
소비자Device tree를 query하는 개발 driver

DTB 제공과 사용 범위를 정리합니다.

DTB 기반 driver test
Test device를 설명하는 FDT blob 생성UML command line에 dtb=filename 추가Boot time에 tree parse개발 driver가 node·property queryProbe와 error path 검증

Virtual hardware description을 UML에 전달합니다.

Using UML as a Test Platform
============================

UML is an excellent test platform for device driver development. As
with most things UML, "some user assembly may be required". It is
up to the user to build their emulation environment. UML at present
provides only the kernel infrastructure.

Part of this infrastructure is the ability to load and parse fdt
device tree blobs as used in Arm or Open Firmware platforms. These
are supplied as an optional extra argument to the kernel command
line::

    dtb=filename

The device tree is loaded and parsed at boottime and is accessible by
drivers which query it. At this moment in time this facility is
intended solely for development purposes. UML's own devices do not
query the device tree.

UML security considerations

1218-1240

Driver와 새 기능은 UML instance 안에서 host에 영향을 줄 수 있는 arbitrary filename, BPF code, 기타 parameter를 기본적으로 받지 않도록 설계해야 합니다.

Driver와 host의 IPC socket을 UML startup command line에서 지정하는 것은 security 측면에서 허용할 수 있습니다. Host 관리자가 시작 시점에 경계를 정하기 때문입니다.

같은 socket path를 loadable module parameter로 guest가 runtime에 지정하도록 허용하는 것은 안전하지 않습니다.

Raw socket network transport의 BPF 'firmware'처럼 필요한 기능이라면 기본값을 off로 두고 startup command-line parameter로 명시적으로 활성화해야 합니다.

이 원칙을 적용해도 UML과 host 사이 isolation level은 상대적으로 약합니다. UML userspace가 arbitrary kernel driver를 load할 수 있으면 attacker가 이를 이용해 UML 밖으로 탈출할 수 있습니다.

Production에서는 필요한 module을 boot 때 모두 load하고 이후 kernel module loading을 disable하는 것이 권장됩니다.

UML 보안 기본값
기능안전한 정책위험한 정책
Filename·pathStartup에서 host가 고정Guest runtime arbitrary path
IPC socketKernel command line에 지정Loadable module parameter
BPF firmware기본 off·명시적 startup enableGuest가 임의 load
Kernel moduleBoot 때 필요한 것만 loadRuntime arbitrary module 허용
ProductionBoot 후 module loading disableWeak isolation에 의존
ThreatHost 영향 surface 최소화UML escape 가능

Host 영향 parameter와 module loading 정책입니다.

Production UML hardening
필요 driver·path·socket·BPF 기능 목록 확정위험 기능은 기본 off 유지Host-controlled command line에서만 명시적 enable필요 module을 boot 중 모두 loadBoot 완료 후 kernel module loading disableUML을 강한 보안 경계로 간주하지 않음

Host가 startup 경계를 고정하고 runtime 확장을 닫습니다.

Security Considerations
-----------------------

Drivers or any new functionality should default to not
accepting arbitrary filename, bpf code or other parameters
which can affect the host from inside the UML instance.
For example, specifying the socket used for IPC communication
between a driver and the host at the UML command line is OK
security-wise. Allowing it as a loadable module parameter
isn't.

If such functionality is desirable for a particular application
(e.g. loading BPF "firmware" for raw socket network transports),
it should be off by default and should be explicitly turned on
as a command line parameter at startup.

Even with this in mind, the level of isolation between UML
and the host is relatively weak. If the UML userspace is
allowed to load arbitrary kernel drivers, an attacker can
use this to break out of UML. Thus, if UML is used in
a production application, it is recommended that all modules
are loaded at boot and kernel module loading is disabled
afterwards.