add netdev ifindex support
authorFelix Fietkau <nbd@openwrt.org>
Sun, 24 Jun 2012 22:55:17 +0000 (00:55 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 24 Jun 2012 22:55:17 +0000 (00:55 +0200)
instance.c
instance.h
utils.c
utils.h

index c70fff63a04ccb261a197ff524769397b486c4a8..19454c7e21294ecbdd596e3c6c6a64860fe99118 100644 (file)
@@ -1,3 +1,6 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
 #include <unistd.h>
 
 #include "procd.h"
@@ -8,6 +11,7 @@ enum {
        INSTANCE_ATTR_COMMAND,
        INSTANCE_ATTR_ENV,
        INSTANCE_ATTR_DATA,
+       INSTANCE_ATTR_NETDEV,
        __INSTANCE_ATTR_MAX
 };
 
@@ -15,6 +19,12 @@ static const struct blobmsg_policy instance_attr[__INSTANCE_ATTR_MAX] = {
        [INSTANCE_ATTR_COMMAND] = { "command", BLOBMSG_TYPE_ARRAY },
        [INSTANCE_ATTR_ENV] = { "env", BLOBMSG_TYPE_TABLE },
        [INSTANCE_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
+       [INSTANCE_ATTR_NETDEV] = { "netdev", BLOBMSG_TYPE_ARRAY },
+};
+
+struct instance_netdev {
+       struct blobmsg_list_node node;
+       int ifindex;
 };
 
 static void
@@ -116,9 +126,29 @@ instance_config_changed(struct service_instance *in, struct service_instance *in
        if (!blobmsg_list_equal(&in->data, &in_new->data))
                return true;
 
+       if (!blobmsg_list_equal(&in->netdev, &in_new->netdev))
+               return true;
+
        return false;
 }
 
+static bool
+instance_netdev_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
+{
+       struct instance_netdev *n1 = container_of(l1, struct instance_netdev, node);
+       struct instance_netdev *n2 = container_of(l2, struct instance_netdev, node);
+
+       return n1->ifindex == n2->ifindex;
+}
+
+static void
+instance_netdev_update(struct blobmsg_list_node *l)
+{
+       struct instance_netdev *n = container_of(l, struct instance_netdev, node);
+
+       n->ifindex = if_nametoindex(n->node.avl.key);
+}
+
 static bool
 instance_config_parse(struct service_instance *in)
 {
@@ -149,15 +179,28 @@ instance_config_parse(struct service_instance *in)
        if ((cur = tb[INSTANCE_ATTR_ENV])) {
                if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
                        return false;
+
                blobmsg_list_fill(&in->env, blobmsg_data(cur), blobmsg_data_len(cur), false);
        }
 
        if ((cur = tb[INSTANCE_ATTR_DATA])) {
                if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
                        return false;
+
                blobmsg_list_fill(&in->data, blobmsg_data(cur), blobmsg_data_len(cur), false);
        }
 
+       if ((cur = tb[INSTANCE_ATTR_NETDEV])) {
+               struct blobmsg_list_node *ndev;
+
+               if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
+                       return false;
+
+               blobmsg_list_fill(&in->netdev, blobmsg_data(cur), blobmsg_data_len(cur), true);
+               blobmsg_list_for_each(&in->netdev, ndev)
+                       instance_netdev_update(ndev);
+       }
+
        return true;
 }
 
@@ -166,6 +209,7 @@ instance_config_cleanup(struct service_instance *in)
 {
        blobmsg_list_free(&in->env);
        blobmsg_list_free(&in->data);
+       blobmsg_list_free(&in->netdev);
 }
 
 static void
@@ -174,8 +218,12 @@ instance_config_move(struct service_instance *in, struct service_instance *in_sr
        instance_config_cleanup(in);
        blobmsg_list_move(&in->env, &in_src->env);
        blobmsg_list_move(&in->data, &in_src->data);
+       blobmsg_list_move(&in->netdev, &in_src->netdev);
        in->command = in_src->command;
        in->name = in_src->name;
+       in->node.avl.key = in_src->node.avl.key;
+       in->config = in_src->config;
+       in_src->config = NULL;
 }
 
 bool
@@ -183,7 +231,6 @@ instance_update(struct service_instance *in, struct service_instance *in_new)
 {
        bool changed = instance_config_changed(in, in_new);
 
-       in->config = in_new->config;
        if (!changed)
                return false;
 
@@ -211,6 +258,7 @@ instance_init(struct service_instance *in, struct service *s, struct blob_attr *
        in->timeout.cb = instance_timeout;
        in->proc.cb = instance_exit;
 
+       blobmsg_list_init(&in->netdev, struct instance_netdev, node, instance_netdev_cmp);
        blobmsg_list_simple_init(&in->env);
        blobmsg_list_simple_init(&in->data);
        in->valid = instance_config_parse(in);
index 011cd9cdfdfdb127a98edb9de70e1a34e99fecfa..59e887c0ef850e163b0fbe8dba39198d141718a1 100644 (file)
@@ -19,6 +19,7 @@ struct service_instance {
        struct blob_attr *command;
        struct blobmsg_list env;
        struct blobmsg_list data;
+       struct blobmsg_list netdev;
 };
 
 void instance_start(struct service_instance *in);
diff --git a/utils.c b/utils.c
index 0f9ce745a9689b217cae75126e0ccbb4c5616834..628136f6c9862892aa3b085b869250f3af6525a5 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -3,11 +3,12 @@
 #include "utils.h"
 
 void
-__blobmsg_list_init(struct blobmsg_list *list, int offset, int len)
+__blobmsg_list_init(struct blobmsg_list *list, int offset, int len, blobmsg_list_cmp cmp)
 {
        avl_init(&list->avl, avl_strcmp, false, NULL);
        list->node_offset = offset;
        list->node_len = len;
+       list->cmp = cmp;
 }
 
 int
@@ -21,7 +22,7 @@ blobmsg_list_fill(struct blobmsg_list *list, void *data, int len, bool array)
        int rem = len;
 
        __blob_for_each_attr(cur, data, rem) {
-               if (!blobmsg_check_attr(cur, true))
+               if (!blobmsg_check_attr(cur, !array))
                        continue;
 
                ptr = calloc(1, list->node_len);
@@ -52,7 +53,7 @@ blobmsg_list_move(struct blobmsg_list *list, struct blobmsg_list *src)
        void *ptr;
 
        avl_remove_all_elements(&src->avl, node, avl, tmp) {
-               if (!avl_insert(&list->avl, &node->avl)) {
+               if (avl_insert(&list->avl, &node->avl)) {
                        ptr = ((char *) node - list->node_offset);
                        free(ptr);
                }
@@ -93,6 +94,9 @@ blobmsg_list_equal(struct blobmsg_list *l1, struct blobmsg_list *l2)
                if (memcmp(n1->data, n2->data, len) != 0)
                        return false;
 
+               if (l1->cmp && !l1->cmp(n1, n2))
+                       return false;
+
                if (!count)
                        break;
 
diff --git a/utils.h b/utils.h
index e20169a5cefc328b8c037a0510b07a6acb900f18..360f9f1a8378d1b17ea6d03584ef4e64a09bbf3a 100644 (file)
--- a/utils.h
+++ b/utils.h
@@ -5,27 +5,31 @@
 #include <libubox/blob.h>
 #include <libubox/blobmsg.h>
 
+struct blobmsg_list_node {
+       struct avl_node avl;
+       struct blob_attr *data;
+};
+
+typedef bool (*blobmsg_list_cmp)(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2);
+
 struct blobmsg_list {
        struct avl_tree avl;
        int node_offset;
        int node_len;
-};
 
-struct blobmsg_list_node {
-       struct avl_node avl;
-       struct blob_attr *data;
+       blobmsg_list_cmp cmp;
 };
 
 #define blobmsg_list_simple_init(list) \
-       __blobmsg_list_init(list, 0, sizeof(struct blobmsg_list_node))
+       __blobmsg_list_init(list, 0, sizeof(struct blobmsg_list_node), NULL)
 
-#define blobmsg_list_init(list, type, field) \
-       __blobmsg_list_init(list, offsetof(type, field), sizeof(type))
+#define blobmsg_list_init(list, type, field, cmp) \
+       __blobmsg_list_init(list, offsetof(type, field), sizeof(type), cmp)
 
 #define blobmsg_list_for_each(list, element) \
        avl_for_each_element(&(list)->avl, element, avl)
 
-void __blobmsg_list_init(struct blobmsg_list *list, int offset, int len);
+void __blobmsg_list_init(struct blobmsg_list *list, int offset, int len, blobmsg_list_cmp cmp);
 int blobmsg_list_fill(struct blobmsg_list *list, void *data, int len, bool array);
 void blobmsg_list_free(struct blobmsg_list *list);
 bool blobmsg_list_equal(struct blobmsg_list *l1, struct blobmsg_list *l2);