blob: 27d8fcc103fb70464ba67e9a6cfcd14dd097aa4b [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;
20
21int get_centisec_diff(void)
22{
23 struct timeval tv;
24 struct timeval now;
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +020025 osmo_gettimeofday(&now, NULL);
Harald Welte57e5b942012-09-07 10:23:44 +020026
27 timersub(&now, &tv_start, &tv);
28
29 return tv.tv_sec * 100 + tv.tv_usec/10000;
30}
31
32/* round to deciseconds to make sure test output is always consistent */
33int round_decisec(int csec_in)
34{
35 int tmp = csec_in / 10;
36
37 return tmp * 10;
38}
39
40static int fc_out_cb(struct bssgp_flow_control *fc, struct msgb *msg,
41 uint32_t llc_pdu_len, void *priv)
42{
43 unsigned int csecs = get_centisec_diff();
44 csecs = round_decisec(csecs);
45
Holger Hans Peter Freyther10dd73c2014-10-10 17:24:34 +020046 printf("%u: FC OUT Nr %lu\n", csecs, (unsigned long) msg->cb[0]);
47 msgb_free(msg);
Holger Hans Peter Freyther5b6416a2013-09-16 14:13:25 +020048 return 0;
Harald Welte57e5b942012-09-07 10:23:44 +020049}
50
51static int fc_in(struct bssgp_flow_control *fc, unsigned int pdu_len)
52{
Holger Hans Peter Freyther10dd73c2014-10-10 17:24:34 +020053 struct msgb *msg;
Harald Welte57e5b942012-09-07 10:23:44 +020054 unsigned int csecs = get_centisec_diff();
55 csecs = round_decisec(csecs);
56
Holger Hans Peter Freyther10dd73c2014-10-10 17:24:34 +020057 msg = msgb_alloc(1, "fc test");
58 msg->cb[0] = in_ctr++;
59
60 printf("%u: FC IN Nr %lu\n", csecs, msg->cb[0]);
61 bssgp_fc_in(fc, msg, pdu_len, NULL);
Holger Hans Peter Freyther5b6416a2013-09-16 14:13:25 +020062 return 0;
Harald Welte57e5b942012-09-07 10:23:44 +020063}
64
65
66static void test_fc(uint32_t bucket_size_max, uint32_t bucket_leak_rate,
67 uint32_t max_queue_depth, uint32_t pdu_len,
68 uint32_t pdu_count)
69{
70 struct bssgp_flow_control *fc = talloc_zero(NULL, struct bssgp_flow_control);
71 int i;
72
Neels Hofmeyr71320112017-02-06 14:39:53 +010073 osmo_gettimeofday_override_time = (struct timeval){
74 .tv_sec = 1486385000,
75 .tv_usec = 423423,
76 };
77 osmo_gettimeofday_override = true;
78
Harald Welte57e5b942012-09-07 10:23:44 +020079 bssgp_fc_init(fc, bucket_size_max, bucket_leak_rate, max_queue_depth,
80 fc_out_cb);
81
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +020082 osmo_gettimeofday(&tv_start, NULL);
Harald Welte57e5b942012-09-07 10:23:44 +020083
84 for (i = 0; i < pdu_count; i++) {
85 fc_in(fc, pdu_len);
86 osmo_timers_check();
87 osmo_timers_prepare();
88 osmo_timers_update();
89 }
90
91 while (1) {
Neels Hofmeyr71320112017-02-06 14:39:53 +010092 osmo_gettimeofday_override_add(0, 100000);
93
Harald Welte57e5b942012-09-07 10:23:44 +020094 osmo_timers_check();
95 osmo_timers_prepare();
96 osmo_timers_update();
97
98 if (llist_empty(&fc->queue))
99 break;
100 }
101}
102
103static void help(void)
104{
105 printf(" -h --help This help message\n");
106 printf(" -s --bucket-size-max N Maximum size of bucket in octets\n");
107 printf(" -r --bucket-leak-rate N Bucket leak rate in octets/sec\n");
108 printf(" -d --max-queue-depth N Maximum length of pending PDU queue (msgs)\n");
109 printf(" -l --pdu-length N Length of each PDU in octets\n");
110}
111
112int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
113{
114 return -1;
115}
116
117static struct log_info info = {};
118
119int main(int argc, char **argv)
120{
121 uint32_t bucket_size_max = 100; /* octets */
122 uint32_t bucket_leak_rate = 100; /* octets / second */
123 uint32_t max_queue_depth = 5; /* messages */
124 uint32_t pdu_length = 10; /* octets */
125 uint32_t pdu_count = 20; /* messages */
126 int c;
127
128 static const struct option long_options[] = {
129 { "bucket-size-max", 1, 0, 's' },
130 { "bucket-leak-rate", 1, 0, 'r' },
131 { "max-queue-depth", 1, 0, 'd' },
132 { "pdu-length", 1, 0, 'l' },
133 { "pdu-count", 1, 0, 'c' },
134 { "help", 0, 0, 'h' },
135 { 0, 0, 0, 0 }
136 };
137
138 osmo_init_logging(&info);
Holger Hans Peter Freytherc302eca2012-09-11 11:49:35 +0200139 log_set_use_color(osmo_stderr_target, 0);
140 log_set_print_filename(osmo_stderr_target, 0);
Harald Welte57e5b942012-09-07 10:23:44 +0200141
142 while ((c = getopt_long(argc, argv, "s:r:d:l:c:",
143 long_options, NULL)) != -1) {
144 switch (c) {
145 case 's':
146 bucket_size_max = atoi(optarg);
147 break;
148 case 'r':
149 bucket_leak_rate = atoi(optarg);
150 break;
151 case 'd':
152 max_queue_depth = atoi(optarg);
153 break;
154 case 'l':
155 pdu_length = atoi(optarg);
156 break;
157 case 'c':
158 pdu_count = atoi(optarg);
159 break;
160 case 'h':
161 help();
162 exit(EXIT_SUCCESS);
163 break;
164 default:
165 exit(EXIT_FAILURE);
166 }
167 }
168
169 /* bucket leak rate less than 100 not supported! */
170 if (bucket_leak_rate < 100) {
171 fprintf(stderr, "Bucket leak rate < 100 not supported!\n");
172 exit(EXIT_FAILURE);
173 }
174
175 printf("===== BSSGP flow-control test START\n");
176 printf("size-max=%u oct, leak-rate=%u oct/s, "
177 "queue-len=%u msgs, pdu_len=%u oct, pdu_cnt=%u\n\n", bucket_size_max,
178 bucket_leak_rate, max_queue_depth, pdu_length, pdu_count);
179 test_fc(bucket_size_max, bucket_leak_rate, max_queue_depth,
180 pdu_length, pdu_count);
181 printf("===== BSSGP flow-control test END\n\n");
182
183 exit(EXIT_SUCCESS);
184}