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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt