Skip to main content

OVS Phần 7: OVS với KVM/Libvirt — Gắn VM Vào Bridge Thật

Phần 7/21 trong loạt Open vSwitch (OVS) — nối tiếp Phần 6, mở đầu Module 2 (Trung cấp). Module 1 đã trang bị đủ bộ công cụ nền tảng (ovs-vsctl, ovs-ofctl) trên một bridge dựng bằng namespace/veth thủ công — Module 2 đưa những công cụ đó vào tình huống thật đầu tiên: một VM chạy trên KVM/libvirt cần lên mạng qua OVS. Namespace/veth ở Bài 4-6 chỉ là mô hình thu nhỏ để học công cụ; từ bài này, "port" không còn là thứ bạn tự tay add-port, mà là thứ một hệ thống khác — libvirt — tự tạo ra và xóa đi theo đúng vòng đời của VM.

Mục tiêu bài học: sau bài này bạn tự viết được domain XML libvirt để gắn một VM vào OVS bridge thay vì Linux bridge truyền thống, phân biệt rõ hai cách khai báo — trực tiếp trong domain XML hay qua một libvirt network riêng — biết chính xác ai tạo và xóa port vnetX trong vòng đời VM (không phải bạn), verify được bằng đúng bộ lệnh ovs-vsctl/ovsdb-client đã học ở Bài 5, và tránh được đúng một hiểu lầm phổ biến nhất khi cấu hình interface type cho port của VM trên OVS.

Ba câu hỏi mà bài này trả lời:

  1. Domain XML cần thay đổi gì để libvirt gắn interface của một VM vào OVS bridge thay vì Linux bridge thường, và thẻ <virtualport type='openvswitch'> thật sự yêu cầu OVS làm gì?
  2. Port vnetX mà libvirt tạo ra khác gì so với port bạn tự ovs-vsctl add-port ở Bài 5 — ai tạo nó, ai xóa nó, và interface type nào mới là đúng?
  3. Có bắt buộc phải định nghĩa một libvirt network riêng cho OVS hay không, và khi nào nên chọn cách nào?

Mục lục


1. Nhắc lại Bài 5: tap interface là gì, và một hiểu lầm cần đính chính trước khi đi tiếp

Bài 5 Mục 2 đã định nghĩa tap — loại interface thứ ba của OVS, bên cạnh systeminternal — là "A TUN/TAP device managed by Open vSwitch", và giải thích cơ chế TUN/TAP của kernel Linux: một network device ảo mà một tiến trình userspace đọc/ghi packet trực tiếp qua file descriptor, đúng cơ chế QEMU/KVM dùng để đẩy packet vào VM. Điều đó đúng ở mức khái niệm kernel, nhưng trước khi bạn tự tay cấu hình bất cứ thứ gì, cần một lát cắt chính xác hơn: tap mà OVS nói tới ở cột type của Interface không phải là loại bạn nên gán cho port của VM.

Tài liệu FAQ chính thức của OVS nói thẳng về đúng tình huống dễ nhầm này: "Open vSwitch has a network device type called 'tap'. This is intended only for implementing 'internal' ports in the OVS userspace switch and should not be used otherwise. In particular, users should not configure KVM 'tap' devices as type 'tap' (use type 'system', the default, instead)." Lý do: kiểu tap trong OVSDB là để OVS tự tạo và tự quản lý một TUN/TAP device (dùng nội bộ khi triển khai userspace datapath) — còn tap device của một VM thì ngược lại, do QEMU tự mở bằng TUNSETIFF và đã tồn tại sẵn như một netdev bình thường trước khi bạn add-port nó vào OVS. Với OVS, một netdev đã tồn tại sẵn trong kernel — bất kể bên trong nó là veth (Bài 4), hay tap device do QEMU tạo — đều rơi vào đúng định nghĩa system: "An ordinary network device". Cùng tài liệu còn lưu ý thêm một điểm sẽ giải thích lý do bạn không cấu hình IP trực tiếp lên nó: "no IP address is configured on the 'tap' device (there is normally an IP address configured in the virtual NIC inside the VM, but this is not visible to the host Linux kernel or to Open vSwitch)".

Tóm gọn cho phần còn lại của bài: khi libvirt gắn một VM vào OVS bridge, port xuất hiện trên br0 sẽ không có dòng type: nào cả trong ovs-vsctl show — giống hệt cách veth0-ovs ở Bài 4 không có type: — vì nó dùng type mặc định system, không phải tap.


2. Từ Linux bridge sang OVS bridge: khác nhau đúng một virtualport

💡 Hình dung như thế này: gắn VM vào Linux bridge truyền thống giống cắm một sợi cáp vào switch không hỗ trợ SNMP hay API quản lý từ xa — bridge chỉ biết forward, không có cách nào để một hệ thống bên ngoài "hỏi" nó đang có port nào. Gắn VM vào OVS bridge vẫn là cùng một hành động vật lý — nối một sợi cáp ảo tap device vào một bridge — nhưng lần này bridge có cả OVSDB phía sau (Bài 1, Bài 5), và libvirt biết cách nói chuyện đúng giao thức đó. Thẻ <virtualport type='openvswitch'> chính là công tắc bật chế độ "nói chuyện qua OVSDB" này thay vì chỉ gọi ip link set ... master br0 như với một Linux bridge bình thường.

Tài liệu chính thức "Open vSwitch with Libvirt" trình bày đúng sự khác biệt này bằng một ví dụ before/after trên cùng một VM. Domain XML mặc định của một VM dùng libvirt network default (Linux bridge quản lý bởi libvirt, có NAT) trông như sau:

<interface type='network'>
<mac address='52:54:00:71:b1:b6'/>
<source network='default'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

Chuyển sang gắn thẳng vào một OVS bridge có sẵn tên ovsbr (dựng bằng đúng ovs-vsctl add-br đã học ở Bài 5, không phải libvirt tạo hộ), tài liệu hướng dẫn sửa thành:

<interface type='bridge'>
<mac address='52:54:00:71:b1:b6'/>
<source bridge='ovsbr'/>
<virtualport type='openvswitch'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

Ba khác biệt đáng chú ý so với bản gốc: type='network' (trỏ vào một libvirt network object) đổi thành type='bridge' (trỏ thẳng vào một bridge trên host); <source network='default'/> đổi thành <source bridge='ovsbr'/>; và quan trọng nhất — thêm dòng <virtualport type='openvswitch'/>. Tài liệu giải thích ngắn gọn: "The interface type must be set to bridge. The <source> XML element specifies to which bridge this interface will be attached to. The <virtualport> element indicates that the bridge in <source> element is an Open vSwitch bridge." Thiếu đúng một dòng <virtualport> này, <source bridge='ovsbr'/> vẫn hợp lệ về mặt cú pháp — nhưng libvirt sẽ cố gắn vnetX vào ovsbr bằng ip link/brctl như với một Linux bridge bình thường, và thất bại (hoặc gắn sai cách) vì ovsbr không phải là bridge kernel-managed theo nghĩa đó.

Có một giới hạn quan trọng cần biết trước khi đi tiếp, cùng tài liệu ghi rõ ở mục Limitations: "Currently there is no Open vSwitch support for networks that are managed by libvirt (e.g. NAT). As of now, only bridged networks are supported (those where the user has to manually create the bridge)." Nói cách khác: libvirt không bao giờ tự tạo OVS bridge hộ bạn — bước ovs-vsctl add-br của Bài 5 luôn phải chạy tay trước, dù bạn dùng cách khai báo nào ở Mục 4 dưới đây.


3. Domain XML đầy đủ: source bridge, virtualport, interfaceid nghĩa là gì

Ghép đầy đủ các thẻ mà tài liệu "Domain XML format" của libvirt.org mô tả cho một interface loại bridge nối OVS, một domain XML thực tế trông như sau:

<interface type='bridge'>
<mac address='52:54:00:71:b1:b6'/>
<source bridge='br0'/>
<virtualport type='openvswitch'>
<parameters interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
</virtualport>
<target dev='vnet7'/>
</interface>

