summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-10-02 20:33:10 +0200
committerFelix Fietkau <nbd@openwrt.org>2011-10-02 20:37:21 +0200
commitfd50535d7d4060d3cb80f1c317a087507ecfdf2b (patch)
tree4092597805e6bb0eed7f5d6c16fcbf14561a21e4
parent504b87e64062fc52fdedea4e35bb03467c8bf97f (diff)
manage interfaces via vlist
-rw-r--r--config.c27
-rw-r--r--config.h6
-rw-r--r--interface.c81
-rw-r--r--interface.h11
4 files changed, 60 insertions, 65 deletions
diff --git a/config.c b/config.c
index 8705c16..d332e57 100644
--- 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
diff --git a/config.h b/config.h
index 5623a40..df088ed 100644
--- 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
diff --git a/interface.c b/interface.c
index 60efc7e..576d2a3 100644
--- a/interface.c
+++ b/interface.c
@@ -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);
+}
diff --git a/interface.h b/interface.h
index 9708a5e..1e8ef44 100644
--- a/interface.h
+++ b/interface.h
@@ -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);