summaryrefslogtreecommitdiffstats
path: root/tests/bits/bitfield_test.c
blob: d6653e329e94e2ed7696f24ad3465a5b87060888 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <inttypes.h>
#include <stdbool.h>
#include <errno.h>
#include <stdint.h>

#include <osmocom/core/utils.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/bitvec.h>

#define INTRO(p) printf("=== start %s(%u) ===\n", __func__, p)
#define OUTRO(p) printf("=== end %s(%u) ===\n\n", __func__, p)

static void test_bitvec_ia_octet_encode_pkt_dl_ass(struct bitvec *dest, uint32_t ttli,
						   uint8_t tfi, uint8_t gamma, uint8_t ta_valid, uint8_t ws_enc,
						   bool use_lh)
{
	unsigned wp = 0;

	INTRO(use_lh);

	/* 3GPP TS 44.018 §10.5.2.16 IA Rest Octets */
	if (use_lh) /* FIXME: add function to encode LH properly */
		bitvec_write_field(dest, &wp, 3, 2);		/* "HH" */
	else
		bitvec_write_field(dest, &wp, 3, 2);		/* "HH" */
	bitvec_write_field(dest, &wp, 1, 2);			/* "01" Packet Downlink Assignment */
	bitvec_write_field(dest, &wp, ttli, 32);		/* TLLI */
	bitvec_write_field(dest, &wp, 1, 1);			/* switch TFI: on */
	bitvec_write_field(dest, &wp, tfi, 5);			/* TFI */
	bitvec_write_field(dest, &wp, 0x0, 1);			/* RLC acknowledged mode */
	bitvec_write_field(dest, &wp, 0x0, 1);			/* ALPHA = not present */
	bitvec_write_field(dest, &wp, gamma, 5);		/* GAMMA power control parameter */
	bitvec_write_field(dest, &wp, 0,1);			/* Polling Bit: off */
	bitvec_write_field(dest, &wp, ta_valid, 1);		/* N. B: NOT related to TAI! */
	bitvec_write_field(dest, &wp, 0, 1);			/* No TIMING_ADVANCE_INDEX: */
	bitvec_write_field(dest, &wp, 0, 1);			/* TBF Starting TIME present */
	bitvec_write_field(dest, &wp, 0, 1);			/* P0 not present */
	if (use_lh) { /* FIXME: add function to encode LH properly */
		bitvec_write_field(dest, &wp, 1, 1);		/* "H" - additional for R99 */
	} else
		bitvec_write_field(dest, &wp, 1, 1);		/* "H" - additional for R99 */
	bitvec_write_field(dest, &wp, ws_enc, 5);		/* EGPRS Window Size */
	bitvec_write_field(dest, &wp, 0, 2);			/* LINK_QUALITY_MEASUREMENT_MODE */
	bitvec_write_field(dest, &wp, 0, 1);			/* BEP_PERIOD2 not present */

	printf("Encoded PKT DL ASS IA Rest Octets: %s\n", osmo_hexdump(dest->data, dest->data_len));

	OUTRO(use_lh);
}

static void test_bitvec_ia_octet_encode_pkt_ul_ass(struct bitvec *dest, uint32_t fn,
						   uint8_t tfi, uint8_t gamma, uint8_t usf, bool tbf, bool use_lh)
{
	unsigned wp = 0;

	INTRO(use_lh);

	/* 3GPP TS 44.018 §10.5.2.37b 10.5.2.16 */
	if (use_lh) /* FIXME: add function to encode LH properly */
		bitvec_write_field(dest, &wp, 3, 2);				/* "HH" */
	else
		bitvec_write_field(dest, &wp, 3, 2);				/* "HH" */
	bitvec_write_field(dest, &wp, 0, 2);					/* "0" Packet Uplink Assignment */
	if (!tbf) {
		bitvec_write_field(dest, &wp, 0, 1);				/* Block Allocation: SBA */
		bitvec_write_field(dest, &wp, 0, 1);				/* ALPHA = not present */
		bitvec_write_field(dest, &wp, gamma, 5);			/* GAMMA power control parameter */
		bitvec_write_field(dest, &wp, 0, 1);				/* No TIMING_ADVANCE_INDEX: */
		bitvec_write_field(dest, &wp, 1, 1); 				/* TBF_STARTING_TIME_FLAG */
		bitvec_write_field(dest, &wp, (fn / (26 * 51)) % 32, 5);	/* T1' */
		bitvec_write_field(dest, &wp, fn % 51, 6);			/* T3 */
		bitvec_write_field(dest, &wp, fn % 26, 5);			/* T2 */
	} else {
		bitvec_write_field(dest, &wp, 1, 1);				/* Block Allocation: Not SBA */
		bitvec_write_field(dest, &wp, tfi, 5);				/* TFI_ASSIGNMENT */
		bitvec_write_field(dest, &wp, 0, 1);				/* POLLING = none */
		bitvec_write_field(dest, &wp, 0, 1);				/* ALLOCATION_TYPE: dynamic */
		bitvec_write_field(dest, &wp, usf, 3);				/* USF */
		bitvec_write_field(dest, &wp, 0, 1);				/* USF_GRANULARITY */
		bitvec_write_field(dest, &wp, 0, 1);				/* "0" power control: Not Present */
		bitvec_write_field(dest, &wp, 0, 2);				/* CHANNEL_CODING_COMMAND */
		bitvec_write_field(dest, &wp, 1, 1);				/* TLLI_BLOCK_CHANNEL_CODING */
		bitvec_write_field(dest, &wp, 0, 1);				/* ALPHA = not present */
		bitvec_write_field(dest, &wp, gamma, 5);			/* GAMMA power control parameter */
		/* note: there is no choise for TAI and no starting time */
		bitvec_write_field(dest, &wp, 0, 1);				/* switch TIMING_ADVANCE_INDEX = off */
		bitvec_write_field(dest, &wp, 0, 1);				/* TBF_STARTING_TIME_FLAG */
	}

	printf("Encoded PKT UL ASS IA Rest Octets: %s\n", osmo_hexdump(dest->data, dest->data_len));

	OUTRO(use_lh);
}

static void test_bitdiff(const struct bitvec *src1, const struct bitvec *src2, unsigned len)
{
	unsigned int bit_err = 0, i, j;
	uint8_t byte_err = 0;

	INTRO(len);

	for (i = 0; i < len; i++) {
		/* byte compare */
		byte_err = src1->data[i] ^ src2->data[i];
		if (byte_err)
			for (j = 0; j < 8; j++)
				bit_err += (byte_err >> j) & 0x01; /* count bits which differ */
	}


	printf("=== total %u bits differ ===\n", bit_err);

	OUTRO(len);
}

static inline void buf_init(struct bitvec *dest, struct bitvec *dest_lh)
{
	/* initialize buffer */
	bitvec_unhex(dest, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
	bitvec_unhex(dest_lh, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
}

static inline void test_enc_ul_ass(struct bitvec *dest, struct bitvec *dest_lh, uint32_t fn,
				   uint8_t tfi, uint8_t gamma, uint8_t usf, bool tbf)
{
	buf_init(dest, dest_lh);

	test_bitvec_ia_octet_encode_pkt_ul_ass(dest, fn, tfi, gamma, usf, tbf, false);
	test_bitvec_ia_octet_encode_pkt_ul_ass(dest_lh, fn, tfi, gamma, usf, tbf, true);

	test_bitdiff(dest, dest_lh, 22);
}

int main(int argc, char **argv)
{
	void *tall_pcu_ctx;
	struct bitvec *dest, *dest_lh;
	uint8_t gamma = 0, ta_valid = 1, ws_enc = 3, usf = 1, tfi = 0; /* Temporary Flow Identity */
	uint32_t ttli = 0xdeadbeef, fn = 1234;

	tall_pcu_ctx = talloc_named_const(NULL, 1, "bitvecTest context");
	if (!tall_pcu_ctx)
		return EXIT_FAILURE;

	dest = bitvec_alloc(22, tall_pcu_ctx);
	dest_lh = bitvec_alloc(22, tall_pcu_ctx);

	buf_init(dest, dest_lh);

	test_bitvec_ia_octet_encode_pkt_dl_ass(dest, ttli, tfi, gamma, ta_valid, ws_enc, false);
	test_bitvec_ia_octet_encode_pkt_dl_ass(dest_lh, ttli, tfi, gamma, ta_valid, ws_enc, true);

	test_bitdiff(dest, dest_lh, 22);

	test_enc_ul_ass(dest, dest_lh, fn, tfi, gamma, usf, false);
	test_enc_ul_ass(dest, dest_lh, fn, tfi, gamma, usf, true);

	bitvec_free(dest);
	bitvec_free(dest_lh);

	talloc_free(tall_pcu_ctx);

	return EXIT_SUCCESS;
}