]>
Commit | Line | Data |
---|---|---|
5a691a50 | 1 | Ext.define('PVE.lxc.NetworkInputPanel', { |
ef4ef788 | 2 | extend: 'Proxmox.panel.InputPanel', |
5a691a50 DM |
3 | alias: 'widget.pveLxcNetworkInputPanel', |
4 | ||
5 | insideWizard: false, | |
6 | ||
c8802a60 | 7 | onlineHelp: 'pct_container_network', |
7f1ac74c | 8 | |
5a691a50 | 9 | setNodename: function(nodename) { |
c511ca9c | 10 | let me = this; |
99541dcc | 11 | |
53e3ea84 | 12 | if (!nodename || me.nodename === nodename) { |
5a691a50 DM |
13 | return; |
14 | } | |
5a691a50 DM |
15 | me.nodename = nodename; |
16 | ||
c511ca9c TL |
17 | let bridgeSelector = me.query("[isFormField][name=bridge]")[0]; |
18 | bridgeSelector.setNodename(nodename); | |
5a691a50 | 19 | }, |
99541dcc | 20 | |
5a691a50 | 21 | onGetValues: function(values) { |
c511ca9c | 22 | let me = this; |
5a691a50 | 23 | |
c511ca9c | 24 | let id; |
d5e771ce | 25 | if (me.isCreate) { |
5a691a50 DM |
26 | id = values.id; |
27 | delete values.id; | |
28 | } else { | |
29 | id = me.ifname; | |
30 | } | |
c511ca9c TL |
31 | let newdata = {}; |
32 | if (id) { | |
33 | if (values.ipv6mode !== 'static') { | |
34 | values.ip6 = values.ipv6mode; | |
35 | } | |
36 | if (values.ipv4mode !== 'static') { | |
37 | values.ip = values.ipv4mode; | |
38 | } | |
39 | newdata[id] = PVE.Parser.printLxcNetwork(values); | |
84de645d | 40 | } |
5a691a50 DM |
41 | return newdata; |
42 | }, | |
43 | ||
8058410f | 44 | initComponent: function() { |
c511ca9c | 45 | let me = this; |
5a691a50 | 46 | |
c511ca9c | 47 | let cdata = {}; |
5a691a50 DM |
48 | if (me.insideWizard) { |
49 | me.ifname = 'net0'; | |
50 | cdata.name = 'eth0'; | |
d8e3d77c | 51 | me.dataCache = {}; |
5a691a50 | 52 | } |
53e3ea84 | 53 | cdata.firewall = me.insideWizard || me.isCreate; |
d8e3d77c TL |
54 | |
55 | if (!me.dataCache) { | |
56 | throw "no dataCache specified"; | |
57 | } | |
58 | ||
d5e771ce | 59 | if (!me.isCreate) { |
5a691a50 DM |
60 | if (!me.ifname) { |
61 | throw "no interface name specified"; | |
62 | } | |
63 | if (!me.dataCache[me.ifname]) { | |
64 | throw "no such interface '" + me.ifname + "'"; | |
65 | } | |
5a691a50 DM |
66 | cdata = PVE.Parser.parseLxcNetwork(me.dataCache[me.ifname]); |
67 | } | |
68 | ||
c511ca9c TL |
69 | for (let i = 0; i < 32; i++) { |
70 | let ifname = 'net' + i.toString(); | |
71 | if (me.isCreate && !me.dataCache[ifname]) { | |
72 | me.ifname = ifname; | |
2517c76b DC |
73 | break; |
74 | } | |
5a691a50 | 75 | } |
5a691a50 | 76 | |
7c7ae44f | 77 | me.column1 = [ |
c511ca9c TL |
78 | { |
79 | xtype: 'hidden', | |
80 | name: 'id', | |
81 | value: me.ifname, | |
82 | }, | |
5a691a50 DM |
83 | { |
84 | xtype: 'textfield', | |
85 | name: 'name', | |
160673c1 TL |
86 | fieldLabel: gettext('Name'), |
87 | emptyText: '(e.g., eth0)', | |
5a691a50 DM |
88 | allowBlank: false, |
89 | value: cdata.name, | |
90 | validator: function(value) { | |
c511ca9c | 91 | for (const [key, netRaw] of Object.entries(me.dataCache)) { |
5a691a50 | 92 | if (!key.match(/^net\d+/) || key === me.ifname) { |
c511ca9c | 93 | continue; |
5a691a50 | 94 | } |
c511ca9c | 95 | let net = PVE.Parser.parseLxcNetwork(netRaw); |
5a691a50 | 96 | if (net.name === value) { |
c511ca9c | 97 | return "interface name already in use"; |
5a691a50 | 98 | } |
ec0bd652 | 99 | } |
ec0bd652 | 100 | return true; |
f6710aac | 101 | }, |
5a691a50 DM |
102 | }, |
103 | { | |
104 | xtype: 'textfield', | |
105 | name: 'hwaddr', | |
106 | fieldLabel: gettext('MAC address'), | |
107 | vtype: 'MacAddress', | |
108 | value: cdata.hwaddr, | |
41bfbd0a | 109 | allowBlank: true, |
f6710aac | 110 | emptyText: 'auto', |
5a691a50 DM |
111 | }, |
112 | { | |
113 | xtype: 'PVE.form.BridgeSelector', | |
114 | name: 'bridge', | |
115 | nodename: me.nodename, | |
116 | fieldLabel: gettext('Bridge'), | |
117 | value: cdata.bridge, | |
f6710aac | 118 | allowBlank: false, |
5a691a50 DM |
119 | }, |
120 | { | |
121 | xtype: 'pveVlanField', | |
122 | name: 'tag', | |
f6710aac | 123 | value: cdata.tag, |
5a691a50 | 124 | }, |
519ca7fa | 125 | { |
896c0d50 | 126 | xtype: 'proxmoxcheckbox', |
5a691a50 DM |
127 | fieldLabel: gettext('Firewall'), |
128 | name: 'firewall', | |
f6710aac TL |
129 | value: cdata.firewall, |
130 | }, | |
5a691a50 DM |
131 | ]; |
132 | ||
c511ca9c | 133 | let dhcp4 = cdata.ip === 'dhcp'; |
5a691a50 DM |
134 | if (dhcp4) { |
135 | cdata.ip = ''; | |
136 | cdata.gw = ''; | |
137 | } | |
138 | ||
c511ca9c TL |
139 | let auto6 = cdata.ip6 === 'auto'; |
140 | let dhcp6 = cdata.ip6 === 'dhcp'; | |
5a691a50 DM |
141 | if (auto6 || dhcp6) { |
142 | cdata.ip6 = ''; | |
143 | cdata.gw6 = ''; | |
144 | } | |
2a4971d8 | 145 | |
5a691a50 DM |
146 | me.column2 = [ |
147 | { | |
148 | layout: { | |
149 | type: 'hbox', | |
f6710aac | 150 | align: 'middle', |
5a691a50 DM |
151 | }, |
152 | border: false, | |
153 | margin: '0 0 5 0', | |
5a691a50 DM |
154 | items: [ |
155 | { | |
156 | xtype: 'label', | |
f6710aac | 157 | text: 'IPv4:', // do not localize |
5a691a50 DM |
158 | }, |
159 | { | |
160 | xtype: 'radiofield', | |
161 | boxLabel: gettext('Static'), | |
162 | name: 'ipv4mode', | |
163 | inputValue: 'static', | |
164 | checked: !dhcp4, | |
165 | margin: '0 0 0 10', | |
166 | listeners: { | |
167 | change: function(cb, value) { | |
a2163454 | 168 | me.down('field[name=ip]').setEmptyText( |
d2021707 | 169 | value ? Proxmox.Utils.NoneText : "", |
a2163454 | 170 | ); |
5a691a50 DM |
171 | me.down('field[name=ip]').setDisabled(!value); |
172 | me.down('field[name=gw]').setDisabled(!value); | |
f6710aac TL |
173 | }, |
174 | }, | |
5a691a50 DM |
175 | }, |
176 | { | |
177 | xtype: 'radiofield', | |
2ce6111f | 178 | boxLabel: 'DHCP', // do not localize |
5a691a50 DM |
179 | name: 'ipv4mode', |
180 | inputValue: 'dhcp', | |
181 | checked: dhcp4, | |
f6710aac TL |
182 | margin: '0 0 0 10', |
183 | }, | |
184 | ], | |
5a691a50 DM |
185 | }, |
186 | { | |
187 | xtype: 'textfield', | |
188 | name: 'ip', | |
189 | vtype: 'IPCIDRAddress', | |
190 | value: cdata.ip, | |
b552db18 | 191 | emptyText: dhcp4 ? '' : Proxmox.Utils.NoneText, |
5a691a50 | 192 | disabled: dhcp4, |
f6710aac | 193 | fieldLabel: 'IPv4/CIDR', // do not localize |
5a691a50 DM |
194 | }, |
195 | { | |
196 | xtype: 'textfield', | |
197 | name: 'gw', | |
198 | value: cdata.gw, | |
199 | vtype: 'IPAddress', | |
200 | disabled: dhcp4, | |
2ce6111f | 201 | fieldLabel: gettext('Gateway') + ' (IPv4)', |
f6710aac | 202 | margin: '0 0 3 0', // override bottom margin to account for the menuseparator |
5a691a50 DM |
203 | }, |
204 | { | |
205 | xtype: 'menuseparator', | |
206 | height: '3', | |
f6710aac | 207 | margin: '0', |
5a691a50 DM |
208 | }, |
209 | { | |
210 | layout: { | |
211 | type: 'hbox', | |
f6710aac | 212 | align: 'middle', |
5a691a50 DM |
213 | }, |
214 | border: false, | |
215 | margin: '0 0 5 0', | |
5a691a50 DM |
216 | items: [ |
217 | { | |
218 | xtype: 'label', | |
f6710aac | 219 | text: 'IPv6:', // do not localize |
5a691a50 DM |
220 | }, |
221 | { | |
222 | xtype: 'radiofield', | |
223 | boxLabel: gettext('Static'), | |
224 | name: 'ipv6mode', | |
225 | inputValue: 'static', | |
226 | checked: !(auto6 || dhcp6), | |
227 | margin: '0 0 0 10', | |
228 | listeners: { | |
229 | change: function(cb, value) { | |
a2163454 | 230 | me.down('field[name=ip6]').setEmptyText( |
d2021707 | 231 | value ? Proxmox.Utils.NoneText : "", |
a2163454 | 232 | ); |
5a691a50 DM |
233 | me.down('field[name=ip6]').setDisabled(!value); |
234 | me.down('field[name=gw6]').setDisabled(!value); | |
f6710aac TL |
235 | }, |
236 | }, | |
5a691a50 DM |
237 | }, |
238 | { | |
239 | xtype: 'radiofield', | |
2ce6111f | 240 | boxLabel: 'DHCP', // do not localize |
5a691a50 DM |
241 | name: 'ipv6mode', |
242 | inputValue: 'dhcp', | |
243 | checked: dhcp6, | |
f6710aac | 244 | margin: '0 0 0 10', |
5a691a50 DM |
245 | }, |
246 | { | |
247 | xtype: 'radiofield', | |
2ce6111f | 248 | boxLabel: 'SLAAC', // do not localize |
5a691a50 DM |
249 | name: 'ipv6mode', |
250 | inputValue: 'auto', | |
251 | checked: auto6, | |
f6710aac TL |
252 | margin: '0 0 0 10', |
253 | }, | |
254 | ], | |
5a691a50 DM |
255 | }, |
256 | { | |
257 | xtype: 'textfield', | |
258 | name: 'ip6', | |
259 | value: cdata.ip6, | |
b552db18 | 260 | emptyText: dhcp6 || auto6 ? '' : Proxmox.Utils.NoneText, |
5a691a50 | 261 | vtype: 'IP6CIDRAddress', |
53e3ea84 | 262 | disabled: dhcp6 || auto6, |
f6710aac | 263 | fieldLabel: 'IPv6/CIDR', // do not localize |
5a691a50 DM |
264 | }, |
265 | { | |
266 | xtype: 'textfield', | |
267 | name: 'gw6', | |
268 | vtype: 'IP6Address', | |
269 | value: cdata.gw6, | |
53e3ea84 | 270 | disabled: dhcp6 || auto6, |
f6710aac TL |
271 | fieldLabel: gettext('Gateway') + ' (IPv6)', |
272 | }, | |
5a691a50 DM |
273 | ]; |
274 | ||
4e192f9d | 275 | me.advancedColumn1 = [ |
4c6c99cc CH |
276 | { |
277 | xtype: 'proxmoxcheckbox', | |
278 | fieldLabel: gettext('Disconnect'), | |
279 | name: 'link_down', | |
280 | value: cdata.link_down, | |
281 | }, | |
4e192f9d DT |
282 | { |
283 | xtype: 'proxmoxintegerfield', | |
284 | fieldLabel: 'MTU', | |
285 | emptyText: gettext('Same as bridge'), | |
286 | name: 'mtu', | |
287 | value: cdata.mtu, | |
288 | minValue: 576, | |
289 | maxValue: 65535, | |
290 | }, | |
291 | ]; | |
292 | ||
37985d65 DT |
293 | me.advancedColumn2 = [ |
294 | { | |
295 | xtype: 'numberfield', | |
296 | name: 'rate', | |
297 | fieldLabel: gettext('Rate limit') + ' (MB/s)', | |
298 | minValue: 0, | |
299 | maxValue: 10*1024, | |
300 | value: cdata.rate, | |
301 | emptyText: 'unlimited', | |
302 | allowBlank: true, | |
303 | }, | |
304 | ]; | |
305 | ||
5a691a50 | 306 | me.callParent(); |
f6710aac | 307 | }, |
5a691a50 | 308 | }); |
d5e771ce | 309 | |
5a691a50 | 310 | Ext.define('PVE.lxc.NetworkEdit', { |
9fccc702 | 311 | extend: 'Proxmox.window.Edit', |
5a691a50 DM |
312 | |
313 | isAdd: true, | |
314 | ||
8058410f | 315 | initComponent: function() { |
c511ca9c | 316 | let me = this; |
5a691a50 DM |
317 | |
318 | if (!me.dataCache) { | |
319 | throw "no dataCache specified"; | |
320 | } | |
5a691a50 DM |
321 | if (!me.nodename) { |
322 | throw "no node name specified"; | |
323 | } | |
324 | ||
5a691a50 DM |
325 | Ext.apply(me, { |
326 | subject: gettext('Network Device') + ' (veth)', | |
327 | digest: me.dataCache.digest, | |
c511ca9c TL |
328 | items: [ |
329 | { | |
330 | xtype: 'pveLxcNetworkInputPanel', | |
331 | ifname: me.ifname, | |
332 | nodename: me.nodename, | |
333 | dataCache: me.dataCache, | |
334 | isCreate: me.isCreate, | |
335 | }, | |
336 | ], | |
5a691a50 DM |
337 | }); |
338 | ||
339 | me.callParent(); | |
f6710aac | 340 | }, |
5a691a50 DM |
341 | }); |
342 | ||
343 | Ext.define('PVE.lxc.NetworkView', { | |
344 | extend: 'Ext.grid.GridPanel', | |
d5e771ce | 345 | alias: 'widget.pveLxcNetworkView', |
5a691a50 | 346 | |
ba93a9c6 DC |
347 | onlineHelp: 'pct_container_network', |
348 | ||
5a691a50 DM |
349 | dataCache: {}, // used to store result of last load |
350 | ||
af603c15 DC |
351 | stateful: true, |
352 | stateId: 'grid-lxc-network', | |
353 | ||
5a691a50 | 354 | load: function() { |
c511ca9c | 355 | let me = this; |
5a691a50 | 356 | |
e7ade592 | 357 | Proxmox.Utils.setErrorMask(me, true); |
5a691a50 | 358 | |
e7ade592 | 359 | Proxmox.Utils.API2Request({ |
5a691a50 DM |
360 | url: me.url, |
361 | failure: function(response, opts) { | |
e7ade592 | 362 | Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus); |
5a691a50 DM |
363 | }, |
364 | success: function(response, opts) { | |
e7ade592 | 365 | Proxmox.Utils.setErrorMask(me, false); |
c511ca9c TL |
366 | let result = Ext.decode(response.responseText); |
367 | me.dataCache = result.data || {}; | |
368 | let records = []; | |
369 | for (const [key, value] of Object.entries(me.dataCache)) { | |
370 | if (key.match(/^net\d+/)) { | |
371 | let net = PVE.Parser.parseLxcNetwork(value); | |
372 | net.id = key; | |
373 | records.push(net); | |
5a691a50 | 374 | } |
c511ca9c | 375 | } |
5a691a50 | 376 | me.store.loadData(records); |
53e3ea84 | 377 | me.down('button[name=addButton]').setDisabled(records.length >= 32); |
f6710aac | 378 | }, |
5a691a50 DM |
379 | }); |
380 | }, | |
381 | ||
8058410f | 382 | initComponent: function() { |
c511ca9c | 383 | let me = this; |
5a691a50 | 384 | |
c511ca9c | 385 | let nodename = me.pveSelNode.data.node; |
5a691a50 DM |
386 | if (!nodename) { |
387 | throw "no node name specified"; | |
388 | } | |
389 | ||
c511ca9c | 390 | let vmid = me.pveSelNode.data.vmid; |
5a691a50 DM |
391 | if (!vmid) { |
392 | throw "no VM ID specified"; | |
393 | } | |
394 | ||
c511ca9c | 395 | let caps = Ext.state.Manager.get('GuiCap'); |
5a691a50 | 396 | |
c511ca9c | 397 | me.url = `/nodes/${nodename}/lxc/${vmid}/config`; |
5a691a50 | 398 | |
c511ca9c | 399 | let store = new Ext.data.Store({ |
5a691a50 DM |
400 | model: 'pve-lxc-network', |
401 | sorters: [ | |
402 | { | |
8058410f | 403 | property: 'id', |
f6710aac TL |
404 | direction: 'ASC', |
405 | }, | |
406 | ], | |
5a691a50 DM |
407 | }); |
408 | ||
c511ca9c | 409 | let sm = Ext.create('Ext.selection.RowModel', {}); |
5a691a50 | 410 | |
c511ca9c TL |
411 | let run_editor = function() { |
412 | let rec = sm.getSelection()[0]; | |
413 | if (!rec || !caps.vms['VM.Config.Network']) { | |
414 | return false; // disable default-propagation when triggered by grid dblclick | |
5a691a50 | 415 | } |
c511ca9c | 416 | Ext.create('PVE.lxc.NetworkEdit', { |
5a691a50 DM |
417 | url: me.url, |
418 | nodename: nodename, | |
419 | dataCache: me.dataCache, | |
f6710aac | 420 | ifname: rec.data.id, |
c511ca9c TL |
421 | listeners: { |
422 | destroy: () => me.load(), | |
423 | }, | |
424 | autoShow: true, | |
5a691a50 | 425 | }); |
c511ca9c | 426 | return undefined; // make eslint happier |
5a691a50 DM |
427 | }; |
428 | ||
f7993618 | 429 | Ext.apply(me, { |
5a691a50 DM |
430 | store: store, |
431 | selModel: sm, | |
5a691a50 DM |
432 | tbar: [ |
433 | { | |
434 | text: gettext('Add'), | |
2517c76b | 435 | name: 'addButton', |
5a691a50 DM |
436 | disabled: !caps.vms['VM.Config.Network'], |
437 | handler: function() { | |
c511ca9c | 438 | Ext.create('PVE.lxc.NetworkEdit', { |
5a691a50 DM |
439 | url: me.url, |
440 | nodename: nodename, | |
d5e771ce | 441 | isCreate: true, |
f6710aac | 442 | dataCache: me.dataCache, |
c511ca9c TL |
443 | listeners: { |
444 | destroy: () => me.load(), | |
445 | }, | |
446 | autoShow: true, | |
447 | }); | |
448 | }, | |
449 | }, | |
450 | { | |
451 | xtype: 'proxmoxButton', | |
452 | text: gettext('Remove'), | |
453 | disabled: true, | |
454 | selModel: sm, | |
455 | enableFn: function(rec) { | |
456 | return !!caps.vms['VM.Config.Network']; | |
457 | }, | |
458 | confirmMsg: ({ data }) => | |
459 | Ext.String.format(gettext('Are you sure you want to remove entry {0}'), `'${data.id}'`), | |
460 | handler: function(btn, e, rec) { | |
461 | Proxmox.Utils.API2Request({ | |
462 | url: me.url, | |
463 | waitMsgTarget: me, | |
464 | method: 'PUT', | |
465 | params: { | |
466 | 'delete': rec.data.id, | |
467 | digest: me.dataCache.digest, | |
468 | }, | |
469 | callback: () => me.load(), | |
470 | failure: (response, opts) => Ext.Msg.alert(gettext('Error'), response.htmlStatus), | |
5a691a50 | 471 | }); |
f6710aac | 472 | }, |
5a691a50 | 473 | }, |
c511ca9c TL |
474 | { |
475 | xtype: 'proxmoxButton', | |
476 | text: gettext('Edit'), | |
477 | selModel: sm, | |
478 | disabled: true, | |
479 | enableFn: rec => !!caps.vms['VM.Config.Network'], | |
480 | handler: run_editor, | |
481 | }, | |
5a691a50 DM |
482 | ], |
483 | columns: [ | |
484 | { | |
a29ff1bc | 485 | header: 'ID', |
5a691a50 | 486 | width: 50, |
f6710aac | 487 | dataIndex: 'id', |
5a691a50 DM |
488 | }, |
489 | { | |
490 | header: gettext('Name'), | |
491 | width: 80, | |
f6710aac | 492 | dataIndex: 'name', |
5a691a50 DM |
493 | }, |
494 | { | |
495 | header: gettext('Bridge'), | |
496 | width: 80, | |
f6710aac | 497 | dataIndex: 'bridge', |
5a691a50 DM |
498 | }, |
499 | { | |
500 | header: gettext('Firewall'), | |
501 | width: 80, | |
502 | dataIndex: 'firewall', | |
f6710aac | 503 | renderer: Proxmox.Utils.format_boolean, |
5a691a50 DM |
504 | }, |
505 | { | |
506 | header: gettext('VLAN Tag'), | |
507 | width: 80, | |
f6710aac | 508 | dataIndex: 'tag', |
5a691a50 DM |
509 | }, |
510 | { | |
511 | header: gettext('MAC address'), | |
512 | width: 110, | |
f6710aac | 513 | dataIndex: 'hwaddr', |
5a691a50 DM |
514 | }, |
515 | { | |
516 | header: gettext('IP address'), | |
517 | width: 150, | |
518 | dataIndex: 'ip', | |
519 | renderer: function(value, metaData, rec) { | |
520 | if (rec.data.ip && rec.data.ip6) { | |
521 | return rec.data.ip + "<br>" + rec.data.ip6; | |
522 | } else if (rec.data.ip6) { | |
523 | return rec.data.ip6; | |
524 | } else { | |
525 | return rec.data.ip; | |
526 | } | |
f6710aac | 527 | }, |
5a691a50 DM |
528 | }, |
529 | { | |
530 | header: gettext('Gateway'), | |
531 | width: 150, | |
532 | dataIndex: 'gw', | |
533 | renderer: function(value, metaData, rec) { | |
534 | if (rec.data.gw && rec.data.gw6) { | |
535 | return rec.data.gw + "<br>" + rec.data.gw6; | |
536 | } else if (rec.data.gw6) { | |
537 | return rec.data.gw6; | |
538 | } else { | |
539 | return rec.data.gw; | |
540 | } | |
f6710aac TL |
541 | }, |
542 | }, | |
4e192f9d DT |
543 | { |
544 | header: gettext('MTU'), | |
545 | width: 80, | |
546 | dataIndex: 'mtu', | |
547 | }, | |
4c6c99cc CH |
548 | { |
549 | header: gettext('Disconnected'), | |
550 | width: 100, | |
551 | dataIndex: 'link_down', | |
552 | renderer: Proxmox.Utils.format_boolean, | |
553 | }, | |
5a691a50 DM |
554 | ], |
555 | listeners: { | |
4b488565 | 556 | activate: me.load, |
f6710aac TL |
557 | itemdblclick: run_editor, |
558 | }, | |
5a691a50 DM |
559 | }); |
560 | ||
561 | me.callParent(); | |
f6710aac | 562 | }, |
5a691a50 | 563 | }, function() { |
5a691a50 DM |
564 | Ext.define('pve-lxc-network', { |
565 | extend: "Ext.data.Model", | |
566 | proxy: { type: 'memory' }, | |
c511ca9c TL |
567 | fields: [ |
568 | 'id', | |
569 | 'name', | |
570 | 'hwaddr', | |
571 | 'bridge', | |
572 | 'ip', | |
573 | 'gw', | |
574 | 'ip6', | |
575 | 'gw6', | |
576 | 'tag', | |
577 | 'firewall', | |
4e192f9d | 578 | 'mtu', |
4c6c99cc | 579 | 'link_down', |
c511ca9c | 580 | ], |
5a691a50 | 581 | }); |
5a691a50 DM |
582 | }); |
583 |