From adf17f7b5cdc628e73bf647130a84c8a2cab7018 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Wed, 27 May 2026 19:28:13 +0300 Subject: [PATCH 01/11] feat: add support new network plugin Signed-off-by: Dmitry Lopatin --- build/components/versions.yml | 2 +- images/virt-artifact/werf.inc.yaml | 12 ++++++++++++ images/virt-handler/werf.inc.yaml | 6 ++++++ .../pkg/controller/kvbuilder/kvvm.go | 10 +++++++++- templates/kubevirt/kubevirt.yaml | 5 +++++ 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/build/components/versions.yml b/build/components/versions.yml index 80a01cdc1d..512ffd8f97 100644 --- a/build/components/versions.yml +++ b/build/components/versions.yml @@ -3,7 +3,7 @@ firmware: libvirt: v10.9.0 edk2: stable202411 core: - 3p-kubevirt: v1.6.2-v12n.49 + 3p-kubevirt: feat/vm/disable-tap-veth-bridge 3p-containerized-data-importer: v1.60.3-v12n.20 distribution: 2.8.3 package: diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 0d75ebb629..3eff6cb5ad 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -13,8 +13,10 @@ secrets: - id: SOURCE_REPO value: {{ $.SOURCE_REPO }} shell: + installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | + echo "$date --------- new ---- 123456789 " echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt @@ -28,6 +30,8 @@ altPackages: - pkg-config - libtool - gcc-c++ +- clang +- libbpf-devel packages: - libmnl - ncurses @@ -113,6 +117,7 @@ shell: - export GOOS=linux - export GOARCH=amd64 - export CGO_ENABLED=0 + - export BPF_CLANG=clang - echo ============== Build container-disk =================== {{- $_ := set $ "ProjectName" (list .ImageName "container-disk" | join "/") }} @@ -201,6 +206,13 @@ shell: - | {{- include "image-build.build" (set $ "BuildCommand" `go build -ldflags="-s -w" -o /kubevirt-binaries/sidecars ./cmd/sidecars/`) | nindent 6 }} + - echo ============== Build bpf_bridge.o ===================== + {{- $_ := set $ "ProjectName" (list $.ImageName "bpf-bridge-obj" | join "/") }} + - mkdir -p /kubevirt-binaries/network-bpf-bridge-binding-assets + - | + {{- include "image-build.build" (set $ "BuildCommand" `clang -O2 -g -target bpf -I/usr/include -c ./pkg/network/bpfbridge/bpf/bpf_bridge.c -o /kubevirt-binaries/network-bpf-bridge-binding-assets/bpf_bridge.o`) | nindent 6 }} + - echo "Built bpf object:" && ls -l /kubevirt-binaries/network-bpf-bridge-binding-assets/ && file /kubevirt-binaries/network-bpf-bridge-binding-assets/bpf_bridge.o || true + - echo ============== Build virtctl ========================== {{- $_ := set $ "ProjectName" (list .ImageName "virtctl" | join "/") }} - | diff --git a/images/virt-handler/werf.inc.yaml b/images/virt-handler/werf.inc.yaml index 760e013749..be325737b8 100644 --- a/images/virt-handler/werf.inc.yaml +++ b/images/virt-handler/werf.inc.yaml @@ -31,6 +31,12 @@ import: after: install includePaths: - .version +- image: {{ .ModuleNamePrefix }}virt-artifact + add: /kubevirt-binaries/network-bpf-bridge-binding-assets/ + to: /usr/share/network-bpf-bridge-binding + after: install + includePaths: + - bpf_bridge.o - image: {{ .ModuleNamePrefix }}virt-artifact add: /kubevirt/cmd/{{ .ImageName }}/ to: /etc diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index c03765de14..0d94cdb388 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -94,6 +94,10 @@ func DefaultOptions(current *v1alpha2.VirtualMachine) KVVMOptions { } } +func (b *KVVM) Options() KVVMOptions { + return b.opts +} + func NewEmptyKVVM(name types.NamespacedName, opts KVVMOptions) *KVVM { return &KVVM{ opts: opts, @@ -811,7 +815,11 @@ func (b *KVVM) SetNetworkInterface(name, macAddress string, acpiIndex int) { Model: devPreset.InterfaceModel, ACPIIndex: acpiIndex, } - iface.Bridge = &virtv1.InterfaceBridge{} + if name == "default" { + iface.Binding = &virtv1.PluginBinding{Name: "bpfbridge"} + } else { + iface.Bridge = &virtv1.InterfaceBridge{} + } if macAddress != "" { iface.MacAddress = macAddress } diff --git a/templates/kubevirt/kubevirt.yaml b/templates/kubevirt/kubevirt.yaml index 01d4228c8c..1d774a9c47 100644 --- a/templates/kubevirt/kubevirt.yaml +++ b/templates/kubevirt/kubevirt.yaml @@ -39,6 +39,11 @@ spec: {{- end }} evictionStrategy: LiveMigrate vmRolloutStrategy: LiveUpdate + network: + binding: + bpfbridge: + domainAttachmentType: tap + migration: {} developerConfiguration: logVerbosity: virtLauncher: {{ $logVerbosity }} From cb2119b4102c0ea61421f9daaae81d685ae8b0dc Mon Sep 17 00:00:00 2001 From: MaxiHunter Date: Thu, 28 May 2026 17:10:12 +0300 Subject: [PATCH 02/11] Build commit Signed-off-by: Maksim Garmonov Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 3eff6cb5ad..773a81cb2b 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date --------- new ---- 123456789 " + echo "$date --------- new ----- 123456789987 " echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From f7775218225f0f59735f7a816e4cd6b1ecbd2127 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Sun, 7 Jun 2026 21:03:46 +0300 Subject: [PATCH 03/11] feat: add support new network plugin Signed-off-by: Dmitry Lopatin --- .../pkg/controller/kvbuilder/kvvm.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index 0d94cdb388..a33c670f52 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -814,12 +814,9 @@ func (b *KVVM) SetNetworkInterface(name, macAddress string, acpiIndex int) { Name: name, Model: devPreset.InterfaceModel, ACPIIndex: acpiIndex, + Binding: &virtv1.PluginBinding{Name: "bpfbridge"}, } - if name == "default" { - iface.Binding = &virtv1.PluginBinding{Name: "bpfbridge"} - } else { - iface.Bridge = &virtv1.InterfaceBridge{} - } + if macAddress != "" { iface.MacAddress = macAddress } From 7ceb7dfb72a7bc99dba01eda633c750a99bdf0bb Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Sun, 7 Jun 2026 21:47:56 +0300 Subject: [PATCH 04/11] wip Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 773a81cb2b..435de27d9b 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date --------- new ----- 123456789987 " + echo "$date --------- new ----- 1234567899876543210 " echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From d0c5a89b16260cdb56708d69074e767e71b55f96 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Tue, 23 Jun 2026 15:22:25 +0300 Subject: [PATCH 05/11] feat: add support new network plugin Signed-off-by: Dmitry Lopatin --- .../pkg/common/annotations/annotations.go | 2 ++ .../virtualization-artifact/pkg/controller/kvbuilder/kvvm.go | 4 ---- .../pkg/controller/vm/internal/sync_kvvm.go | 4 +++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/images/virtualization-artifact/pkg/common/annotations/annotations.go b/images/virtualization-artifact/pkg/common/annotations/annotations.go index b72fa48663..2d3ab4e336 100644 --- a/images/virtualization-artifact/pkg/common/annotations/annotations.go +++ b/images/virtualization-artifact/pkg/common/annotations/annotations.go @@ -209,6 +209,8 @@ const ( AnnNetworksSpec = "network.deckhouse.io/networks-spec" // AnnNetworksStatus is the annotation for view current network configuration into Pod. AnnNetworksStatus = "network.deckhouse.io/networks-status" + // AnnTapProvisionByDVPSupported is the annotation that indicates DVP supports TAP provision for the Pod. + AnnTapProvisionByDVPSupported = "network.deckhouse.io/tap-provision-by-dvp-supported" // AnnVirtualDiskOriginalAnnotations is the annotation for storing original VirtualDisk annotations. AnnVirtualDiskOriginalAnnotations = AnnAPIGroupV + "/vd-original-annotations" diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go index a33c670f52..9a6d31f2e7 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go @@ -94,10 +94,6 @@ func DefaultOptions(current *v1alpha2.VirtualMachine) KVVMOptions { } } -func (b *KVVM) Options() KVVMOptions { - return b.opts -} - func NewEmptyKVVM(name types.NamespacedName, opts KVVMOptions) *KVVM { return &KVVM{ opts: opts, diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go index a2de001ae5..8f6dab8916 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go @@ -1176,7 +1176,8 @@ func (h *SyncKvvmHandler) patchPodNetworkAnnotation(ctx context.Context, s state return nil, fmt.Errorf("failed to serialize network spec: %w", err) } - if pod.Annotations[annotations.AnnNetworksSpec] == networkConfigStr { + if pod.Annotations[annotations.AnnNetworksSpec] == networkConfigStr && + pod.Annotations[annotations.AnnTapProvisionByDVPSupported] == "" { return desired, nil } @@ -1185,6 +1186,7 @@ func (h *SyncKvvmHandler) patchPodNetworkAnnotation(ctx context.Context, s state pod.Annotations = make(map[string]string) } pod.Annotations[annotations.AnnNetworksSpec] = networkConfigStr + pod.Annotations[annotations.AnnTapProvisionByDVPSupported] = "" if err := h.client.Patch(ctx, pod, patch); err != nil { return nil, fmt.Errorf("failed to patch pod %s network annotation: %w", pod.Name, err) } From 640b9f0f88cc2760f4671fd6a7b90b372bb0f6d0 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Tue, 23 Jun 2026 20:15:19 +0300 Subject: [PATCH 06/11] wip Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 435de27d9b..dcb393b518 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date --------- new ----- 1234567899876543210 " + echo "$date" echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From 27f98fbb427cbe928796a774797812d2281bad7e Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Tue, 23 Jun 2026 22:34:38 +0300 Subject: [PATCH 07/11] wip Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index dcb393b518..a8d0f1de04 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date" + echo "$date rebuild 1" echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From 065b06fc3f004fab1f8e2e9ad9ef110fa44b83b2 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Wed, 24 Jun 2026 23:19:35 +0300 Subject: [PATCH 08/11] build Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index a8d0f1de04..de0186ade5 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date rebuild 1" + echo "$date rebuild 2" echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From dc079304375a0baa85e4a2b98ef0e48d9f9e4d13 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Thu, 25 Jun 2026 17:28:16 +0300 Subject: [PATCH 09/11] build Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index de0186ade5..8a15171d5f 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date rebuild 2" + echo "$date rebuild 3" echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From dac1b36b6f18ca7e5a4fcaeba21d0ec638fce145 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Thu, 25 Jun 2026 21:42:20 +0300 Subject: [PATCH 10/11] build Signed-off-by: Dmitry Lopatin --- images/virt-artifact/werf.inc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virt-artifact/werf.inc.yaml b/images/virt-artifact/werf.inc.yaml index 8a15171d5f..8e3caa1121 100644 --- a/images/virt-artifact/werf.inc.yaml +++ b/images/virt-artifact/werf.inc.yaml @@ -16,7 +16,7 @@ shell: installCacheVersion: "{{ now | date "Mon Jan 2 15:04:05 MST 2006" }}" install: - | - echo "$date rebuild 3" + echo "$date rebuild 4" echo "Git clone {{ $gitRepoName }} repository..." git clone --depth=1 $(cat /run/secrets/SOURCE_REPO)/{{ $gitRepoUrl }} --branch {{ $tag }} /src/kubevirt From b3ac7fd07b6d1f7c79efb9ffc9f02cdd95383af6 Mon Sep 17 00:00:00 2001 From: Dmitry Lopatin Date: Fri, 26 Jun 2026 06:20:48 +0300 Subject: [PATCH 11/11] fix Signed-off-by: Dmitry Lopatin --- .../pkg/controller/kvbuilder/kvvm_utils.go | 5 +++++ .../pkg/controller/vm/internal/sync_kvvm.go | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go index 7c29d677fe..e71d4c5809 100644 --- a/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go +++ b/images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_utils.go @@ -500,5 +500,10 @@ func setNetworksAnnotation(kvvm *KVVM, networkSpec network.InterfaceSpecList) er return err } kvvm.SetKVVMIAnnotation(annotations.AnnNetworksSpec, networkConfigStr) + // Signal that DVP provisions TAP devices natively (bpfbridge). Without this annotation + // SDN falls back to legacy tap+bridge wiring for additional interfaces, which conflicts + // with the bpfbridge binding and breaks L2 connectivity for VMs created with secondary + // networks from the start (as opposed to hotplugged later). + kvvm.SetKVVMIAnnotation(annotations.AnnTapProvisionByDVPSupported, "true") return nil } diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go index 8f6dab8916..21cb477af7 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/sync_kvvm.go @@ -1177,7 +1177,7 @@ func (h *SyncKvvmHandler) patchPodNetworkAnnotation(ctx context.Context, s state } if pod.Annotations[annotations.AnnNetworksSpec] == networkConfigStr && - pod.Annotations[annotations.AnnTapProvisionByDVPSupported] == "" { + pod.Annotations[annotations.AnnTapProvisionByDVPSupported] == "true" { return desired, nil } @@ -1186,7 +1186,7 @@ func (h *SyncKvvmHandler) patchPodNetworkAnnotation(ctx context.Context, s state pod.Annotations = make(map[string]string) } pod.Annotations[annotations.AnnNetworksSpec] = networkConfigStr - pod.Annotations[annotations.AnnTapProvisionByDVPSupported] = "" + pod.Annotations[annotations.AnnTapProvisionByDVPSupported] = "true" if err := h.client.Patch(ctx, pod, patch); err != nil { return nil, fmt.Errorf("failed to patch pod %s network annotation: %w", pod.Name, err) }