Sponsored-by: On-Waves ehi
---
 openbsc/include/openbsc/gtphub.h | 42 +++++++++++++++++++++
 openbsc/src/gprs/gtphub.c        | 81 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+)

diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h
index cd4c215..f25c56b 100644
--- a/openbsc/include/openbsc/gtphub.h
+++ b/openbsc/include/openbsc/gtphub.h
@@ -38,6 +38,46 @@ enum gtphub_port_idx {
 extern const char* const gtphub_port_idx_names[GTPH_PORT_N];


+/* Generator for unused TEI IDs. So far this counts upwards from zero, but the
+ * implementation may change in the future. Treat this like an opaque struct. 
*/
+struct tei_pool {
+       uint32_t last_tei;
+};
+
+void tei_pool_init(struct tei_pool *pool);
+
+/* Return the next unused TEI from the tei_pool. */
+uint32_t tei_pool_next(struct tei_pool *pool);
+
+
+struct tei_mapping {
+       struct llist_head entry;
+
+       uint32_t orig;
+       uint32_t repl;
+};
+
+struct tei_map {
+       struct tei_pool *pool;
+       struct llist_head mappings;
+};
+
+/* Initialize an (already allocated) tei_map, and set the map's TEI pool.
+ * Multiple tei_map instances may use the same tei_pool. */
+void tei_map_init(struct tei_map *map, struct tei_pool *pool);
+
+/* Return a replacement TEI for tei_orig. If tei_orig is unknown, create a new
+ * mapping using a so far unused TEI to map tei_orig to. Return 0 on error. */
+uint32_t tei_map_get(struct tei_map *map, uint32_t tei_orig);
+
+/* Return the original TEI for a replacement TEI. If no mapping exists to
+ * tei_repl, return 0. */
+uint32_t tei_map_get_rev(struct tei_map *map, uint32_t tei_repl);
+
+/* Remove the mapping for tei_orig, if it exists. */
+void tei_map_del(struct tei_map *map, uint32_t tei_orig);
+
+
 /* config */

 struct gtphub_cfg_addr {
@@ -68,10 +108,12 @@ struct gtphub_peer {
        struct llist_head entry;

        struct gtphub_addr addr;
+       struct tei_map teim;
 };

 struct gtphub_bind {
        struct osmo_fd ofd;
+       struct tei_pool teip;

        /* list of struct gtphub_peer */
        struct llist_head peers;
diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c
index a8bd276..419b21f 100644
--- a/openbsc/src/gprs/gtphub.c
+++ b/openbsc/src/gprs/gtphub.c
@@ -21,6 +21,7 @@

 #include <string.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <netinet/in.h>

 #include <openbsc/gtphub.h>
@@ -54,6 +55,82 @@ const char* const gtphub_port_idx_names[GTPH_PORT_N] = {
 };


+void tei_pool_init(struct tei_pool *pool)
+{
+       *pool = (struct tei_pool){};
+}
+
+uint32_t tei_pool_next(struct tei_pool *pool)
+{
+       pool->last_tei ++;
+
+       OSMO_ASSERT(pool->last_tei > 0);
+       /* TODO: gracefully handle running out of TEIs. */
+       /* TODO: random TEIs. */
+
+       return pool->last_tei;
+}
+
+void tei_map_init(struct tei_map *map, struct tei_pool *pool)
+{
+       *map = (struct tei_map){};
+       map->pool = pool;
+       INIT_LLIST_HEAD(&map->mappings);
+}
+
+static uint32_t tei_map_new(struct tei_map *map, uint32_t tei_orig)
+{
+       struct tei_mapping *mapping;
+       mapping = talloc_zero(osmo_gtphub_ctx, struct tei_mapping);
+       OSMO_ASSERT(mapping);
+       mapping->orig = tei_orig;
+       mapping->repl = tei_pool_next(map->pool);
+       llist_add(&mapping->entry, &map->mappings);
+       return mapping->repl;
+}
+
+uint32_t tei_map_get(struct tei_map *map, uint32_t tei_orig)
+{
+       OSMO_ASSERT(tei_orig != 0);
+
+       struct tei_mapping *mapping;
+       llist_for_each_entry(mapping, &map->mappings, entry) {
+               if (mapping->orig == tei_orig)
+                       return mapping->repl;
+       }
+       /* Not found. */
+
+       return tei_map_new(map, tei_orig);
+}
+
+uint32_t tei_map_get_rev(struct tei_map *map, uint32_t tei_repl)
+{
+       OSMO_ASSERT(tei_repl != 0);
+
+       struct tei_mapping *pos;
+       llist_for_each_entry(pos, &map->mappings, entry) {
+               if (pos->repl == tei_repl) {
+                       OSMO_ASSERT(pos->orig);
+                       return pos->orig;
+               }
+       }
+       return 0;
+}
+
+void tei_map_del(struct tei_map *map, uint32_t tei_orig)
+{
+       struct tei_mapping *mapping;
+       llist_for_each_entry(mapping, &map->mappings, entry) {
+               if (mapping->orig == tei_orig) {
+                       llist_del(&mapping->entry);
+                       talloc_free(mapping);
+                       return;
+               }
+       }
+       LOGERR("No mapping exists for TEI %" PRIu32 ".\n", tei_orig);
+}
+
+
 /* gtphub */

 void gtphub_zero(struct gtphub *hub)
@@ -93,6 +170,7 @@ static int gtphub_gtp_bind_init(struct gtphub_bind *b,
 {
        memset(b, '\0', sizeof(*b));

+       tei_pool_init(&b->teip);
        INIT_LLIST_HEAD(&b->peers);

        if (gtphub_sock_init(&b->ofd, &cfg->bind, cb, cb_data, ofd_id) != 0)
@@ -238,6 +316,9 @@ int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg)
 struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind)
 {
        struct gtphub_peer *n = talloc_zero(osmo_gtphub_ctx, struct 
gtphub_peer);
+
+       tei_map_init(&n->teim, &bind->teip);
+
        llist_add(&n->entry, &bind->peers);
        return n;
 }
-- 
2.1.4

Reply via email to