diff options
Diffstat (limited to 'tests/libosmo-gtlv')
-rw-r--r-- | tests/libosmo-gtlv/Makefile.am | 2 | ||||
-rw-r--r-- | tests/libosmo-gtlv/gtlv_dec_enc_test.c | 18 | ||||
-rw-r--r-- | tests/libosmo-gtlv/gtlv_test.c | 300 | ||||
-rw-r--r-- | tests/libosmo-gtlv/gtlv_test.ok | 67 | ||||
-rw-r--r-- | tests/libosmo-gtlv/test_tliv/Makefile.am | 60 | ||||
-rw-r--r-- | tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c | 71 | ||||
-rw-r--r-- | tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c | 68 | ||||
-rw-r--r-- | tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h | 50 | ||||
-rw-r--r-- | tests/libosmo-gtlv/test_tliv/tliv_test.c | 217 | ||||
-rw-r--r-- | tests/libosmo-gtlv/test_tliv/tliv_test.ok | 32 |
10 files changed, 768 insertions, 117 deletions
diff --git a/tests/libosmo-gtlv/Makefile.am b/tests/libosmo-gtlv/Makefile.am index 392a73e..45d6ec2 100644 --- a/tests/libosmo-gtlv/Makefile.am +++ b/tests/libosmo-gtlv/Makefile.am @@ -1,5 +1,6 @@ SUBDIRS = \ test_gtlv_gen \ + test_tliv \ $(NULL) AM_CPPFLAGS = \ @@ -45,3 +46,4 @@ update_exp: $(builddir)/gtlv_test >$(srcdir)/gtlv_test.ok $(builddir)/gtlv_dec_enc_test >$(srcdir)/gtlv_dec_enc_test.ok $(MAKE) -C test_gtlv_gen update_exp + $(MAKE) -C test_tliv update_exp diff --git a/tests/libosmo-gtlv/gtlv_dec_enc_test.c b/tests/libosmo-gtlv/gtlv_dec_enc_test.c index 89b4011..e02a2e5 100644 --- a/tests/libosmo-gtlv/gtlv_dec_enc_test.c +++ b/tests/libosmo-gtlv/gtlv_dec_enc_test.c @@ -205,21 +205,21 @@ int enc_to_str_repeat_struct(char *buf, size_t buflen, const void *encode_from) struct osmo_gtlv_coding nested_inner_msg_ies[] = { { - .tag = TAG_FOO, + .ti = { TAG_FOO }, .dec_func = dec_u16, .enc_func = enc_u16, .enc_to_str_func = enc_to_str_u16, .memb_ofs = offsetof(struct nested_inner_msg, foo), }, { - .tag = TAG_BAR, + .ti = { TAG_BAR }, .dec_func = dec_bar, .enc_func = enc_bar, .enc_to_str_func = enc_to_str_bar, .memb_ofs = offsetof(struct nested_inner_msg, bar), }, { - .tag = TAG_BAZ, + .ti = { TAG_BAZ }, .dec_func = dec_baz, .enc_func = enc_baz, .enc_to_str_func = enc_to_str_baz, @@ -230,21 +230,21 @@ struct osmo_gtlv_coding nested_inner_msg_ies[] = { struct osmo_gtlv_coding msg_ie_coding[] = { { - .tag = TAG_FOO, + .ti = { TAG_FOO }, .dec_func = dec_u16, .enc_func = enc_u16, .enc_to_str_func = enc_to_str_u16, .memb_ofs = offsetof(struct decoded_msg, foo), }, { - .tag = TAG_BAR, + .ti = { TAG_BAR }, .dec_func = dec_bar, .enc_func = enc_bar, .enc_to_str_func = enc_to_str_bar, .memb_ofs = offsetof(struct decoded_msg, bar), }, { - .tag = TAG_BAZ, + .ti = { TAG_BAZ }, .dec_func = dec_baz, .enc_func = enc_baz, .enc_to_str_func = enc_to_str_baz, @@ -253,7 +253,7 @@ struct osmo_gtlv_coding msg_ie_coding[] = { .presence_flag_ofs = offsetof(struct decoded_msg, baz_present), }, { - .tag = TAG_REPEAT_INT, + .ti = { TAG_REPEAT_INT }, .dec_func = dec_u16, .enc_func = enc_u16, .enc_to_str_func = enc_to_str_u16, @@ -264,7 +264,7 @@ struct osmo_gtlv_coding msg_ie_coding[] = { .count_max = ARRAY_SIZE(((struct decoded_msg *)0)->repeat_int), }, { - .tag = TAG_REPEAT_STRUCT, + .ti = { TAG_REPEAT_STRUCT }, .dec_func = dec_repeat_struct, .enc_func = enc_repeat_struct, .enc_to_str_func = enc_to_str_repeat_struct, @@ -275,7 +275,7 @@ struct osmo_gtlv_coding msg_ie_coding[] = { .count_max = ARRAY_SIZE(((struct decoded_msg *)0)->repeat_struct), }, { - .tag = TAG_NEST, + .ti = { TAG_NEST }, .memb_ofs = offsetof(struct decoded_msg, nest), .nested_ies = nested_inner_msg_ies, .has_presence_flag = true, diff --git a/tests/libosmo-gtlv/gtlv_test.c b/tests/libosmo-gtlv/gtlv_test.c index c009850..8023699 100644 --- a/tests/libosmo-gtlv/gtlv_test.c +++ b/tests/libosmo-gtlv/gtlv_test.c @@ -33,7 +33,7 @@ void *ctx; struct ie { - int tag; + struct osmo_gtlv_tag_inst ti; const char *val; }; @@ -48,7 +48,7 @@ struct msgb *test_tlv_enc(const struct osmo_gtlv_cfg *cfg, const struct ie *ies) for (ie = ies; ie->val; ie++) { /* put header without knowing length yet */ - OSMO_ASSERT(osmo_gtlv_put_tl(>lv, ie->tag, 0) == 0); + OSMO_ASSERT(osmo_gtlv_put_tli(>lv, &ie->ti, 0) == 0); /* put value data, as much as desired */ msgb_put(gtlv.dst, osmo_hexparse(ie->val, gtlv.dst->tail, msgb_tailroom(gtlv.dst))); /* update header len from amount of written data */ @@ -80,9 +80,10 @@ void test_tlv_dec(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, struct /* end of TLV structure? */ if (!gtlv.val) break; - printf(" T=%d L=%zu v=%s\n", gtlv.tag, gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); - if (gtlv.tag != ie->tag) { - printf(" ERROR loading TLV structure: expected tag %d, got tag %d\n", ie->tag, gtlv.tag); + printf(" T=%s L=%zu", osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), gtlv.len); + printf(" v=%s\n", osmo_hexdump_nospc(gtlv.val, gtlv.len)); + if (gtlv.ti.tag != ie->ti.tag) { + printf(" ERROR loading TLV structure: expected tag %u, got tag %u\n", ie->ti.tag, gtlv.ti.tag); exit(1); } if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len))) { @@ -107,22 +108,28 @@ void test_tlv_peek(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, struct ie = ies; while (1) { int rc; - int next_tag = osmo_gtlv_load_peek_tag(>lv); - if (next_tag == -ENOENT) - printf(" peek T=-ENOENT\n"); - else - printf(" peek T=%d\n", next_tag); - - if (ie->val && next_tag != ie->tag) { - printf(" ERROR peeking tag: expected tag %d, got tag %d\n", ie->tag, next_tag); + struct osmo_gtlv_tag_inst next_tag; + rc = osmo_gtlv_load_peek_tag(>lv, &next_tag); + if (rc == -ENOENT) { + printf(" peek rc=-ENOENT\n"); + } else { + printf(" peek T=%s", osmo_gtlv_tag_inst_to_str_c(ctx, &next_tag, NULL)); + printf("\n"); + } + + if (ie->val && osmo_gtlv_tag_inst_cmp(&next_tag, &ie->ti)) { + printf(" ERROR peeking tag: expected tag %s, got tag %s\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), + osmo_gtlv_tag_inst_to_str_c(ctx, &next_tag, NULL)); exit(1); } - if (!ie->val && next_tag != -ENOENT) { - printf(" ERROR peeking tag: expected -ENOENT, got tag %d\n", next_tag); + if (!ie->val && rc != -ENOENT) { + printf(" ERROR peeking tag: expected -ENOENT, got rc=%d, tag %s\n", rc, + osmo_gtlv_tag_inst_to_str_c(ctx, &next_tag, NULL)); exit(1); } - if (next_tag == -ENOENT) + if (rc == -ENOENT) break; /* go to the next TLV */ @@ -156,25 +163,32 @@ void test_tlv_dec_by_tag(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, for (ie = last_ie; ie >= ies; ie--) { /* each time, look from the beginning */ osmo_gtlv_load_start(>lv); - rc = osmo_gtlv_load_next_by_tag(>lv, ie->tag); + rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); if (rc) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag(%d) rc = %d\n", ie->tag, rc); + printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) rc = %d\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), rc); exit(1); } if (!gtlv.val) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag(%d) returned NULL val\n", - ie->tag); + printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) returned NULL val\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL)); exit(1); } - if (gtlv.tag != ie->tag) { - printf(" ERROR loading TLV structure: expected tag %d, got tag %d\n", ie->tag, gtlv.tag); + if (osmo_gtlv_tag_inst_cmp(>lv.ti, &ie->ti)) { + printf(" ERROR loading TLV structure: expected tag %s, got tag %s\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); exit(1); } if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len))) { while (1) { - printf(" (mismatch: T=%d L=%zu v=%s, checking for another occurrence of T=%d)\n", - gtlv.tag, gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len), gtlv.tag); - rc = osmo_gtlv_load_next_by_tag(>lv, ie->tag); + printf(" (mismatch: T=%s L=%zu v=%s, checking for another occurrence of T=%s)\n", + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), + gtlv.len, + osmo_hexdump_nospc(gtlv.val, gtlv.len), + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); + + rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); if (rc || !gtlv.val) { printf(" ERROR val not found\n"); exit(1); @@ -184,7 +198,9 @@ void test_tlv_dec_by_tag(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, } } } - printf(" T=%d L=%zu v=%s\n", gtlv.tag, gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); + printf(" T=%s L=%zu v=%s\n", + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), + gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); } printf("- decoding every second tag:\n"); @@ -196,25 +212,32 @@ void test_tlv_dec_by_tag(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, if (!ie->val) break; - rc = osmo_gtlv_load_next_by_tag(>lv, ie->tag); + rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); if (rc) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag(%d) rc = %d\n", ie->tag, rc); + printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) rc = %d\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), rc); exit(1); } if (!gtlv.val) { - printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag(%d) returned NULL val\n", - ie->tag); + printf(" ERROR loading TLV structure: osmo_gtlv_load_next_by_tag_inst(%s) returned NULL val\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL)); exit(1); } - if (gtlv.tag != ie->tag) { - printf(" ERROR loading TLV structure: expected tag %d, got tag %d\n", ie->tag, gtlv.tag); + if (osmo_gtlv_tag_inst_cmp(>lv.ti, &ie->ti)) { + printf(" ERROR loading TLV structure: expected tag %s, got tag %s\n", + osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL), + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); exit(1); } if (strcmp(ie->val, osmo_hexdump_nospc(gtlv.val, gtlv.len))) { while (1) { - printf(" (mismatch: T=%d L=%zu v=%s, checking for another occurrence of T=%d)\n", - gtlv.tag, gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len), gtlv.tag); - rc = osmo_gtlv_load_next_by_tag(>lv, ie->tag); + printf(" (mismatch: T=%s L=%zu v=%s, checking for another occurrence of T=%s)\n", + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), + gtlv.len, + osmo_hexdump_nospc(gtlv.val, gtlv.len), + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL)); + + rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); if (rc || !gtlv.val) { printf(" ERROR val not found\n"); exit(1); @@ -224,14 +247,16 @@ void test_tlv_dec_by_tag(const struct osmo_gtlv_cfg *cfg, const struct ie *ies, } } } - printf(" T=%d L=%zu v=%s\n", gtlv.tag, gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); + printf(" T=%s L=%zu v=%s\n", + osmo_gtlv_tag_inst_to_str_c(ctx, >lv.ti, NULL), + gtlv.len, osmo_hexdump_nospc(gtlv.val, gtlv.len)); } printf("- enforcing order: without restart, a past tag is not parsed again:\n"); /* Try to read the first tag, expect that it isn't found because we're already halfway in the message data */ ie = ies; - rc = osmo_gtlv_load_next_by_tag(>lv, ie->tag); - printf(" osmo_gtlv_load_next_by_tag(%d) rc=", ie->tag); + rc = osmo_gtlv_load_next_by_tag_inst(>lv, &ie->ti); + printf(" osmo_gtlv_load_next_by_tag_inst(%s) rc=", osmo_gtlv_tag_inst_to_str_c(ctx, &ie->ti, NULL)); if (rc == -ENOENT) { printf("-ENOENT\n"); } else { @@ -262,14 +287,14 @@ void test_tlv(const char *label, struct ie *tests[], size_t tests_len, const str struct ie t8l8v_test1[] = { /* smallest T */ - { 0, "2342" }, + { {}, "2342" }, /* largest T */ - { 255, "2342" }, + { {255}, "2342" }, /* smallest V (no V data) */ - { 1, "" }, + { {1}, "" }, /* largest V, 255 bytes is the largest that an 8bit size length can express. */ - { 123, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + { {123}, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" @@ -280,22 +305,22 @@ struct ie t8l8v_test1[] = { }, /* arbitrary test data */ - { 101, "11" }, - { 102, "2222" }, - { 103, "333333" }, + { {101}, "11" }, + { {102}, "2222" }, + { {103}, "333333" }, {} }; struct ie t8l8v_test_multi[] = { - { 42, "42" }, - { 2, "0101" }, - { 2, "2222" }, - { 3, "11" }, - { 3, "2222" }, - { 3, "333333" }, - { 23, "23" }, - { 42, "666f72747974776f" }, - { 23, "7477656e74797468726565" }, + { {42}, "42" }, + { {2}, "0101" }, + { {2}, "2222" }, + { {3}, "11" }, + { {3}, "2222" }, + { {3}, "333333" }, + { {23}, "23" }, + { {42}, "666f72747974776f" }, + { {23}, "7477656e74797468726565" }, {} }; @@ -311,14 +336,14 @@ void test_t8l8v() struct ie t16l16v_test1[] = { /* smallest T */ - { 0, "2342" }, + { {}, "2342" }, /* largest T */ - { 65535, "2342" }, + { {65535}, "2342" }, /* smallest V (no V data) */ - { 1, "" }, + { {1}, "" }, /* 256 bytes is one more than an 8bit size length can express. */ - { 123, "0000000000000000000000000000000000000000000000000000000000000000" + { {123}, "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" @@ -329,22 +354,22 @@ struct ie t16l16v_test1[] = { }, /* arbitrary test data */ - { 1001, "11" }, - { 1002, "2222" }, - { 1003, "333333" }, + { {1001}, "11" }, + { {1002}, "2222" }, + { {1003}, "333333" }, {} }; struct ie t16l16v_test_multi[] = { - { 1042, "42" }, - { 102, "0101" }, - { 102, "2222" }, - { 103, "11" }, - { 103, "2222" }, - { 103, "333333" }, - { 1023, "23" }, - { 1042, "666f72747974776f" }, - { 1023, "7477656e74797468726565" }, + { {1042}, "42" }, + { {102}, "0101" }, + { {102}, "2222" }, + { {103}, "11" }, + { {103}, "2222" }, + { {103}, "333333" }, + { {1023}, "23" }, + { {1042}, "666f72747974776f" }, + { {1023}, "7477656e74797468726565" }, {} }; @@ -360,18 +385,18 @@ void test_t16l16v() struct ie txlxv_test1[] = { /* smallest T */ - { 0, "2342" }, + { {}, "2342" }, /* largest T that still fits in one encoded octet (highest bit serves as flag) */ - { 0x7f, "2342" }, + { {0x7f}, "2342" }, /* smallest T that needs two octets to be encoded (first octet = 0x80 flag + 0, second octet = 0x1) */ - { 0x80, "2342" }, + { {0x80}, "2342" }, /* largest T that can be encoded in 16bit - one flag bit. */ - { 0x7fff, "2342" }, + { {0x7fff}, "2342" }, /* smallest V (no V data) */ - { 1, "" }, + { {1}, "" }, /* 256 bytes is one more than an 8bit size length can express. */ - { 123, "0000000000000000000000000000000000000000000000000000000000000000" + { {123}, "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000" @@ -382,21 +407,21 @@ struct ie txlxv_test1[] = { }, /* arbitrary test data */ - { 1002, "2222" }, - { 1003, "333333" }, + { {1002}, "2222" }, + { {1003}, "333333" }, {} }; struct ie txlxv_test_multi[] = { - { 1042, "42" }, - { 1002, "0101" }, - { 1002, "2222" }, - { 103, "11" }, - { 103, "2222" }, - { 103, "333333" }, - { 1023, "23" }, - { 1042, "666f72747974776f" }, - { 1023, "7477656e74797468726565" }, + { {1042}, "42" }, + { {1002}, "0101" }, + { {1002}, "2222" }, + { {103}, "11" }, + { {103}, "2222" }, + { {103}, "333333" }, + { {1023}, "23" }, + { {1042}, "666f72747974776f" }, + { {1023}, "7477656e74797468726565" }, {} }; @@ -413,14 +438,14 @@ int txlxv_load_tl(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t s if (pos[0] & 0x80) { if (pos + 2 > end) return -EINVAL; - gtlv->tag = (((int)pos[1]) << 7) + (pos[0] & 0x7f); + gtlv->ti.tag = (((int)pos[1]) << 7) + (pos[0] & 0x7f); pos += 2; } else { - gtlv->tag = pos[0]; + gtlv->ti.tag = pos[0]; pos++; } - switch (gtlv->tag) { + switch (gtlv->ti.tag) { case 1002: /* fixed-length IE */ gtlv->len = 2; @@ -445,10 +470,12 @@ int txlxv_load_tl(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t s } /* Example of defining a variable TL, where size of T and L depend on the actual tag and length values: store. */ -int txlxv_store_tl(uint8_t *dst_data, size_t dst_data_avail, unsigned int tag, size_t len, struct osmo_gtlv_put *gtlv) +int txlxv_store_tl(uint8_t *dst_data, size_t dst_data_avail, const struct osmo_gtlv_tag_inst *ti, size_t len, + struct osmo_gtlv_put *gtlv) { uint8_t *pos = dst_data; uint8_t *end = dst_data + dst_data_avail; + unsigned int tag = ti->tag; if (tag < 0x80) { if (pos + 1 > end) return -ENOSPC; @@ -496,7 +523,95 @@ const struct osmo_gtlv_cfg txlxv_cfg = { void test_txlxv() { - test_tlv("txlxv_tests", txlxv_tests, ARRAY_SIZE(txlxv_tests), &txlxv_cfg); + test_tlv(__func__, txlxv_tests, ARRAY_SIZE(txlxv_tests), &txlxv_cfg); +} + +/* Example of defining a TLI, with an instance indicator */ +static int tliv_load_tl(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t src_data_len) +{ + /* already validated in next_tl_valid(): src_data_len >= cfg->tl_min_size == 2. */ + gtlv->ti.tag = src_data[0]; + gtlv->len = src_data[1]; + + switch (gtlv->ti.tag) { + /* All tags that are TLIV go here */ + case 5: + case 7: + case 9: + if (src_data_len < 3) + return -ENOSPC; + gtlv->ti.instance_present = true; + gtlv->ti.instance = src_data[2]; + gtlv->val = src_data + 3; + return 0; + default: + gtlv->val = src_data + 2; + return 0; + } +} + +static int tliv_store_tl(uint8_t *dst_data, size_t dst_data_avail, const struct osmo_gtlv_tag_inst *ti, size_t len, + struct osmo_gtlv_put *gtlv) +{ + if (ti->tag > UINT8_MAX) + return -EINVAL; + if (len > UINT8_MAX) + return -EMSGSIZE; + if (dst_data_avail < 2) + return -ENOSPC; + + dst_data[0] = ti->tag; + dst_data[1] = len; + + switch (ti->tag) { + /* All tags that are TLIV go here */ + case 5: + case 7: + case 9: + if (dst_data_avail < 3) + return -ENOSPC; + if (!ti->instance_present) + return -EINVAL; + if (ti->instance > UINT8_MAX) + return -EINVAL; + dst_data[2] = ti->instance; + return 3; + default: + return 2; + } +} + +const struct osmo_gtlv_cfg osmo_tliv_cfg = { + .tl_min_size = 2, + .load_tl = tliv_load_tl, + .store_tl = tliv_store_tl, +}; + +struct ie tliv_test1[] = { + /* TLV */ + { {1}, "0002" }, + /* TLIV */ + { {5, true, 1}, "0017" }, + /* TLIV */ + { {5, true, 2}, "0018" }, + /* TLIV */ + { {5, true, 3}, "0019" }, + /* TLV */ + { {6}, "001a" }, + /* TLIV */ + { {7, true, 1}, "001b" }, + /* TLIV */ + { {9, true, 1}, "001c" }, + {} +}; + +struct ie *tliv_tests[] = { + tliv_test1, +}; + +void test_tliv() +{ + test_tlv(__func__, tliv_tests, ARRAY_SIZE(tliv_tests), &osmo_tliv_cfg); } int main() @@ -507,6 +622,7 @@ int main() test_t8l8v(); test_t16l16v(); test_txlxv(); + test_tliv(); talloc_free(ctx); return 0; diff --git a/tests/libosmo-gtlv/gtlv_test.ok b/tests/libosmo-gtlv/gtlv_test.ok index 3cebd7e..edc6ff3 100644 --- a/tests/libosmo-gtlv/gtlv_test.ok +++ b/tests/libosmo-gtlv/gtlv_test.ok @@ -17,7 +17,7 @@ peek T=101 peek T=102 peek T=103 - peek T=-ENOENT + peek rc=-ENOENT - decoding in reverse order: T=103 L=3 v=333333 T=102 L=2 v=2222 @@ -31,7 +31,7 @@ T=123 L=255 v=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff T=102 L=2 v=2222 - enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag(0) rc=-ENOENT + osmo_gtlv_load_next_by_tag_inst(0) rc=-ENOENT === end: test_t8l8v[0] === start: test_t8l8v[1] @@ -56,7 +56,7 @@ peek T=23 peek T=42 peek T=23 - peek T=-ENOENT + peek rc=-ENOENT - decoding in reverse order: (mismatch: T=23 L=1 v=23, checking for another occurrence of T=23) T=23 L=11 v=7477656e74797468726565 @@ -80,7 +80,7 @@ T=3 L=3 v=333333 T=42 L=8 v=666f72747974776f - enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag(42) rc=-ENOENT + osmo_gtlv_load_next_by_tag_inst(42) rc=-ENOENT === end: test_t8l8v[1] === start: test_t16l16v[0] @@ -101,7 +101,7 @@ peek T=1001 peek T=1002 peek T=1003 - peek T=-ENOENT + peek rc=-ENOENT - decoding in reverse order: T=1003 L=3 v=333333 T=1002 L=2 v=2222 @@ -115,7 +115,7 @@ T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 T=1002 L=2 v=2222 - enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag(0) rc=-ENOENT + osmo_gtlv_load_next_by_tag_inst(0) rc=-ENOENT === end: test_t16l16v[0] === start: test_t16l16v[1] @@ -140,7 +140,7 @@ peek T=1023 peek T=1042 peek T=1023 - peek T=-ENOENT + peek rc=-ENOENT - decoding in reverse order: (mismatch: T=1023 L=1 v=23, checking for another occurrence of T=1023) T=1023 L=11 v=7477656e74797468726565 @@ -164,10 +164,10 @@ T=103 L=3 v=333333 T=1042 L=8 v=666f72747974776f - enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag(1042) rc=-ENOENT + osmo_gtlv_load_next_by_tag_inst(1042) rc=-ENOENT === end: test_t16l16v[1] -=== start: txlxv_tests[0] +=== start: test_txlxv[0] - encoded: 00 02 23 42 7f 02 23 42 80 01 02 23 42 ff ff 02 23 42 01 00 7b 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ea 07 22 22 eb 07 03 33 33 33 . - decoding: T=0 L=2 v=2342 @@ -187,7 +187,7 @@ peek T=123 peek T=1002 peek T=1003 - peek T=-ENOENT + peek rc=-ENOENT - decoding in reverse order: T=1003 L=3 v=333333 T=1002 L=2 v=2222 @@ -203,10 +203,10 @@ T=123 L=256 v=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 T=1003 L=3 v=333333 - enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag(0) rc=-ENOENT -=== end: txlxv_tests[0] + osmo_gtlv_load_next_by_tag_inst(0) rc=-ENOENT +=== end: test_txlxv[0] -=== start: txlxv_tests[1] +=== start: test_txlxv[1] - encoded: 92 08 01 42 ea 07 01 01 ea 07 22 22 67 01 11 67 02 22 22 67 03 33 33 33 ff 07 01 23 92 08 08 66 6f 72 74 79 74 77 6f ff 07 0b 74 77 65 6e 74 79 74 68 72 65 65 . - decoding: T=1042 L=1 v=42 @@ -228,7 +228,7 @@ peek T=1023 peek T=1042 peek T=1023 - peek T=-ENOENT + peek rc=-ENOENT - decoding in reverse order: (mismatch: T=1023 L=1 v=23, checking for another occurrence of T=1023) T=1023 L=11 v=7477656e74797468726565 @@ -252,5 +252,40 @@ T=103 L=3 v=333333 T=1042 L=8 v=666f72747974776f - enforcing order: without restart, a past tag is not parsed again: - osmo_gtlv_load_next_by_tag(1042) rc=-ENOENT -=== end: txlxv_tests[1] + osmo_gtlv_load_next_by_tag_inst(1042) rc=-ENOENT +=== end: test_txlxv[1] + +=== start: test_tliv[0] +- encoded: 01 02 00 02 05 02 01 00 17 05 02 02 00 18 05 02 03 00 19 06 02 00 1a 07 02 01 00 1b 09 02 01 00 1c . +- decoding: + T=1 L=2 v=0002 + T=5[1] L=2 v=0017 + T=5[2] L=2 v=0018 + T=5[3] L=2 v=0019 + T=6 L=2 v=001a + T=7[1] L=2 v=001b + T=9[1] L=2 v=001c +- peeking: + peek T=1 + peek T=5[1] + peek T=5[2] + peek T=5[3] + peek T=6 + peek T=7[1] + peek T=9[1] + peek rc=-ENOENT +- decoding in reverse order: + T=9[1] L=2 v=001c + T=7[1] L=2 v=001b + T=6 L=2 v=001a + T=5[3] L=2 v=0019 + T=5[2] L=2 v=0018 + T=5[1] L=2 v=0017 + T=1 L=2 v=0002 +- decoding every second tag: + T=5[1] L=2 v=0017 + T=5[3] L=2 v=0019 + T=7[1] L=2 v=001b +- enforcing order: without restart, a past tag is not parsed again: + osmo_gtlv_load_next_by_tag_inst(1) rc=-ENOENT +=== end: test_tliv[0] diff --git a/tests/libosmo-gtlv/test_tliv/Makefile.am b/tests/libosmo-gtlv/test_tliv/Makefile.am new file mode 100644 index 0000000..eb95e12 --- /dev/null +++ b/tests/libosmo-gtlv/test_tliv/Makefile.am @@ -0,0 +1,60 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + -I$(bulddir) \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + $(LIBOSMOCORE_CFLAGS) \ + $(NULL) + +noinst_PROGRAMS = \ + gen__myproto_ies_auto \ + tliv_test \ + $(NULL) + +EXTRA_DIST = \ + myproto_ies_custom.h \ + tliv_test.ok \ + $(NULL) + +BUILT_SOURCES = \ + myproto_ies_auto.h \ + myproto_ies_auto.c \ + $(NULL) + +CLEANFILES = \ + myproto_ies_auto.h \ + myproto_ies_auto.c \ + $(NULL) + +gen__myproto_ies_auto_SOURCES = \ + gen__myproto_ies_auto.c \ + myproto_ies_custom.c \ + $(NULL) + +gen__myproto_ies_auto_LDADD = \ + $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ + $(LIBOSMOCORE_LIBS) \ + $(NULL) + +myproto_ies_auto.h: $(builddir)/gen__myproto_ies_auto + $(builddir)/gen__myproto_ies_auto h > $(builddir)/myproto_ies_auto.h +myproto_ies_auto.c: $(builddir)/gen__myproto_ies_auto + $(builddir)/gen__myproto_ies_auto c > $(builddir)/myproto_ies_auto.c + +tliv_test_SOURCES = \ + tliv_test.c \ + myproto_ies_custom.c \ + myproto_ies_auto.c \ + $(NULL) + +tliv_test_LDADD = \ + $(top_builddir)/src/libosmo-gtlv/libosmo-gtlv.a \ + $(LIBOSMOCORE_LIBS) \ + $(NULL) + +.PHONY: update_exp +update_exp: + $(builddir)/tliv_test >$(srcdir)/tliv_test.ok diff --git a/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c b/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c new file mode 100644 index 0000000..21e70d9 --- /dev/null +++ b/tests/libosmo-gtlv/test_tliv/gen__myproto_ies_auto.c @@ -0,0 +1,71 @@ +/* + * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <stdbool.h> +#include <stdio.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/gtlv/gtlv_gen.h> + +#define O OSMO_GTLV_GEN_O +#define M OSMO_GTLV_GEN_M +#define O_MULTI OSMO_GTLV_GEN_O_MULTI +#define M_MULTI OSMO_GTLV_GEN_M_MULTI +#define O_INST OSMO_GTLV_GEN_O_INST +#define M_INST OSMO_GTLV_GEN_M_INST + +#define AUTO osmo_gtlv_gen_ie_auto + +static const struct osmo_gtlv_gen_ie bar = { + .tag_name = "bar", +}; + +static const struct osmo_gtlv_gen_ie_o ies_in_moo_msg[] = { + M_INST("MYPROTO_IEI_BAR_ALPHA", bar, "bar_alpha"), + O_INST("MYPROTO_IEI_BAR_BETA", bar, "bar_beta"), + M_INST("MYPROTO_IEI_BAR_GAMMA", bar, "bar_gamma"), + {} +}; + +static const struct osmo_gtlv_gen_msg msg_defs[] = { + { "moo", ies_in_moo_msg }, + {} +}; + +int main(int argc, const char **argv) +{ + struct osmo_gtlv_gen_cfg cfg = { + .proto_name = "myproto", + .message_type_enum = "enum myproto_msg_type", + .message_type_prefix = "MYPROTO_MSGT_", + .tag_enum = "enum myproto_iei", + .tag_prefix = "MYPROTO_IEI_", + .decoded_type_prefix = "struct myproto_ie_", + .h_header = "#include \"myproto_ies_custom.h\"", + .c_header = "#include <myproto_ies_auto.h>", + .msg_defs = msg_defs, + .add_enc_to_str = true, + }; + return osmo_gtlv_gen_main(&cfg, argc, argv); +} diff --git a/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c new file mode 100644 index 0000000..54164ce --- /dev/null +++ b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.c @@ -0,0 +1,68 @@ +/* Example for defining custom IES for gtlv_gen. */ +/* + * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <errno.h> +#include <inttypes.h> + +#include <osmocom/core/bits.h> +#include <osmocom/core/msgb.h> +#include <osmocom/gtlv/gtlv.h> + +#include <myproto_ies_custom.h> + +int myproto_dec_bar(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *gtlv) +{ + struct myproto_ie_bar *bar = decode_to; + if (gtlv->len < 2) + return -EINVAL; + *bar = (struct myproto_ie_bar){ + .a = gtlv->val[0], + .b = (gtlv->val[1] == 1), + }; + return 0; +} + +int myproto_enc_bar(struct osmo_gtlv_put *gtlv, void *decoded_struct, void *encode_from) +{ + struct myproto_ie_bar *bar = encode_from; + msgb_put_u8(gtlv->dst, bar->a); + msgb_put_u8(gtlv->dst, bar->b ? 1 : 0); + return 0; +} + +int myproto_enc_to_str_bar(char *buf, size_t buflen, void *encode_from) +{ + struct myproto_ie_bar *bar = encode_from; + return snprintf(buf, buflen, "%d,%s", bar->a, bar->b ? "true" : "false"); +} + +const struct value_string myproto_msg_type_names[] = { + { MYPROTO_MSGT_MOO, "MOO" }, + {} +}; + +const struct value_string myproto_iei_names[] = { + { MYPROTO_IEI_BAR, "BAR" }, + {} +}; diff --git a/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h new file mode 100644 index 0000000..64e06ff --- /dev/null +++ b/tests/libosmo-gtlv/test_tliv/myproto_ies_custom.h @@ -0,0 +1,50 @@ +/* Definitions for decoded message IEs, to be used by the auto-generated myproto_ies_auto.c. */ +/* + * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include <osmocom/core/utils.h> + +enum myproto_msg_type { + MYPROTO_MSGT_MOO = 1, +}; + +extern const struct value_string myproto_msg_type_names[]; + +enum myproto_iei { + MYPROTO_IEI_BAR = 1, +}; + +enum myproto_iei_bar_inst { + MYPROTO_IEI_BAR_ALPHA = 2, + MYPROTO_IEI_BAR_BETA = 3, + MYPROTO_IEI_BAR_GAMMA = 5, +}; + +extern const struct value_string myproto_iei_names[]; + +struct myproto_ie_bar { + int a; + bool b; +}; diff --git a/tests/libosmo-gtlv/test_tliv/tliv_test.c b/tests/libosmo-gtlv/test_tliv/tliv_test.c new file mode 100644 index 0000000..fd4e310 --- /dev/null +++ b/tests/libosmo-gtlv/test_tliv/tliv_test.c @@ -0,0 +1,217 @@ +/* + * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <stdio.h> +#include <errno.h> + +#include <osmocom/core/application.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/msgb.h> + +#include <osmocom/gtlv/gtlv.h> + +#include <myproto_ies_auto.h> + +struct myproto_msg { + enum myproto_msg_type type; + union myproto_ies ies; +}; + +static void err_cb(void *data, void *decoded_struct, const char *file, int line, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + //printf("ERR: %s:%d ", file, line); + printf("ERR: "); + vprintf(fmt, args); + va_end(args); +} + +static int myproto_msg_enc(struct msgb *dst, const struct myproto_msg *msg, const struct osmo_gtlv_cfg *cfg) +{ + struct osmo_gtlv_put gtlv = { + .cfg = cfg, + .dst = dst, + }; + + msgb_put_u8(gtlv.dst, msg->type); + return myproto_ies_encode(>lv, (void *)&msg->ies, msg->type, err_cb, NULL, myproto_iei_names); +} + +static int myproto_msg_dec(struct myproto_msg *msg, const uint8_t *data, size_t data_len, + const struct osmo_gtlv_cfg *cfg, bool ordered) +{ + struct osmo_gtlv_load gtlv; + if (data_len < 1) + return -EINVAL; + msg->type = data[0]; + gtlv = (struct osmo_gtlv_load){ + .cfg = cfg, + .src = { data + 1, data_len - 1 }, + }; + return myproto_ies_decode(&msg->ies, >lv, ordered, msg->type, err_cb, NULL, myproto_iei_names); +} + +void *ctx; + +struct myproto_msg tests[] = { + { + MYPROTO_MSGT_MOO, + { + .moo = { + .bar_alpha = { 23, true }, + .bar_gamma = { 42, false }, + }, + }, + }, + { + MYPROTO_MSGT_MOO, + { + .moo = { + .bar_alpha = { 11, true }, + .bar_beta_present = true, + .bar_beta = { 22, false }, + .bar_gamma = { 33, true }, + }, + }, + }, +}; + +int myproto_msg_to_str_buf(char *buf, size_t buflen, const struct myproto_msg *m) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + OSMO_STRBUF_PRINTF(sb, "%s={", get_value_string(myproto_msg_type_names, m->type)); + OSMO_STRBUF_APPEND(sb, osmo_gtlvs_encode_to_str_buf, &m->ies, 0, myproto_get_msg_coding(m->type), + myproto_iei_names); + OSMO_STRBUF_PRINTF(sb, " }"); + return sb.chars_needed; + +} + +char *myproto_msg_to_str(const struct myproto_msg *m) +{ + OSMO_NAME_C_IMPL(ctx, 256, "ERROR", myproto_msg_to_str_buf, m) +} + +void test_enc_dec(const char *label, const struct osmo_gtlv_cfg *cfg, bool ordered) +{ + int i; + for (i = 0; i < ARRAY_SIZE(tests); i++) { + int rc; + const struct myproto_msg *orig = &tests[i]; + struct myproto_msg parsed = {}; + struct msgb *msg; + + printf("\n=== start %s %s[%d]\n", label, __func__, i); + printf("encoded: %s\n", myproto_msg_to_str(orig)); + + msg = msgb_alloc(1024, __func__); + rc = myproto_msg_enc(msg, orig, cfg); + printf("myproto_msg_enc() rc = %d\n", rc); + printf("%s.\n", osmo_hexdump(msg->data, msg->len)); + + rc = myproto_msg_dec(&parsed, msg->data, msg->len, cfg, ordered); + printf("myproto_msg_dec() rc = %d\n", rc); + printf("decoded: %s\n", myproto_msg_to_str(&parsed)); + if (strcmp(myproto_msg_to_str(orig), myproto_msg_to_str(&parsed))) { + printf(" ERROR: parsed != orig\n"); + exit(1); + } + + msgb_free(msg); + printf("=== end %s %s[%d]\n", label, __func__, i); + } +} + +/* Example of defining a TLI, with an instance indicator */ +static int tliv_load_tl(struct osmo_gtlv_load *gtlv, const uint8_t *src_data, size_t src_data_len) +{ + /* already validated in next_tl_valid(): src_data_len >= cfg->tl_min_size == 2. */ + gtlv->ti.tag = src_data[0]; + gtlv->len = src_data[1]; + + switch (gtlv->ti.tag) { + /* All tags that are TLIV go here */ + case MYPROTO_IEI_BAR: + if (src_data_len < 3) + return -ENOSPC; + gtlv->ti.instance_present = true; + gtlv->ti.instance = src_data[2]; + gtlv->val = src_data + 3; + /* In this example, the I is part of the len */ + gtlv->len--; + return 0; + default: + gtlv->val = src_data + 2; + return 0; + } +} + +static int tliv_store_tl(uint8_t *dst_data, size_t dst_data_avail, const struct osmo_gtlv_tag_inst *ti, size_t len, + struct osmo_gtlv_put *gtlv) +{ + if (ti->tag > UINT8_MAX) + return -EINVAL; + if (len > UINT8_MAX) + return -EMSGSIZE; + if (dst_data_avail < 2) + return -ENOSPC; + + dst_data[0] = ti->tag; + + switch (ti->tag) { + /* All tags that are TLIV go here */ + case MYPROTO_IEI_BAR: + if (dst_data_avail < 3) + return -ENOSPC; + if (!ti->instance_present) + return -EINVAL; + if (ti->instance > UINT8_MAX) + return -EINVAL; + /* here, I is part of the len in L; the passed len reflects only the value, so add 1 for I */ + dst_data[1] = len + 1; + dst_data[2] = ti->instance; + return 3; + default: + dst_data[1] = len; + return 2; + } +} + +const struct osmo_gtlv_cfg osmo_tliv_cfg = { + .tl_min_size = 2, + .load_tl = tliv_load_tl, + .store_tl = tliv_store_tl, +}; + +int main() +{ + ctx = talloc_named_const(NULL, 0, "test_gen_tlv"); + msgb_talloc_ctx_init(ctx, 0); + + test_enc_dec("tliv ordered", &osmo_tliv_cfg, true); + test_enc_dec("tliv unordered", &osmo_tliv_cfg, false); + + talloc_free(ctx); + return 0; +} diff --git a/tests/libosmo-gtlv/test_tliv/tliv_test.ok b/tests/libosmo-gtlv/test_tliv/tliv_test.ok new file mode 100644 index 0000000..184ffa6 --- /dev/null +++ b/tests/libosmo-gtlv/test_tliv/tliv_test.ok @@ -0,0 +1,32 @@ + +=== start tliv ordered test_enc_dec[0] +encoded: MOO={ 'BAR'=23,true 'BAR'=42,false } +myproto_msg_enc() rc = 0 +01 01 03 02 17 01 01 03 05 2a 00 . +myproto_msg_dec() rc = 0 +decoded: MOO={ 'BAR'=23,true 'BAR'=42,false } +=== end tliv ordered test_enc_dec[0] + +=== start tliv ordered test_enc_dec[1] +encoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true } +myproto_msg_enc() rc = 0 +01 01 03 02 0b 01 01 03 03 16 00 01 03 05 21 01 . +myproto_msg_dec() rc = 0 +decoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true } +=== end tliv ordered test_enc_dec[1] + +=== start tliv unordered test_enc_dec[0] +encoded: MOO={ 'BAR'=23,true 'BAR'=42,false } +myproto_msg_enc() rc = 0 +01 01 03 02 17 01 01 03 05 2a 00 . +myproto_msg_dec() rc = 0 +decoded: MOO={ 'BAR'=23,true 'BAR'=42,false } +=== end tliv unordered test_enc_dec[0] + +=== start tliv unordered test_enc_dec[1] +encoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true } +myproto_msg_enc() rc = 0 +01 01 03 02 0b 01 01 03 03 16 00 01 03 05 21 01 . +myproto_msg_dec() rc = 0 +decoded: MOO={ 'BAR'=11,true 'BAR'=22,false 'BAR'=33,true } +=== end tliv unordered test_enc_dec[1] |