all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Ryosuke Nakayama <ryosuke.nakayama@ryskn.com>
To: pve-devel@lists.proxmox.com
Subject: [RFC PATCH widget-toolkit 2/2] ui: network: add VPP (fd.io) bridge type support
Date: Tue, 17 Mar 2026 07:28:16 +0900	[thread overview]
Message-ID: <20260316222816.42944-3-ryosuke.nakayama@ryskn.com> (raw)
In-Reply-To: <20260316222816.42944-1-ryosuke.nakayama@ryskn.com>

From: ryskn <ryosuke.nakayama@ryskn.com>

Add VPP bridge domain as a creatable/editable network type in the
Proxmox node network configuration UI.

- Utils.js: add VPPBridge/VPPVlan to network_iface_types with gettext()
- NetworkView.js: add 'vpp' to default types list; add VPPBridge and
  VPPVlan entries to the Create menu; VPPVlan uses a dedicated menu
  entry (no auto-generated default name); render vlan-raw-device in
  Ports/Slaves column for VPPVlan; fix VLAN aware column to render
  vpp_vlan_aware for VPP bridges; declare vpp_bridge/vpp_vlan_aware
  in the proxmox-networks model
- NetworkEdit.js: introduce vppTypes Set as single source of truth for
  VPP type checks; add vppbrN validator for VPPBridge name field; add
  vppbrN validator for vpp_bridge field in VPPVlan; increase maxLength
  to 40 for VPP interface names; hide MTU field for VPP types; exclude
  Autostart and IP/GW fields for VPP types via vppTypes; use VlanName
  vtype for VPPVlan to allow dot notation (e.g. tap0.100)

Signed-off-by: ryskn <ryosuke.nakayama@ryskn.com>
---
 src/Utils.js            |  2 ++
 src/node/NetworkEdit.js | 64 ++++++++++++++++++++++++++++++++++-------
 src/node/NetworkView.js | 35 ++++++++++++++++++----
 3 files changed, 85 insertions(+), 16 deletions(-)

