aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gtphub.h7
-rw-r--r--openbsc/src/gprs/gtphub.c57
-rw-r--r--openbsc/tests/gtphub/gtphub_test.c27
3 files changed, 85 insertions, 6 deletions
diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h
index fa63a20cb..b375391dd 100644
--- a/openbsc/include/openbsc/gtphub.h
+++ b/openbsc/include/openbsc/gtphub.h
@@ -200,6 +200,9 @@ void expiring_item_del(struct expiring_item *item);
* count passed to nr_map_add(). A monotonous clock counter should be used. */
int expiry_tick(struct expiry *exq, time_t now);
+/* Expire all items. */
+void expiry_clear(struct expiry *exq);
+
/* number map */
@@ -429,6 +432,10 @@ int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file);
/* Initialize and start gtphub: bind to ports, run expiry timers. */
int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg);
+/* Close all sockets, expire all maps and peers and free all allocations. The
+ * struct is then unusable, unless gtphub_start() is run on it again. */
+void gtphub_stop(struct gtphub *hub);
+
time_t gtphub_now(void);
/* Remove expired items, empty peers, ... */
diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c
index 4507e6a14..53152493f 100644
--- a/openbsc/src/gprs/gtphub.c
+++ b/openbsc/src/gprs/gtphub.c
@@ -24,6 +24,7 @@
#include <inttypes.h>
#include <time.h>
#include <limits.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -555,6 +556,14 @@ int expiry_tick(struct expiry *exq, time_t now)
return expired;
}
+void expiry_clear(struct expiry *exq)
+{
+ struct expiring_item *m, *n;
+ llist_for_each_entry_safe(m, n, &exq->items, entry) {
+ expiring_item_del(m);
+ }
+}
+
void expiring_item_init(struct expiring_item *item)
{
ZERO_STRUCT(item);
@@ -769,6 +778,13 @@ static int gtphub_sock_init(struct osmo_fd *ofd,
return 0;
}
+static void gtphub_sock_close(struct osmo_fd *ofd)
+{
+ close(ofd->fd);
+ osmo_fd_unregister(ofd);
+ ofd->cb = NULL;
+}
+
static void gtphub_bind_init(struct gtphub_bind *b)
{
ZERO_STRUCT(b);
@@ -788,6 +804,16 @@ static int gtphub_bind_start(struct gtphub_bind *b,
return 0;
}
+static void gtphub_bind_free(struct gtphub_bind *b)
+{
+ OSMO_ASSERT(llist_empty(&b->peers));
+}
+
+static void gtphub_bind_stop(struct gtphub_bind *b) {
+ gtphub_sock_close(&b->ofd);
+ gtphub_bind_free(b);
+}
+
/* Recv datagram from from->fd, write sender's address to *from_addr.
* Return the number of bytes read, zero on error. */
static int gtphub_read(const struct osmo_fd *from,
@@ -1758,6 +1784,37 @@ void gtphub_init(struct gtphub *hub)
hub->to_ggsns[GTPH_PLANE_USER].label = "GGSN User";
}
+/* For the test suite, this is kept separate from gtphub_stop(), which also
+ * closes sockets. The test suite avoids using sockets and would cause
+ * segfaults when trying to close uninitialized ofds. */
+void gtphub_free(struct gtphub *hub)
+{
+ /* By expiring all mappings, a garbage collection should free
+ * everything else. A gtphub_bind_free() will assert that everything is
+ * indeed empty. */
+ expiry_clear(&hub->expire_seq_maps);
+ expiry_clear(&hub->expire_tei_maps);
+
+ int plane_idx;
+ for (plane_idx = 0; plane_idx < GTPH_PLANE_N; plane_idx++) {
+ gtphub_gc_bind(&hub->to_ggsns[plane_idx]);
+ gtphub_bind_free(&hub->to_ggsns[plane_idx]);
+
+ gtphub_gc_bind(&hub->to_sgsns[plane_idx]);
+ gtphub_bind_free(&hub->to_sgsns[plane_idx]);
+ }
+}
+
+void gtphub_stop(struct gtphub *hub)
+{
+ int plane_idx;
+ for (plane_idx = 0; plane_idx < GTPH_PLANE_N; plane_idx++) {
+ gtphub_bind_stop(&hub->to_ggsns[plane_idx]);
+ gtphub_bind_stop(&hub->to_sgsns[plane_idx]);
+ }
+ gtphub_free(hub);
+}
+
static int gtphub_make_proxy(struct gtphub *hub,
struct gtphub_peer_port **pp,
struct gtphub_bind *bind,
diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c
index f983f0615..2dc61eb8e 100644
--- a/openbsc/tests/gtphub/gtphub_test.c
+++ b/openbsc/tests/gtphub/gtphub_test.c
@@ -35,8 +35,6 @@
#include <gtp.h>
#include <gtpie.h>
-#define EXPIRE_ALL ((60 * GTPH_TEI_MAPPING_EXPIRY_MINUTES) + 1)
-
#define ZERO_STRUCT(struct_pointer) memset(struct_pointer, '\0', \
sizeof(*(struct_pointer)))
@@ -55,6 +53,7 @@
printf(label "\n"); }
void gtphub_init(struct gtphub *hub);
+void gtphub_free(struct gtphub *hub);
void *osmo_gtphub_ctx;
@@ -613,6 +612,23 @@ static int setup_test_hub()
return 1;
}
+static int clear_test_hub()
+{
+ /* expire all */
+ gtphub_gc(hub, now + (60 * GTPH_TEI_MAPPING_EXPIRY_MINUTES) + 1);
+
+ int plane_idx;
+ plane_idx = GTPH_PLANE_CTRL;
+ LVL2_ASSERT(llist_empty(&hub->to_ggsns[plane_idx].peers));
+ LVL2_ASSERT(llist_empty(&hub->to_sgsns[plane_idx].peers));
+ plane_idx = GTPH_PLANE_USER;
+ LVL2_ASSERT(llist_empty(&hub->to_ggsns[plane_idx].peers));
+ LVL2_ASSERT(llist_empty(&hub->to_sgsns[plane_idx].peers));
+
+ gtphub_free(hub);
+ return 1;
+}
+
static void test_echo(void)
{
@@ -727,8 +743,7 @@ static void test_echo(void)
OSMO_ASSERT(!pp);
- now += EXPIRE_ALL;
- gtphub_gc(hub, now);
+ OSMO_ASSERT(clear_test_hub());
}
@@ -937,7 +952,7 @@ static void test_create_pdp_ctx(void)
OSMO_ASSERT(nr_map_is(&hub->tei_map[GTPH_PLANE_USER],
"(291->1@21945), (1383->2@21945), "));
- gtphub_gc(hub, now + EXPIRE_ALL);
+ OSMO_ASSERT(clear_test_hub());
}
static void test_user_data(void)
@@ -1013,7 +1028,7 @@ static void test_user_data(void)
u_from_sgsn,
u_to_ggsn));
- gtphub_gc(hub, now + EXPIRE_ALL);
+ OSMO_ASSERT(clear_test_hub());
}