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

Sources/netifd/bridge.c

  1 /*
  2  * netifd - network interface daemon
  3  * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU General Public License version 2
  7  * as published by the Free Software Foundation
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  */
 14 #include <string.h>
 15 #include <stdlib.h>
 16 #include <stdio.h>
 17 #include <assert.h>
 18 #include <errno.h>
 19 
 20 #include "netifd.h"
 21 #include "device.h"
 22 #include "interface.h"
 23 #include "system.h"
 24 #include "ubus.h"
 25 
 26 enum {
 27         BRIDGE_ATTR_PORTS,
 28         BRIDGE_ATTR_STP,
 29         BRIDGE_ATTR_FORWARD_DELAY,
 30         BRIDGE_ATTR_PRIORITY,
 31         BRIDGE_ATTR_IGMP_SNOOP,
 32         BRIDGE_ATTR_AGEING_TIME,
 33         BRIDGE_ATTR_HELLO_TIME,
 34         BRIDGE_ATTR_MAX_AGE,
 35         BRIDGE_ATTR_BRIDGE_EMPTY,
 36         BRIDGE_ATTR_MULTICAST_QUERIER,
 37         BRIDGE_ATTR_HASH_MAX,
 38         BRIDGE_ATTR_ROBUSTNESS,
 39         BRIDGE_ATTR_QUERY_INTERVAL,
 40         BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL,
 41         BRIDGE_ATTR_LAST_MEMBER_INTERVAL,
 42         BRIDGE_ATTR_VLAN_FILTERING,
 43         BRIDGE_ATTR_HAS_VLANS,
 44         BRIDGE_ATTR_STP_KERNEL,
 45         BRIDGE_ATTR_STP_PROTO,
 46         __BRIDGE_ATTR_MAX
 47 };
 48 
 49 static const struct blobmsg_policy bridge_attrs[__BRIDGE_ATTR_MAX] = {
 50         [BRIDGE_ATTR_PORTS] = { "ports", BLOBMSG_TYPE_ARRAY },
 51         [BRIDGE_ATTR_STP] = { "stp", BLOBMSG_TYPE_BOOL },
 52         [BRIDGE_ATTR_FORWARD_DELAY] = { "forward_delay", BLOBMSG_TYPE_INT32 },
 53         [BRIDGE_ATTR_PRIORITY] = { "priority", BLOBMSG_TYPE_INT32 },
 54         [BRIDGE_ATTR_AGEING_TIME] = { "ageing_time", BLOBMSG_TYPE_INT32 },
 55         [BRIDGE_ATTR_HELLO_TIME] = { "hello_time", BLOBMSG_TYPE_INT32 },
 56         [BRIDGE_ATTR_MAX_AGE] = { "max_age", BLOBMSG_TYPE_INT32 },
 57         [BRIDGE_ATTR_IGMP_SNOOP] = { "igmp_snooping", BLOBMSG_TYPE_BOOL },
 58         [BRIDGE_ATTR_BRIDGE_EMPTY] = { "bridge_empty", BLOBMSG_TYPE_BOOL },
 59         [BRIDGE_ATTR_MULTICAST_QUERIER] = { "multicast_querier", BLOBMSG_TYPE_BOOL },
 60         [BRIDGE_ATTR_HASH_MAX] = { "hash_max", BLOBMSG_TYPE_INT32 },
 61         [BRIDGE_ATTR_ROBUSTNESS] = { "robustness", BLOBMSG_TYPE_INT32 },
 62         [BRIDGE_ATTR_QUERY_INTERVAL] = { "query_interval", BLOBMSG_TYPE_INT32 },
 63         [BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL] = { "query_response_interval", BLOBMSG_TYPE_INT32 },
 64         [BRIDGE_ATTR_LAST_MEMBER_INTERVAL] = { "last_member_interval", BLOBMSG_TYPE_INT32 },
 65         [BRIDGE_ATTR_VLAN_FILTERING] = { "vlan_filtering", BLOBMSG_TYPE_BOOL },
 66         [BRIDGE_ATTR_HAS_VLANS] = { "__has_vlans", BLOBMSG_TYPE_BOOL }, /* internal */
 67         [BRIDGE_ATTR_STP_KERNEL] = { "stp_kernel", BLOBMSG_TYPE_BOOL },
 68         [BRIDGE_ATTR_STP_PROTO] = { "stp_proto", BLOBMSG_TYPE_STRING },
 69 };
 70 
 71 static const struct uci_blob_param_info bridge_attr_info[__BRIDGE_ATTR_MAX] = {
 72         [BRIDGE_ATTR_PORTS] = { .type = BLOBMSG_TYPE_STRING },
 73 };
 74 
 75 static const struct uci_blob_param_list bridge_attr_list = {
 76         .n_params = __BRIDGE_ATTR_MAX,
 77         .params = bridge_attrs,
 78         .info = bridge_attr_info,
 79 
 80         .n_next = 1,
 81         .next = { &device_attr_list },
 82 };
 83 
 84 static struct blob_buf b;
 85 static struct device *bridge_create(const char *name, struct device_type *devtype,
 86         struct blob_attr *attr);
 87 static void bridge_config_init(struct device *dev);
 88 static void bridge_dev_vlan_update(struct device *dev);
 89 static void bridge_free(struct device *dev);
 90 static void bridge_stp_init(struct device *dev);
 91 static void bridge_dump_info(struct device *dev, struct blob_buf *b);
 92 static enum dev_change_type
 93 bridge_reload(struct device *dev, struct blob_attr *attr);
 94 
 95 static struct device_type bridge_device_type = {
 96         .name = "bridge",
 97         .config_params = &bridge_attr_list,
 98 
 99         .bridge_capability = true,
100         .name_prefix = "br",
101 
102         .create = bridge_create,
103         .config_init = bridge_config_init,
104         .vlan_update = bridge_dev_vlan_update,
105         .reload = bridge_reload,
106         .free = bridge_free,
107         .dump_info = bridge_dump_info,
108         .stp_init = bridge_stp_init,
109 };
110 
111 struct bridge_state {
112         struct device dev;
113         device_state_cb set_state;
114 
115         struct blob_attr *config_data;
116         struct bridge_config config;
117         struct blob_attr *ports;
118         bool active;
119         bool force_active;
120         bool has_vlans;
121 
122         struct uloop_timeout retry;
123         struct bridge_member *primary_port;
124         struct vlist_tree members;
125         int n_present;
126         int n_failed;
127 };
128 
129 struct bridge_member {
130         struct vlist_node node;
131         struct bridge_state *bst;
132         struct device_user dev;
133         struct uloop_timeout check_timer;
134         struct device_vlan_range *extra_vlan;
135         int n_extra_vlan;
136         uint16_t pvid;
137         bool present;
138         bool active;
139         char name[];
140 };
141 
142 static void
143 bridge_reset_primary(struct bridge_state *bst)
144 {
145         struct bridge_member *bm;
146 
147         if (!bst->primary_port &&
148             (bst->dev.settings.flags & DEV_OPT_MACADDR))
149                 return;
150 
151         bst->primary_port = NULL;
152         bst->dev.settings.flags &= ~DEV_OPT_MACADDR;
153         vlist_for_each_element(&bst->members, bm, node) {
154                 uint8_t *macaddr;
155 
156                 if (!bm->present)
157                         continue;
158 
159                 bst->primary_port = bm;
160                 if (bm->dev.dev->settings.flags & DEV_OPT_MACADDR)
161                         macaddr = bm->dev.dev->settings.macaddr;
162                 else
163                         macaddr = bm->dev.dev->orig_settings.macaddr;
164                 memcpy(bst->dev.settings.macaddr, macaddr, 6);
165                 bst->dev.settings.flags |= DEV_OPT_MACADDR;
166                 return;
167         }
168 }
169 
170 static struct bridge_vlan_port *
171 bridge_find_vlan_member_port(struct bridge_member *bm, struct bridge_vlan *vlan)
172 {
173         struct bridge_vlan_hotplug_port *port;
174         const char *ifname = bm->dev.dev->ifname;
175         int i;
176 
177         for (i = 0; i < vlan->n_ports; i++) {
178                 if (strcmp(vlan->ports[i].ifname, ifname) != 0)
179                         continue;
180 
181                 return &vlan->ports[i];
182         }
183 
184         list_for_each_entry(port, &vlan->hotplug_ports, list) {
185                 if (strcmp(port->port.ifname, ifname) != 0)
186                         continue;
187 
188                 return &port->port;
189         }
190 
191         return NULL;
192 }
193 
194 static bool
195 bridge_member_vlan_is_pvid(struct bridge_member *bm, struct bridge_vlan_port *port)
196 {
197         return (!bm->pvid && (port->flags & BRVLAN_F_UNTAGGED)) ||
198                (port->flags & BRVLAN_F_PVID);
199 }
200 
201 static void
202 __bridge_set_member_vlan(struct bridge_member *bm, struct bridge_vlan *vlan,
203                          struct bridge_vlan_port *port, bool add)
204 {
205         uint16_t flags;
206 
207         flags = port->flags;
208         if (bm->pvid == vlan->vid)
209                 flags |= BRVLAN_F_PVID;
210 
211         system_bridge_vlan(port->ifname, vlan->vid, -1, add, flags);
212 }
213 
214 static void
215 bridge_set_member_vlan(struct bridge_member *bm, struct bridge_vlan *vlan, bool add)
216 {
217         struct bridge_vlan_port *port;
218 
219         if (!bm->present)
220                 return;
221 
222         port = bridge_find_vlan_member_port(bm, vlan);
223         if (!port)
224                 return;
225 
226         if (bridge_member_vlan_is_pvid(bm, port))
227                 bm->pvid = vlan->vid;
228 
229         __bridge_set_member_vlan(bm, vlan, port, add);
230 }
231 
232 static void
233 bridge_set_local_vlan(struct bridge_state *bst, struct bridge_vlan *vlan, bool add)
234 {
235         if (!vlan->local && add)
236                 return;
237 
238         system_bridge_vlan(bst->dev.ifname, vlan->vid, -1, add, BRVLAN_F_SELF);
239 }
240 
241 static void
242 bridge_set_local_vlans(struct bridge_state *bst, bool add)
243 {
244         struct bridge_vlan *vlan;
245 
246         vlist_for_each_element(&bst->dev.vlans, vlan, node)
247                 bridge_set_local_vlan(bst, vlan, add);
248 }
249 
250 static struct bridge_vlan *
251 bridge_recalc_member_pvid(struct bridge_member *bm)
252 {
253         struct bridge_state *bst = bm->bst;
254         struct bridge_vlan_port *port;
255         struct bridge_vlan *vlan, *ret = NULL;
256 
257         vlist_for_each_element(&bst->dev.vlans, vlan, node) {
258                 port = bridge_find_vlan_member_port(bm, vlan);
259                 if (!port)
260                         continue;
261 
262                 if (!bridge_member_vlan_is_pvid(bm, port))
263                         continue;
264 
265                 ret = vlan;
266                 if (port->flags & BRVLAN_F_PVID)
267                         break;
268         }
269 
270         return ret;
271 }
272 
273 static void
274 bridge_set_vlan_state(struct bridge_state *bst, struct bridge_vlan *vlan, bool add)
275 {
276         struct bridge_member *bm;
277         struct bridge_vlan *vlan2;
278 
279         bridge_set_local_vlan(bst, vlan, add);
280 
281         vlist_for_each_element(&bst->members, bm, node) {
282                 struct bridge_vlan_port *port;
283                 int new_pvid = -1;
284 
285                 port = bridge_find_vlan_member_port(bm, vlan);
286                 if (!port)
287                         continue;
288 
289                 if (add) {
290                         if (bridge_member_vlan_is_pvid(bm, port))
291                                 bm->pvid = vlan->vid;
292                 } else if (bm->pvid == vlan->vid) {
293                         vlan2 = bridge_recalc_member_pvid(bm);
294                         if (vlan2 && vlan2->vid != vlan->vid) {
295                                 bridge_set_member_vlan(bm, vlan2, false);
296                                 bridge_set_member_vlan(bm, vlan2, true);
297                         }
298                         new_pvid = vlan2 ? vlan2->vid : 0;
299                 }
300 
301                 if (!bm->present)
302                         continue;
303 
304                 __bridge_set_member_vlan(bm, vlan, port, add);
305                 if (new_pvid >= 0)
306                         bm->pvid = new_pvid;
307         }
308 }
309 
310 static int
311 bridge_disable_member(struct bridge_member *bm, bool keep_dev)
312 {
313         struct bridge_state *bst = bm->bst;
314         struct bridge_vlan *vlan;
315 
316         if (!bm->present || !bm->active)
317                 return 0;
318 
319         bm->active = false;
320         vlist_for_each_element(&bst->dev.vlans, vlan, node)
321                 bridge_set_member_vlan(bm, vlan, false);
322 
323         system_bridge_delif(&bst->dev, bm->dev.dev);
324         if (!keep_dev)
325                 device_release(&bm->dev);
326 
327         device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE);
328 
329         return 0;
330 }
331 
332 static void bridge_stp_notify(struct bridge_state *bst)
333 {
334         struct bridge_config *cfg = &bst->config;
335 
336         if (!cfg->stp || cfg->stp_kernel)
337                 return;
338 
339         blob_buf_init(&b, 0);
340         blobmsg_add_string(&b, "name", bst->dev.ifname);
341         if (cfg->stp_proto)
342                 blobmsg_add_string(&b, "proto", cfg->stp_proto);
343         blobmsg_add_u32(&b, "forward_delay", cfg->forward_delay);
344         blobmsg_add_u32(&b, "hello_time", cfg->hello_time);
345         blobmsg_add_u32(&b, "max_age", cfg->max_age);
346         if (cfg->flags & BRIDGE_OPT_AGEING_TIME)
347                 blobmsg_add_u32(&b, "ageing_time", cfg->ageing_time);
348         netifd_ubus_device_notify("stp_init", b.head, 1000);
349 }
350 
351 static int
352 bridge_enable_interface(struct bridge_state *bst)
353 {
354         struct device *dev = &bst->dev;
355         int i, ret;
356 
357         if (bst->active)
358                 return 0;
359 
360         bridge_stp_notify(bst);
361         ret = system_bridge_addbr(dev, &bst->config);
362         if (ret < 0)
363                 return ret;
364 
365         if (bst->has_vlans) {
366                 /* delete default VLAN 1 */
367                 system_bridge_vlan(bst->dev.ifname, 1, -1, false, BRVLAN_F_SELF);
368 
369                 bridge_set_local_vlans(bst, true);
370         }
371 
372         for (i = 0; i < dev->n_extra_vlan; i++)
373                 system_bridge_vlan(dev->ifname, dev->extra_vlan[i].start,
374                                    dev->extra_vlan[i].end, true, BRVLAN_F_SELF);
375 
376         bst->active = true;
377         return 0;
378 }
379 
380 static void
381 bridge_stp_init(struct device *dev)
382 {
383         struct bridge_state *bst;
384 
385         bst = container_of(dev, struct bridge_state, dev);
386         if (!bst->config.stp || !bst->active)
387                 return;
388 
389         bridge_stp_notify(bst);
390         system_bridge_set_stp_state(&bst->dev, false);
391         system_bridge_set_stp_state(&bst->dev, true);
392 }
393 
394 static void
395 bridge_disable_interface(struct bridge_state *bst)
396 {
397         if (!bst->active)
398                 return;
399 
400         system_bridge_delbr(&bst->dev);
401         bst->active = false;
402 }
403 
404 static void
405 bridge_member_add_extra_vlans(struct bridge_member *bm)
406 {
407         struct device *dev = bm->dev.dev;
408         int i;
409 
410         for (i = 0; i < dev->n_extra_vlan; i++)
411                 system_bridge_vlan(dev->ifname, dev->extra_vlan[i].start,
412                                    dev->extra_vlan[i].end, true, 0);
413         for (i = 0; i < bm->n_extra_vlan; i++)
414                 system_bridge_vlan(dev->ifname, bm->extra_vlan[i].start,
415                                    bm->extra_vlan[i].end, true, 0);
416 }
417 
418 static int
419 bridge_enable_member(struct bridge_member *bm)
420 {
421         struct bridge_state *bst = bm->bst;
422         struct bridge_vlan *vlan;
423         struct device *dev;
424         int ret;
425 
426         if (!bm->present)
427                 return 0;
428 
429         ret = bridge_enable_interface(bst);
430         if (ret)
431                 goto error;
432 
433         /* Disable IPv6 for bridge members */
434         if (!(bm->dev.dev->settings.flags & DEV_OPT_IPV6)) {
435                 bm->dev.dev->settings.ipv6 = 0;
436                 bm->dev.dev->settings.flags |= DEV_OPT_IPV6;
437         }
438 
439         ret = device_claim(&bm->dev);
440         if (ret < 0)
441                 goto error;
442 
443         dev = bm->dev.dev;
444         if (dev->settings.auth && !dev->auth_status)
445                 return -1;
446 
447         if (bm->active)
448                 return 0;
449 
450         ret = system_bridge_addif(&bst->dev, bm->dev.dev);
451         if (ret < 0) {
452                 D(DEVICE, "Bridge device %s could not be added\n", bm->dev.dev->ifname);
453                 goto error;
454         }
455 
456         bm->active = true;
457         if (bst->has_vlans) {
458                 /* delete default VLAN 1 */
459                 system_bridge_vlan(bm->dev.dev->ifname, 1, -1, false, 0);
460 
461                 bridge_member_add_extra_vlans(bm);
462                 vlist_for_each_element(&bst->dev.vlans, vlan, node)
463                         bridge_set_member_vlan(bm, vlan, true);
464         }
465 
466         device_set_present(&bst->dev, true);
467         device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE);
468 
469         return 0;
470 
471 error:
472         bst->n_failed++;
473         bm->present = false;
474         bst->n_present--;
475         device_release(&bm->dev);
476 
477         return ret;
478 }
479 
480 static void
481 bridge_remove_member(struct bridge_member *bm)
482 {
483         struct bridge_state *bst = bm->bst;
484 
485         if (!bm->present)
486                 return;
487 
488         if (bst->dev.active)
489                 bridge_disable_member(bm, false);
490 
491         bm->present = false;
492         bm->bst->n_present--;
493 
494         if (bm == bst->primary_port)
495                 bridge_reset_primary(bst);
496 
497         if (bst->config.bridge_empty)
498                 return;
499 
500         bst->force_active = false;
501         if (bst->n_present == 0)
502                 device_set_present(&bst->dev, false);
503 }
504 
505 static void
506 bridge_free_member(struct bridge_member *bm)
507 {
508         struct bridge_state *bst = bm->bst;
509         struct device *dev = bm->dev.dev;
510         const char *ifname = dev->ifname;
511         struct bridge_vlan *vlan;
512 
513         bridge_remove_member(bm);
514 
515 restart:
516         vlist_for_each_element(&bst->dev.vlans, vlan, node) {
517                 struct bridge_vlan_hotplug_port *port, *tmp;
518                 bool free_port = false;
519 
520                 list_for_each_entry_safe(port, tmp, &vlan->hotplug_ports, list) {
521                         if (strcmp(port->port.ifname, ifname) != 0)
522                                 continue;
523 
524                         list_del(&port->list);
525                         free(port);
526                         free_port = true;
527                 }
528 
529                 if (!free_port || !list_empty(&vlan->hotplug_ports) ||
530                     vlan->n_ports || vlan->node.version != -1)
531                         continue;
532 
533                 vlist_delete(&bst->dev.vlans, &vlan->node);
534                 goto restart;
535         }
536 
537         device_remove_user(&bm->dev);
538         uloop_timeout_cancel(&bm->check_timer);
539 
540         /*
541          * When reloading the config and moving a device from one bridge to
542          * another, the other bridge may have tried to claim this device
543          * before it was removed here.
544          * Ensure that claiming the device is retried by toggling its present
545          * state
546          */
547         if (dev->present) {
548                 device_set_present(dev, false);
549                 device_set_present(dev, true);
550         }
551 
552         free(bm);
553 }
554 
555 static void
556 bridge_check_retry(struct bridge_state *bst)
557 {
558         if (!bst->n_failed)
559                 return;
560 
561         uloop_timeout_set(&bst->retry, 100);
562 }
563 
564 static void
565 bridge_member_check_cb(struct uloop_timeout *t)
566 {
567         struct bridge_member *bm;
568         struct bridge_state *bst;
569 
570         bm = container_of(t, struct bridge_member, check_timer);
571         bst = bm->bst;
572 
573         if (system_bridge_vlan_check(&bst->dev, bm->dev.dev->ifname) <= 0)
574                 return;
575 
576         bridge_disable_member(bm, true);
577         bridge_enable_member(bm);
578 }
579 
580 static void
581 bridge_member_cb(struct device_user *dep, enum device_event ev)
582 {
583         struct bridge_member *bm = container_of(dep, struct bridge_member, dev);
584         struct bridge_state *bst = bm->bst;
585         struct device *dev = dep->dev;
586 
587         switch (ev) {
588         case DEV_EVENT_ADD:
589                 assert(!bm->present);
590 
591                 bm->present = true;
592                 bst->n_present++;
593 
594                 if (bst->n_present == 1)
595                         device_set_present(&bst->dev, true);
596                 fallthrough;
597         case DEV_EVENT_AUTH_UP:
598                 if (!bst->dev.active)
599                         break;
600 
601                 if (bridge_enable_member(bm))
602                         break;
603 
604                 /*
605                  * Adding a bridge member can overwrite the bridge mtu
606                  * in the kernel, apply the bridge settings in case the
607                  * bridge mtu is set
608                  */
609                 system_if_apply_settings(&bst->dev, &bst->dev.settings,
610                                          DEV_OPT_MTU | DEV_OPT_MTU6);
611                 break;
612         case DEV_EVENT_LINK_UP:
613                 if (bst->has_vlans)
614                         uloop_timeout_set(&bm->check_timer, 1000);
615                 break;
616         case DEV_EVENT_LINK_DOWN:
617                 if (!dev->settings.auth)
618                         break;
619 
620                 bridge_disable_member(bm, true);
621                 break;
622         case DEV_EVENT_REMOVE:
623                 if (dep->hotplug) {
624                         vlist_delete(&bst->members, &bm->node);
625                         return;
626                 }
627 
628                 if (bm->present)
629                         bridge_remove_member(bm);
630 
631                 break;
632         default:
633                 return;
634         }
635 }
636 
637 static int
638 bridge_set_down(struct bridge_state *bst)
639 {
640         struct bridge_member *bm;
641 
642         bst->set_state(&bst->dev, false);
643 
644         vlist_for_each_element(&bst->members, bm, node)
645                 bridge_disable_member(bm, false);
646 
647         bridge_disable_interface(bst);
648 
649         return 0;
650 }
651 
652 static int
653 bridge_set_up(struct bridge_state *bst)
654 {
655         struct bridge_member *bm;
656         int ret;
657 
658         bst->has_vlans = !avl_is_empty(&bst->dev.vlans.avl);
659         if (!bst->n_present) {
660                 if (!bst->force_active)
661                         return -ENOENT;
662 
663                 ret = bridge_enable_interface(bst);
664                 if (ret)
665                         return ret;
666         }
667 
668         bst->n_failed = 0;
669         vlist_for_each_element(&bst->members, bm, node)
670                 bridge_enable_member(bm);
671         bridge_check_retry(bst);
672 
673         if (!bst->force_active && !bst->n_present) {
674                 /* initialization of all member interfaces failed */
675                 bridge_disable_interface(bst);
676                 device_set_present(&bst->dev, false);
677                 return -ENOENT;
678         }
679 
680         bridge_reset_primary(bst);
681         ret = bst->set_state(&bst->dev, true);
682         if (ret < 0)
683                 bridge_set_down(bst);
684 
685         return ret;
686 }
687 
688 static int
689 bridge_set_state(struct device *dev, bool up)
690 {
691         struct bridge_state *bst;
692 
693         bst = container_of(dev, struct bridge_state, dev);
694 
695         if (up)
696                 return bridge_set_up(bst);
697         else
698                 return bridge_set_down(bst);
699 }
700 
701 static struct bridge_member *
702 bridge_alloc_member(struct bridge_state *bst, const char *name,
703                     struct device *dev, bool hotplug)
704 {
705         struct bridge_member *bm;
706 
707         bm = calloc(1, sizeof(*bm) + strlen(name) + 1);
708         if (!bm)
709                 return NULL;
710 
711         bm->bst = bst;
712         bm->dev.cb = bridge_member_cb;
713         bm->dev.hotplug = hotplug;
714         bm->check_timer.cb = bridge_member_check_cb;
715         strcpy(bm->name, name);
716         bm->dev.dev = dev;
717 
718         return bm;
719 }
720 
721 static void bridge_insert_member(struct bridge_member *bm, const char *name)
722 {
723         struct bridge_state *bst = bm->bst;
724         bool hotplug = bm->dev.hotplug;
725 
726         vlist_add(&bst->members, &bm->node, bm->name);
727         /*
728          * Need to look up the bridge member again as the above
729          * created pointer will be freed in case the bridge member
730          * already existed
731          */
732         bm = vlist_find(&bst->members, name, bm, node);
733         if (hotplug && bm)
734                 bm->node.version = -1;
735 }
736 
737 static void
738 bridge_create_member(struct bridge_state *bst, const char *name,
739                      struct device *dev, bool hotplug)
740 {
741         struct bridge_member *bm;
742 
743         bm = bridge_alloc_member(bst, name, dev, hotplug);
744         if (bm)
745                 bridge_insert_member(bm, name);
746 }
747 
748 static void
749 bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new,
750                      struct vlist_node *node_old)
751 {
752         struct bridge_member *bm;
753         struct device *dev;
754 
755         if (node_new) {
756                 bm = container_of(node_new, struct bridge_member, node);
757 
758                 if (node_old) {
759                         free(bm);
760                         return;
761                 }
762 
763                 dev = bm->dev.dev;
764                 bm->dev.dev = NULL;
765                 device_add_user(&bm->dev, dev);
766         }
767 
768 
769         if (node_old) {
770                 bm = container_of(node_old, struct bridge_member, node);
771                 bridge_free_member(bm);
772         }
773 }
774 
775 
776 static void
777 bridge_add_member(struct bridge_state *bst, const char *name)
778 {
779         struct device *dev;
780 
781         dev = device_get(name, true);
782         if (!dev)
783                 return;
784 
785         bridge_create_member(bst, name, dev, false);
786 }
787 
788 static struct bridge_vlan *
789 bridge_hotplug_get_vlan(struct bridge_state *bst, uint16_t vid, bool create)
790 {
791         struct bridge_vlan *vlan;
792 
793         vlan = vlist_find(&bst->dev.vlans, &vid, vlan, node);
794         if (vlan || !create)
795                 return vlan;
796 
797         vlan = calloc(1, sizeof(*vlan));
798         vlan->vid = vid;
799         vlan->local = true;
800         INIT_LIST_HEAD(&vlan->hotplug_ports);
801         vlist_add(&bst->dev.vlans, &vlan->node, &vlan->vid);
802         vlan->node.version = -1;
803 
804         return vlan;
805 }
806 
807 static struct bridge_vlan_hotplug_port *
808 bridge_hotplug_get_vlan_port(struct bridge_vlan *vlan, const char *ifname)
809 {
810         struct bridge_vlan_hotplug_port *port;
811 
812         list_for_each_entry(port, &vlan->hotplug_ports, list)
813                 if (!strcmp(port->port.ifname, ifname))
814                         return port;
815 
816         return NULL;
817 }
818 
819 static void
820 bridge_hotplug_set_member_vlans(struct bridge_state *bst, struct blob_attr *vlans,
821                                 const char *ifname, struct bridge_member *bm, bool add)
822 {
823         struct device_vlan_range *r;
824         struct bridge_vlan *vlan;
825         struct blob_attr *cur;
826         int n_vlans;
827         size_t rem;
828 
829         if (!vlans)
830                 return;
831 
832         if (add) {
833                 bm->n_extra_vlan = 0;
834                 n_vlans = blobmsg_check_array(vlans, BLOBMSG_TYPE_STRING);
835                 if (n_vlans < 1)
836                         return;
837 
838                 bm->extra_vlan = realloc(bm->extra_vlan, n_vlans * sizeof(*bm->extra_vlan));
839         }
840 
841         blobmsg_for_each_attr(cur, vlans, rem) {
842                 struct bridge_vlan_hotplug_port *port;
843                 unsigned int vid, vid_end;
844                 uint16_t flags = 0;
845                 char *name_buf;
846                 char *end;
847 
848                 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
849                         continue;
850 
851                 vid = strtoul(blobmsg_get_string(cur), &end, 0);
852                 vid_end = vid;
853                 if (!vid || vid > 4095)
854                         continue;
855 
856                 if (*end == '-') {
857                         vid_end = strtoul(end + 1, &end, 0);
858                         if (vid_end < vid)
859                                 continue;
860                 }
861 
862                 if (end && *end) {
863                         if (*end != ':')
864                                 continue;
865 
866                         for (end++; *end; end++) {
867                                 switch (*end) {
868                                 case 'u':
869                                         flags |= BRVLAN_F_UNTAGGED;
870                                         break;
871                                 case '*':
872                                         flags |= BRVLAN_F_PVID;
873                                         break;
874                                 }
875                         }
876                 }
877 
878                 vlan = bridge_hotplug_get_vlan(bst, vid, !!flags);
879                 if (!vlan || vid_end > vid) {
880                         if (add) {
881                                 r = &bm->extra_vlan[bm->n_extra_vlan++];
882                                 r->start = vid;
883                                 r->end = vid_end;
884                                 if (bm->active)
885                                         system_bridge_vlan(ifname, vid, vid_end, true, 0);
886                         } else if (bm->active) {
887                                 system_bridge_vlan(ifname, vid, vid_end, false, 0);
888                         }
889                         continue;
890                 }
891 
892                 if (vlan->pending) {
893                         vlan->pending = false;
894                         bridge_set_vlan_state(bst, vlan, true);
895                 }
896 
897                 port = bridge_hotplug_get_vlan_port(vlan, ifname);
898                 if (!add) {
899                         if (!port)
900                                 continue;
901 
902                         __bridge_set_member_vlan(bm, vlan, &port->port, false);
903                         list_del(&port->list);
904                         free(port);
905                         continue;
906                 }
907 
908                 if (port) {
909                         if (port->port.flags == flags)
910                                 continue;
911 
912                         __bridge_set_member_vlan(bm, vlan, &port->port, false);
913                         port->port.flags = flags;
914                         __bridge_set_member_vlan(bm, vlan, &port->port, true);
915                         continue;
916                 }
917 
918                 port = calloc_a(sizeof(*port), &name_buf, strlen(ifname) + 1);
919                 if (!port)
920                         continue;
921 
922                 port->port.flags = flags;
923                 port->port.ifname = strcpy(name_buf, ifname);
924                 list_add_tail(&port->list, &vlan->hotplug_ports);
925 
926                 if (!bm)
927                         continue;
928 
929                 __bridge_set_member_vlan(bm, vlan, &port->port, true);
930         }
931 }
932 
933 static int
934 bridge_hotplug_add(struct device *dev, struct device *member, struct blob_attr *vlan)
935 {
936         struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
937         struct bridge_member *bm;
938         bool new_entry = false;
939 
940         bm = vlist_find(&bst->members, member->ifname, bm, node);
941         if (!bm) {
942             new_entry = true;
943             bm = bridge_alloc_member(bst, member->ifname, member, true);
944         }
945         bridge_hotplug_set_member_vlans(bst, vlan, member->ifname, bm, true);
946         if (new_entry)
947                 bridge_insert_member(bm, member->ifname);
948 
949         return 0;
950 }
951 
952 static int
953 bridge_hotplug_del(struct device *dev, struct device *member, struct blob_attr *vlan)
954 {
955         struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
956         struct bridge_member *bm;
957 
958         bm = vlist_find(&bst->members, member->ifname, bm, node);
959         if (!bm)
960                 return UBUS_STATUS_NOT_FOUND;
961 
962         bridge_hotplug_set_member_vlans(bst, vlan, member->ifname, bm, false);
963         if (!bm->dev.hotplug)
964                 return 0;
965 
966         vlist_delete(&bst->members, &bm->node);
967         return 0;
968 }
969 
970 static int
971 bridge_hotplug_prepare(struct device *dev, struct device **bridge_dev)
972 {
973         struct bridge_state *bst;
974 
975         if (bridge_dev)
976                 *bridge_dev = dev;
977 
978         bst = container_of(dev, struct bridge_state, dev);
979         bst->force_active = true;
980         device_set_present(&bst->dev, true);
981 
982         return 0;
983 }
984 
985 static const struct device_hotplug_ops bridge_ops = {
986         .prepare = bridge_hotplug_prepare,
987         .add = bridge_hotplug_add,
988         .del = bridge_hotplug_del
989 };
990 
991 static void
992 bridge_free(struct device *dev)
993 {
994         struct bridge_state *bst;
995 
996         bst = container_of(dev, struct bridge_state, dev);
997         vlist_flush_all(&bst->members);
998         vlist_flush_all(&dev->vlans);
999         kvlist_free(&dev->vlan_aliases);
1000         free(bst->config_data);
1001         free(bst);
1002 }
1003 
1004 static void
1005 bridge_dump_port(struct blob_buf *b, struct bridge_vlan_port *port)
1006 {
1007         bool tagged = !(port->flags & BRVLAN_F_UNTAGGED);
1008         bool pvid = (port->flags & BRVLAN_F_PVID);
1009 
1010         blobmsg_printf(b, NULL, "%s%s%s%s", port->ifname,
1011                 tagged || pvid ? ":" : "",
1012                 tagged ? "t" : "",
1013                 pvid ? "*" : "");
1014 }
1015 
1016 static void
1017 bridge_dump_vlan(struct blob_buf *b, struct bridge_vlan *vlan)
1018 {
1019         struct bridge_vlan_hotplug_port *port;
1020         void *c, *p;
1021         int i;
1022 
1023         c = blobmsg_open_table(b, NULL);
1024 
1025         blobmsg_add_u32(b, "id", vlan->vid);
1026         blobmsg_add_u8(b, "local", vlan->local);
1027 
1028         p = blobmsg_open_array(b, "ports");
1029 
1030         for (i = 0; i < vlan->n_ports; i++)
1031             bridge_dump_port(b, &vlan->ports[i]);
1032 
1033         list_for_each_entry(port, &vlan->hotplug_ports, list)
1034                 bridge_dump_port(b, &port->port);
1035 
1036         blobmsg_close_array(b, p);
1037 
1038         blobmsg_close_table(b, c);
1039 }
1040 
1041 static void
1042 bridge_dump_info(struct device *dev, struct blob_buf *b)
1043 {
1044         struct bridge_config *cfg;
1045         struct bridge_state *bst;
1046         struct bridge_member *bm;
1047         struct bridge_vlan *vlan;
1048         void *list;
1049         void *c;
1050 
1051         bst = container_of(dev, struct bridge_state, dev);
1052         cfg = &bst->config;
1053 
1054         system_if_dump_info(dev, b);
1055         list = blobmsg_open_array(b, "bridge-members");
1056 
1057         vlist_for_each_element(&bst->members, bm, node) {
1058                 if (bm->dev.dev->hidden)
1059                         continue;
1060 
1061                 blobmsg_add_string(b, NULL, bm->dev.dev->ifname);
1062         }
1063 
1064         blobmsg_close_array(b, list);
1065 
1066         c = blobmsg_open_table(b, "bridge-attributes");
1067 
1068         blobmsg_add_u8(b, "stp", cfg->stp);
1069         blobmsg_add_u32(b, "forward_delay", cfg->forward_delay);
1070         blobmsg_add_u32(b, "priority", cfg->priority);
1071         blobmsg_add_u32(b, "ageing_time", cfg->ageing_time);
1072         blobmsg_add_u32(b, "hello_time", cfg->hello_time);
1073         blobmsg_add_u32(b, "max_age", cfg->max_age);
1074         blobmsg_add_u8(b, "igmp_snooping", cfg->igmp_snoop);
1075         blobmsg_add_u8(b, "bridge_empty", cfg->bridge_empty);
1076         blobmsg_add_u8(b, "multicast_querier", cfg->multicast_querier);
1077         blobmsg_add_u32(b, "hash_max", cfg->hash_max);
1078         blobmsg_add_u32(b, "robustness", cfg->robustness);
1079         blobmsg_add_u32(b, "query_interval", cfg->query_interval);
1080         blobmsg_add_u32(b, "query_response_interval", cfg->query_response_interval);
1081         blobmsg_add_u32(b, "last_member_interval", cfg->last_member_interval);
1082         blobmsg_add_u8(b, "vlan_filtering", cfg->vlan_filtering);
1083         blobmsg_add_u8(b, "stp_kernel", cfg->stp_kernel);
1084         if (cfg->stp_proto)
1085                 blobmsg_add_string(b, "stp_proto", cfg->stp_proto);
1086 
1087         blobmsg_close_table(b, c);
1088 
1089         if (avl_is_empty(&dev->vlans.avl))
1090                 return;
1091 
1092         list = blobmsg_open_array(b, "bridge-vlans");
1093 
1094         vlist_for_each_element(&bst->dev.vlans, vlan, node)
1095                 bridge_dump_vlan(b, vlan);
1096 
1097         blobmsg_close_array(b, list);
1098 }
1099 
1100 static void
1101 bridge_config_init(struct device *dev)
1102 {
1103         struct bridge_state *bst;
1104         struct bridge_vlan *vlan;
1105         struct blob_attr *cur;
1106         size_t rem;
1107         int i;
1108 
1109         bst = container_of(dev, struct bridge_state, dev);
1110 
1111         if (bst->config.bridge_empty) {
1112                 bst->force_active = true;
1113                 device_set_present(&bst->dev, true);
1114         }
1115 
1116         bst->n_failed = 0;
1117         vlist_update(&bst->members);
1118         if (bst->ports) {
1119                 blobmsg_for_each_attr(cur, bst->ports, rem) {
1120                         bridge_add_member(bst, blobmsg_data(cur));
1121                 }
1122         }
1123 
1124         vlist_for_each_element(&bst->dev.vlans, vlan, node)
1125                 for (i = 0; i < vlan->n_ports; i++)
1126                         bridge_add_member(bst, vlan->ports[i].ifname);
1127 
1128         vlist_flush(&bst->members);
1129         bridge_check_retry(bst);
1130 }
1131 
1132 static void
1133 bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb)
1134 {
1135         struct bridge_config *cfg = &bst->config;
1136         struct blob_attr *cur;
1137 
1138         /* defaults */
1139         memset(cfg, 0, sizeof(*cfg));
1140         cfg->stp = false;
1141         cfg->stp_kernel = false;
1142         cfg->robustness = 2;
1143         cfg->igmp_snoop = false;
1144         cfg->multicast_querier = false;
1145         cfg->query_interval = 12500;
1146         cfg->query_response_interval = 1000;
1147         cfg->last_member_interval = 100;
1148         cfg->hash_max = 512;
1149         cfg->bridge_empty = false;
1150         cfg->priority = 0x7FFF;
1151         cfg->vlan_filtering = false;
1152 
1153         cfg->forward_delay = 8;
1154         cfg->max_age = 10;
1155         cfg->hello_time = 1;
1156 
1157         if ((cur = tb[BRIDGE_ATTR_STP]))
1158                 cfg->stp = blobmsg_get_bool(cur);
1159 
1160         if ((cur = tb[BRIDGE_ATTR_STP_KERNEL]))
1161                 cfg->stp = blobmsg_get_bool(cur);
1162 
1163         if ((cur = tb[BRIDGE_ATTR_STP_PROTO]))
1164                 cfg->stp_proto = blobmsg_get_string(cur);
1165 
1166         if ((cur = tb[BRIDGE_ATTR_FORWARD_DELAY]))
1167                 cfg->forward_delay = blobmsg_get_u32(cur);
1168 
1169         if ((cur = tb[BRIDGE_ATTR_PRIORITY]))
1170                 cfg->priority = blobmsg_get_u32(cur);
1171 
1172         if ((cur = tb[BRIDGE_ATTR_IGMP_SNOOP]))
1173                 cfg->multicast_querier = cfg->igmp_snoop = blobmsg_get_bool(cur);
1174 
1175         if ((cur = tb[BRIDGE_ATTR_MULTICAST_QUERIER]))
1176                 cfg->multicast_querier = blobmsg_get_bool(cur);
1177 
1178         if ((cur = tb[BRIDGE_ATTR_HASH_MAX]))
1179                 cfg->hash_max = blobmsg_get_u32(cur);
1180 
1181         if ((cur = tb[BRIDGE_ATTR_ROBUSTNESS])) {
1182                 cfg->robustness = blobmsg_get_u32(cur);
1183                 cfg->flags |= BRIDGE_OPT_ROBUSTNESS;
1184         }
1185 
1186         if ((cur = tb[BRIDGE_ATTR_QUERY_INTERVAL])) {
1187                 cfg->query_interval = blobmsg_get_u32(cur);
1188                 cfg->flags |= BRIDGE_OPT_QUERY_INTERVAL;
1189         }
1190 
1191         if ((cur = tb[BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL])) {
1192                 cfg->query_response_interval = blobmsg_get_u32(cur);
1193                 cfg->flags |= BRIDGE_OPT_QUERY_RESPONSE_INTERVAL;
1194         }
1195 
1196         if ((cur = tb[BRIDGE_ATTR_LAST_MEMBER_INTERVAL])) {
1197                 cfg->last_member_interval = blobmsg_get_u32(cur);
1198                 cfg->flags |= BRIDGE_OPT_LAST_MEMBER_INTERVAL;
1199         }
1200 
1201         if ((cur = tb[BRIDGE_ATTR_AGEING_TIME])) {
1202                 cfg->ageing_time = blobmsg_get_u32(cur);
1203                 cfg->flags |= BRIDGE_OPT_AGEING_TIME;
1204         }
1205 
1206         if ((cur = tb[BRIDGE_ATTR_HELLO_TIME]))
1207                 cfg->hello_time = blobmsg_get_u32(cur);
1208 
1209         if ((cur = tb[BRIDGE_ATTR_MAX_AGE]))
1210                 cfg->max_age = blobmsg_get_u32(cur);
1211 
1212         if ((cur = tb[BRIDGE_ATTR_BRIDGE_EMPTY]))
1213                 cfg->bridge_empty = blobmsg_get_bool(cur);
1214 
1215         if ((cur = tb[BRIDGE_ATTR_VLAN_FILTERING]))
1216                 cfg->vlan_filtering = blobmsg_get_bool(cur);
1217 }
1218 
1219 static enum dev_change_type
1220 bridge_reload(struct device *dev, struct blob_attr *attr)
1221 {
1222         struct blob_attr *tb_dev[__DEV_ATTR_MAX];
1223         struct blob_attr *tb_br[__BRIDGE_ATTR_MAX];
1224         enum dev_change_type ret = DEV_CONFIG_APPLIED;
1225         struct bridge_state *bst;
1226         unsigned long diff[2];
1227 
1228         BUILD_BUG_ON(sizeof(diff) < __BRIDGE_ATTR_MAX / BITS_PER_LONG);
1229         BUILD_BUG_ON(sizeof(diff) < __DEV_ATTR_MAX / BITS_PER_LONG);
1230 
1231         bst = container_of(dev, struct bridge_state, dev);
1232         attr = blob_memdup(attr);
1233 
1234         blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev,
1235                 blob_data(attr), blob_len(attr));
1236         blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, tb_br,
1237                 blob_data(attr), blob_len(attr));
1238 
1239         if (tb_dev[DEV_ATTR_MACADDR])
1240                 bst->primary_port = NULL;
1241 
1242         bst->ports = tb_br[BRIDGE_ATTR_PORTS];
1243         device_init_settings(dev, tb_dev);
1244         bridge_apply_settings(bst, tb_br);
1245 
1246         if (bst->config_data) {
1247                 struct blob_attr *otb_dev[__DEV_ATTR_MAX];
1248                 struct blob_attr *otb_br[__BRIDGE_ATTR_MAX];
1249 
1250                 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev,
1251                         blob_data(bst->config_data), blob_len(bst->config_data));
1252 
1253                 diff[0] = diff[1] = 0;
1254                 uci_blob_diff(tb_dev, otb_dev, &device_attr_list, diff);
1255                 if (diff[0] | diff[1]) {
1256                         ret = DEV_CONFIG_RESTART;
1257                         D(DEVICE, "Bridge %s device attributes have changed, diff=[%lx %lx]\n",
1258                           dev->ifname, diff[1], diff[0]);
1259                 }
1260 
1261                 blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, otb_br,
1262                         blob_data(bst->config_data), blob_len(bst->config_data));
1263 
1264                 diff[0] = diff[1] = 0;
1265                 uci_blob_diff(tb_br, otb_br, &bridge_attr_list, diff);
1266                 if (diff[0] & ~(1 << BRIDGE_ATTR_PORTS)) {
1267                         ret = DEV_CONFIG_RESTART;
1268                         D(DEVICE, "Bridge %s attributes have changed, diff=[%lx %lx]\n",
1269                           dev->ifname, diff[1], diff[0]);
1270                 }
1271 
1272                 bridge_config_init(dev);
1273         }
1274 
1275         free(bst->config_data);
1276         bst->config_data = attr;
1277         return ret;
1278 }
1279 
1280 static void
1281 bridge_retry_members(struct uloop_timeout *timeout)
1282 {
1283         struct bridge_state *bst = container_of(timeout, struct bridge_state, retry);
1284         struct bridge_member *bm;
1285 
1286         bst->n_failed = 0;
1287         vlist_for_each_element(&bst->members, bm, node) {
1288                 if (bm->present)
1289                         continue;
1290 
1291                 if (!bm->dev.dev->present)
1292                         continue;
1293 
1294                 bm->present = true;
1295                 bst->n_present++;
1296                 bridge_enable_member(bm);
1297         }
1298 }
1299 
1300 static int bridge_avl_cmp_u16(const void *k1, const void *k2, void *ptr)
1301 {
1302         const uint16_t *i1 = k1, *i2 = k2;
1303 
1304         return *i1 - *i2;
1305 }
1306 
1307 static bool
1308 bridge_vlan_equal(struct bridge_vlan *v1, struct bridge_vlan *v2)
1309 {
1310         int i;
1311 
1312         if (v1->n_ports != v2->n_ports)
1313                 return false;
1314 
1315         for (i = 0; i < v1->n_ports; i++)
1316                 if (v1->ports[i].flags != v2->ports[i].flags ||
1317                     strcmp(v1->ports[i].ifname, v2->ports[i].ifname) != 0)
1318                         return false;
1319 
1320         return true;
1321 }
1322 
1323 static void
1324 bridge_vlan_free(struct bridge_vlan *vlan)
1325 {
1326         struct bridge_vlan_hotplug_port *port, *tmp;
1327 
1328         if (!vlan)
1329                 return;
1330 
1331         list_for_each_entry_safe(port, tmp, &vlan->hotplug_ports, list)
1332                 free(port);
1333 
1334         free(vlan);
1335 }
1336 
1337 static void
1338 bridge_vlan_update(struct vlist_tree *tree, struct vlist_node *node_new,
1339                    struct vlist_node *node_old)
1340 {
1341         struct bridge_state *bst = container_of(tree, struct bridge_state, dev.vlans);
1342         struct bridge_vlan *vlan_new = NULL, *vlan_old = NULL;
1343 
1344         if (!bst->has_vlans || !bst->active)
1345                 goto out;
1346 
1347         if (node_old)
1348                 vlan_old = container_of(node_old, struct bridge_vlan, node);
1349         if (node_new)
1350                 vlan_new = container_of(node_new, struct bridge_vlan, node);
1351 
1352         if (node_new && node_old && bridge_vlan_equal(vlan_old, vlan_new)) {
1353                 list_splice_init(&vlan_old->hotplug_ports, &vlan_new->hotplug_ports);
1354                 goto out;
1355         }
1356 
1357         if (node_old)
1358                 bridge_set_vlan_state(bst, vlan_old, false);
1359 
1360         if (node_old && node_new)
1361                 list_splice_init(&vlan_old->hotplug_ports, &vlan_new->hotplug_ports);
1362 
1363         if (node_new)
1364                 vlan_new->pending = true;
1365 
1366         bst->dev.config_pending = true;
1367 
1368 out:
1369         bridge_vlan_free(vlan_old);
1370 }
1371 
1372 static void
1373 bridge_dev_vlan_update(struct device *dev)
1374 {
1375         struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
1376         struct bridge_vlan *vlan;
1377 
1378         vlist_for_each_element(&dev->vlans, vlan, node) {
1379                 if (!vlan->pending)
1380                         continue;
1381 
1382                 vlan->pending = false;
1383                 bridge_set_vlan_state(bst, vlan, true);
1384         }
1385 }
1386 
1387 static struct device *
1388 bridge_create(const char *name, struct device_type *devtype,
1389         struct blob_attr *attr)
1390 {
1391         struct bridge_state *bst;
1392         struct device *dev = NULL;
1393 
1394         bst = calloc(1, sizeof(*bst));
1395         if (!bst)
1396                 return NULL;
1397 
1398         dev = &bst->dev;
1399 
1400         if (device_init(dev, devtype, name) < 0) {
1401                 device_cleanup(dev);
1402                 free(bst);
1403                 return NULL;
1404         }
1405 
1406         dev->config_pending = true;
1407         bst->retry.cb = bridge_retry_members;
1408 
1409         bst->set_state = dev->set_state;
1410         dev->set_state = bridge_set_state;
1411 
1412         dev->hotplug_ops = &bridge_ops;
1413 
1414         vlist_init(&bst->members, avl_strcmp, bridge_member_update);
1415         bst->members.keep_old = true;
1416 
1417         vlist_init(&dev->vlans, bridge_avl_cmp_u16, bridge_vlan_update);
1418 
1419         bridge_reload(dev, attr);
1420 
1421         return dev;
1422 }
1423 
1424 static void __init bridge_device_type_init(void)
1425 {
1426         device_type_add(&bridge_device_type);
1427 }
1428 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt