From: Michael Tremer Date: Sat, 15 Apr 2023 11:16:33 +0000 (+0000) Subject: port: Implement reading/writing VLAN settings X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c7761af8c8f278f3adb7d422144e13f845089a4b;p=network.git port: Implement reading/writing VLAN settings This is just simple test to see where the configuration could be going. Signed-off-by: Michael Tremer --- diff --git a/src/networkd/port.c b/src/networkd/port.c index aad62106..a240c611 100644 --- a/src/networkd/port.c +++ b/src/networkd/port.c @@ -40,21 +40,32 @@ struct nw_port { // Link nw_link* link; - char name[IF_NAMESIZE]; nw_port_type_t type; + char name[IF_NAMESIZE]; // Configuration nw_config *config; // Common attributes nw_address_t address; + + // VLAN settings + struct nw_port_vlan { + nw_port* parent; + int id; + + // If the parent has not been read from the configuration we will + // save the name and try to find it later. + char __parent_name[IF_NAMESIZE]; + } vlan; }; static const struct nw_port_type_map { nw_port_type_t type; const char* name; } nw_port_type_map[] = { - { NW_PORT_DUMMY, "dummy" }, + { NW_PORT_DUMMY, "dummy" }, + { NW_PORT_VLAN, "vlan" }, { NW_PORT_UNKNOWN, NULL }, }; @@ -128,6 +139,28 @@ static int nw_port_setup_common(nw_port* port) { return 0; } +static int nw_port_setup_vlan(nw_port* port) { + int r; + + // VLAN ID + int id = nw_config_get_int(port->config, "VLAN_ID", NW_VLAN_ID_INVALID); + if (id) { + r = nw_port_set_vlan_id(port, id); + if (r) + return r; + } + + // Parent Port + const char* parent = nw_config_get(port->config, "VLAN_PARENT"); + if (parent) { + r = nw_string_set(port->vlan.__parent_name, parent); + if (r) + return r; + } + + return 0; +} + 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) @@ -183,6 +216,12 @@ static int nw_port_setup(nw_port* port) { // Call any custom initialization switch (port->type) { + case NW_PORT_VLAN: + r = nw_port_setup_vlan(port); + if (r) + goto ERROR; + break; + // These do not need any special initialization case NW_PORT_DUMMY: case NW_PORT_UNKNOWN: @@ -275,14 +314,50 @@ nw_port* nw_port_unref(nw_port* port) { return NULL; } +static int nw_port_save_vlan(nw_port* port) { + int r; + + // VLAN ID + r = nw_config_set_int(port->config, "VLAN_ID", port->vlan.id); + if (r) + return r; + + // Parent Port + r = nw_config_set(port->config, "VLAN_PARENT", + (port->vlan.parent) ? nw_port_name(port->vlan.parent) : port->vlan.__parent_name); + if (r) + return r; + + return 0; +} + int nw_port_save(nw_port* port) { int r; + switch (port->type) { + // VLAN + case NW_PORT_VLAN: + r = nw_port_save_vlan(port); + if (r) + goto ERROR; + break; + + // These types do not have any special settings + case NW_PORT_DUMMY: + case NW_PORT_UNKNOWN: + break; + } + r = nw_config_write(port->config); if (r) return r; return 0; + +ERROR: + ERROR("Could not save configuration for port %s: %m\n", port->name); + + return 1; } const char* nw_port_name(nw_port* port) { @@ -404,3 +479,90 @@ int nw_port_update_stats(nw_port* port) { return 0; } + +static int nw_port_check_type(nw_port* port, const nw_port_type_t type) { + if (port->type == type) + return 0; + + errno = ENOTSUP; + return -errno; +} + +/* + VLAN +*/ +int nw_port_get_vlan_id(nw_port* port) { + int r; + + // Check type + r = nw_port_check_type(port, NW_PORT_VLAN); + if (r < 0) + return r; + + return port->vlan.id; +} + +int nw_port_set_vlan_id(nw_port* port, int id) { + int r; + + // Check type + r = nw_port_check_type(port, NW_PORT_VLAN); + if (r < 0) + return r; + + // Check if the VLAN ID is within range + if (id < NW_VLAN_ID_MIN || id > NW_VLAN_ID_MAX) + return -EINVAL; + + // Store the ID + port->vlan.id = id; + + DEBUG("Port %s: Set VLAN ID to %d\n", port->name, port->vlan.id); + + return 0; +} + +nw_port* nw_port_get_vlan_parent(nw_port* port) { + int r; + + // Check type + r = nw_port_check_type(port, NW_PORT_VLAN); + if (r < 0) + return NULL; + + // Try to find a reference to the parent if none exists + if (!port->vlan.parent && *port->vlan.__parent_name) + port->vlan.parent = nw_daemon_get_port_by_name(port->daemon, port->vlan.__parent_name); + + if (port->vlan.parent) + return nw_port_ref(port->vlan.parent); + + // No port found + return NULL; +} + +int nw_port_set_vlan_parent(nw_port* port, nw_port* parent) { + int r; + + // Check type + r = nw_port_check_type(port, NW_PORT_VLAN); + if (r < 0) + return r; + + // Reset the former parent name + nw_string_empty(port->vlan.__parent_name); + + // Dereference the former parent + if (port->vlan.parent) { + nw_port_unref(port->vlan.parent); + port->vlan.parent = NULL; + } + + // Store the new parent + if (parent) + port->vlan.parent = nw_port_ref(parent); + + DEBUG("Port %s: Set VLAN parent to %s\n", port->name, nw_port_name(port->vlan.parent)); + + return 0; +} diff --git a/src/networkd/port.h b/src/networkd/port.h index 2f4319b8..d89e1e06 100644 --- a/src/networkd/port.h +++ b/src/networkd/port.h @@ -26,8 +26,14 @@ typedef enum nw_port_type { NW_PORT_UNKNOWN = 0, NW_PORT_DUMMY, + NW_PORT_VLAN, } nw_port_type_t; +// VLAN +#define NW_VLAN_ID_INVALID 0 +#define NW_VLAN_ID_MIN 1 +#define NW_VLAN_ID_MAX 4096 + typedef struct nw_port nw_port; #include "address.h" @@ -61,4 +67,11 @@ const struct rtnl_link_stats64* nw_port_get_stats64(nw_port* port); int __nw_port_update_stats(nw_daemon* daemon, nw_port* port, void* data); int nw_port_update_stats(nw_port* port); +// VLAN +int nw_port_get_vlan_id(nw_port* port); +int nw_port_set_vlan_id(nw_port* port, int id); + +nw_port* nw_port_get_vlan_parent(nw_port* port); +int nw_port_set_vlan_parent(nw_port* port, nw_port* parent); + #endif /* NETWORKD_PORT_H */ diff --git a/src/networkd/string.h b/src/networkd/string.h index 6ff44f9e..5bdfc3d2 100644 --- a/src/networkd/string.h +++ b/src/networkd/string.h @@ -120,6 +120,11 @@ static inline int nw_string_strip(char* s) { return 0; } +static inline void nw_string_empty(char* s) { + if (s) + *s = '\0'; +} + /* Paths */