luci-proto-bonding: Modify ipaddr as optional
[project/luci.git] / protocols / luci-proto-bonding / htdocs / luci-static / resources / protocol / bonding.js
1 'use strict';
2 'require ui';
3 'require uci';
4 'require form';
5 'require fs';
6 'require network';
7 'require tools.widgets as widgets';
8
9
10 function getSelectableSlaves(section_id) {
11 var rv = [];
12 var NonUsableMac = /^(00:00:00:00:00:00|null)/;
13 var interfaces = uci.sections('network', 'interface');
14
15 return network.getDevices().then(function(devices) {
16 for (var i = 0; i < devices.length; i++) {
17 var in_use = false;
18 var NotUsable = NonUsableMac.test(devices[i].getMAC());
19
20 // Only "real" interfaces for slaves needed
21 if (NotUsable == false) {
22 for (var j = 0; j < interfaces.length; j++) {
23 if (uci.get('network', interfaces[j]['.name'], 'proto') == 'bonding') {
24 var slaves = L.toArray(uci.get('network', interfaces[j]['.name'], 'slaves'));
25
26 for (var k = 0; k < slaves.length; k++) {
27 if (devices[i].ifname == slaves[k] || devices[i].device == slaves[k]) {
28 if (interfaces[j]['.name'] != section_id) {
29 in_use = true;
30 }
31 }
32 }
33 }
34 }
35 if (in_use == false) {
36 devices[i].device == null ? rv.push(devices[i].ifname) : rv.push(devices[i].device)
37 }
38 }
39 }
40
41 return rv.sort();
42 });
43 }
44
45 function validate_netmask_empty(section, value) {
46 var opt = this.map.lookupOption('ipaddr', section);
47 var ipaddr = opt[0].formvalue(section);
48
49 if (!ipaddr || value) {
50 return true;
51 }
52 else {
53 return _('Expecting: non-empty value');
54 }
55 }
56
57 function updatePrimaries(section, value) {
58
59 var opt = this.map.lookupOption('slaves', section);
60 var selected_slaves = opt[0].formvalue(section);
61
62 var uielem = this.map.lookupOption('primary', section)[0].getUIElement(section);
63 uielem.clearChoices();
64
65 for (var i = 0; i < selected_slaves.length; i++) {
66 uielem.addChoices(selected_slaves[i], selected_slaves[i]);
67 }
68
69 return true;
70 }
71
72 function validate_arp_policy(section, value) {
73
74 var opt = this.map.lookupOption('link_monitoring', section);
75 var selected_link_monitoring = opt[0].formvalue(section);
76
77 var opt = this.map.lookupOption('bonding_policy', section);
78 var selected_policy = opt[0].formvalue(section);
79
80 if (selected_link_monitoring == 'arp') {
81 if (selected_policy == '802.3ad' || selected_policy == 'balance-tlb' || selected_policy == 'balance-alb') {
82 return _('ARP monitoring is not supported for the selected policy!');
83 }
84 }
85
86 return true;
87 }
88
89 function validate_arp_ip_targets(section, value) {
90
91 var opt = this.map.lookupOption('link_monitoring', section);
92 var selected_link_monitoring = opt[0].formvalue(section);
93
94 var opt = this.map.lookupOption('arp_ip_target', section);
95 var selected_arp_ip_targets = opt[0].formvalue(section);
96
97 var opt = this.map.lookupOption('bonding_policy', section);
98 var selected_policy = opt[0].formvalue(section);
99
100 if (selected_link_monitoring == 'arp' && selected_arp_ip_targets.length == 0) {
101 return _('You must select at least one ARP IP target if ARP monitoring is selected!');
102 }
103
104 return true;
105 }
106
107 function validate_primary_interface(section, value) {
108
109 var opt = this.map.lookupOption('bonding_policy', section);
110 var selected_policy = opt[0].formvalue(section);
111
112 var opt = this.map.lookupOption('slaves', section);
113 var selected_slaves = opt[0].formvalue(section);
114
115 var opt = this.map.lookupOption('primary', section);
116 var selected_primary = opt[0].formvalue(section);
117
118 if (selected_policy == 'active-backup' || selected_policy == 'balance-tlb' || selected_policy == 'balance-alb') {
119 if (selected_slaves.filter(function(slave) { return slave == selected_primary }).length == 0)
120 return _('You must select a primary interface which is included in selected slave interfaces!');
121 }
122
123 return true;
124 }
125
126 return network.registerProtocol('bonding', {
127 getI18n: function() {
128 return _('Link Aggregation (Channel Bonding)');
129 },
130
131 getIfname: function() {
132 return null;
133 },
134
135 getOpkgPackage: function() {
136 return 'bonding';
137 },
138
139 isFloating: function() {
140 return true;
141 },
142
143 isCreateable: function(ifname) {
144 return getSelectableSlaves(ifname).then(L.bind(function(devices) {
145 return devices.length == 0 ? _('No more slaves available') : null;
146 }, this));
147
148 return _('No more slaves available');
149 },
150
151 isVirtual: function() {
152 return true;
153 },
154
155 getDevices: function() {
156 return null;
157 },
158
159 containsDevice: function(ifname) {
160 return (network.getIfnameOf(ifname) == this.getIfname());
161 },
162
163 renderFormOptions: function(s) {
164 var o;
165
166 o = s.taboption('general', form.Value, 'ipaddr',
167 _('IPv4 address'),
168 _('The local IPv4 address'));
169 o.datatype = 'ip4addr';
170 o.optional = true;
171 o.rmempty = false;
172
173 o = s.taboption('general', form.Value, 'netmask',
174 _('IPv4 netmask'),
175 _('The local IPv4 netmask'));
176 o.datatype = 'ip4addr';
177 o.optional = true;
178 o.validate = validate_netmask_empty;
179 o.rmempty = false;
180 o.value("255.255.255.0");
181 o.value("255.255.0.0");
182 o.value("255.0.0.0");
183
184 o = s.taboption('advanced', form.MultiValue, 'slaves',
185 _('Slave Interfaces'),
186 _('Specifies which slave interfaces should be attached to this bonding interface'));
187 o.load = function(section_id) {
188 return getSelectableSlaves(section_id).then(L.bind(function(devices) {
189 for (var i = 0; i < devices.length; i++) {
190 this.value(devices[i], devices[i]);
191 }
192
193 if (devices.length == 0) {
194 this.placeholder = _('No more slaves available, can not save interface');
195 this.value('', '');
196 return '';
197 }
198
199 return uci.get('network', section_id, 'slaves');
200 }, this));
201 };
202 o.validate = updatePrimaries;
203 o.rmempty = false;
204
205 o = s.taboption('advanced', form.ListValue, 'bonding_policy',
206 _('Bonding Policy'),
207 _('Specifies the mode to be used for this bonding interface'));
208 o.default = 'balance-rr';
209 o.value('balance-rr', _('Round-Robin policy (balance-rr, 0)'));
210 o.value('active-backup', _('Active-Backup policy (active-backup, 1)'));
211 o.value('balance-xor', _('XOR policy (balance-xor, 2)'));
212 o.value('broadcast', _('Broadcast policy (broadcast, 3)'));
213 o.value('802.3ad', _('IEEE 802.3ad Dynamic link aggregation (802.3ad, 4)'));
214 o.value('balance-tlb', _('Adaptive transmit load balancing (balance-tlb, 5)'));
215 o.value('balance-alb', _('Adaptive load balancing (balance-alb, 6)'));
216
217 o = s.taboption('advanced', widgets.DeviceSelect, 'primary',
218 _('Primary Slave'),
219 _('Specifies which slave is the primary device. It will always be the active slave while it is available'));
220 o.depends('bonding_policy', 'active-backup');
221 o.depends('bonding_policy', 'balance-tlb');
222 o.depends('bonding_policy', 'balance-alb');
223 o.filter = function(section_id, value) {
224 // Never return anything as valid, as the valid possibilities
225 // will be set in the slaves validate function
226 return false;
227 };
228 o.validate = validate_primary_interface;
229
230 o = s.taboption('advanced', form.ListValue, 'primary_reselect',
231 _('Reselection policy for primary slave'),
232 _('Specifies the reselection policy for the primary slave when failure of the active slave or recovery of the primary slave occurs'));
233 o.default = 'always';
234 o.value('always', _('Primary becomes active slave whenever it comes back up (always, 0)'));
235 o.value('better', _('Primary becomes active slave when it comes back up if speed and duplex better than current slave (better, 1)'));
236 o.value('failure', _('Only if current active slave fails and the primary slave is up (failure, 2)'));
237 o.depends('bonding_policy', 'active-backup');
238 o.depends('bonding_policy', 'balance-tlb');
239 o.depends('bonding_policy', 'balance-alb');
240
241 o = s.taboption('advanced', form.Value, 'min_links',
242 _('Minimum Number of Links'),
243 _('Specifies the minimum number of links that must be active before asserting carrier'));
244 o.datatype = 'uinteger';
245 o.default = 0;
246 o.rmempty = false;
247 o.depends('bonding_policy', '802.3ad');
248
249 o = s.taboption('advanced', form.Value, 'ad_actor_sys_prio',
250 _('System Priority'),
251 _('Specifies the system priority'));
252 o.datatype = 'range(1,65535)';
253 o.default = 65535;
254 o.rmempty = false;
255 o.depends('bonding_policy', '802.3ad');
256
257 o = s.taboption('advanced', form.Value, 'ad_actor_system',
258 _('MAC Address For The Actor'),
259 _("Specifies the mac-address for the actor in protocol packet exchanges (LACPDUs). If empty, masters' mac address defaults to system default"));
260 o.datatype = 'macaddr';
261 o.default = '';
262 o.depends('bonding_policy', '802.3ad');
263
264 o = s.taboption('advanced', form.ListValue, 'ad_select',
265 _('Aggregation Selection Logic'),
266 _('Specifies the aggregation selection logic to use'));
267 o.default = 'stable';
268 o.value('stable', _('Aggregator: All slaves down or has no slaves (stable, 0)'));
269 o.value('bandwidth', _('Aggregator: Slave added/removed or state changes (bandwidth, 1)'));
270 o.value('count', _('Aggregator: Chosen by the largest number of ports + slave added/removed or state changes (count, 2)'));
271 o.depends('bonding_policy', '802.3ad');
272
273 o = s.taboption('advanced', form.ListValue, 'lacp_rate',
274 _('LACPDU Packets'),
275 _('Specifies the rate in which the link partner will be asked to transmit LACPDU packets'));
276 o.default = 'slow';
277 o.value('slow', _('Every 30 seconds (slow, 0)'));
278 o.value('fast', _('Every second (fast, 1)'));
279 o.depends('bonding_policy', '802.3ad');
280
281 o = s.taboption('advanced', form.Value, 'packets_per_slave',
282 _('Packets To Transmit Before Moving To Next Slave'),
283 _("Specifies the number of packets to transmit through a slave before moving to the next one"));
284 o.datatype = 'range(0,65535)';
285 o.default = '1';
286 o.rmempty = false;
287 o.depends('bonding_policy', 'balance-rr');
288
289 o = s.taboption('advanced', form.Value, 'lp_interval',
290 _('Interval For Sending Learning Packets'),
291 _("Specifies the number of seconds between instances where the bonding driver sends learning packets to each slaves peer switch"));
292 o.datatype = 'range(1,2147483647)';
293 o.default = '1';
294 o.rmempty = false;
295 o.depends('bonding_policy', 'balance-tlb');
296 o.depends('bonding_policy', 'balance-alb');
297
298 o = s.taboption('advanced', form.ListValue, 'tlb_dynamic_lb',
299 _('Enable Dynamic Shuffling Of Flows'),
300 _('Specifies whether to shuffle active flows across slaves based on the load'));
301 o.default = '1';
302 o.value('1', _('Yes'));
303 o.value('0', _('No'));
304 o.depends('bonding_policy', 'balance-tlb');
305
306 o = s.taboption('advanced', form.ListValue, 'fail_over_mac',
307 _('Set same MAC Address to all slaves'),
308 _('Specifies whether active-backup mode should set all slaves to the same MAC address at enslavement'));
309 o.default = 'none';
310 o.value('none', _('Yes (none, 0)'));
311 o.value('active', _('Set to currently active slave (active, 1)'));
312 o.value('follow', _('Set to first slave added to the bond (follow, 2)'));
313 o.depends('bonding_policy', 'active-backup');
314
315 o = s.taboption('advanced', form.Value, 'num_grat_arp__num_unsol_na',
316 _('Number of peer notifications after failover event'),
317 _("Specifies the number of peer notifications (gratuitous ARPs and unsolicited IPv6 Neighbor Advertisements) to be issued after a failover event"));
318 o.datatype = 'range(0,255)';
319 o.default = '1';
320 o.rmempty = false;
321 o.depends('bonding_policy', 'active-backup');
322
323 o = s.taboption('advanced', form.ListValue, 'xmit_hash_policy',
324 _('Transmit Hash Policy'),
325 _('Selects the transmit hash policy to use for slave selection'));
326 o.default = 'layer2';
327 o.value('layer2', _('Use XOR of hardware MAC addresses (layer2)'));
328 o.value('layer2+3', _('Use XOR of hardware MAC addresses and IP addresses (layer2+3)'));
329 o.value('layer3+4', _('Use upper layer protocol information (layer3+4)'));
330 o.value('encap2+3', _('Use XOR of hardware MAC addresses and IP addresses, rely on skb_flow_dissect (encap2+3)'));
331 o.value('encap3+4', _('Use upper layer protocol information, rely on skb_flow_dissect (encap3+4)'));
332 o.depends('bonding_policy', 'balance-xor');
333 o.depends('bonding_policy', 'balance-alb');
334 o.depends('bonding_policy', 'balance-tlb');
335 o.depends('bonding_policy', '802.3ad');
336
337 o = s.taboption('advanced', form.Value, 'resend_igmp',
338 _('Number of IGMP membership reports'),
339 _("Specifies the number of IGMP membership reports to be issued after a failover event in 200ms intervals"));
340 o.datatype = 'range(0,255)';
341 o.default = '1';
342 o.rmempty = false;
343 o.depends('bonding_policy', 'balance-tlb');
344 o.depends('bonding_policy', 'balance-alb');
345
346 o = s.taboption('advanced', form.ListValue, 'all_slaves_active',
347 _('Drop Duplicate Frames'),
348 _('Specifies that duplicate frames (received on inactive ports) should be dropped or delivered'));
349 o.default = '0';
350 o.value('0', _('Yes'));
351 o.value('1', _('No'));
352
353 o = s.taboption('advanced', form.ListValue, 'link_monitoring',
354 _('Link Monitoring'),
355 _('Method of link monitoring'));
356 o.default = 'off';
357 o.value('off', _('Off'));
358 o.value('arp', _('ARP'));
359 o.value('mii', _('MII'));
360 o.validate = validate_arp_policy;
361
362 o = s.taboption('advanced', form.Value, 'arp_interval',
363 _('ARP Interval'),
364 _("Specifies the ARP link monitoring frequency in milliseconds"));
365 o.datatype = 'uinteger';
366 o.default = '0';
367 o.rmempty = false;
368 o.depends('link_monitoring', 'arp');
369
370 o = s.taboption('advanced', form.DynamicList, 'arp_ip_target',
371 _('ARP IP Targets'),
372 _('Specifies the IP addresses to use for ARP monitoring'));
373 o.datatype = 'ipaddr';
374 o.cast = 'string';
375 o.depends('link_monitoring', 'arp');
376 o.validate = validate_arp_ip_targets;
377
378 o = s.taboption('advanced', form.ListValue, 'arp_all_targets',
379 _('ARP mode to consider a slave as being up'),
380 _('Specifies the quantity of ARP IP targets that must be reachable'));
381 o.default = 'any';
382 o.value('any', _('Consider the slave up when any ARP IP target is reachable (any, 0)'));
383 o.value('all', _('Consider the slave up when all ARP IP targets are reachable (all, 1)'));
384 o.depends({link_monitoring: 'arp', bonding_policy: 'active-backup'});
385
386 o = s.taboption('advanced', form.ListValue, 'arp_validate',
387 _('ARP Validation'),
388 _('Specifies whether ARP probes and replies should be validated or non-ARP traffic should be filtered for link monitoring'));
389 o.default = 'filter';
390 o.value('none', _('No validation or filtering'));
391 o.value('active', _('Validation only for active slave'));
392 o.value('backup', _('Validation only for backup slaves'));
393 o.value('all', _('Validation for all slaves'));
394 o.value('filter', _('Filtering for all slaves, no validation'));
395 o.value('filter_active', _('Filtering for all slaves, validation only for active slave'));
396 o.value('filter_backup', _('Filtering for all slaves, validation only for backup slaves'));
397 o.depends('link_monitoring', 'arp');
398
399 o = s.taboption('advanced', form.Value, 'miimon',
400 _('MII Interval'),
401 _("Specifies the MII link monitoring frequency in milliseconds"));
402 o.datatype = 'uinteger';
403 o.default = '0';
404 o.rmempty = false;
405 o.depends('link_monitoring', 'mii');
406
407 o = s.taboption('advanced', form.Value, 'downdelay',
408 _('Down Delay'),
409 _("Specifies the time in milliseconds to wait before disabling a slave after a link failure detection"));
410 o.datatype = 'uinteger';
411 o.default = '0';
412 o.rmempty = false;
413 o.depends('link_monitoring', 'mii');
414
415 o = s.taboption('advanced', form.Value, 'updelay',
416 _('Up Delay'),
417 _("Specifies the time in milliseconds to wait before enabling a slave after a link recovery detection"));
418 o.datatype = 'uinteger';
419 o.default = '0';
420 o.rmempty = false;
421 o.depends('link_monitoring', 'mii');
422
423 o = s.taboption('advanced', form.ListValue, 'use_carrier',
424 _('Method to determine link status'),
425 _('Specifies whether or not miimon should use MII or ETHTOOL ioctls vs. netif_carrier_ok()'));
426 o.default = '1';
427 o.value('0', _('MII / ETHTOOL ioctls'));
428 o.value('1', _('netif_carrier_ok()'));
429 o.depends('link_monitoring', 'mii');
430 }
431 });