1 /* 2 * netifd - network interface daemon 3 * Copyright (C) 2015 Arne Kappen <arne.kappen@hhi.fraunhofer.de> 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 * 15 * extdev - external device handler interface 16 * 17 * This allows to integrate external daemons that configure network devices 18 * with netifd. At startup, netifd generates device handler stubs from 19 * descriptions in /lib/netifd/extdev-config and adds them to the list of 20 * device handlers. A device handler is an instance of struct device_type 21 * The descriptions are in JSON format and specify 22 * - names of the device type and of the external device handler on ubus, 23 * - whether the device is bridge-like, 24 * - a prefix for device names, 25 * - the UCI config options for devices of this type, and 26 * - the format of calls to dump() and info() 27 * These device handlers stubs act as relays forwarding calls against the 28 * device handler interface to the external daemon. 29 */ 30 31 #include <libubox/blobmsg.h> 32 #include <libubox/list.h> 33 #include <libubus.h> 34 #include <assert.h> 35 36 #include "netifd.h" 37 #include "handler.h" 38 #include "device.h" 39 #include "ubus.h" 40 #include "extdev.h" 41 #include "interface.h" 42 #include "system.h" 43 44 45 static struct blob_buf b; 46 static int confdir_fd = -1; 47 48 struct extdev_type { 49 struct device_type handler; 50 51 const char *name; 52 uint32_t peer_id; 53 struct ubus_subscriber ubus_sub; 54 bool subscribed; 55 struct ubus_event_handler obj_wait; 56 57 struct uci_blob_param_list *config_params; 58 char *config_strbuf; 59 60 struct uci_blob_param_list *info_params; 61 char *info_strbuf; 62 63 struct uci_blob_param_list *stats_params; 64 char *stats_strbuf; 65 }; 66 67 struct extdev_device { 68 struct device dev; 69 struct extdev_type *etype; 70 const char *dep_name; 71 struct uloop_timeout retry; 72 }; 73 74 struct extdev_bridge { 75 struct extdev_device edev; 76 device_state_cb set_state; 77 78 struct blob_attr *config; 79 bool empty; 80 struct blob_attr *ifnames; 81 bool active; 82 bool force_active; 83 84 struct uloop_timeout retry; 85 struct vlist_tree members; 86 int n_present; 87 int n_failed; 88 }; 89 90 struct extdev_bridge_member { 91 struct vlist_node node; 92 struct extdev_bridge *parent_br; 93 struct device_user dev_usr; 94 bool present; 95 char *name; 96 }; 97 98 static void __bridge_config_init(struct extdev_bridge *ebr); 99 static enum dev_change_type __bridge_reload(struct extdev_bridge *ebr, struct blob_attr *config); 100 101 enum { 102 METHOD_CREATE, 103 METHOD_CONFIG_INIT, 104 METHOD_RELOAD, 105 METHOD_DUMP_INFO, 106 METHOD_DUMP_STATS, 107 METHOD_CHECK_STATE, 108 METHOD_FREE, 109 METHOD_HOTPLUG_PREPARE, 110 METHOD_HOTPLUG_ADD, 111 METHOD_HOTPLUG_REMOVE, 112 __METHODS_MAX 113 }; 114 115 static const char *__extdev_methods[__METHODS_MAX] = { 116 [METHOD_CREATE] = "create", 117 [METHOD_CONFIG_INIT] = "config_init", 118 [METHOD_RELOAD] = "reload", 119 [METHOD_DUMP_INFO] = "dump_info", 120 [METHOD_DUMP_STATS] = "dump_stats", 121 [METHOD_CHECK_STATE] = "check_state", 122 [METHOD_FREE] = "free", 123 [METHOD_HOTPLUG_PREPARE] = "prepare", 124 [METHOD_HOTPLUG_ADD] = "add", 125 [METHOD_HOTPLUG_REMOVE] = "remove", 126 }; 127 128 static inline int 129 netifd_extdev_create(struct extdev_device *edev, struct blob_attr *msg) 130 { 131 D(DEVICE, "create %s '%s' at external device handler\n", edev->dev.type->name, 132 edev->dev.ifname); 133 return netifd_extdev_invoke(edev->etype->peer_id, __extdev_methods[METHOD_CREATE], msg, 134 NULL, NULL); 135 } 136 137 static inline int 138 netifd_extdev_config_init(struct extdev_device *edev, struct blob_attr *msg) 139 { 140 return netifd_extdev_invoke(edev->etype->peer_id, __extdev_methods[METHOD_CONFIG_INIT], 141 msg, NULL, NULL); 142 } 143 144 static inline int 145 netifd_extdev_reload(struct extdev_device *edev, struct blob_attr *msg) 146 { 147 D(DEVICE, "reload %s '%s' at external device handler\n", edev->dev.type->name, 148 edev->dev.ifname); 149 return netifd_extdev_invoke(edev->etype->peer_id, __extdev_methods[METHOD_RELOAD], msg, 150 NULL, NULL); 151 } 152 153 static inline int 154 netifd_extdev_free(struct extdev_device *edev, struct blob_attr *msg) 155 { 156 D(DEVICE, "delete %s '%s' with external device handler\n", edev->dev.type->name, 157 edev->dev.ifname); 158 return netifd_extdev_invoke(edev->etype->peer_id, __extdev_methods[METHOD_FREE], msg, 159 NULL, NULL); 160 } 161 162 static inline int 163 netifd_extdev_prepare(struct extdev_bridge *ebr, struct blob_attr *msg) 164 { 165 D(DEVICE, "prepare %s bridge '%s' at external device handler\n", ebr->edev.dev.type->name, 166 ebr->edev.dev.ifname); 167 return netifd_extdev_invoke(ebr->edev.etype->peer_id, 168 __extdev_methods[METHOD_HOTPLUG_PREPARE], msg, NULL, NULL); 169 } 170 171 static inline int 172 netifd_extdev_add(struct extdev_bridge *ebr, struct blob_attr *msg) 173 { 174 D(DEVICE, "add a member to %s bridge '%s' at external device handler\n", 175 ebr->edev.dev.type->name, ebr->edev.dev.ifname); 176 return netifd_extdev_invoke(ebr->edev.etype->peer_id, 177 __extdev_methods[METHOD_HOTPLUG_ADD], msg,NULL, NULL); 178 } 179 180 static inline int 181 netifd_extdev_remove(struct extdev_bridge *ebr, struct blob_attr *msg) 182 { 183 D(DEVICE, "remove a member from %s bridge '%s' at external device handler\n", 184 ebr->edev.dev.type->name, ebr->edev.dev.ifname); 185 return netifd_extdev_invoke(ebr->edev.etype->peer_id, 186 __extdev_methods[METHOD_HOTPLUG_REMOVE], msg, NULL, NULL); 187 } 188 189 static inline void 190 extdev_invocation_error(int error, const char *method, const char *devname) 191 { 192 netifd_log_message(L_CRIT, "'%s' failed for '%s': %s\n", 193 method, devname, ubus_strerror(error)); 194 } 195 196 static struct ubus_method extdev_ubus_obj_methods[] = {}; 197 198 static struct ubus_object_type extdev_ubus_object_type = 199 UBUS_OBJECT_TYPE("netifd_extdev", extdev_ubus_obj_methods); 200 201 static int 202 extdev_lookup_id(struct extdev_type *etype) 203 { 204 int ret = UBUS_STATUS_UNKNOWN_ERROR; 205 206 if (!etype || !etype->name) 207 goto error; 208 209 ret = ubus_lookup_id(ubus_ctx, etype->name, &etype->peer_id); 210 if (ret) 211 goto error; 212 213 return 0; 214 215 error: 216 netifd_log_message(L_CRIT, "Could not find '%s' ubus ID: %s\n", 217 etype->name, ubus_strerror(ret)); 218 return ret; 219 } 220 221 static int 222 extdev_ext_ubus_obj_wait(struct ubus_event_handler *h) 223 { 224 return ubus_register_event_handler(ubus_ctx, h, "ubus.object.add"); 225 } 226 227 static int 228 extdev_subscribe(struct extdev_type *etype) 229 { 230 int ret; 231 232 ret = extdev_lookup_id(etype); 233 if (ret) { 234 etype->subscribed = false; 235 return ret; 236 } 237 238 ret = ubus_subscribe(ubus_ctx, &etype->ubus_sub, etype->peer_id); 239 if (ret) { 240 etype->subscribed = false; 241 extdev_ext_ubus_obj_wait(&etype->obj_wait); 242 } else { 243 netifd_log_message(L_NOTICE, "subscribed to external device handler '%s'\n", 244 etype->name); 245 etype->subscribed = true; 246 } 247 248 return ret; 249 } 250 251 static void 252 extdev_wait_ev_cb(struct ubus_context *ctx, struct ubus_event_handler *ev_handler, 253 const char *type, struct blob_attr *msg) 254 { 255 static const struct blobmsg_policy wait_policy = { 256 "path", BLOBMSG_TYPE_STRING 257 }; 258 259 struct blob_attr *attr; 260 const char *path; 261 struct extdev_type *etype; 262 263 etype = container_of(ev_handler, struct extdev_type, obj_wait); 264 265 if (strcmp(type, "ubus.object.add")) 266 return; 267 268 blobmsg_parse(&wait_policy, 1, &attr, blob_data(msg), blob_len(msg)); 269 if (!attr) 270 return; 271 272 path = blobmsg_data(attr); 273 if (strcmp(etype->name, path)) 274 return; 275 276 extdev_subscribe(etype); 277 } 278 279 static int 280 extdev_bridge_disable_interface(struct extdev_bridge *ebr) 281 { 282 int ret; 283 284 if (!ebr->active) 285 return 0; 286 287 blob_buf_init(&b, 0); 288 blobmsg_add_string(&b, "name", ebr->edev.dev.ifname); 289 290 ret = netifd_extdev_free(&ebr->edev, b.head); 291 292 if (ret && ret != UBUS_STATUS_NOT_FOUND) 293 goto error; 294 295 ebr->active = false; 296 return 0; 297 298 error: 299 extdev_invocation_error(ret, __extdev_methods[METHOD_FREE], ebr->edev.dev.ifname); 300 return ret; 301 } 302 303 static int 304 extdev_bridge_enable_interface(struct extdev_bridge *ebr) 305 { 306 int ret; 307 308 if (ebr->active) 309 return 0; 310 311 ret = netifd_extdev_create(&ebr->edev, ebr->config); 312 if (ret) 313 goto error; 314 315 ebr->active = true; 316 return 0; 317 318 error: 319 extdev_invocation_error(ret, __extdev_methods[METHOD_CREATE], ebr->edev.dev.ifname); 320 return ret; 321 } 322 323 static int 324 extdev_bridge_enable_member(struct extdev_bridge_member *ubm) 325 { 326 int ret; 327 struct extdev_bridge *ebr = ubm->parent_br; 328 329 D(DEVICE, "%s enable member %s\n", ebr->edev.dev.ifname, ubm->name); 330 331 if (!ubm->present) 332 return 0; 333 334 ret = extdev_bridge_enable_interface(ebr); 335 if (ret) 336 goto error; 337 338 ret = device_claim(&ubm->dev_usr); 339 if (ret < 0) 340 goto error; 341 342 blob_buf_init(&b, 0); 343 blobmsg_add_string(&b, "bridge", ebr->edev.dev.ifname); 344 blobmsg_add_string(&b, "member", ubm->dev_usr.dev->ifname); 345 346 /* use hotplug add as addif equivalent. Maybe we need a dedicated ubus 347 * method on the external handler for this sort of operation. */ 348 ret = netifd_extdev_add(ebr, b.head); 349 if (ret) { 350 extdev_invocation_error(ret, __extdev_methods[METHOD_HOTPLUG_ADD], 351 ubm->dev_usr.dev->ifname); 352 goto error; 353 } 354 355 device_set_present(&ebr->edev.dev, true); 356 device_broadcast_event(&ebr->edev.dev, DEV_EVENT_TOPO_CHANGE); 357 358 return 0; 359 360 error: 361 D(DEVICE, "%s: failed to enable member '%s'\n", ebr->edev.dev.ifname, ubm->name); 362 363 ebr->n_failed++; 364 ubm->present = false; 365 ebr->n_present--; 366 367 return ret; 368 } 369 370 static int 371 extdev_bridge_disable_member(struct extdev_bridge_member *ubm) 372 { 373 int ret; 374 struct extdev_bridge *ebr = ubm->parent_br; 375 376 if (!ubm->present) 377 return 0; 378 379 D(DEVICE, "%s disable member %s\n", ubm->parent_br->edev.dev.ifname, ubm->name); 380 381 blob_buf_init(&b, 0); 382 blobmsg_add_string(&b, "bridge", ebr->edev.dev.ifname); 383 blobmsg_add_string(&b, "member", ubm->dev_usr.dev->ifname); 384 385 /* use hotplug remove as delif equivalent. Maybe we need a dedicated 386 * ubus method on the external handler for this sort of operation. */ 387 ret = netifd_extdev_remove(ebr, b.head); 388 389 /* continue in case of NOT FOUND since we're trying to remove anyway */ 390 if (ret && ret != UBUS_STATUS_NOT_FOUND) 391 goto error; 392 393 device_release(&ubm->dev_usr); 394 device_broadcast_event(&ebr->edev.dev, DEV_EVENT_TOPO_CHANGE); 395 396 return 0; 397 398 error: 399 extdev_invocation_error(ret, __extdev_methods[METHOD_HOTPLUG_REMOVE], 400 ubm->dev_usr.dev->ifname); 401 402 return ret; 403 } 404 405 static int 406 extdev_bridge_set_down(struct extdev_bridge *ebr) 407 { 408 D(DEVICE, "set %s bridge %s down\n", ebr->edev.dev.type->name, ebr->edev.dev.ifname); 409 410 struct extdev_bridge_member *ubm; 411 412 ebr->set_state(&ebr->edev.dev, false); 413 414 vlist_for_each_element(&ebr->members, ubm, node) 415 extdev_bridge_disable_member(ubm); 416 417 extdev_bridge_disable_interface(ebr); 418 419 return 0; 420 } 421 422 static void 423 extdev_bridge_check_retry(struct extdev_bridge *ebr) 424 { 425 if (!ebr->n_failed) 426 return; 427 428 uloop_timeout_set(&ebr->retry, 200); 429 } 430 431 static int 432 extdev_bridge_set_up(struct extdev_bridge *ebr) 433 { 434 D(DEVICE, "set %s bridge %s up\n", ebr->edev.dev.type->name, ebr->edev.dev.ifname); 435 436 struct extdev_bridge_member *ubm; 437 int ret; 438 439 if (!ebr->n_present) { 440 if (!ebr->force_active) 441 return -ENOENT; 442 443 ret = extdev_bridge_enable_interface(ebr); 444 if (ret) 445 return ret; 446 } 447 448 ebr->n_failed = 0; 449 vlist_for_each_element(&ebr->members, ubm, node) 450 extdev_bridge_enable_member(ubm); 451 452 extdev_bridge_check_retry(ebr); 453 454 if (!ebr->force_active && !ebr->n_present) { 455 extdev_bridge_disable_interface(ebr); 456 device_set_present(&ebr->edev.dev, false); 457 return -ENOENT; 458 } 459 460 return 0; 461 } 462 463 static int 464 extdev_bridge_set_state(struct device *dev, bool up) 465 { 466 struct extdev_bridge *ebr; 467 468 if (!dev->type->bridge_capability) 469 return -1; 470 471 ebr = container_of(dev, struct extdev_bridge, edev.dev); 472 473 if (up) 474 return extdev_bridge_set_up(ebr); 475 else 476 return extdev_bridge_set_down(ebr); 477 } 478 479 static void 480 extdev_bridge_remove_member(struct extdev_bridge_member *member) 481 { 482 struct extdev_bridge *ebr = member->parent_br; 483 484 if (!member->present) 485 return; 486 487 if (ebr->edev.dev.active) 488 extdev_bridge_disable_member(member); 489 490 member->present = false; 491 ebr->n_present--; 492 493 if (ebr->empty) 494 return; 495 496 ebr->force_active = false; 497 if (ebr->n_present == 0) 498 device_set_present(&ebr->edev.dev, false); 499 } 500 501 static void 502 extdev_bridge_member_cb(struct device_user *usr, enum device_event event) 503 { 504 int ret; 505 struct extdev_bridge_member *ubm; 506 struct extdev_bridge *ebr; 507 508 ubm = container_of(usr, struct extdev_bridge_member, dev_usr); 509 ebr = ubm->parent_br; 510 511 switch (event) { 512 case DEV_EVENT_ADD: 513 assert(!ubm->present); 514 515 ubm->present = true; 516 ebr->n_present++; 517 518 /* if this member is the first one that is brought up, 519 * create the bridge at the external device handler */ 520 if (ebr->n_present == 1) { 521 ret = netifd_extdev_create(&ebr->edev, ebr->config); 522 if (ret) 523 goto error; 524 525 ebr->active = true; 526 ret = ebr->set_state(&ebr->edev.dev, true); 527 if (ret < 0) 528 extdev_bridge_set_down(ebr); 529 device_set_present(&ebr->edev.dev, true); 530 } 531 532 extdev_bridge_enable_member(ubm); 533 break; 534 case DEV_EVENT_REMOVE: 535 if (usr->hotplug) { 536 vlist_delete(&ebr->members, &ubm->node); 537 return; 538 } 539 540 if (ubm->present) 541 extdev_bridge_remove_member(ubm); 542 break; 543 default: 544 break; 545 } 546 547 return; 548 549 error: 550 netifd_log_message(L_CRIT, "Failed to create %s bridge %s: %s\n", 551 ebr->edev.dev.type->name, ebr->edev.dev.ifname, ubus_strerror(ret)); 552 ubm->present = false; 553 ebr->n_present--; 554 } 555 556 static void 557 __bridge_enable_members(struct extdev_bridge *ebr) 558 { 559 struct extdev_bridge_member *cur; 560 561 ebr->n_failed = 0; 562 563 vlist_for_each_element(&ebr->members, cur, node) { 564 if (cur->present) 565 continue; 566 567 if (!cur->dev_usr.dev->present) 568 continue; 569 570 cur->present = true; 571 ebr->n_present++; 572 extdev_bridge_enable_member(cur); 573 } 574 } 575 576 static void 577 extdev_bridge_retry_enable_members(struct uloop_timeout *timeout) 578 { 579 struct extdev_bridge *ebr = container_of(timeout, struct extdev_bridge, retry); 580 581 D(DEVICE, "%s retry enable members\n", ebr->edev.dev.ifname); 582 583 __bridge_enable_members(ebr); 584 } 585 586 static struct extdev_bridge_member * 587 extdev_bridge_create_member(struct extdev_bridge *ebr, struct device *dev) 588 { 589 struct extdev_bridge_member *ubm; 590 char *name; 591 592 ubm = calloc_a(sizeof(*ubm), &name, strlen(dev->ifname) + 1); 593 if (!ubm) 594 return NULL; 595 596 ubm->parent_br = ebr; 597 ubm->name = name; 598 strcpy(name, dev->ifname); 599 ubm->dev_usr.dev = dev; 600 ubm->dev_usr.cb = extdev_bridge_member_cb; 601 vlist_add(&ebr->members, &ubm->node, ubm->name); 602 /* Need to look up the bridge member again as the above 603 * created pointer will be freed in case the bridge member 604 * already existed */ 605 ubm = vlist_find(&ebr->members, dev->ifname, ubm, node); 606 if (!ubm) 607 return NULL; 608 609 return ubm; 610 } 611 612 static void 613 extdev_bridge_add_member(struct extdev_bridge *ebr, const char *name) 614 { 615 D(DEVICE, "%s add member %s\n", ebr->edev.dev.ifname, name); 616 617 struct device *dev; 618 619 dev = device_get(name, 1); 620 if (!dev) 621 return; 622 623 extdev_bridge_create_member(ebr, dev); 624 } 625 626 /* TODO: how to handle vlan arg? */ 627 static int 628 extdev_hotplug_add(struct device *ebr_dev, struct device *ebm_dev, struct blob_attr *vlan) 629 { 630 D(DEVICE, "%s hotplug add member %s\n", ebr_dev->ifname, ebm_dev->ifname); 631 632 struct extdev_bridge *ebr; 633 struct extdev_bridge_member *ubm; 634 635 if (!ebr_dev->type->bridge_capability) 636 return UBUS_STATUS_NOT_SUPPORTED; 637 638 ebr = container_of(ebr_dev, struct extdev_bridge, edev.dev); 639 640 if (!ebr->edev.etype->subscribed) 641 return UBUS_STATUS_NOT_FOUND; 642 643 ubm = extdev_bridge_create_member(ebr, ebm_dev); 644 if (!ubm) 645 return UBUS_STATUS_UNKNOWN_ERROR; 646 647 device_broadcast_event(&ebr->edev.dev, DEV_EVENT_TOPO_CHANGE); 648 649 return 0; 650 } 651 652 static int 653 extdev_hotplug_remove(struct device *dev, struct device *member) 654 { 655 struct extdev_bridge *ebr; 656 struct extdev_bridge_member *ubm; 657 658 if (!dev->type->bridge_capability) 659 return UBUS_STATUS_NOT_SUPPORTED; 660 661 ebr = container_of(dev, struct extdev_bridge, edev.dev); 662 663 if (!ebr->edev.etype->subscribed) 664 return UBUS_STATUS_NOT_FOUND; 665 666 ubm = vlist_find(&ebr->members, member->ifname, ubm, node); 667 if (!ubm) 668 return UBUS_STATUS_NOT_FOUND; 669 670 vlist_delete(&ebr->members, &ubm->node); 671 extdev_bridge_remove_member(ubm); 672 673 return 0; 674 } 675 676 static int 677 extdev_hotplug_prepare(struct device *dev, struct device **bridge_dev) 678 { 679 struct extdev_bridge *ebr; 680 int ret; 681 682 if (!dev->type->bridge_capability) 683 return UBUS_STATUS_NOT_SUPPORTED; 684 685 if (bridge_dev) 686 *bridge_dev = dev; 687 688 ebr = container_of(dev, struct extdev_bridge, edev.dev); 689 690 blob_buf_init(&b, 0); 691 blobmsg_add_string(&b, "name", dev->ifname); 692 693 ret = netifd_extdev_prepare(ebr, b.head); 694 if (ret) 695 goto error; 696 697 ebr->force_active = true; 698 device_set_present(&ebr->edev.dev, true); 699 700 return 0; 701 702 error: 703 extdev_invocation_error(ret, __extdev_methods[METHOD_HOTPLUG_PREPARE], dev->ifname); 704 return ret; 705 } 706 707 static void 708 extdev_bridge_free_member(struct extdev_bridge_member *ubm) 709 { 710 struct device *dev = ubm->dev_usr.dev; 711 712 extdev_bridge_remove_member(ubm); 713 device_remove_user(&ubm->dev_usr); 714 715 if (dev->present) { 716 device_set_present(dev, false); 717 device_set_present(dev, true); 718 } 719 720 free(ubm); 721 } 722 723 static void 724 extdev_bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new, 725 struct vlist_node *node_old) 726 { 727 struct extdev_bridge_member *ubm; 728 struct device *dev; 729 730 if (node_new) { 731 ubm = container_of(node_new, struct extdev_bridge_member, node); 732 733 if (node_old) { 734 free(ubm); 735 return; 736 } 737 738 dev = ubm->dev_usr.dev; 739 ubm->dev_usr.dev = NULL; 740 device_add_user(&ubm->dev_usr, dev); 741 } 742 743 if (node_old) { 744 ubm = container_of(node_old, struct extdev_bridge_member, node); 745 extdev_bridge_free_member(ubm); 746 } 747 } 748 749 750 static void 751 bridge_dependency_retry(struct uloop_timeout *timeout) 752 { 753 struct extdev_bridge *ebr; 754 755 ebr = container_of(timeout, struct extdev_bridge, edev.retry); 756 757 __bridge_reload(ebr, NULL); 758 } 759 760 static void 761 __buf_add_all(struct blob_attr *attr) 762 { 763 struct blob_attr *cur; 764 int rem; 765 766 blobmsg_for_each_attr(cur, attr, rem) 767 blobmsg_add_field(&b, blobmsg_type(cur), blobmsg_name(cur), blobmsg_data(cur), 768 blobmsg_data_len(cur)); 769 } 770 771 enum { 772 BRIDGE_EMPTY, 773 BRIDGE_IFNAMES, 774 BRIDGE_DEPENDS_ON, 775 __BRIDGE_MAX 776 }; 777 778 static const struct blobmsg_policy brpol[__BRIDGE_MAX] = { 779 [BRIDGE_EMPTY] = { "empty", BLOBMSG_TYPE_BOOL }, 780 [BRIDGE_IFNAMES] = { "ifname", BLOBMSG_TYPE_ARRAY }, 781 [BRIDGE_DEPENDS_ON] = { "depends_on", BLOBMSG_TYPE_STRING }, 782 }; 783 784 static enum dev_change_type 785 __do_bridge_reload(struct extdev_bridge *ebr, struct blob_attr *config) 786 { 787 void *cfg_table; 788 int ret; 789 790 blob_buf_init(&b, 0); 791 cfg_table = blobmsg_open_table(&b, "old"); 792 __buf_add_all(ebr->config); 793 blobmsg_close_table(&b, cfg_table); 794 cfg_table = blobmsg_open_table(&b, "new"); 795 __buf_add_all(config); 796 blobmsg_close_table(&b, cfg_table); 797 798 ret = netifd_extdev_reload(&ebr->edev, b.head); 799 800 if (ret) { 801 netifd_log_message(L_WARNING, "%s config reload failed: %s\n", 802 ebr->edev.dev.ifname, ubus_strerror(ret)); 803 return DEV_CONFIG_RECREATE; 804 } else { 805 return DEV_CONFIG_RESTART; 806 } 807 } 808 809 static enum dev_change_type 810 __bridge_reload(struct extdev_bridge *ebr, struct blob_attr *config) 811 { 812 int n_params = ebr->edev.dev.type->config_params->n_params; 813 struct blob_attr *tb[__BRIDGE_MAX]; 814 const struct uci_blob_param_list *config_params; 815 const struct blobmsg_policy *pol; 816 struct blob_attr *old_tb[n_params], *brtb[n_params]; 817 enum dev_change_type change = DEV_CONFIG_APPLIED; 818 struct device *dev; 819 unsigned long diff = 0; 820 821 if (config) { 822 config = blob_memdup(config); 823 blobmsg_parse(brpol, __BRIDGE_MAX, tb, blobmsg_data(config), blobmsg_len(config)); 824 ebr->edev.dep_name = blobmsg_get_string(tb[BRIDGE_DEPENDS_ON]); 825 826 if (tb[BRIDGE_EMPTY] && blobmsg_get_bool(tb[BRIDGE_EMPTY])) 827 ebr->empty = true; 828 829 if (ebr->config) { 830 config_params = ebr->edev.dev.type->config_params; 831 pol = config_params->params; 832 833 blobmsg_parse(pol, n_params, old_tb, blobmsg_data(ebr->config), 834 blobmsg_len(ebr->config)); 835 blobmsg_parse(pol, n_params, brtb, blobmsg_data(config), blobmsg_len 836 (config)); 837 838 diff = 0; 839 uci_blob_diff(brtb, old_tb, config_params, &diff); 840 if (diff) { 841 if (diff & ~(1 << BRIDGE_IFNAMES)) { 842 change = DEV_CONFIG_RESTART; 843 } else { 844 change = __do_bridge_reload(ebr, config); 845 } 846 847 free(ebr->config); 848 } 849 } 850 851 ebr->ifnames = tb[BRIDGE_IFNAMES]; 852 ebr->config = config; 853 } 854 855 if (ebr->edev.dep_name) { 856 dev = device_get(ebr->edev.dep_name, 0); 857 if (!(dev && dev->current_config)) { 858 D(DEVICE, "%s: cannot yet init config since dependency '%s' is not ready\n", 859 ebr->edev.dev.ifname, ebr->edev.dep_name); 860 ebr->edev.retry.cb = bridge_dependency_retry; 861 uloop_timeout_set(&ebr->edev.retry, 200); 862 return DEV_CONFIG_RESTART; 863 } 864 } 865 866 __bridge_config_init(ebr); 867 ebr->edev.dev.config_pending = false; 868 uloop_timeout_cancel(&ebr->edev.retry); 869 870 return change; 871 } 872 873 static enum dev_change_type 874 __reload(struct extdev_device *edev, struct blob_attr *config) 875 { 876 unsigned long diff = 0; 877 struct uci_blob_param_list *params; 878 879 params = edev->etype->config_params; 880 881 struct blob_attr *tb[params->n_params]; 882 struct blob_attr *old_tb[params->n_params]; 883 884 blobmsg_parse(params->params, params->n_params, tb, blobmsg_data(config), 885 blobmsg_len(config)); 886 blobmsg_parse(params->params, params->n_params, old_tb, blobmsg_data(edev->dev.config), 887 blobmsg_len(edev->dev.config)); 888 889 uci_blob_diff(tb, old_tb, edev->etype->config_params, &diff); 890 if (!diff) 891 return DEV_CONFIG_NO_CHANGE; 892 893 // TODO: make reload ubus call with old and new config 894 895 device_set_present(&edev->dev, false); 896 device_set_present(&edev->dev, true); 897 898 return DEV_CONFIG_APPLIED; 899 } 900 901 static enum dev_change_type 902 extdev_reload(struct device *dev, struct blob_attr *config) 903 { 904 struct extdev_type *etype; 905 struct extdev_device *edev; 906 struct extdev_bridge *ebr; 907 908 etype = container_of(dev->type, struct extdev_type, handler); 909 910 if (!etype->subscribed) 911 return DEV_CONFIG_NO_CHANGE; 912 913 edev = container_of(dev, struct extdev_device, dev); 914 915 if (dev->type->bridge_capability) { 916 ebr = container_of(edev, struct extdev_bridge, edev); 917 return __bridge_reload(ebr, config); 918 } else { 919 return __reload(edev, config); 920 } 921 } 922 923 static struct device* 924 __create(const char *name, struct device_type *type, struct blob_attr *config) 925 { 926 struct extdev_device *edev; 927 struct extdev_type *etype; 928 int ret; 929 930 etype = container_of(type, struct extdev_type, handler); 931 edev = calloc(1, sizeof(struct extdev_device)); 932 if (!edev) 933 return NULL; 934 935 ret = device_init(&edev->dev, type, name); 936 if (ret) 937 goto error; 938 939 edev->etype = etype; 940 941 ret = netifd_extdev_create(edev, config); 942 if (ret) 943 goto inv_error; 944 945 edev->dev.config_pending = false; 946 947 return &edev->dev; 948 949 inv_error: 950 extdev_invocation_error(ret, __extdev_methods[METHOD_CREATE], name); 951 error: 952 device_lock(); 953 free(edev->dev.config); 954 device_cleanup(&edev->dev); 955 free(edev); 956 device_unlock(); 957 netifd_log_message(L_WARNING, "Failed to create %s %s\n", type->name, name); 958 return NULL; 959 } 960 961 static const struct device_hotplug_ops extdev_hotplug_ops = { 962 .prepare = extdev_hotplug_prepare, 963 .add = extdev_hotplug_add, 964 .del = extdev_hotplug_remove 965 }; 966 967 static struct device* 968 __bridge_create(const char *name, struct device_type *devtype, struct blob_attr *config) 969 { 970 struct extdev_bridge *ebr; 971 972 ebr = calloc(1, sizeof(*ebr)); 973 if (!ebr) 974 return NULL; 975 976 device_init(&ebr->edev.dev, devtype, name); 977 ebr->edev.dev.config_pending = true; 978 ebr->retry.cb = extdev_bridge_retry_enable_members; 979 ebr->edev.etype = container_of(devtype, struct extdev_type, handler); 980 ebr->set_state = ebr->edev.dev.set_state; 981 ebr->edev.dev.set_state = extdev_bridge_set_state; 982 ebr->edev.dev.hotplug_ops = &extdev_hotplug_ops; 983 vlist_init(&ebr->members, avl_strcmp, extdev_bridge_member_update); 984 ebr->members.keep_old = true; 985 __bridge_reload(ebr, config); 986 987 return &ebr->edev.dev; 988 } 989 990 /* Device creation process: 991 * For bridges without dependencies: 992 * 1) The bridge state is initialized in netifd. Devices for the members are 993 * created and added to the members vlist by config_init automatically. 994 * 2) When the first bridge member device is brought up in 995 * extdev_bridge_enable_member the 'create' call to the external device 996 * handler is issued. 997 * 3) After successful device creation the bridge is marked "present" and a 998 * new attempt at adding the member is made. 999 * For bridges with dependencies: 1000 * 1) The bridge state is initialized in netifd. If a dependency is expressed 1001 * via the 'depends_on' UCI option and the dependency is not ready (i.e. it 1002 * does not exist or config_pending == true) the call to 1003 * __bridge_config_init() is postponed and a retry timer is started. Retries 1004 * happen until the dependency is ready. Then, __bridge_config_init() gets 1005 * called and the process continues as with bridges without dependencies 1006 * For regular devices: 1007 * 1) The device structure is created in netifd. 1008 * 2) config_init is called automatically which issues the 'create' call to the 1009 * external device handler. 1010 */ 1011 static struct device * 1012 extdev_create(const char *name, struct device_type *devtype, struct blob_attr *config) 1013 { 1014 struct extdev_type *etype = container_of(devtype, struct extdev_type, handler); 1015 1016 if (!etype->subscribed) 1017 return NULL; 1018 1019 if (devtype->bridge_capability) 1020 return __bridge_create(name, devtype, config); 1021 else 1022 return __create(name, devtype, config); 1023 } 1024 1025 static void 1026 extdev_free(struct device *dev) 1027 { 1028 struct extdev_type *etype; 1029 struct extdev_device *edev; 1030 struct extdev_bridge *ebr; 1031 int ret; 1032 1033 etype = container_of(dev->type, struct extdev_type, handler); 1034 edev = container_of(dev, struct extdev_device, dev); 1035 1036 if (!etype->subscribed) 1037 return; 1038 1039 blob_buf_init(&b, 0); 1040 blobmsg_add_string(&b, "name", dev->ifname); 1041 1042 ret = netifd_extdev_free(edev, b.head); 1043 1044 if (ret && ret != UBUS_STATUS_NOT_FOUND) 1045 goto error; 1046 1047 if (dev->type->bridge_capability) { 1048 ebr = container_of(dev, struct extdev_bridge, edev.dev); 1049 1050 vlist_flush_all(&ebr->members); 1051 // vlist_flush_all(&dev->vlans); TODO: do we need this? 1052 1053 free(ebr->config); 1054 free(ebr); 1055 } 1056 1057 return; 1058 1059 error: 1060 extdev_invocation_error(ret, __extdev_methods[METHOD_FREE], 1061 dev->ifname); 1062 } 1063 1064 static void 1065 __bridge_config_init(struct extdev_bridge *ebr) 1066 { 1067 int rem, ret; 1068 struct blob_attr *cur; 1069 1070 if (ebr->empty) { 1071 ebr->force_active = true; 1072 ret = netifd_extdev_create(&ebr->edev, ebr->config); 1073 if (ret) 1074 goto error; 1075 device_set_present(&ebr->edev.dev, true); 1076 } 1077 1078 ebr->n_failed = 0; 1079 vlist_update(&ebr->members); 1080 if (ebr->ifnames) { 1081 blobmsg_for_each_attr(cur, ebr->ifnames, rem) 1082 extdev_bridge_add_member(ebr, blobmsg_data(cur)); 1083 } 1084 1085 vlist_flush(&ebr->members); 1086 extdev_bridge_check_retry(ebr); 1087 return; 1088 1089 error: 1090 fprintf(stderr, "Failed to init config for '%s': %s\n", ebr->edev.dev.ifname, 1091 ubus_strerror(ret)); 1092 } 1093 1094 static void 1095 extdev_config_init(struct device *dev) 1096 { 1097 struct extdev_type *etype; 1098 struct extdev_bridge *ebr; 1099 1100 etype = container_of(dev->type, struct extdev_type, handler); 1101 1102 if (!etype->subscribed) 1103 return; 1104 1105 if (dev->type->bridge_capability) { 1106 ebr = container_of(dev, struct extdev_bridge, edev.dev); 1107 __bridge_config_init(ebr); 1108 } 1109 } 1110 1111 static void 1112 extdev_buf_add_list(struct blob_attr *attr, int len, const char *name, 1113 struct blob_buf *buf, bool array) 1114 { 1115 struct blob_attr *cur; 1116 struct blobmsg_hdr *hdr; 1117 void *list; 1118 int type; 1119 1120 if (array) 1121 list = blobmsg_open_array(buf, name); 1122 else 1123 list = blobmsg_open_table(buf, name); 1124 1125 blobmsg_for_each_attr(cur, attr, len) { 1126 hdr = blob_data(cur); 1127 type = blobmsg_type(cur); 1128 switch (type) { 1129 case BLOBMSG_TYPE_STRING: 1130 blobmsg_add_string(buf, (char *) hdr->name, 1131 blobmsg_get_string(cur)); 1132 break; 1133 case BLOBMSG_TYPE_TABLE: 1134 case BLOBMSG_TYPE_ARRAY: 1135 extdev_buf_add_list(blobmsg_data(cur), blobmsg_data_len(cur), 1136 (char *) hdr->name, buf, type == BLOBMSG_TYPE_ARRAY); 1137 break; 1138 case BLOBMSG_TYPE_INT64: 1139 blobmsg_add_u64(buf, (char *) hdr->name, blobmsg_get_u64(cur)); 1140 break; 1141 case BLOBMSG_TYPE_INT32: 1142 blobmsg_add_u32(buf, (char *) hdr->name, blobmsg_get_u32(cur)); 1143 break; 1144 case BLOBMSG_TYPE_INT16: 1145 blobmsg_add_u16(buf, (char *) hdr->name, blobmsg_get_u16(cur)); 1146 break; 1147 case BLOBMSG_TYPE_INT8: 1148 blobmsg_add_u8(buf, (char *) hdr->name, blobmsg_get_u8(cur)); 1149 break; 1150 default: 1151 break; 1152 } 1153 } 1154 1155 if (array) 1156 blobmsg_close_array(buf, list); 1157 else 1158 blobmsg_close_table(buf, list); 1159 } 1160 1161 static void 1162 add_parsed_data(struct blob_attr **tb, const struct blobmsg_policy *policy, int n_params, 1163 struct blob_buf *buf) 1164 { 1165 for (int i = 0; i < n_params; i++) { 1166 if (!tb[i]) 1167 continue; 1168 1169 switch (policy[i].type) { 1170 case BLOBMSG_TYPE_STRING: 1171 blobmsg_add_string(buf, policy[i].name, blobmsg_get_string(tb[i])); 1172 break; 1173 case BLOBMSG_TYPE_ARRAY: 1174 case BLOBMSG_TYPE_TABLE: 1175 extdev_buf_add_list(blobmsg_data(tb[i]), blobmsg_data_len(tb[i]), 1176 policy[i].name, buf, policy[i].type == BLOBMSG_TYPE_ARRAY); 1177 break; 1178 case BLOBMSG_TYPE_INT64: 1179 blobmsg_add_u64(buf, policy[i].name, blobmsg_get_u64(tb[i])); 1180 break; 1181 case BLOBMSG_TYPE_INT32: 1182 blobmsg_add_u32(buf, policy[i].name, blobmsg_get_u32(tb[i])); 1183 break; 1184 case BLOBMSG_TYPE_INT16: 1185 blobmsg_add_u16(buf, policy[i].name, blobmsg_get_u16(tb[i])); 1186 break; 1187 case BLOBMSG_TYPE_INT8: 1188 blobmsg_add_u8(buf, policy[i].name, blobmsg_get_u8(tb[i])); 1189 break; 1190 default: 1191 break; 1192 } 1193 } 1194 } 1195 1196 struct dump_data { 1197 const struct device *dev; 1198 struct blob_buf *buf; 1199 }; 1200 1201 static void 1202 dump_cb(struct ubus_request *req, int type, struct blob_attr *reply) 1203 { 1204 struct dump_data *data; 1205 struct extdev_type *etype; 1206 const struct blobmsg_policy *info_policy; 1207 int n_params; 1208 struct blob_buf *buf; 1209 1210 data = req->priv; 1211 etype = container_of(data->dev->type, struct extdev_type, handler); 1212 info_policy = etype->info_params->params; 1213 n_params = etype->info_params->n_params; 1214 buf = data->buf; 1215 1216 struct blob_attr *tb[n_params]; 1217 1218 blobmsg_parse(info_policy, n_params, tb, blobmsg_data(reply), blobmsg_len(reply)); 1219 add_parsed_data(tb, info_policy, n_params, buf); 1220 } 1221 1222 static void 1223 extdev_dump(const char *method, struct device *dev, struct blob_buf *buf) 1224 { 1225 static struct dump_data data; 1226 struct extdev_type *etype; 1227 1228 etype = container_of(dev->type, struct extdev_type, handler); 1229 1230 if (!etype->subscribed) 1231 return; 1232 1233 data.dev = dev; 1234 data.buf = buf; 1235 1236 blob_buf_init(&b, 0); 1237 blobmsg_add_string(&b, "name", dev->ifname); 1238 1239 netifd_extdev_invoke(etype->peer_id, method, b.head, dump_cb, &data); 1240 } 1241 1242 static void 1243 extdev_dump_info(struct device *dev, struct blob_buf *buf) 1244 { 1245 extdev_dump(__extdev_methods[METHOD_DUMP_INFO], dev, buf); 1246 } 1247 1248 static void 1249 extdev_dump_stats(struct device *dev, struct blob_buf *buf) 1250 { 1251 extdev_dump(__extdev_methods[METHOD_DUMP_STATS], dev, buf); 1252 } 1253 1254 static void 1255 extdev_ext_handler_remove_cb(struct ubus_context *ctx, 1256 struct ubus_subscriber *obj, uint32_t id) 1257 { 1258 struct extdev_type *etype; 1259 etype = container_of(obj, struct extdev_type, ubus_sub); 1260 1261 netifd_log_message(L_NOTICE, "%s: external device handler " 1262 "'%s' disappeared. Waiting for it to re-appear.\n", 1263 etype->handler.name, etype->name); 1264 1265 etype->peer_id = 0; 1266 etype->subscribed = false; 1267 1268 extdev_ext_ubus_obj_wait(&etype->obj_wait); 1269 } 1270 1271 static void 1272 extdev_add_devtype(const char *cfg_file, const char *tname, const char *ubus_name, 1273 bool bridge_capability, const char *br_prefix, json_object *cfg_obj, 1274 json_object *info_obj, json_object *stats_obj) 1275 { 1276 static const char *OBJ_PREFIX = "network.device."; 1277 1278 struct extdev_type *etype; 1279 struct device_type *devtype; 1280 char *ubus_obj_name, *devtype_name, *ext_dev_handler_name, *name_prefix; 1281 struct uci_blob_param_list *config_params, *info_params, *stats_params; 1282 int ret; 1283 1284 etype = calloc_a(sizeof(*etype), 1285 &ubus_obj_name, strlen(OBJ_PREFIX) + strlen(ubus_name) + 1, 1286 &devtype_name, strlen(tname) + 1, 1287 &ext_dev_handler_name, strlen(ubus_name) + 1, 1288 &config_params, sizeof(struct uci_blob_param_list), 1289 &info_params, sizeof(struct uci_blob_param_list), 1290 &stats_params, sizeof(struct uci_blob_param_list)); 1291 1292 if (!etype) 1293 return; 1294 1295 etype->config_params = config_params; 1296 etype->info_params = info_params; 1297 etype->name = strcpy(ext_dev_handler_name, ubus_name); 1298 1299 devtype = &etype->handler; 1300 devtype->name = strcpy(devtype_name, tname); 1301 devtype->create = extdev_create; 1302 devtype->free = extdev_free; 1303 devtype->config_init = extdev_config_init; 1304 devtype->reload = extdev_reload; 1305 devtype->dump_info = extdev_dump_info; 1306 devtype->dump_stats = extdev_dump_stats; 1307 devtype->bridge_capability = bridge_capability; 1308 devtype->config_params = etype->config_params; 1309 1310 if (bridge_capability) { 1311 name_prefix = malloc(strlen(br_prefix) + 1); 1312 if (!name_prefix) 1313 goto error; 1314 1315 strcpy(name_prefix, br_prefix); 1316 devtype->name_prefix = name_prefix; 1317 } 1318 1319 /* subscribe to external device handler */ 1320 sprintf(ubus_obj_name, "%s%s", OBJ_PREFIX, ubus_name); 1321 etype->ubus_sub.obj.name = ubus_obj_name; 1322 etype->ubus_sub.obj.type = &extdev_ubus_object_type; 1323 ret = ubus_register_subscriber(ubus_ctx, &etype->ubus_sub); 1324 if (ret) { 1325 fprintf(stderr, "Failed to register subscriber object '%s'\n", 1326 etype->ubus_sub.obj.name); 1327 goto error; 1328 } 1329 etype->obj_wait.cb = extdev_wait_ev_cb; 1330 etype->ubus_sub.remove_cb = extdev_ext_handler_remove_cb; 1331 extdev_subscribe(etype); 1332 1333 /* parse config params from JSON object */ 1334 etype->config_strbuf = netifd_handler_parse_config(etype->config_params, cfg_obj); 1335 if (!etype->config_strbuf) 1336 goto error; 1337 1338 /* parse info dump params from JSON object */ 1339 if (!info_obj) { 1340 devtype->dump_info = NULL; 1341 } else { 1342 etype->info_strbuf = netifd_handler_parse_config(etype->info_params, info_obj); 1343 if (!etype->info_strbuf) 1344 devtype->dump_info = NULL; 1345 } 1346 1347 /* parse statistics dump params from JSON object */ 1348 if (!stats_obj) { 1349 devtype->dump_stats = NULL; 1350 } else { 1351 etype->stats_strbuf = netifd_handler_parse_config(etype->stats_params, stats_obj); 1352 if (!etype->stats_strbuf) 1353 devtype->dump_stats = NULL; 1354 } 1355 1356 ret = device_type_add(devtype); 1357 if (ret) 1358 goto config_error; 1359 1360 return; 1361 1362 config_error: 1363 free(etype->config_strbuf); 1364 free(etype->info_strbuf); 1365 free(etype->stats_strbuf); 1366 1367 error: 1368 fprintf(stderr, "Failed to create device handler for device" 1369 "type '%s' from file '%s'\n", tname, cfg_file); 1370 free(ubus_obj_name); 1371 free(devtype_name); 1372 free(etype); 1373 } 1374 1375 /* create extdev device handler stubs from JSON description */ 1376 void 1377 extdev_init(void) 1378 { 1379 confdir_fd = netifd_open_subdir("extdev-config"); 1380 if (confdir_fd < 0) 1381 return; 1382 netifd_init_extdev_handlers(confdir_fd, extdev_add_devtype); 1383 } 1384
This page was automatically generated by LXR 0.3.1. • OpenWrt