Patchwork [2/6] vlan: transform untagged/tagged vlan description into vlan_id

login
register
mail settings
Submitter michael-dev@fami-braun.de
Date April 8, 2013, 4:18 p.m.
Message ID <1365437921-11715-3-git-send-email-michael-dev@fami-braun.de>
Download mbox | patch
Permalink /patch/234831/
State Superseded
Headers show

Comments

michael-dev@fami-braun.de - April 8, 2013, 4:18 p.m.
From: Michael Braun <michael-dev@fami-braun.de>

Signed-hostap: Michael Braun <michael-dev@fami-braun.de>
---
 src/ap/vlan_init.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ap/vlan_init.h | 16 ++++++++++
 2 files changed, 107 insertions(+)

Patch

diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index c25381d..27afbc8 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -35,6 +35,18 @@ 
 #include "drivers/priv_netlink.h"
 #include "utils/eloop.h"
 
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+#ifdef CONFIG_VLAN_TAGGED
+struct vlan_info_list {
+       unsigned int counter;
+       unsigned int size;
+       struct vlan_info *vlan;
+};
+static struct vlan_info_list vlan_mapping;
+#endif /* CONFIG_VLAN_TAGGED */
+
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
 
 struct full_dynamic_vlan {
 	int s; /* socket on which to listen for new/removed interfaces. */
@@ -952,3 +964,82 @@  int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
 
 	return 0;
 }
+
+#ifdef CONFIG_VLAN_TAGGED
+static int cmp_vlan(const void *a, const void *b)
+{
+	const int *ia = (const int *) a;
+	const int *ib = (const int *) b;
+	return (*ia > *ib) - (*ia < *ib);
+}
+
+/* make tagged vlans unique and sorted */
+void vlan_cleanup(struct vlan_info *a) {
+	int i, offset=0;
+	qsort(a->tagged, a->num_tagged, sizeof(int), cmp_vlan);
+	for (i=1; i < a->num_tagged; i++) {
+		if (a->tagged[i-1-offset] == a->tagged[i])
+			offset++;
+		else if (offset > 0)
+			a->tagged[i-offset] = a->tagged[i];
+	}
+	a->num_tagged -= offset;
+}
+
+int vlan_equals(struct vlan_info *a, struct vlan_info *b) {
+	int i;
+	if (!a && !b) return 1;
+	if (!a || !b) return 0;
+	if (a->untagged != b->untagged) return 0;
+	if (a->num_tagged != b->num_tagged) return 0;
+	for (i=0; i < a->num_tagged; i++)
+		if (a->tagged[i] != b->tagged[i]) return 0;
+	return 1;
+}
+
+int vlan_get_id(struct vlan_info* a) {
+	int i;
+
+	/* no tagged/untagged vlan => vlan_id = 0 */
+	if (!a) return 0;
+	if (!a->untagged && !a->num_tagged) return 0;
+
+	/* all other untagged/tagged configurations get vlan_id > 0 */
+	if(vlan_mapping.counter > vlan_mapping.size) {
+		wpa_printf(MSG_ERROR, "VLAN: internal mapping data structure is corrupt.");
+		return -1;
+	}
+	for (i=0; i < vlan_mapping.counter; i++)
+		if (vlan_equals(a, &vlan_mapping.vlan[i]))
+			return i + 1;
+	/* resize cache, amortized O(1) */
+	if (vlan_mapping.size == vlan_mapping.counter) {
+		unsigned int newsize = 2 * vlan_mapping.size;
+		if (newsize == 0)
+			newsize = 1;
+		if (newsize < vlan_mapping.size) /* overflow */
+			return -1;
+		struct vlan_info *new_vlan = os_malloc(sizeof(struct vlan_info) * newsize);
+		if (!new_vlan)
+			return -1;
+		if (vlan_mapping.size > 0)
+			os_memcpy(new_vlan, vlan_mapping.vlan, sizeof(struct vlan_info) * vlan_mapping.size);
+		os_free(vlan_mapping.vlan);
+		vlan_mapping.vlan = new_vlan; new_vlan = NULL;
+		vlan_mapping.size = newsize;
+	}
+	/* add new entry */
+	vlan_mapping.vlan[vlan_mapping.counter] = *a;
+	vlan_mapping.counter++;
+
+	char buf[IFNAMSIZ], *pos;
+	pos = buf;
+	pos += os_snprintf(pos, sizeof(buf) + buf - pos, "%d", a->untagged);
+	for (i=0; i < a->num_tagged; i++) {
+		pos += os_snprintf(pos, sizeof(buf) + buf - pos, "t%d", a->tagged[i]);
+	}
+
+	wpa_printf(MSG_DEBUG, "VLAN: assign %s to %d", buf, vlan_mapping.counter);
+	return vlan_mapping.counter;
+}
+#endif
diff --git a/src/ap/vlan_init.h b/src/ap/vlan_init.h
index 382d5de..75fda69 100644
--- a/src/ap/vlan_init.h
+++ b/src/ap/vlan_init.h
@@ -17,6 +17,12 @@ 
 #define VLAN_INIT_H
 
 #ifndef CONFIG_NO_VLAN
+struct vlan_info {
+	int untagged;
+	unsigned int num_tagged;
+	int* tagged;
+};
+
 int vlan_init(struct hostapd_data *hapd);
 void vlan_deinit(struct hostapd_data *hapd);
 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
@@ -26,6 +32,16 @@  int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id);
 int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
 			      struct hostapd_ssid *mssid,
 			      const char *dyn_vlan);
+#ifdef CONFIG_VLAN_TAGGED
+int vlan_get_id(struct vlan_info *a);
+void vlan_cleanup(struct vlan_info *a);
+#else
+static inline int vlan_get_id(struct vlan_info *a) {
+	if (!a) return 0;
+	return a->untagged;
+}
+#endif /* VLAN_CONFIG_TAGGED */
+
 #else /* CONFIG_NO_VLAN */
 static inline int vlan_init(struct hostapd_data *hapd)
 {