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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt