/* TCAP parsing tests */ #include #include #include #include #include #include #include #include #include #include #include "ss7_asp.h" #include "ss7_as.h" #include "tcap_transaction_tracking.h" typedef void (*tcap_trxn_track_test_func_t)(void); tcap_trxn_track_test_func_t tcap_trxn_track_tests[]; static struct osmo_sccp_addr gvlr = { .presence = OSMO_SCCP_ADDR_T_GT | OSMO_SCCP_ADDR_T_SSN, .ri = OSMO_SCCP_RI_GT, .gt = { .gti = OSMO_SCCP_GTI_TT_NPL_ENC_NAI, .tt = 0, .npi = OSMO_SCCP_NPI_E164_ISDN, .nai = OSMO_SCCP_NAI_INTL, .digits = "919969679389", }, .ssn = OSMO_SCCP_SSN_VLR, }; static struct osmo_sccp_addr ghlr = { .presence = OSMO_SCCP_ADDR_T_GT | OSMO_SCCP_ADDR_T_SSN, .ri = OSMO_SCCP_RI_GT, .gt = { .gti = OSMO_SCCP_GTI_TT_NPL_ENC_NAI, .tt = 0, .npi = OSMO_SCCP_NPI_E164_ISDN, .nai = OSMO_SCCP_NAI_INTL, .digits = "919911111111", }, .ssn = OSMO_SCCP_SSN_VLR, }; static void init_as(struct osmo_ss7_as *as) { as->cfg.loadshare.tcap.enabled = true; as->cfg.loadshare.tcap.timeout_s = 10; hash_init(as->tcap.tid_ranges); hash_init(as->tcap.trxn_track_own); hash_init(as->tcap.trxn_track_peer); } static void init_asp(struct osmo_ss7_asp *asp) { asp->tcap.enabled = true; } static size_t count_unique_hash_entries(struct osmo_ss7_as *as) { size_t counter = 0; struct tcap_trxn_track_entry *entry; struct hlist_node *tmp; int i; /* count entries with only own_tid and own_tid && peer_tid */ hash_for_each_safe(as->tcap.trxn_track_own, i, tmp, entry, own_tid.list) { counter++; } /* only count those who doesn't have a valid own tid */ hash_for_each_safe(as->tcap.trxn_track_peer, i, tmp, entry, peer_tid.list) { if (!entry->own_tid.tid_valid) counter++; } return counter; } void tcap_trxn_track_test_create_find_free(void) { void *ctx = talloc_new(NULL); struct osmo_ss7_as *as = talloc_zero(ctx, struct osmo_ss7_as); init_as(as); struct osmo_ss7_asp *asp = talloc_zero(ctx, struct osmo_ss7_asp); init_asp(asp); size_t before_test = talloc_total_size(ctx), after_test; uint32_t hlr_tid = 23; uint32_t vlr_tid = 42; struct tcap_trxn_track_entry *entry1, *entry2, *entry3, *search; printf("Create/Find/Free test\n"); /* create an entry */ entry1 = tcap_trxn_track_create_entry(as, asp, &ghlr, NULL, &gvlr, &vlr_tid); OSMO_ASSERT(entry1); /* should find it regardless of the missing own tid in the entry */ search = tcap_trxn_track_find_entry(as, &ghlr, &hlr_tid, &gvlr, &vlr_tid); OSMO_ASSERT(search == entry1); /* should not find it (entry still without own tid) */ search = tcap_trxn_track_find_entry(as, &ghlr, &hlr_tid, &gvlr, NULL); OSMO_ASSERT(!search); search = tcap_trxn_track_find_entry(as, &ghlr, NULL, &gvlr, &vlr_tid); OSMO_ASSERT(search == entry1); tcap_trxn_track_free_entry(search); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_own)); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_peer)); /* create an entries */ entry1 = tcap_trxn_track_create_entry(as, asp, &ghlr, &hlr_tid, &gvlr, NULL); OSMO_ASSERT(entry1); hlr_tid = 24; entry2 = tcap_trxn_track_create_entry(as, asp, &ghlr, &hlr_tid, &gvlr, NULL); OSMO_ASSERT(entry2); hlr_tid = 25; entry3 = tcap_trxn_track_create_entry(as, asp, &ghlr, &hlr_tid, &gvlr, NULL); OSMO_ASSERT(entry3); search = tcap_trxn_track_find_entry(as, &ghlr, &hlr_tid, &gvlr, NULL); OSMO_ASSERT(search == entry3); tcap_trxn_track_free_asp_entries(as, asp); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_own)); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_peer)); after_test = talloc_total_size(ctx); fprintf(stderr, "Consuming %lu bytes after test. Failing if not %lu.\n", after_test, before_test); OSMO_ASSERT(after_test == before_test); talloc_free(ctx); } void tcap_trxn_track_test_transaction(void) { void *ctx = talloc_new(NULL); struct osmo_ss7_as *as = talloc_zero(ctx, struct osmo_ss7_as); init_as(as); struct osmo_ss7_asp *asp = talloc_zero(ctx, struct osmo_ss7_asp); init_asp(asp); size_t before_test = talloc_total_size(ctx), after_test; uint32_t hlr_tid = 23; uint32_t vlr_tid = 42; struct tcap_trxn_track_entry *entry; struct osmo_ss7_asp *search_asp; printf("Full transaction test\n"); /* create an entry (VLR -> HLR (TCAP Begin otid 23) */ entry = tcap_trxn_track_begin(as, asp, &ghlr, NULL, &gvlr, &vlr_tid); OSMO_ASSERT(entry); OSMO_ASSERT(count_unique_hash_entries(as) == 1); /* should find it regardless of the missing own tid and update the missing tid */ search_asp = tcap_trxn_track_continue(as, &ghlr, &hlr_tid, &gvlr, &vlr_tid); OSMO_ASSERT(search_asp == asp); OSMO_ASSERT(count_unique_hash_entries(as) == 1); /* update entry by use tcap_trxn_track_connection_get() */ search_asp = tcap_trxn_track_continue(as, &ghlr, &hlr_tid, &gvlr, NULL); OSMO_ASSERT(search_asp == asp); search_asp = tcap_trxn_track_end(as, &gvlr, NULL, &gvlr, &vlr_tid); OSMO_ASSERT(search_asp); OSMO_ASSERT(search_asp == asp); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_own)); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_peer)); after_test = talloc_total_size(ctx); fprintf(stderr, "Consuming %lu bytes after test. Failing if not %lu.\n", after_test, before_test); OSMO_ASSERT(after_test == before_test); talloc_free(ctx); } static void tcap_trxn_track_test_gc(void) { void *ctx = talloc_new(NULL); struct osmo_ss7_as *as = talloc_zero(ctx, struct osmo_ss7_as); init_as(as); struct osmo_ss7_asp *asp = talloc_zero(ctx, struct osmo_ss7_asp); init_asp(asp); size_t before_test = talloc_total_size(ctx), after_test; uint32_t hlr_tids[] = { 24, 25, 26}; uint32_t vlr_tids[] = { 44, 45, 46}; struct tcap_trxn_track_entry *entry; printf("GC test\n"); /* create 3 entries */ for (int i = 0; i < ARRAY_SIZE(hlr_tids); i++) { entry = tcap_trxn_track_create_entry(as, asp, &ghlr, &hlr_tids[i], &gvlr, &vlr_tids[i]); OSMO_ASSERT(entry); } OSMO_ASSERT(count_unique_hash_entries(as) == 3); /* No entries should be GC'ed, because all entries should be within 10 secs */ OSMO_ASSERT(tcap_trxn_track_garbage_collect(as) == 0); OSMO_ASSERT(count_unique_hash_entries(as) == 3); entry->tstamp = 1; OSMO_ASSERT(tcap_trxn_track_garbage_collect(as) == 1); OSMO_ASSERT(count_unique_hash_entries(as) == 2); tcap_trxn_track_free_all_entries(as); OSMO_ASSERT(count_unique_hash_entries(as) == 0); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_own)); OSMO_ASSERT(hash_empty(as->tcap.trxn_track_peer)); after_test = talloc_total_size(ctx); fprintf(stderr, "Consuming %lu bytes after test. Failing if not %lu.\n", after_test, before_test); OSMO_ASSERT(after_test == before_test); talloc_free(ctx); } int main(int argc, char **argv) { printf("Start running tests.\n"); tcap_trxn_track_test_func_t iter = NULL; for (int i = 0; ((iter = tcap_trxn_track_tests[i])); i++) { printf("Starting test %d\n", i); iter(); printf("Finished test %d\n", i); } printf("All tests passed.\n"); return 0; } tcap_trxn_track_test_func_t tcap_trxn_track_tests[] = { tcap_trxn_track_test_create_find_free, tcap_trxn_track_test_transaction, tcap_trxn_track_test_gc, NULL };