Max | 9818664 | 2017-10-18 13:14:49 +0200 | [diff] [blame] | 1 | #include <inttypes.h> |
| 2 | #include <stdbool.h> |
| 3 | #include <errno.h> |
| 4 | #include <stdint.h> |
| 5 | |
| 6 | #include <osmocom/core/utils.h> |
| 7 | #include <osmocom/core/bits.h> |
| 8 | #include <osmocom/core/bitvec.h> |
| 9 | |
| 10 | #define INTRO(p) printf("=== start %s(%u) ===\n", __func__, p) |
| 11 | #define OUTRO(p) printf("=== end %s(%u) ===\n\n", __func__, p) |
| 12 | |
| 13 | static void test_bitvec_ia_octet_encode_pkt_dl_ass(struct bitvec *dest, uint32_t ttli, |
| 14 | uint8_t tfi, uint8_t gamma, uint8_t ta_valid, uint8_t ws_enc, |
| 15 | bool use_lh) |
| 16 | { |
| 17 | unsigned wp = 0; |
| 18 | |
| 19 | INTRO(use_lh); |
| 20 | |
| 21 | /* 3GPP TS 44.018 §10.5.2.16 IA Rest Octets */ |
| 22 | if (use_lh) /* FIXME: add function to encode LH properly */ |
| 23 | bitvec_write_field(dest, &wp, 3, 2); /* "HH" */ |
| 24 | else |
| 25 | bitvec_write_field(dest, &wp, 3, 2); /* "HH" */ |
| 26 | bitvec_write_field(dest, &wp, 1, 2); /* "01" Packet Downlink Assignment */ |
| 27 | bitvec_write_field(dest, &wp, ttli, 32); /* TLLI */ |
| 28 | bitvec_write_field(dest, &wp, 1, 1); /* switch TFI: on */ |
| 29 | bitvec_write_field(dest, &wp, tfi, 5); /* TFI */ |
| 30 | bitvec_write_field(dest, &wp, 0x0, 1); /* RLC acknowledged mode */ |
| 31 | bitvec_write_field(dest, &wp, 0x0, 1); /* ALPHA = not present */ |
| 32 | bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power control parameter */ |
| 33 | bitvec_write_field(dest, &wp, 0,1); /* Polling Bit: off */ |
| 34 | bitvec_write_field(dest, &wp, ta_valid, 1); /* N. B: NOT related to TAI! */ |
| 35 | bitvec_write_field(dest, &wp, 0, 1); /* No TIMING_ADVANCE_INDEX: */ |
| 36 | bitvec_write_field(dest, &wp, 0, 1); /* TBF Starting TIME present */ |
| 37 | bitvec_write_field(dest, &wp, 0, 1); /* P0 not present */ |
| 38 | if (use_lh) { /* FIXME: add function to encode LH properly */ |
| 39 | bitvec_write_field(dest, &wp, 1, 1); /* "H" - additional for R99 */ |
| 40 | } else |
| 41 | bitvec_write_field(dest, &wp, 1, 1); /* "H" - additional for R99 */ |
| 42 | bitvec_write_field(dest, &wp, ws_enc, 5); /* EGPRS Window Size */ |
| 43 | bitvec_write_field(dest, &wp, 0, 2); /* LINK_QUALITY_MEASUREMENT_MODE */ |
| 44 | bitvec_write_field(dest, &wp, 0, 1); /* BEP_PERIOD2 not present */ |
| 45 | |
| 46 | printf("Encoded PKT DL ASS IA Rest Octets: %s\n", osmo_hexdump(dest->data, dest->data_len)); |
| 47 | |
| 48 | OUTRO(use_lh); |
| 49 | } |
| 50 | |
| 51 | static void test_bitvec_ia_octet_encode_pkt_ul_ass(struct bitvec *dest, uint32_t fn, |
| 52 | uint8_t tfi, uint8_t gamma, uint8_t usf, bool tbf, bool use_lh) |
| 53 | { |
| 54 | unsigned wp = 0; |
| 55 | |
| 56 | INTRO(use_lh); |
| 57 | |
| 58 | /* 3GPP TS 44.018 §10.5.2.37b 10.5.2.16 */ |
| 59 | if (use_lh) /* FIXME: add function to encode LH properly */ |
| 60 | bitvec_write_field(dest, &wp, 3, 2); /* "HH" */ |
| 61 | else |
| 62 | bitvec_write_field(dest, &wp, 3, 2); /* "HH" */ |
| 63 | bitvec_write_field(dest, &wp, 0, 2); /* "0" Packet Uplink Assignment */ |
| 64 | if (!tbf) { |
| 65 | bitvec_write_field(dest, &wp, 0, 1); /* Block Allocation: SBA */ |
| 66 | bitvec_write_field(dest, &wp, 0, 1); /* ALPHA = not present */ |
| 67 | bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power control parameter */ |
| 68 | bitvec_write_field(dest, &wp, 0, 1); /* No TIMING_ADVANCE_INDEX: */ |
| 69 | bitvec_write_field(dest, &wp, 1, 1); /* TBF_STARTING_TIME_FLAG */ |
| 70 | bitvec_write_field(dest, &wp, (fn / (26 * 51)) % 32, 5); /* T1' */ |
| 71 | bitvec_write_field(dest, &wp, fn % 51, 6); /* T3 */ |
| 72 | bitvec_write_field(dest, &wp, fn % 26, 5); /* T2 */ |
| 73 | } else { |
| 74 | bitvec_write_field(dest, &wp, 1, 1); /* Block Allocation: Not SBA */ |
| 75 | bitvec_write_field(dest, &wp, tfi, 5); /* TFI_ASSIGNMENT */ |
| 76 | bitvec_write_field(dest, &wp, 0, 1); /* POLLING = none */ |
| 77 | bitvec_write_field(dest, &wp, 0, 1); /* ALLOCATION_TYPE: dynamic */ |
| 78 | bitvec_write_field(dest, &wp, usf, 3); /* USF */ |
| 79 | bitvec_write_field(dest, &wp, 0, 1); /* USF_GRANULARITY */ |
| 80 | bitvec_write_field(dest, &wp, 0, 1); /* "0" power control: Not Present */ |
| 81 | bitvec_write_field(dest, &wp, 0, 2); /* CHANNEL_CODING_COMMAND */ |
| 82 | bitvec_write_field(dest, &wp, 1, 1); /* TLLI_BLOCK_CHANNEL_CODING */ |
| 83 | bitvec_write_field(dest, &wp, 0, 1); /* ALPHA = not present */ |
| 84 | bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power control parameter */ |
| 85 | /* note: there is no choise for TAI and no starting time */ |
| 86 | bitvec_write_field(dest, &wp, 0, 1); /* switch TIMING_ADVANCE_INDEX = off */ |
| 87 | bitvec_write_field(dest, &wp, 0, 1); /* TBF_STARTING_TIME_FLAG */ |
| 88 | } |
| 89 | |
| 90 | printf("Encoded PKT UL ASS IA Rest Octets: %s\n", osmo_hexdump(dest->data, dest->data_len)); |
| 91 | |
| 92 | OUTRO(use_lh); |
| 93 | } |
| 94 | |
| 95 | static void test_bitdiff(const struct bitvec *src1, const struct bitvec *src2, unsigned len) |
| 96 | { |
| 97 | unsigned int bit_err = 0, i, j; |
| 98 | uint8_t byte_err = 0; |
| 99 | |
| 100 | INTRO(len); |
| 101 | |
| 102 | for (i = 0; i < len; i++) { |
| 103 | /* byte compare */ |
| 104 | byte_err = src1->data[i] ^ src2->data[i]; |
| 105 | if (byte_err) |
| 106 | for (j = 0; j < 8; j++) |
| 107 | bit_err += (byte_err >> j) & 0x01; /* count bits which differ */ |
| 108 | } |
| 109 | |
| 110 | |
| 111 | printf("=== total %u bits differ ===\n", bit_err); |
| 112 | |
| 113 | OUTRO(len); |
| 114 | } |
| 115 | |
| 116 | static inline void buf_init(struct bitvec *dest, struct bitvec *dest_lh) |
| 117 | { |
| 118 | /* initialize buffer */ |
| 119 | bitvec_unhex(dest, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); |
| 120 | bitvec_unhex(dest_lh, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"); |
| 121 | } |
| 122 | |
| 123 | static inline void test_enc_ul_ass(struct bitvec *dest, struct bitvec *dest_lh, uint32_t fn, |
| 124 | uint8_t tfi, uint8_t gamma, uint8_t usf, bool tbf) |
| 125 | { |
| 126 | buf_init(dest, dest_lh); |
| 127 | |
| 128 | test_bitvec_ia_octet_encode_pkt_ul_ass(dest, fn, tfi, gamma, usf, tbf, false); |
| 129 | test_bitvec_ia_octet_encode_pkt_ul_ass(dest_lh, fn, tfi, gamma, usf, tbf, true); |
| 130 | |
| 131 | test_bitdiff(dest, dest_lh, 22); |
| 132 | } |
| 133 | |
| 134 | int main(int argc, char **argv) |
| 135 | { |
| 136 | void *tall_pcu_ctx; |
| 137 | struct bitvec *dest, *dest_lh; |
| 138 | uint8_t gamma = 0, ta_valid = 1, ws_enc = 3, usf = 1, tfi = 0; /* Temporary Flow Identity */ |
| 139 | uint32_t ttli = 0xdeadbeef, fn = 1234; |
| 140 | |
| 141 | tall_pcu_ctx = talloc_named_const(NULL, 1, "bitvecTest context"); |
| 142 | if (!tall_pcu_ctx) |
| 143 | return EXIT_FAILURE; |
| 144 | |
| 145 | dest = bitvec_alloc(22, tall_pcu_ctx); |
| 146 | dest_lh = bitvec_alloc(22, tall_pcu_ctx); |
| 147 | |
| 148 | buf_init(dest, dest_lh); |
| 149 | |
| 150 | test_bitvec_ia_octet_encode_pkt_dl_ass(dest, ttli, tfi, gamma, ta_valid, ws_enc, false); |
| 151 | test_bitvec_ia_octet_encode_pkt_dl_ass(dest_lh, ttli, tfi, gamma, ta_valid, ws_enc, true); |
| 152 | |
| 153 | test_bitdiff(dest, dest_lh, 22); |
| 154 | |
| 155 | test_enc_ul_ass(dest, dest_lh, fn, tfi, gamma, usf, false); |
| 156 | test_enc_ul_ass(dest, dest_lh, fn, tfi, gamma, usf, true); |
| 157 | |
| 158 | bitvec_free(dest); |
| 159 | bitvec_free(dest_lh); |
| 160 | |
| 161 | talloc_free(tall_pcu_ctx); |
| 162 | |
| 163 | return EXIT_SUCCESS; |
| 164 | } |