blob: 64e4b4eba22e3a1c22c01a155344e6831fab55e7 [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;
25 gettimeofday(&now, NULL);
26
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
46 printf("%u: FC OUT Nr %lu\n", csecs, (unsigned long) msg);
Holger Hans Peter Freyther5b6416a2013-09-16 14:13:25 +020047 return 0;
Harald Welte57e5b942012-09-07 10:23:44 +020048}
49
50static int fc_in(struct bssgp_flow_control *fc, unsigned int pdu_len)
51{
52 unsigned int csecs = get_centisec_diff();
53 csecs = round_decisec(csecs);
54
55 printf("%u: FC IN Nr %lu\n", csecs, in_ctr);
56 bssgp_fc_in(fc, (struct msgb *) in_ctr, pdu_len, NULL);
57 in_ctr++;
Holger Hans Peter Freyther5b6416a2013-09-16 14:13:25 +020058 return 0;
Harald Welte57e5b942012-09-07 10:23:44 +020059}
60
61
62static void test_fc(uint32_t bucket_size_max, uint32_t bucket_leak_rate,
63 uint32_t max_queue_depth, uint32_t pdu_len,
64 uint32_t pdu_count)
65{
66 struct bssgp_flow_control *fc = talloc_zero(NULL, struct bssgp_flow_control);
67 int i;
68
69 bssgp_fc_init(fc, bucket_size_max, bucket_leak_rate, max_queue_depth,
70 fc_out_cb);
71
72 gettimeofday(&tv_start, NULL);
73
74 for (i = 0; i < pdu_count; i++) {
75 fc_in(fc, pdu_len);
76 osmo_timers_check();
77 osmo_timers_prepare();
78 osmo_timers_update();
79 }
80
81 while (1) {
82 usleep(100000);
83 osmo_timers_check();
84 osmo_timers_prepare();
85 osmo_timers_update();
86
87 if (llist_empty(&fc->queue))
88 break;
89 }
90}
91
92static void help(void)
93{
94 printf(" -h --help This help message\n");
95 printf(" -s --bucket-size-max N Maximum size of bucket in octets\n");
96 printf(" -r --bucket-leak-rate N Bucket leak rate in octets/sec\n");
97 printf(" -d --max-queue-depth N Maximum length of pending PDU queue (msgs)\n");
98 printf(" -l --pdu-length N Length of each PDU in octets\n");
99}
100
101int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
102{
103 return -1;
104}
105
106static struct log_info info = {};
107
108int main(int argc, char **argv)
109{
110 uint32_t bucket_size_max = 100; /* octets */
111 uint32_t bucket_leak_rate = 100; /* octets / second */
112 uint32_t max_queue_depth = 5; /* messages */
113 uint32_t pdu_length = 10; /* octets */
114 uint32_t pdu_count = 20; /* messages */
115 int c;
116
117 static const struct option long_options[] = {
118 { "bucket-size-max", 1, 0, 's' },
119 { "bucket-leak-rate", 1, 0, 'r' },
120 { "max-queue-depth", 1, 0, 'd' },
121 { "pdu-length", 1, 0, 'l' },
122 { "pdu-count", 1, 0, 'c' },
123 { "help", 0, 0, 'h' },
124 { 0, 0, 0, 0 }
125 };
126
127 osmo_init_logging(&info);
Holger Hans Peter Freytherc302eca2012-09-11 11:49:35 +0200128 log_set_use_color(osmo_stderr_target, 0);
129 log_set_print_filename(osmo_stderr_target, 0);
Harald Welte57e5b942012-09-07 10:23:44 +0200130
131 while ((c = getopt_long(argc, argv, "s:r:d:l:c:",
132 long_options, NULL)) != -1) {
133 switch (c) {
134 case 's':
135 bucket_size_max = atoi(optarg);
136 break;
137 case 'r':
138 bucket_leak_rate = atoi(optarg);
139 break;
140 case 'd':
141 max_queue_depth = atoi(optarg);
142 break;
143 case 'l':
144 pdu_length = atoi(optarg);
145 break;
146 case 'c':
147 pdu_count = atoi(optarg);
148 break;
149 case 'h':
150 help();
151 exit(EXIT_SUCCESS);
152 break;
153 default:
154 exit(EXIT_FAILURE);
155 }
156 }
157
158 /* bucket leak rate less than 100 not supported! */
159 if (bucket_leak_rate < 100) {
160 fprintf(stderr, "Bucket leak rate < 100 not supported!\n");
161 exit(EXIT_FAILURE);
162 }
163
164 printf("===== BSSGP flow-control test START\n");
165 printf("size-max=%u oct, leak-rate=%u oct/s, "
166 "queue-len=%u msgs, pdu_len=%u oct, pdu_cnt=%u\n\n", bucket_size_max,
167 bucket_leak_rate, max_queue_depth, pdu_length, pdu_count);
168 test_fc(bucket_size_max, bucket_leak_rate, max_queue_depth,
169 pdu_length, pdu_count);
170 printf("===== BSSGP flow-control test END\n\n");
171
172 exit(EXIT_SUCCESS);
173}