manage interfaces via vlist
authorFelix Fietkau <nbd@openwrt.org>
Sun, 2 Oct 2011 18:33:10 +0000 (20:33 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 2 Oct 2011 18:37:21 +0000 (20:37 +0200)
config.c
config.h
interface.c
interface.h

index 8705c16accaa799dcd32e91bc3734838df89e2d5..d332e57a4e4359da1b8310d7208349400a0ecc68 100644 (file)
--- a/config.c
+++ b/config.c
@@ -14,7 +14,6 @@ bool config_init = false;
 static struct uci_context *uci_ctx;
 static struct uci_package *uci_network;
 static struct blob_buf b;
-static unsigned int config_version = 1;
 
 static void uci_attr_to_blob(struct blob_buf *b, const char *str,
                             const char *name, enum blobmsg_type type)
@@ -142,21 +141,12 @@ config_parse_bridge_interface(struct uci_section *s)
        return 0;
 }
 
-void
-config_set_state(struct config_state *state, const struct blob_attr *attr)
-{
-       state->data = malloc(blob_pad_len(attr));
-       if (!state->data)
-               return;
-
-       memcpy(state->data, attr, blob_pad_len(attr));
-}
-
 static void
 config_parse_interface(struct uci_section *s)
 {
        struct interface *iface;
        const char *type;
+       struct blob_attr *config;
 
        DPRINTF("Create interface '%s'\n", s->e.name);
 
@@ -168,16 +158,23 @@ config_parse_interface(struct uci_section *s)
                        return;
 
        uci_to_blob(&b, s, &interface_attr_list);
-       iface = interface_alloc(s->e.name, b.head);
+       iface = calloc(1, sizeof(*iface));
        if (!iface)
                return;
 
-       blob_buf_init(&b, 0);
+       interface_init(iface, s->e.name, b.head);
+
        if (iface->proto_handler && iface->proto_handler->config_params)
                uci_to_blob(&b, s, iface->proto_handler->config_params);
 
-       proto_init_interface(iface, b.head);
-       iface->config.version = config_version;
+       config = malloc(blob_pad_len(b.head));
+       if (!config) {
+               free(iface);
+               return;
+       }
+
+       memcpy(config, b.head, blob_pad_len(b.head));
+       interface_add(iface, config);
 }
 
 static void
index 5623a40fcd0022ec74d2ee2f6e44b845e1291941..df088edda631fe6dd74a4196f897965c8aa8f60e 100644 (file)
--- a/config.h
+++ b/config.h
@@ -25,12 +25,6 @@ struct config_param_list {
        const struct config_param_list *next[];
 };
 
-struct config_state {
-       struct blob_attr *data;
-       unsigned int version;
-};
-
 void config_init_interfaces(const char *name);
-void config_set_state(struct config_state *state, const struct blob_attr *attr);
 
 #endif
index 60efc7e43950fc8f28bc97289cee59ea1a5089ca..576d2a3a42848e7b8b8ca3ef9ddd408131ca489b 100644 (file)
@@ -10,7 +10,7 @@
 #include "ubus.h"
 #include "config.h"
 
-static LIST_HEAD(interfaces);
+struct vlist_tree interfaces;
 
 enum {
        IFACE_ATTR_IFNAME,
@@ -211,30 +211,23 @@ void interface_set_proto_state(struct interface *iface, struct interface_proto_s
        state->iface = iface;
 }
 
-struct interface *
-interface_alloc(const char *name, struct blob_attr *attr)
+void
+interface_init(struct interface *iface, const char *name,
+              struct blob_attr *config)
 {
-       struct interface *iface;
        struct blob_attr *tb[IFACE_ATTR_MAX];
        struct blob_attr *cur;
        struct device *dev;
        const char *proto_name = NULL;
 
-       iface = interface_get(name);
-       if (iface)
-               return iface;
-
-       iface = calloc(1, sizeof(*iface));
-       iface->main_dev.cb = interface_cb;
-       iface->l3_dev = &iface->main_dev;
        strncpy(iface->name, name, sizeof(iface->name) - 1);
-       list_add_tail(&iface->list, &interfaces);
        INIT_LIST_HEAD(&iface->errors);
 
-       interface_ip_init(iface);
+       iface->main_dev.cb = interface_cb;
+       iface->l3_dev = &iface->main_dev;
 
        blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb,
-                     blob_data(attr), blob_len(attr));
+                     blob_data(config), blob_len(config));
 
        if ((cur = tb[IFACE_ATTR_PROTO]))
                proto_name = blobmsg_data(cur);
