]> git.ipfire.org Git - people/ms/network.git/blobdiff - src/networkd/port-vlan.c
string: Define an own type for string tables
[people/ms/network.git] / src / networkd / port-vlan.c
index c9581f68d3a8171e8fd35c68f8314431ccfbcebb..792fd28e26c8af95cc95e532fa8c72714626cd7a 100644 (file)
 #                                                                             #
 #############################################################################*/
 
+#include <linux/if_link.h>
+
+#include <systemd/sd-netlink.h>
+
 #include "config.h"
 #include "daemon.h"
+#include "json.h"
 #include "logging.h"
 #include "port.h"
 #include "port-vlan.h"
 #include "string.h"
 
-static int nw_port_vlan_config_read(nw_port* port) {
-       int r;
+const nw_string_table_t nw_port_vlan_proto[] = {
+       { NW_VLAN_PROTO_8021Q,  "802.1Q" },
+       { NW_VLAN_PROTO_8021ad, "802.1ad" },
+       { -1, NULL },
+};
 
-       // 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;
-       }
+NW_STRING_TABLE_LOOKUP(nw_port_vlan_proto_t, nw_port_vlan_proto)
 
-       // 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;
+static int nw_port_vlan_read_proto(nw_config* config,
+               const char* key, void* value, void* data) {
+       nw_port_vlan_proto_t* proto = (nw_port_vlan_proto_t*)value;
+
+       const char* p = nw_config_get(config, key);
+       if (p) {
+               *proto = nw_port_vlan_proto_from_string(p);
+               if (!*proto)
+                       return -errno;
        }
 
        return 0;
 }
 
-static int nw_port_vlan_config_write(nw_port* port) {
+static int nw_port_vlan_write_proto(nw_config* config,
+               const char* key, const void* value, void* data) {
+       const nw_port_vlan_proto_t* proto = (nw_port_vlan_proto_t*)value;
+
+       return nw_config_set(config, key, nw_port_vlan_proto_to_string(*proto));
+}
+
+static int nw_port_vlan_setup(nw_port* port) {
        int r;
 
        // VLAN ID
-       r = nw_config_set_int(port->config, "VLAN_ID", port->vlan.id);
-       if (r)
+       r = NW_CONFIG_OPTION_INT(port->config, "VLAN_ID", &port->vlan.id);
+       if (r < 0)
+               return r;
+
+       // VLAN Protocol
+       r = NW_CONFIG_OPTION(port->config, "VLAN_PROTO", &port->vlan.proto,
+                       nw_port_vlan_read_proto, nw_port_vlan_write_proto, NULL);
+       if (r < 0)
                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)
+       r = NW_CONFIG_OPTION_STRING(port->config, "VLAN_PARENT", &port->vlan.__parent_name);
+       if (r < 0)
                return r;
 
        return 0;
 }
 
-nw_port_ops_t nw_port_ops_vlan = {
-       // Configuration
-       .config_read = nw_port_vlan_config_read,
-       .config_write = nw_port_vlan_config_write,
+static int nw_port_vlan_create_link(nw_port* port, sd_netlink_message* m) {
+       int r;
+
+       // Set VLAN ID
+       r = sd_netlink_message_append_u16(m, IFLA_VLAN_ID, port->vlan.id);
+       if (r < 0)
+               return r;
+
+       // Set VLAN protocol
+       r = sd_netlink_message_append_u16(m, IFLA_VLAN_PROTOCOL, htobe16(port->vlan.proto));
+       if (r < 0)
+               return r;
+
+       return 0;
+}
+
+static int nw_port_vlan_to_json(nw_port* port, struct json_object* o) {
+       nw_port* parent = NULL;
+       int r;
+
+       // Add the VLAN ID
+       r = json_object_add_int64(o, "VLANId", port->vlan.id);
+       if (r < 0)
+               goto ERROR;
+
+       // Add the VLAN Protocol
+       r = json_object_add_string(o, "VLANProtocol",
+                       nw_port_vlan_proto_to_string(port->vlan.proto));
+       if (r < 0)
+               goto ERROR;
+
+       // Fetch the parent
+       parent = nw_port_get_parent_port(port);
+       if (parent) {
+               r = json_object_add_string(o, "VLANParentPort", nw_port_name(parent));
+               if (r < 0)
+                       goto ERROR;
+       }
+
+ERROR:
+       if (parent)
+               nw_port_unref(parent);
+
+       return r;
+}
+
+const nw_port_info_t nw_port_info_vlan = {
+       .kind = "vlan",
+
+       // Operations
+       .ops = {
+               // Configuration
+               .setup = nw_port_vlan_setup,
+
+               .get_parent_port = nw_port_get_vlan_parent,
+
+               // Link
+               .create_link = nw_port_vlan_create_link,
+
+               // JSON
+               .to_json = nw_port_vlan_to_json,
+       },
 };
 
 /*
@@ -104,6 +179,20 @@ int nw_port_set_vlan_id(nw_port* port, int id) {
        return 0;
 }
 
+int nw_port_set_vlan_proto(nw_port* port, const nw_port_vlan_proto_t proto) {
+       switch (proto) {
+               case NW_VLAN_PROTO_8021Q:
+               case NW_VLAN_PROTO_8021ad:
+                       port->vlan.proto = proto;
+                       break;
+
+               default:
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 nw_port* nw_port_get_vlan_parent(nw_port* port) {
        int r;