]> git.ipfire.org Git - network.git/commitdiff
port: Implement reading/writing VLAN settings
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 15 Apr 2023 11:16:33 +0000 (11:16 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 15 Apr 2023 11:16:33 +0000 (11:16 +0000)
This is just simple test to see where the configuration could be going.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/networkd/port.c
src/networkd/port.h
src/networkd/string.h

index aad62106a60cb7cfc0d4bec79c06e2061ab65d31..a240c6118a6b0af501b23eef7aba7f32c8520b81 100644 (file)
@@ -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;
+}
index 2f4319b843fc641cf2c87a67c9d3da470e242ba4..d89e1e0634a755080adb445e4262ffbb00b033c8 100644 (file)
 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 */
index 6ff44f9ef91f838a81dedbf3de1633e25849e566..5bdfc3d24c4949091236c1b3ec75968b12f66e7e 100644 (file)
@@ -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
 */