blob: d77f141adb270fa4d9cb750cdf2f39990bf3275c [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
73 bssgp_fc_init(fc, bucket_size_max, bucket_leak_rate, max_queue_depth,
74 fc_out_cb);
75
Neels Hofmeyr8e2f7e82016-09-22 03:58:13 +020076 osmo_gettimeofday(&tv_start, NULL);
Harald Welte57e5b942012-09-07 10:23:44 +020077
78 for (i = 0; i < pdu_count; i++) {
79 fc_in(fc, pdu_len);
80 osmo_timers_check();
81 osmo_timers_prepare();
82 osmo_timers_update();
83 }
84
85 while (1) {
86 usleep(100000);
87 osmo_timers_check();
88 osmo_timers_prepare();
89 osmo_timers_update();
90
91 if (llist_empty(&fc->queue))
92 break;
93 }
94}
95
96static void help(void)
97{
98 printf(" -h --help This help message\n");
99 printf(" -s --bucket-size-max N Maximum size of bucket in octets\n");
100 printf(" -r --bucket-leak-rate N Bucket leak rate in octets/sec\n");
101 printf(" -d --max-queue-depth N Maximum length of pending PDU queue (msgs)\n");
102 printf(" -l --pdu-length N Length of each PDU in octets\n");
103}
104
105int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
106{
107 return -1;
108}
109
110static struct log_info info = {};
111
112int main(int argc, char **argv)
113{
114 uint32_t bucket_size_max = 100; /* octets */
115 uint32_t bucket_leak_rate = 100; /* octets / second */
116 uint32_t max_queue_depth = 5; /* messages */
117 uint32_t pdu_length = 10; /* octets */
118 uint32_t pdu_count = 20; /* messages */
119 int c;
120
121 static const struct option long_options[] = {
122 { "bucket-size-max", 1, 0, 's' },
123 { "bucket-leak-rate", 1, 0, 'r' },
124 { "max-queue-depth", 1, 0, 'd' },
125 { "pdu-length", 1, 0, 'l' },
126 { "pdu-count", 1, 0, 'c' },
127 { "help", 0, 0, 'h' },
128 { 0, 0, 0, 0 }
129 };
130
131 osmo_init_logging(&info);
Holger Hans Peter Freytherc302eca2012-09-11 11:49:35 +0200132 log_set_use_color(osmo_stderr_target, 0);
133 log_set_print_filename(osmo_stderr_target, 0);
Harald Welte57e5b942012-09-07 10:23:44 +0200134
135 while ((c = getopt_long(argc, argv, "s:r:d:l:c:",
136 long_options, NULL)) != -1) {
137 switch (c) {
138 case 's':
139 bucket_size_max = atoi(optarg);
140 break;
141 case 'r':
142 bucket_leak_rate = atoi(optarg);
143 break;
144 case 'd':
145 max_queue_depth = atoi(optarg);
146 break;
147 case 'l':
148 pdu_length = atoi(optarg);
149 break;
150 case 'c':
151 pdu_count = atoi(optarg);
152 break;
153 case 'h':
154 help();
155 exit(EXIT_SUCCESS);
156 break;
157 default:
158 exit(EXIT_FAILURE);
159 }
160 }
161
162 /* bucket leak rate less than 100 not supported! */
163 if (bucket_leak_rate < 100) {
164 fprintf(stderr, "Bucket leak rate < 100 not supported!\n");
165 exit(EXIT_FAILURE);
166 }
167
168 printf("===== BSSGP flow-control test START\n");
169 printf("size-max=%u oct, leak-rate=%u oct/s, "
170 "queue-len=%u msgs, pdu_len=%u oct, pdu_cnt=%u\n\n", bucket_size_max,
171 bucket_leak_rate, max_queue_depth, pdu_length, pdu_count);
172 test_fc(bucket_size_max, bucket_leak_rate, max_queue_depth,
173 pdu_length, pdu_count);
174 printf("===== BSSGP flow-control test END\n\n");
175
176 exit(EXIT_SUCCESS);
177}