From: Michael Tremer Date: Fri, 14 Apr 2023 14:15:01 +0000 (+0000) Subject: networkd: Automatically reference/dereference links to zones/ports X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=611d4aca5d48567a7a7ddb0dd3446a97e91aad54;p=network.git networkd: Automatically reference/dereference links to zones/ports Signed-off-by: Michael Tremer --- diff --git a/src/networkd/daemon.c b/src/networkd/daemon.c index c6dad91e..02ca8e2e 100644 --- a/src/networkd/daemon.c +++ b/src/networkd/daemon.c @@ -540,6 +540,13 @@ nw_ports* nw_daemon_ports(nw_daemon* daemon) { return nw_ports_ref(daemon->ports); } +int nw_daemon_ports_walk(nw_daemon* daemon, nw_ports_walk_callback callback, void* data) { + if (!daemon->ports) + return 0; + + return nw_ports_walk(daemon->ports, callback, data); +} + nw_port* nw_daemon_get_port_by_name(nw_daemon* daemon, const char* name) { if (!daemon->ports) return NULL; diff --git a/src/networkd/daemon.h b/src/networkd/daemon.h index ce9a6602..a14d33b2 100644 --- a/src/networkd/daemon.h +++ b/src/networkd/daemon.h @@ -60,6 +60,7 @@ nw_link* nw_daemon_get_link_by_name(nw_daemon* daemon, const char* name); Ports */ nw_ports* nw_daemon_ports(nw_daemon* daemon); +int nw_daemon_ports_walk(nw_daemon* daemon, nw_ports_walk_callback callback, void* data); nw_port* nw_daemon_get_port_by_name(nw_daemon* daemon, const char* name); /* diff --git a/src/networkd/link.c b/src/networkd/link.c index 949d0d8d..09b9a622 100644 --- a/src/networkd/link.c +++ b/src/networkd/link.c @@ -114,6 +114,10 @@ int nw_link_ifindex(nw_link* link) { } const char* nw_link_ifname(nw_link* link) { + // Return NULL if name isn't set + if (!*link->ifname) + return NULL; + return link->ifname; } @@ -154,6 +158,12 @@ static int nw_link_update_ifname(nw_link* link, sd_netlink_message* message) { DEBUG("Link %d has been renamed to '%s'\n", link->ifindex, link->ifname); + // Assign link to ports + nw_daemon_ports_walk(link->daemon, __nw_port_set_link, link); + + // Assign link to zones + nw_daemon_zones_walk(link->daemon, __nw_zone_set_link, link); + return 0; } diff --git a/src/networkd/links.c b/src/networkd/links.c index 3dd06d0f..40926f3e 100644 --- a/src/networkd/links.c +++ b/src/networkd/links.c @@ -141,6 +141,12 @@ void nw_links_drop_link(nw_links* links, struct nw_link* link) { STAILQ_REMOVE(&links->entries, entry, nw_links_entry, nodes); links->num--; + + // Drop link from all ports + nw_daemon_ports_walk(links->daemon, __nw_port_drop_link, link); + + // Drop link from all zones + nw_daemon_zones_walk(links->daemon, __nw_zone_drop_link, link); } int nw_links_enumerate(nw_links* links) { diff --git a/src/networkd/port.c b/src/networkd/port.c index 7d023050..37ab3a7c 100644 --- a/src/networkd/port.c +++ b/src/networkd/port.c @@ -135,39 +135,65 @@ static nw_port_type_t nw_port_setup_type(nw_port* port) { return nw_port_type_from_string(type); } +static int nw_port_set_link(nw_port* port, nw_link* link) { + // Do nothing if the same link is being re-assigned + if (port->link == link) + return 0; + + // Dereference the former link if set + if (port->link) + nw_link_unref(port->link); + + // Store the new link + if (link) { + port->link = nw_link_ref(link); + + DEBUG("Port %s: Assigned link %d\n", port->name, nw_link_ifindex(port->link)); + + // Or clear the pointer if no link has been provided + } else { + port->link = NULL; + + DEBUG("Port %s: Removed link\n", port->name); + } + + return 0; +} + static int nw_port_setup(nw_port* port) { + nw_link* link = NULL; char path[PATH_MAX]; int r; // Find the link - port->link = nw_daemon_get_link_by_name(port->daemon, port->name); - if (port->link) { - DEBUG("%s: Found matching link %d\n", port->name, nw_link_ifindex(port->link)); - } else { - DEBUG("%s: Could not find matching link\n", port->name); + link = nw_daemon_get_link_by_name(port->daemon, port->name); + if (link) { + r = nw_port_set_link(port, link); + if (r) + goto ERROR; } // Compose the path to the main configuration file r = nw_path_join(path, PORT_CONFIG_DIR, port->name); if (r) - return r; + goto ERROR; // Initialize the configuration r = nw_config_create(&port->config, path); if (r) - return r; + goto ERROR; // Determine type port->type = nw_port_setup_type(port); if (!port->type) { ERROR("Could not determine type of port %s\n", port->name); - return 0; + goto ERROR; } // Perform some common initialization r = nw_port_setup_common(port); if (r) - return r; + goto ERROR; // Call any custom initialization switch (port->type) { @@ -177,7 +203,11 @@ static int nw_port_setup(nw_port* port) { break; } - return 0; +ERROR: + if (link) + nw_link_unref(link); + + return r; } int nw_port_create(nw_port** port, nw_daemon* daemon, const char* name) { @@ -252,11 +282,35 @@ char* nw_port_bus_path(nw_port* port) { return p; } -static nw_link* nw_port_get_link(nw_port* port) { - if (!port->link) - return NULL; +int __nw_port_set_link(nw_daemon* daemon, nw_port* port, void* data) { + nw_link* link = (nw_link*)data; + + // Fetch the link name + const char* ifname = nw_link_ifname(link); + if (!ifname) { + ERROR("Link does not have a name set\n"); + return 1; + } + + // Set link if the name matches + if (strcmp(port->name, ifname) == 0) + return nw_port_set_link(port, link); + + // If we have the link set but the name did not match, we will remove it + else if (port->link == link) + return nw_port_set_link(port, NULL); + + return 0; +} + +int __nw_port_drop_link(nw_daemon* daemon, nw_port* port, void* data) { + nw_link* link = (nw_link*)data; - return nw_link_ref(port->link); + // Drop the link if it matches + if (port->link == link) + return nw_port_set_link(port, NULL); + + return 0; } const nw_address_t* nw_port_get_address(nw_port* port) { diff --git a/src/networkd/port.h b/src/networkd/port.h index 17c8c3cd..3981c82a 100644 --- a/src/networkd/port.h +++ b/src/networkd/port.h @@ -44,6 +44,9 @@ const char* nw_port_name(nw_port* port); char* nw_port_bus_path(nw_port* port); +int __nw_port_set_link(nw_daemon* daemon, nw_port* port, void* data); +int __nw_port_drop_link(nw_daemon* daemon, nw_port* port, void* data); + const nw_address_t* nw_port_get_address(nw_port* port); int nw_port_reconfigure(nw_port* port); diff --git a/src/networkd/zone.c b/src/networkd/zone.c index 9daa0d3d..00ab017f 100644 --- a/src/networkd/zone.c +++ b/src/networkd/zone.c @@ -80,29 +80,59 @@ static void nw_zone_free(nw_zone* zone) { free(zone); } +static int nw_zone_set_link(nw_zone* zone, nw_link* link) { + // Do nothing if the same link is being re-assigned + if (zone->link == link) + return 0; + + // Dereference the former link if set + if (zone->link) + nw_link_unref(zone->link); + + // Store the new link + if (link) { + zone->link = nw_link_ref(link); + + DEBUG("Zone %s: Assigned link %d\n", zone->name, nw_link_ifindex(zone->link)); + + // Or clear the pointer if no link has been provided + } else { + zone->link = NULL; + + DEBUG("Zone %s: Removed link\n", zone->name); + } + + return 0; +} + static int nw_zone_setup(nw_zone* zone) { + nw_link* link = NULL; char path[PATH_MAX]; int r; // Find the link - zone->link = nw_daemon_get_link_by_name(zone->daemon, zone->name); - if (zone->link) { - DEBUG("%s: Found matching link %d\n", zone->name, nw_link_ifindex(zone->link)); - } else { - DEBUG("%s: Could not find matching link\n", zone->name); + link = nw_daemon_get_link_by_name(zone->daemon, zone->name); + if (link) { + r = nw_zone_set_link(zone, link); + if (r) + goto ERROR; } // Compose the path to the main configuration file r = nw_zone_path(zone, path, "%s", "settings"); if (r) - return r; + goto ERROR; // Initialize the configuration r = nw_config_create(&zone->config, path); if (r) - return r; + goto ERROR; - return 0; +ERROR: + if (link) + nw_link_unref(link); + + return r; } int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const char* name) { @@ -177,11 +207,35 @@ char* nw_zone_bus_path(nw_zone* zone) { return p; } -static nw_link* nw_zone_get_link(nw_zone* zone) { - if (!zone->link) - return NULL; +int __nw_zone_set_link(nw_daemon* daemon, nw_zone* zone, void* data) { + nw_link* link = (nw_link*)data; + + // Fetch the link name + const char* ifname = nw_link_ifname(link); + if (!ifname) { + ERROR("Link does not have a name set\n"); + return 1; + } + + // Set link if the name matches + if (strcmp(zone->name, ifname) == 0) + return nw_zone_set_link(zone, link); + + // If we have the link set but the name did not match, we will remove it + else if (zone->link == link) + return nw_zone_set_link(zone, NULL); - return nw_link_ref(zone->link); + return 0; +} + +int __nw_zone_drop_link(nw_daemon* daemon, nw_zone* zone, void* data) { + nw_link* link = (nw_link*)data; + + // Drop the link if it matches + if (zone->link == link) + return nw_zone_set_link(zone, NULL); + + return 0; } int nw_zone_reconfigure(nw_zone* zone) { diff --git a/src/networkd/zone.h b/src/networkd/zone.h index 591e467d..ad348d71 100644 --- a/src/networkd/zone.h +++ b/src/networkd/zone.h @@ -41,6 +41,9 @@ const char* nw_zone_name(nw_zone* zone); char* nw_zone_bus_path(nw_zone* zone); +int __nw_zone_set_link(nw_daemon* daemon, nw_zone* zone, void* data); +int __nw_zone_drop_link(nw_daemon* daemon, nw_zone* zone, void* data); + int nw_zone_reconfigure(nw_zone* zone); int nw_zone_has_carrier(nw_zone* zone);