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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt