blob: d98636afc4d7c08417dddd796548aa459c2cea32 [file] [log] [blame]
Jacob Erlbeck626369c2015-06-15 11:04:25 +02001/*
2 * LlcTest.cpp
3 *
4 * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23extern "C" {
24 #include <osmocom/core/linuxlist.h>
25}
26
27#include "llc.h"
28#include "gprs_debug.h"
29
30extern "C" {
31#include "pcu_vty.h"
32
33#include <osmocom/core/application.h>
34#include <osmocom/core/msgb.h>
35#include <osmocom/core/talloc.h>
36#include <osmocom/core/utils.h>
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +010037#include <osmocom/core/timer.h>
Jacob Erlbeck626369c2015-06-15 11:04:25 +020038#include <osmocom/vty/vty.h>
39}
40
41
42void *tall_pcu_ctx;
43int16_t spoof_mnc = 0, spoof_mcc = 0;
Neels Hofmeyrbdc55fa2018-02-21 00:39:07 +010044bool spoof_mnc_3_digits = false;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +010045static struct timespec *clk_mono_override_time;
Jacob Erlbeck626369c2015-06-15 11:04:25 +020046
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020047static void enqueue_data(gprs_llc_queue *queue, const uint8_t *data, size_t len,
Pau Espin Pedrol1de68732020-03-11 14:04:52 +010048 const struct timespec *expire_time)
Jacob Erlbeck626369c2015-06-15 11:04:25 +020049{
Pau Espin Pedrol1de68732020-03-11 14:04:52 +010050 struct timespec *tv;
Jacob Erlbeck626369c2015-06-15 11:04:25 +020051 uint8_t *msg_data;
52 struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv) * 2,
53 "llc_pdu_queue");
54
Jacob Erlbeck626369c2015-06-15 11:04:25 +020055 msg_data = (uint8_t *)msgb_put(llc_msg, len);
56
57 memcpy(msg_data, data, len);
58
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +010059 queue->enqueue(llc_msg, expire_time);
Jacob Erlbeck626369c2015-06-15 11:04:25 +020060}
61
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020062static void dequeue_and_check(gprs_llc_queue *queue, const uint8_t *exp_data,
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010063 size_t len, const MetaInfo *exp_info)
Jacob Erlbeck626369c2015-06-15 11:04:25 +020064{
65 struct msgb *llc_msg;
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010066 const MetaInfo *info_res;
Jacob Erlbeck626369c2015-06-15 11:04:25 +020067
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020068 llc_msg = queue->dequeue(&info_res);
Jacob Erlbeck626369c2015-06-15 11:04:25 +020069 OSMO_ASSERT(llc_msg != NULL);
70
Neels Hofmeyrd34646a2017-02-08 17:07:40 +010071 fprintf(stderr, "dequeued msg, length %u (expected %zu), data %s\n",
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020072 msgb_length(llc_msg), len, msgb_hexdump(llc_msg));
Jacob Erlbeck626369c2015-06-15 11:04:25 +020073
Maxd3a0d912019-03-05 16:15:01 +010074 if (!msgb_eq_data_print(llc_msg, exp_data, len))
75 fprintf(stderr, "check failed!\n");
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020076
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +010077 if (exp_info) {
78 OSMO_ASSERT(memcmp(&exp_info->recv_time, &info_res->recv_time, sizeof(info_res->recv_time)) == 0);
79 OSMO_ASSERT(memcmp(&exp_info->expire_time, &info_res->expire_time, sizeof(info_res->expire_time)) == 0);
80 }
Jacob Erlbeck626369c2015-06-15 11:04:25 +020081 msgb_free(llc_msg);
82}
83
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020084static void enqueue_data(gprs_llc_queue *queue, const char *message,
Pau Espin Pedrol1de68732020-03-11 14:04:52 +010085 const struct timespec *expire_time)
Jacob Erlbeck626369c2015-06-15 11:04:25 +020086{
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +010087 enqueue_data(queue, (uint8_t *)(message), strlen(message), expire_time);
Jacob Erlbeck626369c2015-06-15 11:04:25 +020088}
89
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020090static void dequeue_and_check(gprs_llc_queue *queue, const char *exp_message,
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +010091 const MetaInfo *exp_info = 0)
Jacob Erlbeck626369c2015-06-15 11:04:25 +020092{
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +020093 dequeue_and_check(queue,
94 (uint8_t *)(exp_message), strlen(exp_message), exp_info);
Jacob Erlbeck626369c2015-06-15 11:04:25 +020095}
96
97static void test_llc_queue()
98{
99 gprs_llc_queue queue;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100100 struct timespec expire_time = {0};
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200101
102 printf("=== start %s ===\n", __func__);
103
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100104 llc_queue_init(&queue);
105 OSMO_ASSERT(llc_queue_size(&queue) == 0);
106 OSMO_ASSERT(llc_queue_octets(&queue) == 0);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200107
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100108 enqueue_data(&queue, "LLC message", &expire_time);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100109 OSMO_ASSERT(llc_queue_size(&queue) == 1);
110 OSMO_ASSERT(llc_queue_octets(&queue) == 11);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200111
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100112 enqueue_data(&queue, "other LLC message", &expire_time);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100113 OSMO_ASSERT(llc_queue_size(&queue) == 2);
114 OSMO_ASSERT(llc_queue_octets(&queue) == 28);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200115
116 dequeue_and_check(&queue, "LLC message");
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100117 OSMO_ASSERT(llc_queue_size(&queue) == 1);
118 OSMO_ASSERT(llc_queue_octets(&queue) == 17);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200119
120 dequeue_and_check(&queue, "other LLC message");
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100121 OSMO_ASSERT(llc_queue_size(&queue) == 0);
122 OSMO_ASSERT(llc_queue_octets(&queue) == 0);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200123
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100124 enqueue_data(&queue, "LLC", &expire_time);
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100125 OSMO_ASSERT(llc_queue_size(&queue) == 1);
126 OSMO_ASSERT(llc_queue_octets(&queue) == 3);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200127
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100128 llc_queue_clear(&queue, NULL);
129 OSMO_ASSERT(llc_queue_size(&queue) == 0);
130 OSMO_ASSERT(llc_queue_octets(&queue) == 0);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200131
132 printf("=== end %s ===\n", __func__);
133}
134
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +0200135static void test_llc_meta()
136{
137 gprs_llc_queue queue;
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100138 MetaInfo info1 = {0};
139 MetaInfo info2 = {0};
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +0200140
141 printf("=== start %s ===\n", __func__);
142
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100143 llc_queue_init(&queue);
144 OSMO_ASSERT(llc_queue_size(&queue) == 0);
145 OSMO_ASSERT(llc_queue_octets(&queue) == 0);
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +0200146
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100147 info1.recv_time.tv_sec = 123456777;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100148 info1.recv_time.tv_nsec = 123456000;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100149 info1.expire_time.tv_sec = 123456789;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100150 info1.expire_time.tv_nsec = 987654000;
151 *clk_mono_override_time = info1.recv_time;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100152 enqueue_data(&queue, "LLC message 1", &info1.expire_time);
153
Pau Espin Pedrol40d4e352020-03-11 13:06:13 +0100154 info2.recv_time.tv_sec = 123458000;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100155 info2.recv_time.tv_nsec = 547352000;
Pau Espin Pedrol40d4e352020-03-11 13:06:13 +0100156 info2.expire_time.tv_sec = 123458006;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100157 info2.expire_time.tv_nsec = 867252000;
158 *clk_mono_override_time = info2.recv_time;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100159 enqueue_data(&queue, "LLC message 2", &info2.expire_time);
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +0200160
161 dequeue_and_check(&queue, "LLC message 1", &info1);
162 dequeue_and_check(&queue, "LLC message 2", &info2);
163
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100164 llc_queue_clear(&queue, NULL);
165 OSMO_ASSERT(llc_queue_size(&queue) == 0);
166 OSMO_ASSERT(llc_queue_octets(&queue) == 0);
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +0200167
168 printf("=== end %s ===\n", __func__);
169}
170
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200171static void test_llc_merge()
172{
173 gprs_llc_queue queue1;
174 gprs_llc_queue queue2;
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100175 struct timespec expire_time = {0};
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200176
177 printf("=== start %s ===\n", __func__);
178
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100179 llc_queue_init(&queue1);
180 llc_queue_init(&queue2);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200181
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100182 clk_mono_override_time->tv_sec += 1;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100183 enqueue_data(&queue1, "*A*", &expire_time);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200184
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100185 clk_mono_override_time->tv_sec += 1;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100186 enqueue_data(&queue1, "*B*", &expire_time);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200187
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100188 clk_mono_override_time->tv_sec += 1;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100189 enqueue_data(&queue2, "*C*", &expire_time);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200190
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100191 clk_mono_override_time->tv_sec += 1;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100192 enqueue_data(&queue1, "*D*", &expire_time);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200193
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100194 clk_mono_override_time->tv_sec += 1;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100195 enqueue_data(&queue2, "*E*", &expire_time);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200196
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100197 OSMO_ASSERT(llc_queue_size(&queue1) == 3);
198 OSMO_ASSERT(llc_queue_octets(&queue1) == 9);
199 OSMO_ASSERT(llc_queue_size(&queue2) == 2);
200 OSMO_ASSERT(llc_queue_octets(&queue2) == 6);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200201
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100202 llc_queue_move_and_merge(&queue2, &queue1);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200203
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100204 OSMO_ASSERT(llc_queue_size(&queue1) == 0);
205 OSMO_ASSERT(llc_queue_octets(&queue1) == 0);
206 OSMO_ASSERT(llc_queue_size(&queue2) == 5);
207 OSMO_ASSERT(llc_queue_octets(&queue2) == 15);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200208
209 dequeue_and_check(&queue2, "*A*");
210 dequeue_and_check(&queue2, "*B*");
211 dequeue_and_check(&queue2, "*C*");
212 dequeue_and_check(&queue2, "*D*");
213 dequeue_and_check(&queue2, "*E*");
214
Pau Espin Pedrolda971ee2020-12-16 15:59:45 +0100215 OSMO_ASSERT(llc_queue_size(&queue2) == 0);
216 OSMO_ASSERT(llc_queue_octets(&queue2) == 0);
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200217
218 printf("=== end %s ===\n", __func__);
219}
220
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200221int main(int argc, char **argv)
222{
223 struct vty_app_info pcu_vty_info = {0};
224
225 tall_pcu_ctx = talloc_named_const(NULL, 1, "LlcTest context");
226 if (!tall_pcu_ctx)
227 abort();
228
Neels Hofmeyrd34646a2017-02-08 17:07:40 +0100229 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +0200230 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200231 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrol00f52cc2021-02-19 14:01:52 +0100232 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200233 log_set_log_level(osmo_stderr_target, LOGL_INFO);
Maxd3a0d912019-03-05 16:15:01 +0100234 log_parse_category_mask(osmo_stderr_target, "DPCU,3:DLGLOBAL,1:");
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200235
236 vty_init(&pcu_vty_info);
Pau Espin Pedrolcd2ac562019-08-05 14:30:44 +0200237 pcu_vty_init();
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200238
Pau Espin Pedrol1de68732020-03-11 14:04:52 +0100239 osmo_clock_override_enable(CLOCK_MONOTONIC, true);
240 clk_mono_override_time = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
241 clk_mono_override_time->tv_sec = 123456777;
242 clk_mono_override_time->tv_nsec = 123456000;
Pau Espin Pedrol5fc6e012020-02-26 20:05:33 +0100243
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200244 test_llc_queue();
Jacob Erlbeckb671dbf2015-06-15 14:32:33 +0200245 test_llc_meta();
Jacob Erlbeck257b6302015-08-21 18:07:47 +0200246 test_llc_merge();
Jacob Erlbeck626369c2015-06-15 11:04:25 +0200247
248 if (getenv("TALLOC_REPORT_FULL"))
249 talloc_report_full(tall_pcu_ctx, stderr);
250
251 return EXIT_SUCCESS;
252}
253
254extern "C" {
255void l1if_pdch_req() { abort(); }
256void l1if_connect_pdch() { abort(); }
257void l1if_close_pdch() { abort(); }
258void l1if_open_pdch() { abort(); }
259}