From: ryskn <[email protected]> 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 <[email protected]> --- 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)
