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)
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox