diff options
-rw-r--r-- | openbsc/include/openbsc/gtphub.h | 7 | ||||
-rw-r--r-- | openbsc/src/gprs/gtphub.c | 57 | ||||
-rw-r--r-- | openbsc/tests/gtphub/gtphub_test.c | 27 |
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()); } |