Klemens Nanni <k...@openbsd.org> writes:

> kern.version=OpenBSD 7.4-current (GENERIC.MP) #1667: Wed Feb  7 20:09:35 MST 
> 2024
>     dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
>
> 'locked addr' in `switch' block yields
>       vm/foo/vionet0: vionet_rx_copy: invalid injected packet object
>
> Minimal reproducer from my vm.conf(5) that used to work fine:
>
>       # ifconfig vport0 inet6 fd00::1 up
>       # ifconfig veb0 add vport0
>       # cat /tmp/vm.conf
>       switch uplink {
>               interface veb0
>               locked lladdr
>       }
>       vm foo {
>               disable
>               boot /bsd.rd
>               disk /tmp/disk.img
>               interface {
>                       switch uplink
>                       locked lladdr
>               }
>       }
>       # vmctl create -s1m /tmp/foo.img
>       # `which vmd` -f/tmp/vm.conf -dvv
>
> vmd: startup
> vmd: /tmp/vm.conf:4: switch "uplink" registered
> vmd: vm_register: registering vm 1
> vmd: /tmp/vm.conf:13: vm "foo" registered (disabled)
> vmd: vm_priv_brconfig: interface veb0 description switch1-uplink
> vmd: vmd_configure: setting staggered start configuration to parallelism: 12 
> and delay: 30
> vmd: vmd_configure: starting vms in staggered fashion
> vmd: start_vm_batch: starting batch of 12 vms
> vmd: start_vm_batch: not starting vm foo (disabled)
> vmd: start_vm_batch: done starting vms
> priv: config_getconfig: priv retrieving config
> vmm: config_getconfig: vmm retrieving config
> agentx: config_getconfig: agentx retrieving config
> control: config_getconfig: control retrieving config
>
>       # vmctl start -c foo
>
> vmd: vm_opentty: vm foo tty /dev/ttyp7 uid 0 gid 4 mode 620
> vmm: vm_register: registering vm 1
> vmd: vm_priv_ifconfig: interface tap0 description vm1-if0-foo
> vmd: vm_priv_ifconfig: switch "uplink" interface veb0 add tap0
> vmd: started foo (vm 1) successfully, tty /dev/ttyp7
> vm/foo: loadfile_elf: loaded ELF kernel
> vm/foo: pic_set_elcr: setting level triggered mode for irq 3
> vm/foo: pic_set_elcr: setting level triggered mode for irq 5
> vm/foo: virtio_init: vm "foo" vio0 lladdr fe:e1:bb:d1:5a:58, locked
> vm/foo: pic_set_elcr: setting level triggered mode for irq 6
> vm/foo: foo: launching vioblk0
> vm/foo: virtio_dev_launch: sending 'd' type device struct
> vm/foo: virtio_dev_launch: sending vm message for 'foo'
> vm/foo/vioblk: vioblk_main: got viblk dev. num disk fds = 1, sync fd = 16, 
> async fd = 18, capacity = 0 seg_max = 126, vmm fd = 5
> vm/foo/vioblk0: vioblk_main: initialized vioblk0 with raw image 
> (capacity=2048)
> vm/foo/vioblk0: vioblk_main: wiring in async vm event handler (fd=18)
> vm/foo/vioblk0: vm_device_pipe: initializing 'd' device pipe (fd=18)
> vm/foo/vioblk0: vioblk_main: wiring in sync channel handler (fd=16)
> vm/foo/vioblk0: vioblk_main: telling vm foo device is ready
> vm/foo/vioblk0: vioblk_main: sending heartbeat
> vm/foo: virtio_dev_launch: receiving reply
> vm/foo: virtio_dev_launch: device reports ready via sync channel
> vm/foo: vm_device_pipe: initializing 'd' device pipe (fd=17)
> vm/foo: foo: launching vionet0
> vm/foo: virtio_dev_launch: sending 'n' type device struct
> vm/foo: virtio_dev_launch: sending vm message for 'foo'
> vm/foo/vionet: vionet_main: got vionet dev. tap fd = 8, syncfd = 16, asyncfd 
> = 19, vmm fd = 5
> vm/foo/vionet0: vionet_main: wiring in async vm event handler (fd=19)
> vm/foo/vionet0: vm_device_pipe: initializing 'n' device pipe (fd=19)
> vm/foo/vionet0: vionet_main: wiring in tap fd handler (fd=8)
> vm/foo/vionet0: vionet_main: wiring in packet injection handler (fd=3)
> vm/foo/vionet0: vionet_main: wiring in sync channel handler (fd=16)
> vm/foo/vionet0: vionet_main: telling vm foo device is ready
> vm/foo/vionet0: vionet_main: sending async ready message
> vm/foo: virtio_dev_launch: receiving reply
> vm/foo: virtio_dev_launch: device reports ready via sync channel
> vm/foo: vm_device_pipe: initializing 'n' device pipe (fd=18)
> vm/foo: pic_set_elcr: setting level triggered mode for irq 7
> vm/foo: run_vm: starting 1 vcpu thread(s) for vm foo
> vm/foo: vcpu_reset: resetting vcpu 0 for vm 29
> vm/foo: run_vm: waiting on events for VM foo
> vm/foo: foo: received tap addr fe:e1:ba:dd:0e:e5 for nic 0
> vm/foo: handle_dev_msg: device reports ready
> vm/foo: handle_dev_msg: device reports ready
> vm/foo/vionet0: dev_dispatch_vm: set hostmac
> vm/foo: vcpu_exit_i8253: channel 0 reset, mode=2, start=65535
> vm/foo: vcpu_process_com_lcr: set baudrate = 115200
> vm/foo: i8259_write_datareg: master pic, reset IRQ vector to 0x20
> vm/foo: i8259_write_datareg: slave pic, reset IRQ vector to 0x28
> vm/foo: vcpu_exit_i8253: channel 0 reset, mode=2, start=11932
> vm/foo: vcpu_process_com_lcr: set baudrate = 115200
> vm/foo: vcpu_exit_eptviolation: fault already handled
> vm/foo: vcpu_exit_eptviolation: fault already handled
> vm/foo: vcpu_process_com_lcr: set baudrate = 115200
> vm/foo: vcpu_exit_eptviolation: fault already handled
>
>       Welcome to the OpenBSD/amd64 7.4 installation program.
>       (I)nstall, (U)pgrade, (A)utoinstall or (S)hell? s
>       # ifconfig vio0 inet6 fd00::2
>       # ping6 -c1 fd00::1
>       PING fd00::1 (fd00::1): 56 data bytes
>
>       --- fd00::1 ping statistics ---
>       1 packets transmitted, 0 packets received, 100.0% packet loss
>
> vm/foo/vionet0: vionet_rx_copy: invalid injected packet object

Turns out I had a bug in my packet injection logic. Locked addr forces
use of the copy mode (i.e. not the zero-copy mode) and my logic was
thinking the packet being read was an "injected" packet from the dhcp
intercept. I don't think this is ipv6 specific.

> Removing 'locked addr' from either `switch' or `interface' is not enough,
> both lines must be removed for packets to flow again:
>
>       # ping6 -qc1 fd00::1
>       PING fd00::1 (fd00::1): 56 data bytes
>
>       --- fd00::1 ping statistics ---
>       1 packets transmitted, 1 packets received, 0.0% packet loss
>       round-trip min/avg/max/std-dev = 0.838/0.838/0.838/0.000 ms

Try this diff:

diff /usr/src
commit - e56f03c81d8d8caa46c3a9dd3ebf582fb69cd317
path + /usr/src
blob - 6f4b741bd1f960913774ee51c4ffd8dc98068d17
file + usr.sbin/vmd/vionet.c
--- usr.sbin/vmd/vionet.c
+++ usr.sbin/vmd/vionet.c
@@ -514,8 +514,9 @@ vionet_rx_copy(struct vionet_dev *dev, int fd, const s
                /* If reading the tap(4), we should get valid ethernet. */
                log_warnx("%s: invalid packet size", __func__);
                return (0);
-       } else if (sz != sizeof(struct packet)) {
-               log_warnx("%s: invalid injected packet object", __func__);
+       } else if (fd == pipe_inject[READ] && sz != sizeof(struct packet)) {
+               log_warnx("%s: invalid injected packet object (sz=%ld)",
+                   __func__, sz);
                return (0);
        }

Reply via email to