@@ -253,33 +246,13 @@ interface_alloc(const char *name, struct blob_attr *attr)
                iface->autostart = blobmsg_get_bool(cur);
        else
                iface->autostart = true;
-
-       netifd_ubus_add_interface(iface);
-       config_set_state(&iface->config, attr);
-
-       return iface;
 }
 
 void
-interface_free(struct interface *iface)
+interface_add(struct interface *iface, struct blob_attr *config)
 {
-       netifd_ubus_remove_interface(iface);
-       list_del(&iface->list);
-       if (iface->proto->free)
-               iface->proto->free(iface->proto);
-       free(iface);
-}
-
-struct interface *
-interface_get(const char *name)
-{
-       struct interface *iface;
-
-       list_for_each_entry(iface, &interfaces, list) {
-               if (!strcmp(iface->name, name))
-                       return iface;
-       }
-       return NULL;
+       iface->config = config;
+       vlist_add(&interfaces, &iface->node);
 }
 
 void
@@ -331,7 +304,7 @@ int
 interface_set_down(struct interface *iface)
 {
        if (!iface) {
-               list_for_each_entry(iface, &interfaces, list)
+               vlist_for_each_element(&interfaces, iface, node)
                        __interface_set_down(iface, false);
        } else {
                iface->autostart = false;
@@ -346,8 +319,38 @@ interface_start_pending(void)
 {
        struct interface *iface;
 
-       list_for_each_entry(iface, &interfaces, list) {
+       vlist_for_each_element(&interfaces, iface, node) {
                if (iface->available && iface->autostart)
                        interface_set_up(iface);
        }
 }
+
+static void
+interface_update(struct vlist_tree *tree, struct vlist_node *node_new,
+                struct vlist_node *node_old)
+{
+       struct interface *if_old = container_of(node_old, struct interface, node);
+       struct interface *if_new = container_of(node_new, struct interface, node);
+
+       if (node_old) {
+               free(if_old->config);
+               netifd_ubus_remove_interface(if_old);
+               if (if_old->proto->free)
+                       if_old->proto->free(if_old->proto);
+               free(if_old);
+       }
+
+       if (node_new) {
+               proto_init_interface(if_new, if_new->config);
+               interface_ip_init(if_new);
+               netifd_ubus_add_interface(if_new);
+       }
+}
+
+
+static void __init
+interface_init_list(void)
+{
+       vlist_init(&interfaces, avl_strcmp, interface_update,
+                  struct interface, node, name);
+}
index 9708a5e4113230dba9fe45ade8fa81926fd85e68..1e8ef44bccfd1eb776d68fc473da4cbfd7dc8fa4 100644 (file)
@@ -31,7 +31,7 @@ struct interface_error {
  * interface configuration
  */
 struct interface {
-       struct list_head list;
+       struct vlist_node node;
 
        char name[IFNAMSIZ];
 
@@ -46,7 +46,7 @@ struct interface {
        /* interface that layer 3 communication will go through */
        struct device_user *l3_dev;
 
-       struct config_state config;
+       struct blob_attr *config;
 
        /* primary protocol state */
        const struct proto_handler *proto_handler;
@@ -63,9 +63,10 @@ struct interface {
 
 extern const struct config_param_list interface_attr_list;
 
-struct interface *interface_get(const char *name);
-struct interface *interface_alloc(const char *name, struct blob_attr *attr);
-void interface_free(struct interface *iface);
+void interface_init(struct interface *iface, const char *name,
+                   struct blob_attr *config);
+
+void interface_add(struct interface *iface, struct blob_attr *config);
 
 void interface_set_proto_state(struct interface *iface, struct interface_proto_state *state);