diff --git a/src/Utils.js b/src/Utils.js
index 5457ffa..fa88fb1 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -707,6 +707,8 @@ Ext.define('Proxmox.Utils', {
             OVSBond: 'OVS Bond',
             OVSPort: 'OVS Port',
             OVSIntPort: 'OVS IntPort',
+            VPPBridge: gettext('VPP Bridge'),
+            VPPVlan: gettext('VPP VLAN'),
         },
 
         render_network_iface_type: function (value) {
diff --git a/src/node/NetworkEdit.js b/src/node/NetworkEdit.js
index c945139..c53cd90 100644
--- a/src/node/NetworkEdit.js
+++ b/src/node/NetworkEdit.js
@@ -21,7 +21,12 @@ Ext.define('Proxmox.node.NetworkEdit', {
 
         me.isCreate = !me.iface;
 
+        // Canonical set of VPP interface types — used to gate autostart,
+        // IP config, MTU, and other kernel-only fields.
+        const vppTypes = new Set(['VPPBridge', 'VPPVlan']);
+
         let iface_vtype;
+        let iface_validator; // optional extra validator for the Name field
 
         if (me.iftype === 'bridge') {
             iface_vtype = 'BridgeName';
@@ -39,6 +44,12 @@ Ext.define('Proxmox.node.NetworkEdit', {
             iface_vtype = 'InterfaceName';
         } else if (me.iftype === 'OVSPort') {
             iface_vtype = 'InterfaceName';
+        } else if (me.iftype === 'VPPBridge') {
+            iface_vtype = 'InterfaceName';
+            iface_validator = (v) =>
+                /^vppbr\d+$/.test(v) || gettext('Name must match vppbrN format (e.g. vppbr1)');
+        } else if (me.iftype === 'VPPVlan') {
+            iface_vtype = 'VlanName';
         } else {
             console.log(me.iftype);
             throw 'unknown network device type specified';
@@ -52,7 +63,7 @@ Ext.define('Proxmox.node.NetworkEdit', {
             advancedColumn1 = [],
             advancedColumn2 = [];
 
-        if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' || me.iftype === 'OVSBond')) {
+        if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' || me.iftype === 'OVSBond' || vppTypes.has(me.iftype))) {
             column2.push({
                 xtype: 'proxmoxcheckbox',
                 fieldLabel: gettext('Autostart'),
@@ -295,6 +306,32 @@ Ext.define('Proxmox.node.NetworkEdit', {
                 fieldLabel: gettext('OVS options'),
                 name: 'ovs_options',
             });
+        } else if (me.iftype === 'VPPBridge') {
+            column2.push({
+                xtype: 'proxmoxcheckbox',
+                fieldLabel: gettext('VLAN aware'),
+                name: 'vpp_vlan_aware',
+                deleteEmpty: !me.isCreate,
+            });
+        } else if (me.iftype === 'VPPVlan') {
+            column2.push({
+                xtype: 'displayfield',
+                userCls: 'pmx-hint',
+                value: gettext('Name format: <parent>.<vlan-id>, e.g. tap0.100'),
+            });
+            column2.push({
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                fieldLabel: gettext('Bridge domain'),
+                name: 'vpp_bridge',
+                emptyText: gettext('none'),
+                allowBlank: true,
+                validator: (v) =>
+                    !v || /^vppbr\d+$/.test(v) || gettext('Must match vppbrN format (e.g. vppbr1)'),
+                autoEl: {
+                    tag: 'div',
+                    'data-qtip': gettext('VPP bridge domain to attach this VLAN interface to, e.g. vppbr1'),
+                },
+            });
         }
 
         column2.push({
@@ -328,8 +365,9 @@ Ext.define('Proxmox.node.NetworkEdit', {
                 name: 'iface',
                 value: me.iface,
                 vtype: iface_vtype,
+                validator: iface_validator,
                 allowBlank: false,
-                maxLength: iface_vtype === 'BridgeName' ? 10 : 15,
+                maxLength: iface_vtype === 'BridgeName' ? 10 : (vppTypes.has(me.iftype) ? 40 : 15),
                 autoEl: {
                     tag: 'div',
                     'data-qtip': gettext('For example, vmbr0.100, vmbr0, vlan0.100, vlan0'),
@@ -391,6 +429,8 @@ Ext.define('Proxmox.node.NetworkEdit', {
                     name: 'ovs_bonds',
                 },
             );
+        } else if (vppTypes.has(me.iftype)) {
+            // VPP interfaces do not use kernel IP configuration
         } else {
             column1.push(
                 {
@@ -423,15 +463,17 @@ Ext.define('Proxmox.node.NetworkEdit', {
                 },
             );
         }
-        advancedColumn1.push({
-            xtype: 'proxmoxintegerfield',
-            minValue: 1280,
-            maxValue: 65520,
-            deleteEmpty: !me.isCreate,
-            emptyText: 1500,
-            fieldLabel: 'MTU',
-            name: 'mtu',
-        });
+        if (!vppTypes.has(me.iftype)) {
+            advancedColumn1.push({
+                xtype: 'proxmoxintegerfield',
+                minValue: 1280,
+                maxValue: 65520,
+                deleteEmpty: !me.isCreate,
+                emptyText: 1500,
+                fieldLabel: 'MTU',
+                name: 'mtu',
+            });
+        }
 
         Ext.applyIf(me, {
             url: url,
diff --git a/src/node/NetworkView.js b/src/node/NetworkView.js
index 0ff9649..164b349 100644
--- a/src/node/NetworkView.js
+++ b/src/node/NetworkView.js
@@ -19,6 +19,8 @@ Ext.define('proxmox-networks', {
         'type',
         'vlan-id',
         'vlan-raw-device',
+        'vpp_bridge',
+        'vpp_vlan_aware',
     ],
     idProperty: 'iface',
 });
@@ -30,7 +32,7 @@ Ext.define('Proxmox.node.NetworkView', {
 
     // defines what types of network devices we want to create
     // order is always the same
-    types: ['bridge', 'bond', 'vlan', 'ovs'],
+    types: ['bridge', 'bond', 'vlan', 'ovs', 'vpp'],
 
     showApplyBtn: false,
 
@@ -223,6 +225,27 @@ Ext.define('Proxmox.node.NetworkView', {
             });
         }
 
+        if (me.types.indexOf('vpp') !== -1) {
+            if (menu_items.length > 0) {
+                menu_items.push({ xtype: 'menuseparator' });
+            }
+
+            addEditWindowToMenu('VPPBridge', 'vppbr');
+            menu_items.push({
+                text: Proxmox.Utils.render_network_iface_type('VPPVlan'),
+                handler: () =>
+                    Ext.create('Proxmox.node.NetworkEdit', {
+                        autoShow: true,
+                        nodename: me.nodename,
+                        iftype: 'VPPVlan',
+                        ...me.editOptions,
+                        listeners: {
+                            destroy: () => reload(),
+                        },
+                    }),
+            });
+        }
+
         let renderer_generator = function (fieldname) {
             return function (val, metaData, rec) {
                 let tmp = [];
@@ -326,14 +349,14 @@ Ext.define('Proxmox.node.NetworkView', {
                             undefinedText: Proxmox.Utils.noText,
                         },
                         {
-                            xtype: 'booleancolumn',
                             header: gettext('VLAN aware'),
                             width: 80,
                             sortable: true,
                             dataIndex: 'bridge_vlan_aware',
-                            trueText: Proxmox.Utils.yesText,
-                            falseText: Proxmox.Utils.noText,
-                            undefinedText: Proxmox.Utils.noText,
+                            renderer: (value, metaData, { data }) => {
+                                const v = data.bridge_vlan_aware || data.vpp_vlan_aware;
+                                return v ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
+                            },
                         },
                         {
                             header: gettext('Ports/Slaves'),
@@ -347,6 +370,8 @@ Ext.define('Proxmox.node.NetworkView', {
                                     return data.ovs_ports;
                                 } else if (value === 'OVSBond') {
                                     return data.ovs_bonds;
+                                } else if (value === 'VPPVlan') {
+                                    return data['vlan-raw-device'];
                                 }
                                 return '';
                             },
-- 
2.50.1 (Apple Git-155)




  parent reply	other threads:[~2026-03-16 22:28 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-16 22:28 [RFC PATCH 0/2] network: add VPP (fd.io) as alternative dataplane Ryosuke Nakayama
2026-03-16 22:28 ` [RFC PATCH manager 1/2] api: network: add VPP (fd.io) dataplane bridge support Ryosuke Nakayama
2026-03-16 22:28 ` Ryosuke Nakayama [this message]
2026-03-17  6:39 ` [RFC PATCH 0/2] network: add VPP (fd.io) as alternative dataplane Stefan Hanreich
2026-03-17 10:18 ` DERUMIER, Alexandre
2026-03-17 11:14   ` Ryosuke Nakayama
2026-03-17 11:14     ` [RFC PATCH qemu-server 1/2] qemu: add VPP vhost-user dataplane support Ryosuke Nakayama
2026-03-17 11:14     ` [RFC PATCH qemu-server 2/2] qemu: VPP: clean up vhost-user interfaces on stop, fix tx_queue_size Ryosuke Nakayama
2026-03-17 11:26     ` [RFC PATCH qemu-server 1/2] qemu: add VPP vhost-user dataplane support Ryosuke Nakayama
2026-03-17 11:21 ` [RFC PATCH 0/2] network: add VPP (fd.io) as alternative dataplane Ryosuke Nakayama
2026-03-17 11:21   ` [RFC PATCH pve-common] network: add VPP bridge helpers for vhost-user dataplane Ryosuke Nakayama

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=20260316222816.42944-3-ryosuke.nakayama@ryskn.com \
    --to=ryosuke.nakayama@ryskn.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