Từng thẻ, theo đúng tài liệu:

  • <source bridge='br0'/>: tên OVS bridge đã tồn tại sẵn trên host — chính xác cái tên bạn gõ trong ovs-vsctl add-br br0 ở Bài 5.
  • <virtualport type='openvswitch'>: bật chế độ nói chuyện qua OVSDB. Bên trong nó, tài liệu mô tả: "The Open vSwitch type virtualport accepts two parameters in its <parameters> element — an interfaceid which is a standard uuid used to uniquely identify this particular interface to Open vSwitch (if you do not specify one, a random interfaceid will be generated for you when you first define the interface), and an optional profileid which is sent to Open vSwitch as the interfaces 'port-profile'." — nghĩa là bạn có thể để trống hoàn toàn <virtualport type='openvswitch'/> (như ví dụ Mục 2), libvirt sẽ tự sinh một UUID ngẫu nhiên ngay lần đầu định nghĩa VM và ghi UUID đó lại vào chính domain XML.
  • interfaceid: chỉ là một UUID định danh — bản thân nó không mã hóa VLAN, MAC hay bất cứ điều gì. Vai trò thật của nó lộ ra ở Mục 5: đây chính là giá trị libvirt ghi vào cột external_ids:iface-id của port trên OVSDB khi tạo port, cho phép các hệ thống khác (OVN, Neutron, hoặc chính bạn dùng ovsdb-client dump) tra cứu port nào thuộc VM nào mà không cần đoán qua tên vnetX (tên này có thể đổi số thứ tự giữa các lần boot).
  • <target dev='vnet7'/>: override tên tap device thay vì để libvirt tự đặt số tăng dần. Tài liệu lưu ý một ràng buộc dễ bỏ sót: "the name should not start with either 'vnet', 'vif', 'macvtap', or 'macvlan', which are prefixes reserved by libvirt and certain hypervisors. Manually specified targets using these prefixes may be ignored." — nói cách khác, bạn được phép đặt tên tùy ý cho target dev, nhưng không được đặt trùng tiền tố vnet mà libvirt tự dùng, kẻo bị bỏ qua.
VM đến OVS bridge: vnetX là mắt xích ở giữaKVM HostQEMU / VM processeth0 bên trong guestvnet0 (tap)libvirt tự tạoOVS bridge br0add-port vnet0, type mặc địnheth0uplink vật lý, add-port tayMạng vật lý / switch upstreamvnet0 chỉ tồn tại khi VM đang chạy — libvirt add-port lúc boot, del-port lúc VM tắteth0 là port bạn tự add-port tay ở Bài 4/5 — luôn tồn tại, không phụ thuộc VM nào

4. Hai cách khai báo: domain XML trực tiếp hay một libvirt network riêng

Mục 2-3 dùng cách trực tiếp: khai <source bridge='br0'/><virtualport type='openvswitch'/> ngay trong domain XML của từng VM. Đó không phải cách duy nhất. Libvirt còn hỗ trợ định nghĩa một network object riêng — một bản mô tả tái sử dụng được cho nhiều VM — trỏ vào chính OVS bridge đó, theo tài liệu "Network XML format": một network với forward mode='bridge' có thể mô tả "an existing Open vSwitch bridge that was configured outside of libvirt (if both a <bridge name='xyz'/> element and a <virtualport type='openvswitch'/> have been specified Since 0.10.0)".

💡 Hình dung như thế này: khai trực tiếp <source bridge=...>/<virtualport ...> trong domain XML giống việc bạn dán riêng một tờ hướng dẫn cấu hình lên từng máy tính trong công ty — chắc chắn đúng cho từng máy, nhưng đổi một chi tiết chung (đổi bridge, đổi VLAN mặc định) nghĩa là phải bóc tờ giấy đó ra rồi dán lại trên từng máy một. Định nghĩa một network object giống việc treo đúng một bảng hướng dẫn chung ngay tại lối vào — mọi máy chỉ cần trỏ tới bảng đó, sửa một chỗ là toàn bộ máy dùng theo ngay lập tức, không phải sửa tay từng cái.

Ví dụ chính thức, định nghĩa network ovs-net trỏ vào bridge ovsbr0, kèm cấu hình VLAN mặc định qua <vlan> và một portgroup riêng:

<network>
<name>ovs-net</name>
<forward mode='bridge'/>
<bridge name='ovsbr0'/>
<virtualport type='openvswitch'>
<parameters interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
</virtualport>
<vlan trunk='yes'>
<tag id='42' nativeMode='untagged'/>
<tag id='47'/>
</vlan>
<portgroup name='dontpanic'>
<vlan>
<tag id='42'/>
</vlan>
</portgroup>
</network>

Nạp network này bằng virsh net-define ovs-net.xml rồi virsh net-start ovs-net, sau đó domain XML của từng VM chỉ cần một dòng ngắn gọn, không phải lặp lại <source bridge=...>/<virtualport ...> ở mỗi VM:

<interface type='network'>
<source network='ovs-net' portgroup='dontpanic'/>
</interface>

Khác biệt cốt lõi giữa hai cách:

  • Trực tiếp trong domain XML (type='bridge', Mục 2-3): đơn giản, đủ dùng cho một VM đơn lẻ hoặc lab thử nghiệm, nhưng mỗi VM phải tự khai lại <source bridge=...>/<virtualport ...>.
  • Qua network object (type='network', Mục này): định nghĩa một lần, nhiều VM dùng chung qua <source network=...>; cho phép gắn thêm portgroup để mỗi nhóm VM có VLAN mặc định khác nhau mà không phải sửa từng domain XML — hữu ích khi số VM tăng lên.

Dù chọn cách nào, giới hạn ở Mục 2 vẫn áp dụng nguyên vẹn: bản thân OVS bridge (ovsbr0 trong ví dụ) vẫn phải được bạn tự ovs-vsctl add-br trước — không cách nào trong hai cách trên khiến libvirt tự tạo OVS bridge hộ bạn.


5. Vòng đời của vnetX: ai tạo, ai xóa, và verify bằng ovs-vsctl show

💡 Hình dung như thế này: port bạn tự ovs-vsctl add-port ở Bài 5 giống một chân cắm bạn tự đấu dây trên switch vật lý — nó nằm đó mãi cho tới khi chính bạn rút dây. Port vnetX của một VM lại giống chân cắm trên một patch panel tự động: mỗi lần VM khởi động, một hệ thống khác (libvirt) tự đấu dây vào; mỗi lần VM tắt, hệ thống đó tự rút dây ra — bạn không cần, và cũng không nên, tự tay add-port/del-port cho port này.

Khi bạn virsh start một VM có interface type='bridge' + virtualport type='openvswitch', chuỗi sự kiện diễn ra ở phía host: libvirt tạo một TUN/TAP device mới (tên vnetN mặc định, hoặc tên override ở <target dev>), bật interface đó lên, rồi tự gọi ovs-vsctl add-port br0 vnetN để gắn nó vào bridge — đúng lệnh bạn đã gõ tay ở Bài 4/5, chỉ khác người gõ. Đồng thời, libvirt còn ghi thêm dữ liệu định danh vào cột external_ids của Interface đó: attached-mac (MAC bên trong VM), iface-id (chính giá trị interfaceid trong domain XML ở Mục 3), vm-id (UUID của domain), và iface-status=active. Khi VM tắt, chuỗi ngược lại diễn ra: libvirt del-port rồi xóa tap device — vnetN biến mất khỏi br0 hoàn toàn, không để lại dấu vết trong OVSDB.

Đây là điểm khác biệt lớn nhất so với mọi port Bài 5 đã dựng: veth0-ovs/mgmt0/uplink0 bền trong conf.db qua mọi lần khởi động lại ovs-vswitchd (đúng như Bài 5 Mục 1 đã giải thích) — còn vnetX chỉ tồn tại đúng bằng thời gian VM đang chạy, vì vòng đời của nó gắn với vòng đời VM, không phải với ovsdb-server.

Vòng đời port vnetX: ai tạo, ai xóaKhi VM khởi động — virsh start vm1virsh start vm1bạn gõ lệnh nàylibvirt tạo tapdevice vnetN mớiovs-vsctl add-portbr0 vnetNPort activeghi external_idsvnetN tồn tại trong OVSDB đúng bằng thời gian VM đang chạyKhi VM tắt — virsh destroy vm1virsh destroy vm1bạn gõ lệnh nàylibvirt del-portbr0 vnetNtap devicebị xóa khỏi hostPort biến mấtkhỏi br0 hoàn toànSo sánh Bài 5: veth0-ovs/uplink0 bền trong conf.db qua mọi lần restart ovs-vswitchdvnetN thì không — vòng đời của nó gắn với vòng đời VM, không phải với ovsdb-server

Walkthrough dựa trên tài liệu chính thức — nếu bạn có sẵn máy KVM/libvirt thật, tự chạy để đối chiếu; nếu không, phần này chỉ để hiểu đúng luồng, không phải bịa một lần chạy cụ thể:

# Bridge phải tồn tại trước, giống hệt yêu cầu ở Mục 2
sudo ovs-vsctl add-br br0

# Sửa domain XML theo Mục 3, rồi khởi động VM
sudo virsh define vm1.xml
sudo virsh start vm1
sudo ovs-vsctl show
# Output minh họa
Bridge br0
Port "vnet0"
Interface "vnet0"
Port br0
Interface br0
type: internal
ovs_version: "3.3.0"

(Output minh họa — cấu trúc đúng theo lệnh thật, số liệu cụ thể tùy máy.) Đúng như Mục 1 đã nói trước: Port "vnet0" không có dòng type: nào — vì nó dùng system mặc định, không phải tap.

Đối chiếu bằng ovsdb-client dump (Bài 5 Mục 4) để tự thấy external_ids libvirt vừa ghi:

sudo ovsdb-client dump Open_vSwitch Interface
# Output minh họa
Interface table
_uuid external_ids name ...
-------------- ----------------------------------------------------------------------------------------------- -------- ---
a1b2c3d4-.... {attached-mac="52:54:00:71:b1:b6", iface-id="09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f", iface-status=active, vm-id="4d6e5f7a-...."} "vnet0" ...

(Output minh họa — cấu trúc đúng theo lệnh thật, số liệu cụ thể tùy máy; số cột thật nhiều hơn, đã lược bớt để dễ đọc.) Giá trị iface-id ở đây phải khớp chính xác với interfaceid bạn khai (hoặc để libvirt tự sinh) trong <parameters interfaceid='...'/> ở Mục 3 — tự virsh dumpxml vm1 để đối chiếu hai UUID này với nhau.

Tắt VM và xác nhận port biến mất hoàn toàn:

sudo virsh destroy vm1
sudo ovs-vsctl show # "vnet0" không còn xuất hiện trong br0 nữa

6. VLAN cho VM: tag= áp dụng lại nguyên xi từ Bài 5

💡 Hình dung như thế này: gán VLAN cho port của một VM trên OVS giống hệt gán VLAN cho cổng switch vật lý cắm dây một máy chủ ảo hóa — bạn cấu hình VLAN ngay tại switch, máy ảo bên trong hoàn toàn không biết, không cần biết. Chỉ khác một chỗ: "switch" ở đây là OVS bridge, và "cổng" là port vnetX mà libvirt vừa tự tạo, không phải port bạn tự tay add-port.

Sau khi VM đã boot, vnet0 chỉ là một Port bình thường trong bảng Port của OVSDB — mọi thứ Bài 5 Mục 3 đã dạy về tag=/trunks= áp dụng nguyên vẹn, không cần cú pháp mới:

sudo ovs-vsctl set port vnet0 tag=100

Chính tài liệu howto "Isolating VM Traffic Using VLANs" của OVS minh họa đúng kịch bản này với hai VM trên cùng một host: "Add vm1 as an 'access port' on VLAN 100... $ ovs-vsctl add-port br0 tap0 tag=100", và ghi chú thêm — khớp đúng những gì Bài 6 chưa nhắc tới — "VM interfaces may appear as Linux devices with names like vnet0, vnet1, etc.".

Có một điều cần lưu ý trước khi bạn coi đây là cách "chuẩn" để gán VLAN cho VM lâu dài: ovs-vsctl set port vnet0 tag=100 chạy tay sau khi VM đã boot sẽ mất khi VM khởi động lại. Lý do nằm ở đúng Mục 5 — mỗi lần boot, libvirt del-port port cũ rồi add-port port mới hoàn toàn từ domain XML, và nếu domain XML không có <vlan><tag id='100'/></vlan>, VLAN vừa set tay sẽ không được tái tạo. Cách bền hơn là khai VLAN ngay trong domain XML (hoặc trong portgroup của network object ở Mục 4) bằng phần tử <vlan> — tài liệu libvirt xác nhận nó hoạt động "Since 0.10.0" cho "type='bridge' interfaces connected to an Open vSwitch bridge". Đào sâu cú pháp đầy đủ của <vlan>/portgroup, và các chế độ native-tagged/native-untagged tương ứng với vlan_mode Bài 5 đã nhắc, là chủ đề Bài 8.

Nếu chỉ nhớ được một điều sau bài này, hãy nhớ: <virtualport type='openvswitch'> không tạo ra một loại bridge mới — nó chỉ báo cho libvirt biết hãy gọi ovs-vsctl thay vì ip link/brctl khi tạo và xóa port của VM; toàn bộ kiến thức add-port/tag=/ovs-vsctl show/ovsdb-client dump của Bài 5 áp dụng nguyên vẹn lên port đó, chỉ khác ai là người gõ lệnh — libvirt, không phải bạn.


