all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Hannes Laimer <h.laimer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: superseded: [RFC cluster/docs/ifupdown2/manager/network/proxmox{-ebpf,-ve-rs,-perl-rs} 00/16] sdn: add microsegmentation support
Date: Thu, 9 Jul 2026 11:20:38 +0200	[thread overview]
Message-ID: <9da00602-7f6a-43d6-a817-c57a1c6cc0eb@proxmox.com> (raw)
In-Reply-To: <20260609132522.235917-1-h.laimer@proxmox.com>

superseded-by:
https://lore.proxmox.com/pve-devel/20260709091852.538885-1-h.laimer@proxmox.com/T/#m0cbbbfddbde18a12ffa26a5ae2ac0a1450ea0749

On 2026-06-09 15:25, Hannes Laimer wrote:
> This adds support for microsegmentation using eBPF programs attached to
> interfaces. Mostly the tap/veth interfaces on the guests directly.
> 
> # Overview
> Each guest interface can be assigned a group, then, on these groups it is
> possible to define policies/rules between these groups. A policy is a mapping
>  `(src,dst) -> allow`
> Each interface can be assigned to only a *single* group. Groups however can be
> part of groups, that should cover most use cases I came up with. In case multiple
> policies would match (possibly because groups/sub-groups could have policies that overlap)
> the most specific policy wins: the one that names the destination group closest in
> the tree, and if two name it equally closely, the one that names the source closest, so:
> 
>  - web      (db,web)->allow
>    - wiki                    # from `web`: (db,web)->allow
>      * CT100,net0
>    - wol    (db,wol)->deny   # closer than the (db,web)->allow inherited from web, so deny wins
>      * CT101,net0            # => packets from db to CT101,net0 are denied
> 
>  - db       (web,db)->allow
>    * CT200,net1              # packets from `web` reaching CT200,net1 will be allowed
> 
> Because each group has a single parent, the destination-then-source ordering always
> picks exactly one rule, so there is no tie to resolve (a malformed config with
> duplicate rules falls back to deny).
> 
> If an interface has a group assigned, it needs an explicit (0,dst) rule to
> accept un-tagged packets.
> 
> Enforcement happens on the receiving side, cause that's where we for sure know both
>  - where the packet is from
>  - and, its destination (us)
> 
> # config and API
> The config is a single section-config, `sdn/microseg.cfg`, owned by Rust (the types
> live in `proxmox-ve-config`, with a `PVE::RS::SDN::Microseg` binding) the same way the
> fabric config is. It holds four object types, keyed by section id:
>  - group, a numeric `mark` (auto-assigned if omitted) and an optional `parent`
>  - rule, `(src,dst) -> allow`, an absent `src` matches un-tagged traffic
>  - assignment, binds a guest NIC (`vmid` plus `iface` index) to a group
>  - bridge, marks a bridge-facing interface as an SRv6 carrier (no UI yet)
> The API exposes per-type endpoints under
> `/cluster/sdn/microseg/{group,rule,assignment,bridge}`, guarded by SDN.Audit for reads
> and SDN.Allocate for writes. Rule and assignment ids are derived from their contents
> (`p{src_mark}-{dst_mark}`, `vm{vmid}i{iface}`), groups and bridges take a chosen id. On
> commit the config is rendered into `.running-config`, which is what the agent reads.
> 
> # skb->mark
> Every packet in the kernel lives in a `sk_buff` struct, this struct has a
> 32-bit field `mark`. This field can be written to and read while the packet
> passes through the kernel. We don't do that currently in our SDN stack, so
> currently we can't really overwrite stuff written by a different part of our
> stack. But this is something to keep in mind in case we should end up using
> this again in the future. For now microsegmentation only uses the lower 16 bits.
> We use this to assign packets to groups, with these 16 bits we support up to
> 65535 distinct groups (mark 0 is reserved for unstamped traffic). This `mark`
> however only lives as long as the packet does not leave the kernel, and given
> the nature of networking, chances are it'll leave it eventually. To transport
> this group identity between hosts we have to attach it to the actual network
> packet that hits the wire. For this we currently support both
>  - VXLAN-GBP, the 16-bit GBP field on the VXLAN encapsulation
>  - and, SRv6, the 16-bit Tag field on the SRH
> conveniently the kernel already handles putting the `mark` into the VXLAN-GBP
> encapsulation, and also taking it out of there (found out way too late :P). For
> SRv6 we need a small eBPF program that handles this.
> 
> # eBPF
> Both tagging (setting `mark`) and enforcement happen in an eBPF program
> directly attached to the guest's interface. The programs themselves read and
> write to/from two maps:
>  - tap_to_group, so we know what to set `mark` to
>  - rules, map of (src,dst)->action, we know src from the `mark` and `dst` is
>    the group we are in
> 
> Specifically, on ingress we set the mark, and on egress we enforce.
> 
> # Implementation
> 
> We have an `agent` that reads the running sdn config, and applies that state to
> the kernel. The binary doing this is stateless, it runs on SDN apply, tap_plug
> of interfaces of guests and on boot after pve-sdn-commit but before guests
> start. It keeps track of what is currently running loaded in the kernel with
> two files under `/run/proxmox-ebpf`. One keeping track of the bpf program that
> was compiled into the binary, and one for keeping track of changes to the
> data structures the bpf program accesses. The distinction is useful cause for
> only a program change we can swap the currently attached program with the
> updated one atomically. In case the data structure (the maps) changed there is
> no other way than to tear-down all the current state and repopulate the maps
> and re-attach the programs. Swapping out the maps first would have old programs
> interact with a new data schema, and swapping the programs first will lead
> to new programs accessing an old data schema. Either way, not good, so we wipe
> the state in that case and re-build it. So, in case we change the structure of
> the data our bpf programs access, there will be a bunch of ms where the
> configured segmentation is not enforced. But that is the only scenario where
> that can happen.
> 
> ## aya, aya-ebpf
> Aya is a rust lib that helps with working with BPF more easily. It has both a
> userspace part(`aya`) and a part(`aya-ebpf`) that compiles to bpf. I chose to
> only use the userspace part, and use C for the BPF programs themselves. The reasons were:
>  - we don't have `aya-ebpf` packaged
>  - `aya-ebpf` *requires* nightly toolchain to compile
>  - the bpf programs are very small, in case this should change at some point we
>    can reconsider. Also, it doesn't matter what produces the .o file, so this
>    could be swapped in really easily if we decided to
> 
> So we compile the bpf program written in C to a .o targeting bpf using clang
> and include it when compiling the agent binary.
> 
> ## agent
> The agent is not a long running daemon, the triggers mentioned before should cover
> all situations where we'd have to touch the kernel state. When started, the
> first thing it does is check both the program and schema version, so what it
> was compiled with, and what the last invocation did to the kernel. If either
> the program or the schema differs it either swaps out the program currently
> loaded by the kernel and pins it. If the schema version differs it does that as
> well, but additionally also tears down all state and rebuilds it.
> 
> The agent also populates the `rules` map, so it creates all the inherited rules
> and resolves multiple matches to the closest one as described before.
> 
> ## SRv6
> This also adds support for SRv6 as a transport, we don't support that yet in
> our SDN stack, but could be useful for basic routing between simple zones on
> multiple nodes. A bit like EVPN-lite since it's only L3. I did most of my
> testing with SRv6 as transport between kernels, before I found out the kernel
> does it for VXLAN automatically. I didn't wire up any UI for it yet, but I
> decided to include it in this RFC for now.
> 
> # enabling VXLAN-GBP
> The kernel only moves the mark into the GBP field if the vxlan device was
> created with the GBP flag set, and it's create-only: the kernel won't
> toggle it on a running device. ifupdown2 had no attribute for this, so
> this series includes a small ifupdown2 patch adding `vxlan-gbp`, which
> threads the flag through to the netlink/iproute2 create path.
> 
> # testing
> I have put pre-built packages on sani, these include ifupdown2 with the patch
> 
> # building
> 1. proxmox-ve-rs (install)
> 2. proxmox-ebpf
> 3. pve-cluster (install)
> 4. proxmox-perl-rs (install)
> 5. pve-network
> 6. pve-manager
> 
> # notes
> I did not send the first commit for `proxmox-ebpf` since it contains a
> `vmlinux.h` which is rather large but is needed for compiling. The commit is in
> my staff repo.
> 
> # feedback wanted
>  - the general desgin, specifically with the agent being one-shot and triggered
>    rather than a running service
>  - I put the VXLAN-GBP flag into the zones that run on vxlan for now, so it has
>    to be enabled on the zone, and will affect all vxlan interfaces that are
>    part of it. The only real alternative is enabling it always, or trying to
>    infer if a nic is assigned a vnet that is in a zone that does vxlan and
>    corss-referencing that with potentially configured microseg
>    groups/assignments. This seemed brittle, and since the needed flag is
>    additionally create-only, a simple flag on the zone appeard to be the better
>    approach
>  - and the ui, very likely needs some polishing, and im very open to
>    alternative approaches
> 
> 
> proxmox-ebpf:
> 
> Hannes Laimer (3):
>   agent: add userspace coordinator and stateless policy subsystem
>   bpf: add bridge subsystem
>   debian: add packaging and boot-time oneshot unit
> 
>  Makefile                    |  66 +++++++
>  debian/changelog            |   5 +
>  debian/control              |  34 ++++
>  debian/copyright            |  18 ++
>  debian/proxmox-ebpf.install |   1 +
>  debian/proxmox-ebpf.postrm  |  11 ++
>  debian/proxmox-ebpf.prerm   |  12 ++
>  debian/proxmox-ebpf.service |  15 ++
>  debian/rules                |  33 ++++
>  debian/source/format        |   1 +
>  include/mark.h              |  30 +++
>  src/agent.rs                | 105 ++++++++++
>  src/bridge/bpf/srv6.bpf.c   |  76 +++++++
>  src/bridge/mod.rs           |  75 +++++++
>  src/main.rs                 |  69 +++++++
>  src/policy/bpf/tap.bpf.c    |  66 +++++++
>  src/policy/bpf/types.h      |  23 +++
>  src/policy/mod.rs           | 268 +++++++++++++++++++++++++
>  src/policy/types.rs         |  45 +++++
>  src/running_config.rs       |  38 ++++
>  src/state.rs                | 303 ++++++++++++++++++++++++++++
>  src/subsystem.rs            | 384 ++++++++++++++++++++++++++++++++++++
>  src/tc.rs                   | 152 ++++++++++++++
>  23 files changed, 1830 insertions(+)
>  create mode 100644 Makefile
>  create mode 100644 debian/changelog
>  create mode 100644 debian/control
>  create mode 100644 debian/copyright
>  create mode 100644 debian/proxmox-ebpf.install
>  create mode 100755 debian/proxmox-ebpf.postrm
>  create mode 100755 debian/proxmox-ebpf.prerm
>  create mode 100644 debian/proxmox-ebpf.service
>  create mode 100755 debian/rules
>  create mode 100644 debian/source/format
>  create mode 100644 include/mark.h
>  create mode 100644 src/agent.rs
>  create mode 100644 src/bridge/bpf/srv6.bpf.c
>  create mode 100644 src/bridge/mod.rs
>  create mode 100644 src/main.rs
>  create mode 100644 src/policy/bpf/tap.bpf.c
>  create mode 100644 src/policy/bpf/types.h
>  create mode 100644 src/policy/mod.rs
>  create mode 100644 src/policy/types.rs
>  create mode 100644 src/running_config.rs
>  create mode 100644 src/state.rs
>  create mode 100644 src/subsystem.rs
>  create mode 100644 src/tc.rs
> 
> 
> proxmox-ve-rs:
> 
> Hannes Laimer (1):
>   ve-config: sdn: add microseg config types
> 
>  proxmox-ve-config/src/sdn/config.rs   |   9 +-
>  proxmox-ve-config/src/sdn/microseg.rs | 847 ++++++++++++++++++++++++++
>  proxmox-ve-config/src/sdn/mod.rs      |   1 +
>  3 files changed, 856 insertions(+), 1 deletion(-)
>  create mode 100644 proxmox-ve-config/src/sdn/microseg.rs
> 
> 
> proxmox-perl-rs:
> 
> Hannes Laimer (1):
>   sdn: add microseg config binding
> 
>  pve-rs/Makefile                     |   1 +
>  pve-rs/src/bindings/sdn/microseg.rs | 172 ++++++++++++++++++++++++++++
>  pve-rs/src/bindings/sdn/mod.rs      |   1 +
>  3 files changed, 174 insertions(+)
>  create mode 100644 pve-rs/src/bindings/sdn/microseg.rs
> 
> 
> pve-cluster:
> 
> Hannes Laimer (1):
>   cfs: add 'sdn/microseg.cfg' to observed files
> 
>  src/PVE/Cluster.pm | 1 +
>  1 file changed, 1 insertion(+)
> 
> 
> pve-network:
> 
> Hannes Laimer (4):
>   sdn: microseg: add config and API
>   sdn: zones: trigger microseg apply on tap_plug
>   sdn: zones: add vxlan-gbp option to vxlan and evpn zones
>   evpn: disable vxlan-learning on create if GBP is enabled
> 
>  src/PVE/API2/Network/SDN.pm                   |  12 +
>  src/PVE/API2/Network/SDN/Makefile             |   2 +
>  src/PVE/API2/Network/SDN/Microseg.pm          | 126 +++++++
>  .../API2/Network/SDN/Microseg/Assignment.pm   | 163 +++++++++
>  src/PVE/API2/Network/SDN/Microseg/Bridge.pm   | 171 ++++++++++
>  src/PVE/API2/Network/SDN/Microseg/Group.pm    | 171 ++++++++++
>  src/PVE/API2/Network/SDN/Microseg/Makefile    |   8 +
>  src/PVE/API2/Network/SDN/Microseg/Rule.pm     | 163 +++++++++
>  src/PVE/Network/SDN.pm                        |   5 +
>  src/PVE/Network/SDN/Makefile                  |   1 +
>  src/PVE/Network/SDN/Microseg.pm               | 316 ++++++++++++++++++
>  src/PVE/Network/SDN/Zones.pm                  |   6 +
>  src/PVE/Network/SDN/Zones/EvpnPlugin.pm       |  11 +
>  src/PVE/Network/SDN/Zones/VxlanPlugin.pm      |   9 +
>  14 files changed, 1164 insertions(+)
>  create mode 100644 src/PVE/API2/Network/SDN/Microseg.pm
>  create mode 100644 src/PVE/API2/Network/SDN/Microseg/Assignment.pm
>  create mode 100644 src/PVE/API2/Network/SDN/Microseg/Bridge.pm
>  create mode 100644 src/PVE/API2/Network/SDN/Microseg/Group.pm
>  create mode 100644 src/PVE/API2/Network/SDN/Microseg/Makefile
>  create mode 100644 src/PVE/API2/Network/SDN/Microseg/Rule.pm
>  create mode 100644 src/PVE/Network/SDN/Microseg.pm
> 
> 
> pve-manager:
> 
> Hannes Laimer (3):
>   ui: sdn: add microsegmentation
>   network: apply microseg state on reload
>   ui: sdn: zones: add vxlan-gbp checkbox to vxlan and evpn
> 
>  PVE/API2/Network.pm                           |   4 +
>  www/manager6/Makefile                         |   9 +
>  www/manager6/Utils.js                         |  23 +
>  www/manager6/dc/Config.js                     |   8 +
>  www/manager6/form/MicrosegGroupSelector.js    |  64 +++
>  www/manager6/form/MicrosegGuestNicSelector.js | 107 +++++
>  www/manager6/form/MicrosegGuestSelector.js    |  83 ++++
>  www/manager6/sdn/MicrosegView.js              | 408 ++++++++++++++++++
>  www/manager6/sdn/microseg/AssignmentEdit.js   |  63 +++
>  www/manager6/sdn/microseg/Base.js             |  88 ++++
>  www/manager6/sdn/microseg/GroupEdit.js        |  61 +++
>  www/manager6/sdn/microseg/PolicyView.js       | 221 ++++++++++
>  www/manager6/sdn/microseg/RuleEdit.js         |  49 +++
>  www/manager6/sdn/zones/EvpnEdit.js            |   8 +
>  www/manager6/sdn/zones/VxlanEdit.js           |  11 +
>  15 files changed, 1207 insertions(+)
>  create mode 100644 www/manager6/form/MicrosegGroupSelector.js
>  create mode 100644 www/manager6/form/MicrosegGuestNicSelector.js
>  create mode 100644 www/manager6/form/MicrosegGuestSelector.js
>  create mode 100644 www/manager6/sdn/MicrosegView.js
>  create mode 100644 www/manager6/sdn/microseg/AssignmentEdit.js
>  create mode 100644 www/manager6/sdn/microseg/Base.js
>  create mode 100644 www/manager6/sdn/microseg/GroupEdit.js
>  create mode 100644 www/manager6/sdn/microseg/PolicyView.js
>  create mode 100644 www/manager6/sdn/microseg/RuleEdit.js
> 
> 
> pve-docs:
> 
> Hannes Laimer (2):
>   sdn: add microsegmentation section
>   sdn: add VXLAN-GBP flag to evpn/vxlan zone sections
> 
>  pvesdn.adoc | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
> 
> 
> ifupdown2:
> 
> Hannes Laimer (1):
>   d/patches: add support for VXLAN-GBP flag
> 
>  ...addons-vxlan-add-vxlan-gbp-attribute.patch | 228 ++++++++++++++++++
>  debian/patches/series                         |   1 +
>  2 files changed, 229 insertions(+)
>  create mode 100644 debian/patches/pve/0016-addons-vxlan-add-vxlan-gbp-attribute.patch
> 
> 
> Summary over all repositories:
>   62 files changed, 5548 insertions(+), 1 deletions(-)
> 





      parent reply	other threads:[~2026-07-09  9:24 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-09 13:25 [RFC cluster/docs/ifupdown2/manager/network/proxmox{-ebpf,-ve-rs,-perl-rs} 00/16] sdn: add microsegmentation support Hannes Laimer
2026-06-09 13:25 ` [PATCH proxmox-ebpf 01/16] agent: add userspace coordinator and stateless policy subsystem Hannes Laimer
2026-06-09 13:25 ` [PATCH proxmox-ebpf 02/16] bpf: add bridge subsystem Hannes Laimer
2026-06-09 13:25 ` [PATCH proxmox-ebpf 03/16] debian: add packaging and boot-time oneshot unit Hannes Laimer
2026-06-09 13:25 ` [PATCH proxmox-ve-rs 04/16] ve-config: sdn: add microseg config types Hannes Laimer
2026-06-09 13:25 ` [PATCH proxmox-perl-rs 05/16] sdn: add microseg config binding Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-cluster 06/16] cfs: add 'sdn/microseg.cfg' to observed files Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-network 07/16] sdn: microseg: add config and API Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-network 08/16] sdn: zones: trigger microseg apply on tap_plug Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-network 09/16] sdn: zones: add vxlan-gbp option to vxlan and evpn zones Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-network 10/16] evpn: disable vxlan-learning on create if GBP is enabled Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-manager 11/16] ui: sdn: add microsegmentation Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-manager 12/16] network: apply microseg state on reload Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-manager 13/16] ui: sdn: zones: add vxlan-gbp checkbox to vxlan and evpn Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-docs 14/16] sdn: add microsegmentation section Hannes Laimer
2026-06-09 13:25 ` [PATCH pve-docs 15/16] sdn: add VXLAN-GBP flag to evpn/vxlan zone sections Hannes Laimer
2026-06-09 13:25 ` [PATCH ifupdown2 16/16] d/patches: add support for VXLAN-GBP flag Hannes Laimer
2026-06-18 13:10 ` [RFC cluster/docs/ifupdown2/manager/network/proxmox{-ebpf,-ve-rs,-perl-rs} 00/16] sdn: add microsegmentation support Lukas Sichert
2026-07-09  9:20 ` Hannes Laimer [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9da00602-7f6a-43d6-a817-c57a1c6cc0eb@proxmox.com \
    --to=h.laimer@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal