networkd-bridge.c revision bf1bc6701574f5e935fafc3163659372abdcde63
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering LIST_REMOVE(callbacks, bridge->callbacks, callback);
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering hashmap_remove(bridge->manager->bridges, bridge->name);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringint bridge_get(Manager *manager, const char *name, Bridge **ret) {
818f766b12e025683cf4fed12b3da2a025bb0b31Lennart Poettering bridge = hashmap_get(manager->bridges, name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int bridge_enter_failed(Bridge *bridge) {
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poetteringstatic int bridge_join_ready(Bridge *bridge, Link* link, sd_rtnl_message_handler_t callback) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bridge->state == BRIDGE_STATE_READY);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering log_error("Could not allocate RTM_SETLINK message: %s",
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering r = sd_rtnl_message_append_u32(req, IFLA_MASTER, bridge->link->ifindex);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering log_error("Could not append IFLA_MASTER attribute: %s",
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_rtnl_call_async(bridge->manager->rtnl, req, callback, link, 0, NULL);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("Could not send rtnetlink message: %s", strerror(-r));
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int bridge_enter_ready(Bridge *bridge) {
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering log_info("Bridge '%s' ready", bridge->name);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering LIST_FOREACH(callbacks, callback, bridge->callbacks) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering /* join the links that were attempted to be joined befor the
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering * link was ready */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bridge_join_ready(bridge, callback->link, callback->callback);
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poetteringstatic int bridge_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
8ba9fd9cee0eef572f7b3ed7a8c3ed31160e93d3Lennart Poettering assert(bridge->state == BRIDGE_STATE_CREATING);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_warning("Bridge '%s' failed: %s", bridge->name, strerror(-r));
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poetteringstatic int bridge_create(Bridge *bridge) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(bridge->state == _BRIDGE_STATE_INVALID);
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = sd_rtnl_message_link_new(RTM_NEWLINK, 0, &req);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("Could not allocate RTM_NEWLINK message: %s",
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = sd_rtnl_message_append_string(req, IFLA_IFNAME, bridge->name);
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering log_error("Could not append IFLA_IFNAME attribute: %s",
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Colud not open IFLA_LINKINFO container: %s",
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering r = sd_rtnl_message_append_string(req, IFLA_INFO_KIND, "bridge");
309e9d86f0e7f9c5f0a2a09227bdfdb3174d4436Lennart Poettering log_error("Could not append IFLA_INFO_KIND attribute: %s",
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = sd_rtnl_message_close_container(req);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Could not close IFLA_LINKINFO container %s",
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = sd_rtnl_call_async(bridge->manager->rtnl, req, &bridge_create_handler, bridge, 0, NULL);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_error("Could not send rtnetlink message: %s", strerror(-r));
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering log_info("Creating bridge '%s'", bridge->name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint bridge_join(Bridge *bridge, Link *link, sd_rtnl_message_handler_t callback) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (bridge->state == BRIDGE_STATE_READY) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* the bridge is not yet read, save this request for when it is*/
51323288fc628a5cac50914df915545d685b793eLennart Poettering LIST_PREPEND(callbacks, bridge->callbacks, cb);
51323288fc628a5cac50914df915545d685b793eLennart Poetteringint bridge_set_link(Manager *m, Link *link) {
51323288fc628a5cac50914df915545d685b793eLennart Poettering bridge = hashmap_get(m->bridges, link->ifname);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (bridge->link && bridge->link != link)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (bridge->state == BRIDGE_STATE_CREATED)
51323288fc628a5cac50914df915545d685b793eLennart Poetteringstatic int bridge_load_one(Manager *manager, const char *filename) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bridge_free_ Bridge *bridge = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = config_parse(NULL, filename, file, "Bridge\0", config_item_perf_lookup,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (void*) network_gperf_lookup, false, false, bridge);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Could not parse config file %s: %s", filename, strerror(-r));
966c66e34940001a40806142ecebaae61b478444Lennart Poettering log_debug("Parsed configuration file %s", filename);
82bd6dddc4a363a9c3c6f41eb46eb171a80dca27Lennart Poettering log_warning("Bridge without Name configured in %s. Ignoring", filename);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = hashmap_put(bridge->manager->bridges, bridge->name, bridge);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while ((bridge = hashmap_first(manager->bridges)))
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering r = conf_files_list_strv(&files, ".netdev", NULL, (const char **)manager->network_dirs);
3339cb71d44c5198f9546f113674f06dc7b01a6fLennart Poettering log_error("Failed to enumerate netdev files: %s", strerror(-r));