Bài tập cuối bài

  1. Trên một máy có KVM/libvirt và OVS thật, dựng (hoặc dùng lại) hai VM cùng gắn vào một OVS bridge nhưng đặt VLAN khác nhau bằng đúng cú pháp ovs-vsctl set port <vnetX> tag=<N> đã học ở Bài 5 Mục 3 (ví dụ VM1 tag=100, VM2 tag=200). Ping chéo giữa hai VM để xác nhận timeout do khác VLAN, rồi đổi tag hai VM về cùng giá trị để xác nhận ping lại thông — đúng lại bài lab VLAN isolation Bài 5 đã làm với namespace, lần này lặp lại với VM thật.
  2. Định nghĩa một libvirt network object trỏ vào cùng OVS bridge đó bằng virsh net-define (dùng cú pháp <forward mode='bridge'/>, <bridge name='...'/>, <virtualport type='openvswitch'/> ở Mục 4), rồi gắn một VM vào network này qua <source network='...'/> thay vì khai <source bridge=...>/<virtualport ...> trực tiếp trong domain XML. Sau khi VM chạy, dùng ovsdb-client dump Open_vSwitch Interface (Bài 5 Mục 4) để tự tìm đúng port vnetX của VM này, xác nhận cột external_ids chứa iface-id, attached-mac, vm-id — đối chiếu UUID trong iface-id với interfaceidvirsh dumpxml <vm> cho thấy libvirt đã tự sinh.

Nguồn tham khảo

  • Domain XML before/after gắn VM vào OVS bridge (<interface type='bridge'>, <source bridge='ovsbr'/>, <virtualport type='openvswitch'/>), lệnh ovs-vsctl add-br, virsh edit <vm>, và giới hạn "Currently there is no Open vSwitch support for networks that are managed by libvirt (e.g. NAT). As of now, only bridged networks are supported"Open vSwitch with Libvirt, docs.openvswitch.org.
  • Cột parameters interfaceid: "a standard uuid used to uniquely identify this particular interface to Open vSwitch (if you do not specify one, a random interfaceid will be generated for you when you first define the interface)", profileid tùy chọn "sent to Open vSwitch as the interfaces 'port-profile'"; quy tắc đặt tên <target dev>: "the name should not start with either 'vnet', 'vif', 'macvtap', or 'macvlan', which are prefixes reserved by libvirt"; phần tử <vlan> áp dụng cho "type='bridge' interfaces connected to an Open vSwitch bridge" "Since 0.10.0"Domain XML format, libvirt.org.
  • Định nghĩa libvirt network object trỏ vào OVS bridge có sẵn: "an existing Open vSwitch bridge that was configured outside of libvirt (if both a <bridge name='xyz'/> element and a <virtualport type='openvswitch'/> have been specified Since 0.10.0)", ví dụ XML ovs-net với <forward mode='bridge'/>/<bridge name='ovsbr0'/>/<virtualport type='openvswitch'>Network XML format, libvirt.org.
  • Cảnh báo chính thức về việc dùng nhầm interface type tap cho port của VM: "users should not configure KVM 'tap' devices as type 'tap' (use type 'system', the default, instead)", và "no IP address is configured on the 'tap' device" khi dùng đúng cách — Common Configuration Issues FAQ, docs.openvswitch.org.
  • Ví dụ access port VLAN cho VM bằng tag= (ovs-vsctl add-port br0 tap0 tag=100) và ghi chú "VM interfaces may appear as Linux devices with names like vnet0, vnet1, etc."Isolating VM Traffic Using VLANs, docs.openvswitch.org.
  • Cột external_ids : iface-id, attached-mac, iface-status, vm-id trong bảng Interface, nhóm "Virtual Machine Identifiers", và định nghĩa gốc tap: "A TUN/TAP device managed by Open vSwitch" — cùng nguồn ovs-vswitchd.conf.db(5) đã dùng ở Bài 5, ovs-vswitchd.conf.db(5), openvswitch.org.
  • libvirt tự set external_ids:attached-mac, external_ids:iface-id, external_ids:vm-id (Domain UUID) và external_ids:iface-status=active khi gọi ovs-vsctl add-port lúc VM khởi động — xác nhận qua thảo luận phát triển chính thức của dự án libvirt, libvir-list mailing list, redhat.com.

Tiếp theo: Module 2, Bài 8 — VLAN trunking & isolation trên OVS.