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 bool clear_pvid = false; 282 283 bridge_set_local_vlan(bst, vlan, add); 284 285 vlist_for_each_element(&bst->members, bm, node) { 286 struct bridge_vlan_port *port; 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) 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); 731 } 732 733 static void 734 bridge_check_retry(struct bridge_state *bst) 735 { 736 if (!bst->n_failed) 737 return; 738 739 uloop_timeout_set(&bst->retry, 100); 740 } 741 742 static void 743 bridge_member_check_cb(struct uloop_timeout *t) 744 { 745 struct bridge_member *bm; 746 struct bridge_state *bst; 747 748 bm = container_of(t, struct bridge_member, check_timer); 749 bst = bm->bst; 750 751 if (system_bridge_vlan_check(&bst->dev, bm->dev.dev->ifname) <= 0) 752 return; 753 754 bridge_disable_member(bm, true); 755 bridge_enable_member(bm); 756 } 757 758 static void 759 bridge_member_cb(struct device_user *dep, enum device_event ev) 760 { 761 struct bridge_member *bm = container_of(dep, struct bridge_member, dev); 762 struct bridge_state *bst = bm->bst; 763 struct device *dev = dep->dev; 764 765 switch (ev) { 766 case DEV_EVENT_ADD: 767 assert(!bm->present); 768 769 bm->present = true; 770 bst->n_present++; 771 772 if (bst->n_present == 1) 773 device_set_present(&bst->dev, true); 774 fallthrough; 775 case DEV_EVENT_AUTH_UP: 776 if (!bst->dev.active) 777 break; 778 779 if (bridge_enable_member(bm)) 780 break; 781 782 /* 783 * Adding a bridge member can overwrite the bridge mtu 784 * in the kernel, apply the bridge settings in case the 785 * bridge mtu is set 786 */ 787 system_if_apply_settings(&bst->dev, &bst->dev.settings, 788 DEV_OPT_MTU | DEV_OPT_MTU6); 789 break; 790 case DEV_EVENT_LINK_UP: 791 if (!bst->has_vlans) 792 break; 793 794 if (dev->settings.auth) 795 bridge_enable_member(bm); 796 797 uloop_timeout_set(&bm->check_timer, 1000); 798 break; 799 case DEV_EVENT_LINK_DOWN: 800 if (!dev->settings.auth) 801 break; 802 803 bridge_disable_member(bm, true); 804 break; 805 case DEV_EVENT_REMOVE: 806 if (dep->hotplug && !dev->sys_present) { 807 vlist_delete(&bst->members, &bm->node); 808 return; 809 } 810 811 if (bm->present) 812 bridge_remove_member(bm); 813 814 break; 815 default: 816 return; 817 } 818 } 819 820 static int 821 bridge_set_down(struct bridge_state *bst) 822 { 823 struct bridge_member *bm; 824 825 bst->set_state(&bst->dev, false); 826 827 vlist_for_each_element(&bst->members, bm, node) 828 bridge_disable_member(bm, false); 829 830 bridge_disable_interface(bst); 831 832 return 0; 833 } 834 835 static int 836 bridge_set_up(struct bridge_state *bst) 837 { 838 struct bridge_member *bm; 839 int ret; 840 841 bst->has_vlans = !avl_is_empty(&bst->dev.vlans.avl); 842 if (!bst->n_present) { 843 if (!bst->force_active) 844 return -ENOENT; 845 846 ret = bridge_enable_interface(bst); 847 if (ret) 848 return ret; 849 } 850 851 bst->n_failed = 0; 852 vlist_for_each_element(&bst->members, bm, node) 853 bridge_enable_member(bm); 854 bridge_check_retry(bst); 855 856 if (!bst->force_active && !bst->n_present) { 857 /* initialization of all member interfaces failed */ 858 bridge_disable_interface(bst); 859 device_set_present(&bst->dev, false); 860 return -ENOENT; 861 } 862 863 bridge_reset_primary(bst); 864 ret = bst->set_state(&bst->dev, true); 865 if (ret < 0) 866 bridge_set_down(bst); 867 868 return ret; 869 } 870 871 static int 872 bridge_set_state(struct device *dev, bool up) 873 { 874 struct bridge_state *bst; 875 876 bst = container_of(dev, struct bridge_state, dev); 877 878 if (up) 879 return bridge_set_up(bst); 880 else 881 return bridge_set_down(bst); 882 } 883 884 static struct bridge_member * 885 bridge_alloc_member(struct bridge_state *bst, const char *name, 886 struct device *dev, bool hotplug) 887 { 888 struct bridge_member *bm; 889 890 bm = calloc(1, sizeof(*bm) + strlen(name) + 1); 891 if (!bm) 892 return NULL; 893 894 bm->bst = bst; 895 bm->dev.cb = bridge_member_cb; 896 bm->dev.hotplug = hotplug; 897 bm->check_timer.cb = bridge_member_check_cb; 898 strcpy(bm->name, name); 899 bm->dev.dev = dev; 900 901 return bm; 902 } 903 904 static void bridge_insert_member(struct bridge_member *bm, const char *name) 905 { 906 struct bridge_state *bst = bm->bst; 907 bool hotplug = bm->dev.hotplug; 908 909 vlist_add(&bst->members, &bm->node, bm->name); 910 /* 911 * Need to look up the bridge member again as the above 912 * created pointer will be freed in case the bridge member 913 * already existed 914 */ 915 bm = vlist_find(&bst->members, name, bm, node); 916 if (hotplug && bm) 917 bm->node.version = -1; 918 } 919 920 static void 921 bridge_create_member(struct bridge_state *bst, const char *name, 922 struct device *dev, bool hotplug) 923 { 924 struct bridge_member *bm; 925 926 bm = bridge_alloc_member(bst, name, dev, hotplug); 927 if (bm) 928 bridge_insert_member(bm, name); 929 } 930 931 static void 932 bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new, 933 struct vlist_node *node_old) 934 { 935 struct bridge_member *bm; 936 struct device *dev; 937 938 if (node_new) { 939 bm = container_of(node_new, struct bridge_member, node); 940 941 if (node_old) { 942 struct device *dev = bm->dev.dev; 943 944 free(bm); 945 946 bm = container_of(node_old, struct bridge_member, node); 947 if (!dev || dev == bm->dev.dev) 948 return; 949 950 bridge_remove_member(bm); 951 device_add_user(&bm->dev, dev); 952 return; 953 } 954 955 dev = bm->dev.dev; 956 bm->dev.dev = NULL; 957 device_add_user(&bm->dev, dev); 958 } 959 960 961 if (node_old) { 962 bm = container_of(node_old, struct bridge_member, node); 963 bridge_free_member(bm); 964 } 965 } 966 967 968 static void 969 bridge_add_member(struct bridge_state *bst, const char *name) 970 { 971 struct device *dev; 972 973 dev = device_get(name, true); 974 if (!dev) 975 return; 976 977 bridge_create_member(bst, name, dev, false); 978 } 979 980 static int 981 bridge_hotplug_add(struct device *dev, struct device *member, struct blob_attr *vlan) 982 { 983 struct bridge_state *bst = container_of(dev, struct bridge_state, dev); 984 struct bridge_member *bm; 985 bool new_entry = false; 986 987 bm = vlist_find(&bst->members, member->ifname, bm, node); 988 if (!bm) { 989 new_entry = true; 990 bm = bridge_alloc_member(bst, member->ifname, member, true); 991 } 992 bridge_hotplug_set_member_vlans(bst, vlan, bm, true, false); 993 if (new_entry) 994 bridge_insert_member(bm, member->ifname); 995 996 return 0; 997 } 998 999 static int 1000 bridge_hotplug_del(struct device *dev, struct device *member, struct blob_attr *vlan) 1001 { 1002 struct bridge_state *bst = container_of(dev, struct bridge_state, dev); 1003 struct bridge_member *bm; 1004 1005 bm = vlist_find(&bst->members, member->ifname, bm, node); 1006 if (!bm) 1007 return UBUS_STATUS_NOT_FOUND; 1008 1009 bridge_hotplug_set_member_vlans(bst, vlan, bm, false, false); 1010 if (!bm->dev.hotplug) 1011 return 0; 1012 1013 vlist_delete(&bst->members, &bm->node); 1014 return 0; 1015 } 1016 1017 static int 1018 bridge_hotplug_prepare(struct device *dev, struct device **bridge_dev) 1019 { 1020 struct bridge_state *bst; 1021 1022 if (bridge_dev) 1023 *bridge_dev = dev; 1024 1025 bst = container_of(dev, struct bridge_state, dev); 1026 bst->force_active = true; 1027 device_set_present(&bst->dev, true); 1028 1029 return 0; 1030 } 1031 1032 static const struct device_hotplug_ops bridge_ops = { 1033 .prepare = bridge_hotplug_prepare, 1034 .add = bridge_hotplug_add, 1035 .del = bridge_hotplug_del 1036 }; 1037 1038 static void 1039 bridge_free(struct device *dev) 1040 { 1041 struct bridge_state *bst; 1042 1043 bst = container_of(dev, struct bridge_state, dev); 1044 vlist_flush_all(&bst->members); 1045 vlist_flush_all(&dev->vlans); 1046 1047 system_bridge_delbr(dev); 1048 1049 kvlist_free(&dev->vlan_aliases); 1050 free(bst->config_data); 1051 free(bst); 1052 } 1053 1054 static void 1055 bridge_dump_port(struct blob_buf *b, struct bridge_vlan_port *port) 1056 { 1057 bool tagged = !(port->flags & BRVLAN_F_UNTAGGED); 1058 bool pvid = (port->flags & BRVLAN_F_PVID); 1059 1060 blobmsg_printf(b, NULL, "%s%s%s%s", port->ifname, 1061 tagged || pvid ? ":" : "", 1062 tagged ? "t" : "", 1063 pvid ? "*" : ""); 1064 } 1065 1066 static void 1067 bridge_dump_vlan(struct blob_buf *b, struct bridge_vlan *vlan) 1068 { 1069 struct bridge_vlan_hotplug_port *port; 1070 void *c, *p; 1071 int i; 1072 1073 c = blobmsg_open_table(b, NULL); 1074 1075 blobmsg_add_u32(b, "id", vlan->vid); 1076 blobmsg_add_u8(b, "local", vlan->local); 1077 1078 p = blobmsg_open_array(b, "ports"); 1079 1080 for (i = 0; i < vlan->n_ports; i++) 1081 bridge_dump_port(b, &vlan->ports[i]); 1082 1083 list_for_each_entry(port, &vlan->hotplug_ports, list) 1084 bridge_dump_port(b, &port->port); 1085 1086 blobmsg_close_array(b, p); 1087 1088 blobmsg_close_table(b, c); 1089 } 1090 1091 static void 1092 bridge_dump_info(struct device *dev, struct blob_buf *b) 1093 { 1094 struct bridge_config *cfg; 1095 struct bridge_state *bst; 1096 struct bridge_member *bm; 1097 struct bridge_vlan *vlan; 1098 void *list; 1099 void *c; 1100 1101 bst = container_of(dev, struct bridge_state, dev); 1102 cfg = &bst->config; 1103 1104 system_if_dump_info(dev, b); 1105 list = blobmsg_open_array(b, "bridge-members"); 1106 1107 vlist_for_each_element(&bst->members, bm, node) { 1108 if (bm->dev.dev->hidden) 1109 continue; 1110 1111 blobmsg_add_string(b, NULL, bm->dev.dev->ifname); 1112 } 1113 1114 blobmsg_close_array(b, list); 1115 1116 c = blobmsg_open_table(b, "bridge-attributes"); 1117 1118 blobmsg_add_u8(b, "stp", cfg->stp); 1119 blobmsg_add_u32(b, "forward_delay", cfg->forward_delay); 1120 blobmsg_add_u32(b, "priority", cfg->priority); 1121 blobmsg_add_u32(b, "ageing_time", cfg->ageing_time); 1122 blobmsg_add_u32(b, "hello_time", cfg->hello_time); 1123 blobmsg_add_u32(b, "max_age", cfg->max_age); 1124 blobmsg_add_u8(b, "igmp_snooping", cfg->igmp_snoop); 1125 blobmsg_add_u8(b, "bridge_empty", cfg->bridge_empty); 1126 blobmsg_add_u8(b, "multicast_querier", cfg->multicast_querier); 1127 blobmsg_add_u32(b, "hash_max", cfg->hash_max); 1128 blobmsg_add_u32(b, "robustness", cfg->robustness); 1129 blobmsg_add_u32(b, "query_interval", cfg->query_interval); 1130 blobmsg_add_u32(b, "query_response_interval", cfg->query_response_interval); 1131 blobmsg_add_u32(b, "last_member_interval", cfg->last_member_interval); 1132 blobmsg_add_u8(b, "vlan_filtering", cfg->vlan_filtering); 1133 blobmsg_add_u8(b, "stp_kernel", cfg->stp_kernel); 1134 if (cfg->stp_proto) 1135 blobmsg_add_string(b, "stp_proto", cfg->stp_proto); 1136 1137 blobmsg_close_table(b, c); 1138 1139 if (avl_is_empty(&dev->vlans.avl)) 1140 return; 1141 1142 list = blobmsg_open_array(b, "bridge-vlans"); 1143 1144 vlist_for_each_element(&bst->dev.vlans, vlan, node) 1145 bridge_dump_vlan(b, vlan); 1146 1147 blobmsg_close_array(b, list); 1148 } 1149 1150 static void 1151 bridge_config_init(struct device *dev) 1152 { 1153 struct bridge_state *bst; 1154 struct bridge_vlan *vlan; 1155 struct blob_attr *cur; 1156 size_t rem; 1157 int i; 1158 1159 bst = container_of(dev, struct bridge_state, dev); 1160 1161 if (bst->config.bridge_empty) { 1162 bst->force_active = true; 1163 device_set_present(&bst->dev, true); 1164 } 1165 1166 bst->n_failed = 0; 1167 vlist_update(&bst->members); 1168 if (bst->ports) { 1169 blobmsg_for_each_attr(cur, bst->ports, rem) { 1170 bridge_add_member(bst, blobmsg_data(cur)); 1171 } 1172 } 1173 1174 vlist_for_each_element(&bst->dev.vlans, vlan, node) 1175 for (i = 0; i < vlan->n_ports; i++) 1176 bridge_add_member(bst, vlan->ports[i].ifname); 1177 1178 vlist_flush(&bst->members); 1179 bridge_check_retry(bst); 1180 } 1181 1182 static void 1183 bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb) 1184 { 1185 struct bridge_config *cfg = &bst->config; 1186 struct blob_attr *cur; 1187 1188 /* defaults */ 1189 memset(cfg, 0, sizeof(*cfg)); 1190 cfg->stp = false; 1191 cfg->stp_kernel = false; 1192 cfg->robustness = 2; 1193 cfg->igmp_snoop = false; 1194 cfg->multicast_querier = false; 1195 cfg->query_interval = 12500; 1196 cfg->query_response_interval = 1000; 1197 cfg->last_member_interval = 100; 1198 cfg->hash_max = 512; 1199 cfg->bridge_empty = false; 1200 cfg->priority = 0x7FFF; 1201 cfg->vlan_filtering = false; 1202 1203 cfg->forward_delay = 8; 1204 cfg->max_age = 10; 1205 cfg->hello_time = 1; 1206 1207 if ((cur = tb[BRIDGE_ATTR_STP])) 1208 cfg->stp = blobmsg_get_bool(cur); 1209 1210 if ((cur = tb[BRIDGE_ATTR_STP_KERNEL])) 1211 cfg->stp = blobmsg_get_bool(cur); 1212 1213 if ((cur = tb[BRIDGE_ATTR_STP_PROTO])) 1214 cfg->stp_proto = blobmsg_get_string(cur); 1215 1216 if ((cur = tb[BRIDGE_ATTR_FORWARD_DELAY])) 1217 cfg->forward_delay = blobmsg_get_u32(cur); 1218 1219 if ((cur = tb[BRIDGE_ATTR_PRIORITY])) 1220 cfg->priority = blobmsg_get_u32(cur); 1221 1222 if ((cur = tb[BRIDGE_ATTR_IGMP_SNOOP])) 1223 cfg->multicast_querier = cfg->igmp_snoop = blobmsg_get_bool(cur); 1224 1225 if ((cur = tb[BRIDGE_ATTR_MULTICAST_QUERIER])) 1226 cfg->multicast_querier = blobmsg_get_bool(cur); 1227 1228 if ((cur = tb[BRIDGE_ATTR_HASH_MAX])) 1229 cfg->hash_max = blobmsg_get_u32(cur); 1230 1231 if ((cur = tb[BRIDGE_ATTR_ROBUSTNESS])) { 1232 cfg->robustness = blobmsg_get_u32(cur); 1233 cfg->flags |= BRIDGE_OPT_ROBUSTNESS; 1234 } 1235 1236 if ((cur = tb[BRIDGE_ATTR_QUERY_INTERVAL])) { 1237 cfg->query_interval = blobmsg_get_u32(cur); 1238 cfg->flags |= BRIDGE_OPT_QUERY_INTERVAL; 1239 } 1240 1241 if ((cur = tb[BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL])) { 1242 cfg->query_response_interval = blobmsg_get_u32(cur); 1243 cfg->flags |= BRIDGE_OPT_QUERY_RESPONSE_INTERVAL; 1244 } 1245 1246 if ((cur = tb[BRIDGE_ATTR_LAST_MEMBER_INTERVAL])) { 1247 cfg->last_member_interval = blobmsg_get_u32(cur); 1248 cfg->flags |= BRIDGE_OPT_LAST_MEMBER_INTERVAL; 1249 } 1250 1251 if ((cur = tb[BRIDGE_ATTR_AGEING_TIME])) { 1252 cfg->ageing_time = blobmsg_get_u32(cur); 1253 cfg->flags |= BRIDGE_OPT_AGEING_TIME; 1254 } 1255 1256 if ((cur = tb[BRIDGE_ATTR_HELLO_TIME])) 1257 cfg->hello_time = blobmsg_get_u32(cur); 1258 1259 if ((cur = tb[BRIDGE_ATTR_MAX_AGE])) 1260 cfg->max_age = blobmsg_get_u32(cur); 1261 1262 if ((cur = tb[BRIDGE_ATTR_BRIDGE_EMPTY])) 1263 cfg->bridge_empty = blobmsg_get_bool(cur); 1264 1265 if ((cur = tb[BRIDGE_ATTR_VLAN_FILTERING])) 1266 cfg->vlan_filtering = blobmsg_get_bool(cur); 1267 } 1268 1269 static enum dev_change_type 1270 bridge_reload(struct device *dev, struct blob_attr *attr, 1271 struct blob_attr **tb_dev) 1272 { 1273 struct blob_attr *tb_br[__BRIDGE_ATTR_MAX]; 1274 enum dev_change_type ret = DEV_CONFIG_APPLIED; 1275 struct bridge_state *bst; 1276 unsigned long diff[2] = {}; 1277 1278 BUILD_BUG_ON(sizeof(diff) < __BRIDGE_ATTR_MAX / BITS_PER_LONG); 1279 1280 bst = container_of(dev, struct bridge_state, dev); 1281 attr = blob_memdup(attr); 1282 1283 blobmsg_parse_attr(bridge_attrs, __BRIDGE_ATTR_MAX, tb_br, attr); 1284 1285 if (tb_dev[DEV_ATTR_MACADDR]) 1286 bst->primary_port = NULL; 1287 1288 bst->ports = tb_br[BRIDGE_ATTR_PORTS]; 1289 bridge_apply_settings(bst, tb_br); 1290 1291 if (bst->config_data) { 1292 struct blob_attr *otb_br[__BRIDGE_ATTR_MAX]; 1293 1294 blobmsg_parse_attr(bridge_attrs, __BRIDGE_ATTR_MAX, otb_br, bst->config_data); 1295 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 dev->config_pending = true; 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 || v1->local != v2->local) 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 device_init_config(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