blob: 63e8308a18fd9b520e4698538100b6e17d239028 [file] [log] [blame]
Harald Welte57e5b942012-09-07 10:23:44 +02001/* test routines for BSSGP flow control implementation in libosmogb
2 * (C) 2012 by Harald Welte <laforge@gnumonks.org>
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <stdint.h>
8#include <string.h>
9#include <getopt.h>
Holger Hans Peter Freyther5b6416a2013-09-16 14:13:25 +020010#include <unistd.h>
Harald Welte57e5b942012-09-07 10:23:44 +020011
Holger Hans Peter Freytherc302eca2012-09-11 11:49:35 +020012#include <osmocom/core/application.h>
Harald Welte57e5b942012-09-07 10:23:44 +020013#include <osmocom/core/utils.h>
14#include <osmocom/core/logging.h>
15#include <osmocom/core/talloc.h>
16#include <osmocom/gprs/gprs_bssgp.h>
17
18static unsigned long in_ctr = 1;
19static struct timeval tv_start;
Neels Hofmeyra829b452018-04-05 03:02:35 +020020void *ctx = NULL;
Harald Welte57e5b942012-09-07 10:23:44 +020021
22int get_centisec_diff(void)
23{
24 struct timeval tv;
25 struct timeval now;
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +020026 osmo_gettimeofday(&now, NULL);
Harald Welte57e5b942012-09-07 10:23:44 +020027
28 timersub(&now, &tv_start, &tv);
29
30 return tv.tv_sec * 100 + tv.tv_usec/10000;
31}
32
Harald Welte57e5b942012-09-07 10:23:44 +020033static int fc_out_cb(struct bssgp_flow_control *fc, struct msgb *msg,
34 uint32_t llc_pdu_len, void *priv)
35{
36 unsigned int csecs = get_centisec_diff();
Harald Welte57e5b942012-09-07 10:23:44 +020037
Holger Hans Peter Freyther10dd73c2014-10-10 17:24:34 +020038 printf("%u: FC OUT Nr %lu\n", csecs, (unsigned long) msg->cb[0]);
39 msgb_free(msg);
Holger Hans Peter Freyther5b6416a2013-09-16 14:13:25 +020040 return 0;
Harald Welte57e5b942012-09-07 10:23:44 +020041}
42
Neels Hofmeyr9541a682017-11-16 22:55:02 +010043static void fc_in(struct bssgp_flow_control *fc, unsigned int pdu_len)
Harald Welte57e5b942012-09-07 10:23:44 +020044{
Holger Hans Peter Freyther10dd73c2014-10-10 17:24:34 +020045 struct msgb *msg;
Harald Welte57e5b942012-09-07 10:23:44 +020046 unsigned int csecs = get_centisec_diff();
Neels Hofmeyr9541a682017-11-16 22:55:02 +010047 int rc;
Harald Welte57e5b942012-09-07 10:23:44 +020048
Holger Hans Peter Freyther10dd73c2014-10-10 17:24:34 +020049 msg = msgb_alloc(1, "fc test");
50 msg->cb[0] = in_ctr++;
51
52 printf("%u: FC IN Nr %lu\n", csecs, msg->cb[0]);
Neels Hofmeyr9541a682017-11-16 22:55:02 +010053 rc = bssgp_fc_in(fc, msg, pdu_len, NULL);
54 switch (rc) {
55 case 0:
56 printf(" -> %d: ok\n", rc);
57 break;
58 case -ENOSPC:
59 printf(" -> %d: queue full, msg dropped.\n", rc);
60 break;
61 case -EIO:
62 printf(" -> %d: PDU too large, msg dropped.\n", rc);
63 break;
64 default:
65 printf(" -> %d: error, msg dropped.\n", rc);
66 break;
67 }
Harald Welte57e5b942012-09-07 10:23:44 +020068}
69
70
71static void test_fc(uint32_t bucket_size_max, uint32_t bucket_leak_rate,
72 uint32_t max_queue_depth, uint32_t pdu_len,
73 uint32_t pdu_count)
74{
Neels Hofmeyra829b452018-04-05 03:02:35 +020075 struct bssgp_flow_control *fc = talloc_zero(ctx, struct bssgp_flow_control);
Harald Welte57e5b942012-09-07 10:23:44 +020076 int i;
77
Neels Hofmeyr71320112017-02-06 14:39:53 +010078 osmo_gettimeofday_override_time = (struct timeval){
79 .tv_sec = 1486385000,
80 .tv_usec = 423423,
81 };
82 osmo_gettimeofday_override = true;
83
Harald Welte57e5b942012-09-07 10:23:44 +020084 bssgp_fc_init(fc, bucket_size_max, bucket_leak_rate, max_queue_depth,
85 fc_out_cb);
86
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +020087 osmo_gettimeofday(&tv_start, NULL);
Harald Welte57e5b942012-09-07 10:23:44 +020088
Neels Hofmeyr9541a682017-11-16 22:55:02 +010089 /* Fill the queue with PDUs, possibly beyond the queue being full. If it is full, additional PDUs
90 * are discarded. */
Harald Welte57e5b942012-09-07 10:23:44 +020091 for (i = 0; i < pdu_count; i++) {
92 fc_in(fc, pdu_len);
93 osmo_timers_check();
94 osmo_timers_prepare();
95 osmo_timers_update();
96 }
97
98 while (1) {
Neels Hofmeyr71320112017-02-06 14:39:53 +010099 osmo_gettimeofday_override_add(0, 100000);
100
Harald Welte57e5b942012-09-07 10:23:44 +0200101 osmo_timers_check();
102 osmo_timers_prepare();
103 osmo_timers_update();
104
105 if (llist_empty(&fc->queue))
106 break;
107 }
Neels Hofmeyr85f5a2c2017-11-16 22:31:57 +0100108
109 talloc_free(fc);
Harald Welte57e5b942012-09-07 10:23:44 +0200110}
111
112static void help(void)
113{
114 printf(" -h --help This help message\n");
115 printf(" -s --bucket-size-max N Maximum size of bucket in octets\n");
116 printf(" -r --bucket-leak-rate N Bucket leak rate in octets/sec\n");
117 printf(" -d --max-queue-depth N Maximum length of pending PDU queue (msgs)\n");
118 printf(" -l --pdu-length N Length of each PDU in octets\n");
119}
120
121int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
122{
123 return -1;
124}
125
126static struct log_info info = {};
127
128int main(int argc, char **argv)
129{
130 uint32_t bucket_size_max = 100; /* octets */
131 uint32_t bucket_leak_rate = 100; /* octets / second */
132 uint32_t max_queue_depth = 5; /* messages */
133 uint32_t pdu_length = 10; /* octets */
134 uint32_t pdu_count = 20; /* messages */
135 int c;
Neels Hofmeyr0128c782017-11-16 22:32:36 +0100136 void *tall_msgb_ctx;
Neels Hofmeyra829b452018-04-05 03:02:35 +0200137 ctx = talloc_named_const(NULL, 0, "bssgp_fc_test");
Harald Welte57e5b942012-09-07 10:23:44 +0200138
139 static const struct option long_options[] = {
140 { "bucket-size-max", 1, 0, 's' },
141 { "bucket-leak-rate", 1, 0, 'r' },
142 { "max-queue-depth", 1, 0, 'd' },
143 { "pdu-length", 1, 0, 'l' },
144 { "pdu-count", 1, 0, 'c' },
145 { "help", 0, 0, 'h' },
146 { 0, 0, 0, 0 }
147 };
148
Neels Hofmeyra829b452018-04-05 03:02:35 +0200149 osmo_init_logging2(ctx, &info);
Holger Hans Peter Freytherc302eca2012-09-11 11:49:35 +0200150 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrol01e0d3e2021-02-18 19:25:44 +0100151 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
Pau Espin Pedrol690b6612021-02-18 19:10:28 +0100152 log_set_print_category(osmo_stderr_target, 0);
153 log_set_print_category_hex(osmo_stderr_target, 0);
Harald Welte57e5b942012-09-07 10:23:44 +0200154
Neels Hofmeyra829b452018-04-05 03:02:35 +0200155 tall_msgb_ctx = msgb_talloc_ctx_init(ctx, 0);
Neels Hofmeyr0128c782017-11-16 22:32:36 +0100156
Harald Welte57e5b942012-09-07 10:23:44 +0200157 while ((c = getopt_long(argc, argv, "s:r:d:l:c:",
158 long_options, NULL)) != -1) {
159 switch (c) {
160 case 's':
161 bucket_size_max = atoi(optarg);
162 break;
163 case 'r':
164 bucket_leak_rate = atoi(optarg);
165 break;
166 case 'd':
167 max_queue_depth = atoi(optarg);
168 break;
169 case 'l':
170 pdu_length = atoi(optarg);
171 break;
172 case 'c':
173 pdu_count = atoi(optarg);
174 break;
175 case 'h':
176 help();
177 exit(EXIT_SUCCESS);
178 break;
179 default:
180 exit(EXIT_FAILURE);
181 }
182 }
183
184 /* bucket leak rate less than 100 not supported! */
185 if (bucket_leak_rate < 100) {
186 fprintf(stderr, "Bucket leak rate < 100 not supported!\n");
187 exit(EXIT_FAILURE);
188 }
189
190 printf("===== BSSGP flow-control test START\n");
191 printf("size-max=%u oct, leak-rate=%u oct/s, "
192 "queue-len=%u msgs, pdu_len=%u oct, pdu_cnt=%u\n\n", bucket_size_max,
193 bucket_leak_rate, max_queue_depth, pdu_length, pdu_count);
194 test_fc(bucket_size_max, bucket_leak_rate, max_queue_depth,
195 pdu_length, pdu_count);
Neels Hofmeyr0128c782017-11-16 22:32:36 +0100196 printf("msgb ctx: %zu b in %zu blocks (0 b in 1 block == just the context)\n",
197 talloc_total_size(tall_msgb_ctx),
198 talloc_total_blocks(tall_msgb_ctx));
Neels Hofmeyrcd325ef2017-11-16 22:32:36 +0100199 OSMO_ASSERT(talloc_total_size(tall_msgb_ctx) == 0);
200 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Neels Hofmeyr0128c782017-11-16 22:32:36 +0100201 talloc_free(tall_msgb_ctx);
Harald Welte57e5b942012-09-07 10:23:44 +0200202 printf("===== BSSGP flow-control test END\n\n");
203
204 exit(EXIT_SUCCESS);
205}