• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/netifd/examples/wireless.uc

  1 'use strict';
  2 
  3 import * as libubus from "ubus";
  4 import { realpath } from "fs";
  5 import {
  6         handler_load, handler_attributes,
  7         parse_attribute_list, parse_bool, parse_array,
  8         TYPE_ARRAY, TYPE_STRING, TYPE_INT, TYPE_BOOL
  9 } from "./utils.uc";
 10 import * as wdev from "./wireless-device.uc";
 11 
 12 let ubus = netifd.ubus;
 13 let wireless = netifd.wireless = {
 14         handlers: {},
 15         devices: {},
 16         path: realpath(netifd.main_path + "/wireless"),
 17 };
 18 
 19 function update_config(new_devices)
 20 {
 21         for (let name, dev in wireless.devices)
 22                 if (!new_devices[name])
 23                         dev.destroy();
 24 
 25         for (let name, dev in new_devices) {
 26                 let cur_dev = wireless.devices[name];
 27                 if (cur_dev) {
 28                         cur_dev.update(dev);
 29                         continue;
 30                 }
 31 
 32                 let handler = wireless.handlers[dev.config.type];
 33                 cur_dev = wdev.new(dev, handler.script);
 34                 if (!cur_dev)
 35                         continue;
 36 
 37                 wireless.devices[name] = cur_dev;
 38         }
 39 }
 40 
 41 function config_init(uci)
 42 {
 43         let config = uci.get_all("wireless");
 44 
 45         let handlers = {};
 46         let devices = {};
 47         let vifs = {};
 48         let mlo_device;
 49 
 50         let sections = {
 51                 device: {},
 52                 iface: {},
 53                 vlan: {},
 54                 station: {},
 55         };
 56         let radio_idx = {};
 57 
 58         for (let name, data in config) {
 59                 let type = data[".type"];
 60                 if (parse_bool(data.disabled) && type != "wifi-device")
 61                         continue;
 62 
 63                 if (substr(type, 0, 5) != "wifi-")
 64                         continue;
 65 
 66                 let list = sections[substr(type, 5)];
 67                 if (list)
 68                         list[name] = data;
 69 
 70                 if (type == "wifi-iface" && parse_bool(data.mlo))
 71                         mlo_device = true;
 72         }
 73 
 74         if (mlo_device) {
 75                 devices[wdev.mlo_name] = {
 76                         name: wdev.mlo_name,
 77                         config: {
 78                                 type: "mac80211",
 79                         },
 80                         vif: [],
 81                 };
 82                 handlers[wdev.mlo_name] = wireless.handlers.mac80211;
 83         }
 84 
 85         for (let name, data in sections.device) {
 86                 if (!data.type)
 87                         continue;
 88 
 89                 let handler = wireless.handlers[data.type];
 90                 if (!handler)
 91                         continue;
 92 
 93                 if (data.radio != null)
 94                         radio_idx[name] = +data.radio;
 95 
 96                 let config = parse_attribute_list(data, handler.device);
 97                 devices[name] = {
 98                         name,
 99                         config,
100 
101                         vif: [],
102                 };
103                 handlers[name] = handler;
104         }
105 
106         for (let name, data in sections.iface) {
107                 let dev_names = parse_array(data.device);
108                 let mlo_vif = parse_bool(data.mlo);
109                 let radios = map(dev_names, (v) => radio_idx[v]);
110                 radios = filter(radios, (v) => v != null);
111                 let radio_config = map(dev_names, (v) => devices[v].config);
112                 if (mlo_vif)
113                         dev_names = [ wdev.mlo_name, ...dev_names ];
114                 for (let dev_name in dev_names) {
115                         let dev = devices[dev_name];
116                         if (!dev)
117                                 continue;
118 
119                         let handler = handlers[dev_name];
120                         if (!handler)
121                                 continue;
122 
123                         let config = parse_attribute_list(data, handler.iface);
124                         if (mlo_vif)
125                                 if (dev_name == wdev.mlo_name)
126                                         config.radio_config = radio_config;
127                                 else
128                                         config.mode = "link";
129                         config.radios = radios;
130 
131                         let vif = {
132                                 name, config,
133                                 device: dev_name,
134 
135                                 vlan: [],
136                                 sta: [],
137                         };
138                         push(dev.vif, vif);
139 
140                         vifs[name] ??= [];
141                         push(vifs[name], vif);
142                 }
143         }
144 
145         for (let name, data in sections.vlan) {
146                 if (!data.iface || !vifs[data.iface])
147                         continue;
148 
149                 for (let vif in vifs[data.iface]) {
150                         let dev = devices[vif.device];
151                         let handler = handlers[vif.device];
152                         if (!dev || !handler)
153                                 continue;
154 
155                         let config = parse_attribute_list(data, handler.vlan);
156 
157                         let vlan = {
158                                 name,
159                                 config
160                         };
161                         push(vif.vlan, vlan);
162                 }
163         }
164 
165         for (let name, data in sections.station) {
166                 if (!data.iface || !vifs[data.iface])
167                         continue;
168 
169                 for (let vif in vifs[data.iface]) {
170                         let dev = devices[vif.device];
171                         let handler = handlers[vif.device];
172                         if (!dev || !handler)
173                                 continue;
174 
175                         let config = parse_attribute_list(data, handler.station);
176 
177                         let sta = {
178                                 name,
179                                 config
180                         };
181                         push(vif.sta, sta);
182                 }
183         }
184 
185         let udata = ubus.call({
186                 object: "service",
187                 method: "get_data",
188                 data: {
189                         type: "wifi-device"
190                 },
191         });
192         for (let svcname, svc in udata) {
193                 for (let insname, ins in svc) {
194                         for (let typename, data in ins) {
195                                 for (let radio, config in data) {
196                                         if (type(config) != "object")
197                                                 continue;
198 
199                                         let dev = devices[radio];
200                                         if (dev) {
201                                                 dev.config = { ...dev.config, ...config };
202                                                 continue;
203                                         }
204 
205                                         let handler = wireless.handlers[config.type];
206                                         if (!handler)
207                                                 continue;
208 
209                                         dev = devices[radio] = {
210                                                 name,
211                                                 config,
212 
213                                                 vif: [],
214                                         };
215                                         handlers[radio] = handler;
216                                 }
217                         }
218                 }
219         }
220 
221 
222         udata = ubus.call({
223                 object: "service",
224                 method: "get_data",
225                 data: {
226                         type: "wifi-iface"
227                 },
228         });
229 
230         for (let svcname, svc in udata) {
231                 for (let insname, ins in svc) {
232                         for (let typename, data in ins) {
233                                 for (let radio, vifs in data) {
234                                         if (type(vifs) != "object")
235                                                 continue;
236 
237                                         for (let name, vif in vifs) {
238                                                 let devs = vif.device;
239                                                 if (type(devs) != "array")
240                                                         devs = [ devs ];
241                                                 let config = vif.config;
242                                                 if (!config)
243                                                         continue;
244                                                 for (let device in devs) {
245                                                         let dev = devices[device];
246                                                         if (!dev)
247                                                                 continue;
248 
249                                                         let vif_data = {
250                                                                 name, device, config,
251                                                                 vlan: [],
252                                                                 sta: []
253                                                         };
254                                                         if (vif.vlans)
255                                                                 vif_data.vlans = vif.vlans;
256                                                         if (vif.stations)
257                                                                 vif_data.sta = vif.stations;
258                                                         vifs[name] ??= [];
259                                                         push(vifs[name], vif_data);
260                                                         push(dev.vif, vif_data);
261                                                 }
262                                         }
263                                 }
264                         }
265                 }
266         }
267 
268         update_config(devices);
269 }
270 
271 function config_start()
272 {
273         for (let name, dev in wireless.devices)
274                 if (dev.autostart)
275                         dev.start();
276 
277 }
278 
279 function check_interfaces()
280 {
281         for (let name, dev in wireless.devices)
282                 if (dev.autostart)
283                         dev.check();
284 }
285 
286 function hotplug(ifname, add)
287 {
288         for (let name, dev in wireless.devices)
289                 if (dev.autostart)
290                         dev.hotplug(ifname, add);
291 }
292 
293 const network_config_attr = {
294         network: TYPE_ARRAY,
295         network_vlan: TYPE_ARRAY,
296         bridge_isolate: TYPE_BOOL,
297         isolate: TYPE_BOOL,
298         proxy_arp: TYPE_BOOL,
299         multicast_to_unicast: TYPE_BOOL,
300 };
301 
302 const default_config_attr = {
303         device: {
304                 disabled: TYPE_BOOL,
305                 type: TYPE_STRING,
306         },
307         iface: {
308                 ...network_config_attr,
309                 device: TYPE_STRING,
310                 mode: TYPE_STRING,
311         },
312         station: {
313                 iface: TYPE_STRING,
314 
315                 mac: TYPE_STRING,
316                 key: TYPE_STRING,
317                 vid: TYPE_STRING,
318         },
319         vlan: {
320                 ...network_config_attr,
321                 iface: TYPE_STRING,
322                 name: TYPE_STRING,
323                 vid: TYPE_STRING,
324         },
325 };
326 
327 const wdev_args = {
328         device: ""
329 };
330 
331 function wdev_call(req, cb)
332 {
333         let dev = req.args.device;
334         if (dev) {
335                 dev = wireless.devices[dev];
336                 if (!dev)
337                         return libubus.STATUS_NOT_FOUND;
338 
339                 return cb(dev);
340         }
341 
342         for (let name, dev in wireless.devices) {
343                 if (name == wdev.mlo_name)
344                         continue;
345                 cb(dev);
346         }
347 
348         return 0;
349 }
350 
351 function attr_validate(attr_type, validate)
352 {
353         if (validate)
354                 return validate;
355         switch (attr_type) {
356         case TYPE_STRING:
357                 return "string";
358         case TYPE_ARRAY:
359                 return "list(string)";
360         case TYPE_INT:
361                 return "uinteger";
362         case TYPE_BOOL:
363                 return "bool";
364         }
365 }
366 
367 function get_validate_info(ret, handler)
368 {
369         for (let kind in default_config_attr) {
370                 let cur = ret[kind == "iface" ? "interface" : kind] = {};
371                 let validate = handler[kind + "_validate"];
372 
373                 for (let attr, attr_type in handler[kind]) {
374                         let val = attr_validate(attr_type, validate[attr]);
375                         if (val != null)
376                                 cur[attr] = val;
377                 }
378         }
379 
380         return ret;
381 }
382 
383 const ubus_obj = {
384         up: {
385                 args: wdev_args,
386                 call: function(req) {
387                         let mlo_dev = wireless.devices[wdev.mlo_name];
388                         if (mlo_dev)
389                                 mlo_dev.start();
390 
391                         return wdev_call(req, (dev) => {
392                                 dev.start();
393                                 return 0;
394                         });
395                 }
396         },
397         down: {
398                 args: wdev_args,
399                 call: function(req) {
400                         let mlo_dev = wireless.devices[wdev.mlo_name];
401                         if (mlo_dev)
402                                 mlo_dev.config_change = true;
403 
404                         return wdev_call(req, (dev) => {
405                                 dev.stop();
406                                 return 0;
407                         });
408                 }
409         },
410         reconf: {
411                 args: wdev_args,
412                 call: function(req) {
413                         let mlo_dev = wireless.devices[wdev.mlo_name];
414                         if (mlo_dev)
415                                 mlo_dev.update();
416 
417                         return wdev_call(req, (dev) => {
418                                 dev.update();
419                                 return 0;
420                         });
421                 }
422         },
423         status: {
424                 args: wdev_args,
425                 call: function(req) {
426                         let ret = {};
427                         let err = wdev_call(req, (dev) => {
428                                 ret[dev.data.name] = dev.status();
429                                 return 0;
430                         });
431                         if (err != 0)
432                                 return err;
433 
434                         return ret;
435                 }
436         },
437         notify: {
438                 args: {
439                         ...wdev_args,
440                         command: 0,
441                         interface: "",
442                         vlan: "",
443                         data: {},
444                 },
445                 call: function(req) {
446                         let dev = req.args.device;
447                         if (!dev)
448                                 return libubus.STATUS_INVALID_ARGUMENT;
449 
450                         dev = wireless.devices[dev];
451                         if (!dev)
452                                 return libubus.STATUS_NOT_FOUND;
453 
454                         return dev.notify(req);
455                 }
456         },
457         get_validate: {
458                 args: wdev_args,
459                 call: function(req) {
460                         let ret = {};
461                         let err = wdev_call(req, (dev) => {
462                                 let dev_type = dev.data.config.type;
463                                 let cur = ret[dev.data.name] = {};
464                                 get_validate_info(cur, wireless.handlers[dev_type]);
465                                 return 0;
466                         });
467                         if (err != 0)
468                                 return err;
469 
470                         return ret;
471                 }
472         },
473 };
474 
475 
476 handler_load(wireless.path, (script, data) => {
477         if (!data.name)
478                 return;
479 
480         let handler = wireless.handlers[data.name] = {
481                 script,
482         };
483         for (let kind, attr in default_config_attr) {
484                 let validate = handler[kind + "_validate"] = {};
485                 handler[kind] = handler_attributes(data[kind], attr, validate);
486         }
487 });
488 
489 wireless.obj = ubus.publish("network.wireless", ubus_obj);
490 
491 return {
492         hotplug,
493         config_init,
494         config_start,
495         check_interfaces,
496 };

This page was automatically generated by LXR 0.3.1.  •  OpenWrt