summaryrefslogtreecommitdiff
path: root/btree.c
diff options
context:
space:
mode:
Diffstat (limited to 'btree.c')
-rw-r--r--btree.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/btree.c b/btree.c
new file mode 100644
index 0000000..92912e5
--- /dev/null
+++ b/btree.c
@@ -0,0 +1,174 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <net/if.h>
+
+/* maybe just use
+http://cjson.sourceforge.net/
+or maybe even better:
+https://bitbucket.org/zserge/jsmn/src
+
+for the parsing? *
+
+
+/* parse downstream configuration file
+ format:
+ port;vlan;remote-id;subscriber-id;trusted
+
+ port:
+ interface name
+ vlan:
+ vlanid || 0
+ remote-id:
+ string for REMOTE-ID attribute (requires enterprise number as input option)
+ subscriber-id:
+ string for SUBSCRIBER-ID attribute
+ trusted:
+ boolean 0 || 1 indicating whether we allow RELAY-FORW messages from this port
+
+
+ example:
+ eth2;604;123abc;hansen;0
+
+ output:
+ we combine port+vlan into a 32bit value which is used directly as the INTERFACE-ID key
+
+ a structure is allocated with pointers to the remote-id and
+
+ a rather large structure is allocated for each new port:
+
+
+
+
+*/
+
+/* flags */
+#define SUB_F_TRUSTED 1
+#define SUB_F_ALL SUB_F_TRUSTED
+
+/* suscriber struct */
+struct subscriber {
+ int interfaceid;
+ int flags;
+ char *remoteid;
+ char *subscriberid;
+};
+
+/* bintree structure */
+struct e_btree {
+ struct subscriber data;
+ struct e_btree *l,*r;
+
+};
+
+static struct e_btree *head = NULL;
+
+/* simple recursive bintree insert */
+struct e_btree *binsert(struct e_btree **p, struct subscriber *data)
+{
+ if (!*p) {
+ *p = malloc(sizeof(struct e_btree));
+ if (!*p)
+ return NULL; /* malloc failed? */
+ (*p)->l = NULL;
+ (*p)->r = NULL;
+ memcpy(&(*p)->data, data, sizeof(struct subscriber));
+ return *p;
+ }
+ if (data->interfaceid < (*p)->data.interfaceid) {
+ fprintf(stderr, "%d < %d\n", data->interfaceid, (*p)->data.interfaceid);
+ return binsert(&(*p)->l, data);
+}
+ fprintf(stderr, "%d > %d\n", data->interfaceid, (*p)->data.interfaceid);
+ return binsert(&(*p)->r, data);
+}
+
+/* simple recursive bintree shift() */
+struct subscriber *bshift(struct e_btree **p, struct subscriber *e)
+{
+ static int level = 0;
+
+ if (!*p)
+ return NULL; /* finished */
+
+ /* dump right tree */
+ if ((*p)->r)
+ bshift(&(*p)->r, e);
+
+
+ /* we can now finish this node */
+ fprintf(stderr, "going to return ifid=%d now\n", (*p)->data.interfaceid);
+
+ /* dump left tree */
+ if ((*p)->l)
+ bshift(&(*p)->l, e);
+
+/* memcpy(e, &(*p)->data, sizeof(*e));
+ free(*p);
+ *p = NULL;
+ return e;
+*/
+ return NULL;
+}
+
+/* global array holding all the entries */
+static struct subscriber sentry[];
+static int nsubscribers = 0;
+
+
+/* strategy:
+ dynamically allocate entries as they are parsed and temporarily store them in a bintree
+ allocate an array which is just big enough after parsing
+ store all entries *sorted* in the array
+
+ the reason for not keeping the bintree is that it most likely is very sub-optimal, as the
+ data typically will appear in a semi-sorted order in the configuration file
+
+ use binary search when looking up an entry
+
+ note that lookup is only necessary for down => up packets
+*/
+
+
+int parse_config(char *fname)
+{
+ FILE *f;
+ int n, i = 0;
+ char ifname[IFNAMSIZ];
+ struct subscriber e;
+
+ f = fopen(fname, "r");
+ if (!f) {
+ fprintf(stderr, "%s(): cannot open configuration file \"%s\": %m\n", __FUNCTION__, fname);
+ return -1;
+ }
+ while (n = fscanf(f, " %[^;] ; %u ; %m[^;] ; %m[^;] ; %u ; ", &ifname, &e.interfaceid, &e.remoteid, &e.subscriberid, &e.flags) > 0) {
+ /* FIXME: do cached lookup of ifindex for ifname and add to interfaceid */
+
+ e.interfaceid &= 0xfff; /* VLAN tags are 12bit only */
+ e.flags &= SUB_F_ALL; /* mask out invalid flags */
+ fprintf(stderr, "parsed entry %d (ifname=%s, ifid=%d)\n", i, ifname, e.interfaceid);
+ binsert(&head, &e);
+ i++;
+ }
+ fclose(f);
+}
+
+
+int main(int argc, char *argv[])
+{
+ struct subscriber e;
+
+ if (argc < 2)
+ return -1;
+
+
+ parse_config(argv[1]);
+
+ while (bshift(&head, &e))
+ ;;
+// fprintf(stderr, "ifid=%d, rid=%s, sid=%s, flags=%d\n", e.interfaceid, e.remoteid, e.subscriberid, e.flags);
+
+ return 0;
+}