// 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 },
};
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)
// 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:
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) {
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;
+}
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"
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 */