5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * hdlc_tests.c
|
|
5 *
|
|
6 * Written by Steve Underwood <steveu@coppice.org>
|
|
7 *
|
|
8 * Copyright (C) 2003 Steve Underwood
|
|
9 *
|
|
10 * All rights reserved.
|
|
11 *
|
|
12 * This program is free software; you can redistribute it and/or modify
|
|
13 * it under the terms of the GNU General Public License version 2, as
|
|
14 * published by the Free Software Foundation.
|
|
15 *
|
|
16 * This program is distributed in the hope that it will be useful,
|
|
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19 * GNU General Public License for more details.
|
|
20 *
|
|
21 * You should have received a copy of the GNU General Public License
|
|
22 * along with this program; if not, write to the Free Software
|
|
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
24 *
|
|
25 * $Id: hdlc_tests.c,v 1.30 2006/11/19 14:07:27 steveu Exp $
|
|
26 */
|
|
27
|
|
28 /*! \file */
|
|
29
|
|
30 /*! \page hdlc_tests_page HDLC tests
|
|
31 \section hdlc_tests_page_sec_1 What does it do?
|
|
32 The HDLC tests exercise the HDLC module, and verifies correct operation
|
|
33 using both 16 and 32 bit CRCs.
|
|
34 */
|
|
35
|
|
36 #ifdef HAVE_CONFIG_H
|
|
37 #include "config.h"
|
|
38 #endif
|
|
39
|
|
40 #include <stdio.h>
|
|
41 #include <inttypes.h>
|
|
42 #include <stdlib.h>
|
|
43 #include <string.h>
|
|
44 #if defined(HAVE_TGMATH_H)
|
|
45 #include <tgmath.h>
|
|
46 #endif
|
|
47 #if defined(HAVE_MATH_H)
|
|
48 #include <math.h>
|
|
49 #endif
|
|
50 #include <tiffio.h>
|
|
51
|
|
52 #include "spandsp.h"
|
|
53
|
|
54 int ref_len;
|
|
55 uint8_t buf[1000];
|
|
56
|
|
57 int frame_handled;
|
|
58 int frame_len_errors;
|
|
59 int frame_data_errors;
|
|
60 int underflow_reported;
|
|
61
|
|
62 hdlc_rx_state_t rx;
|
|
63 hdlc_tx_state_t tx;
|
|
64
|
|
65 int frames_sent;
|
|
66 int bytes_sent;
|
|
67 uint64_t start;
|
|
68 uint64_t end;
|
|
69
|
|
70 /* Use a local random generator, so the results are consistent across platforms. We have hard coded
|
|
71 correct results for a message sequence generated by this particular PRNG. */
|
|
72 static int my_rand(void)
|
|
73 {
|
|
74 static int rndnum = 1234567;
|
|
75
|
|
76 return (rndnum = 1664525U*rndnum + 1013904223U) >> 8;
|
|
77 }
|
|
78 /*- End of function --------------------------------------------------------*/
|
|
79
|
|
80 static int cook_up_msg(uint8_t *buf)
|
|
81 {
|
|
82 int i;
|
|
83 int len;
|
|
84
|
|
85 /* Use medium length messages, with some randomised length variation. */
|
|
86 /* TODO: this doesn't exercise extremely short or long messages. */
|
|
87 len = (my_rand() & 0x3F) + 100;
|
|
88 for (i = 0; i < len; i++)
|
|
89 buf[i] = my_rand();
|
|
90 return len;
|
|
91 }
|
|
92 /*- End of function --------------------------------------------------------*/
|
|
93
|
|
94 static void frame_handler(void *user_data, int ok, const uint8_t *pkt, int len)
|
|
95 {
|
|
96 if (len < 0)
|
|
97 {
|
|
98 /* Special conditions */
|
|
99 switch (len)
|
|
100 {
|
|
101 case PUTBIT_TRAINING_FAILED:
|
|
102 printf("Training failed\n");
|
|
103 break;
|
|
104 case PUTBIT_TRAINING_SUCCEEDED:
|
|
105 printf("Training succeeded\n");
|
|
106 break;
|
|
107 case PUTBIT_CARRIER_UP:
|
|
108 printf("Carrier up\n");
|
|
109 break;
|
|
110 case PUTBIT_CARRIER_DOWN:
|
|
111 printf("Carrier down\n");
|
|
112 break;
|
|
113 case PUTBIT_FRAMING_OK:
|
|
114 //printf("Framing OK\n");
|
|
115 break;
|
|
116 case PUTBIT_ABORT:
|
|
117 printf("Abort\n");
|
|
118 break;
|
|
119 default:
|
|
120 printf("Eh!\n");
|
|
121 break;
|
|
122 }
|
|
123 return;
|
|
124 }
|
|
125 if (len != ref_len)
|
|
126 {
|
|
127 printf("Len error - %d %d\n", len, ref_len);
|
|
128 frame_len_errors++;
|
|
129 return;
|
|
130 }
|
|
131 if (memcmp(pkt, buf, len))
|
|
132 {
|
|
133 printf("Frame data error\n");
|
|
134 frame_data_errors++;
|
|
135 return;
|
|
136 }
|
|
137 frame_handled = TRUE;
|
|
138 }
|
|
139 /*- End of function --------------------------------------------------------*/
|
|
140
|
|
141 static void underflow_handler(void *user_data)
|
|
142 {
|
|
143 //printf("Underflow reported\n");
|
|
144 underflow_reported = TRUE;
|
|
145 }
|
|
146 /*- End of function --------------------------------------------------------*/
|
|
147
|
|
148 static void check_result(void)
|
|
149 {
|
|
150 hdlc_rx_stats_t rx_stats;
|
|
151
|
|
152 hdlc_rx_get_stats(&rx, &rx_stats);
|
|
153 printf("%lu bytes\n", rx_stats.bytes);
|
|
154 printf("%lu good frames\n", rx_stats.good_frames);
|
|
155 printf("%lu CRC errors\n", rx_stats.crc_errors);
|
|
156 printf("%lu length errors\n", rx_stats.length_errors);
|
|
157 printf("%lu aborts\n", rx_stats.aborts);
|
|
158 printf("%d frame length errors\n", frame_len_errors);
|
|
159 printf("%d frame data errors\n", frame_data_errors);
|
|
160 printf("Test duration %" PRIu64 " ticks\n", end - start);
|
|
161 if (rx_stats.bytes != bytes_sent
|
|
162 ||
|
|
163 rx_stats.good_frames != frames_sent
|
|
164 ||
|
|
165 rx_stats.crc_errors != 0
|
|
166 ||
|
|
167 rx_stats.length_errors != 0
|
|
168 ||
|
|
169 rx_stats.aborts != 0
|
|
170 ||
|
|
171 frame_len_errors != 0
|
|
172 ||
|
|
173 frame_data_errors != 0)
|
|
174 {
|
|
175 printf("Tests failed.\n");
|
|
176 exit(2);
|
|
177 }
|
|
178 printf("Test passed.\n\n");
|
|
179 }
|
|
180 /*- End of function --------------------------------------------------------*/
|
|
181
|
|
182 int main(int argc, char *argv[])
|
|
183 {
|
|
184 int i;
|
|
185 int j;
|
|
186 int len;
|
|
187 int nextbyte;
|
|
188 int progress;
|
|
189 int progress_delay;
|
|
190
|
|
191 printf("HDLC module tests\n");
|
|
192
|
|
193 /* Try a few random messages through the CRC logic. */
|
|
194 printf("Testing the CRC-16 routines\n");
|
|
195 for (i = 0; i < 100; i++)
|
|
196 {
|
|
197 ref_len = cook_up_msg(buf);
|
|
198 len = crc_itu16_append(buf, ref_len);
|
|
199 if (!crc_itu16_check(buf, len))
|
|
200 {
|
|
201 printf("CRC-16 failure\n");
|
|
202 exit(2);
|
|
203 }
|
|
204 }
|
|
205 printf("Test passed.\n\n");
|
|
206
|
|
207 printf("Testing the CRC-32 routines\n");
|
|
208 for (i = 0; i < 100; i++)
|
|
209 {
|
|
210 ref_len = cook_up_msg(buf);
|
|
211 len = crc_itu32_append(buf, ref_len);
|
|
212 if (!crc_itu32_check(buf, len))
|
|
213 {
|
|
214 printf("CRC-32 failure\n");
|
|
215 exit(2);
|
|
216 }
|
|
217 }
|
|
218 printf("Test passed.\n\n");
|
|
219
|
|
220 /* Now try sending HDLC messages with CRC-16 */
|
|
221 printf("Testing with CRC-16 (byte by byte)\n");
|
|
222 frame_len_errors = 0;
|
|
223 frame_data_errors = 0;
|
|
224 hdlc_tx_init(&tx, FALSE, 1, FALSE, underflow_handler, NULL);
|
|
225 hdlc_rx_init(&rx, FALSE, FALSE, 5, frame_handler, NULL);
|
|
226 underflow_reported = FALSE;
|
|
227
|
|
228 start = rdtscll();
|
|
229 hdlc_tx_preamble(&tx, 40);
|
|
230 /* Push an initial message so we should NOT get an underflow after the preamble. */
|
|
231 ref_len = cook_up_msg(buf);
|
|
232 hdlc_tx_frame(&tx, buf, ref_len);
|
|
233 frame_handled = FALSE;
|
|
234 frames_sent = 0;
|
|
235 bytes_sent = 0;
|
|
236 for (i = 0; i < 1000000; i++)
|
|
237 {
|
|
238 nextbyte = hdlc_tx_get_byte(&tx);
|
|
239 hdlc_rx_put_byte(&rx, nextbyte);
|
|
240 if (underflow_reported)
|
|
241 {
|
|
242 underflow_reported = FALSE;
|
|
243 nextbyte = hdlc_tx_get_byte(&tx);
|
|
244 hdlc_rx_put_byte(&rx, nextbyte);
|
|
245 frames_sent++;
|
|
246 bytes_sent += ref_len;
|
|
247 if (!frame_handled)
|
|
248 {
|
|
249 printf("Frame not received.\n");
|
|
250 printf("Tests failed.\n");
|
|
251 exit(2);
|
|
252 }
|
|
253 ref_len = cook_up_msg(buf);
|
|
254 hdlc_tx_frame(&tx, buf, ref_len);
|
|
255 frame_handled = FALSE;
|
|
256 }
|
|
257 }
|
|
258 end = rdtscll();
|
|
259 check_result();
|
|
260
|
|
261 /* Now try sending HDLC messages with CRC-16 bit by bit */
|
|
262 printf("Testing with CRC-16 (bit by bit)\n");
|
|
263 frame_len_errors = 0;
|
|
264 frame_data_errors = 0;
|
|
265 hdlc_tx_init(&tx, FALSE, 2, FALSE, underflow_handler, NULL);
|
|
266 hdlc_rx_init(&rx, FALSE, FALSE, 5, frame_handler, NULL);
|
|
267 underflow_reported = FALSE;
|
|
268
|
|
269 start = rdtscll();
|
|
270 hdlc_tx_preamble(&tx, 40);
|
|
271 /* Don't push an initial message so we should get an underflow after the preamble. */
|
|
272 /* Lie for the first message, as there isn't really one */
|
|
273 frame_handled = TRUE;
|
|
274 frames_sent = 0;
|
|
275 bytes_sent = 0;
|
|
276 ref_len = 0;
|
|
277 for (i = 0; i < 8*1000000; i++)
|
|
278 {
|
|
279 nextbyte = hdlc_tx_get_bit(&tx);
|
|
280 hdlc_rx_put_bit(&rx, nextbyte);
|
|
281 if (underflow_reported)
|
|
282 {
|
|
283 underflow_reported = FALSE;
|
|
284 for (j = 0; j < 20; j++)
|
|
285 {
|
|
286 nextbyte = hdlc_tx_get_bit(&tx);
|
|
287 hdlc_rx_put_bit(&rx, nextbyte);
|
|
288 }
|
|
289 if (ref_len)
|
|
290 {
|
|
291 frames_sent++;
|
|
292 bytes_sent += ref_len;
|
|
293 }
|
|
294 if (!frame_handled)
|
|
295 {
|
|
296 printf("Frame not received.\n");
|
|
297 printf("Tests failed.\n");
|
|
298 exit(2);
|
|
299 }
|
|
300 ref_len = cook_up_msg(buf);
|
|
301 hdlc_tx_frame(&tx, buf, ref_len);
|
|
302 frame_handled = FALSE;
|
|
303 }
|
|
304 }
|
|
305 end = rdtscll();
|
|
306 check_result();
|
|
307
|
|
308 /* Now try sending HDLC messages with CRC-32 */
|
|
309 printf("Testing with CRC-32 (byte by byte)\n");
|
|
310 frame_len_errors = 0;
|
|
311 frame_data_errors = 0;
|
|
312 hdlc_tx_init(&tx, TRUE, 1, FALSE, underflow_handler, NULL);
|
|
313 hdlc_rx_init(&rx, TRUE, FALSE, 1, frame_handler, NULL);
|
|
314 underflow_reported = FALSE;
|
|
315
|
|
316 start = rdtscll();
|
|
317 hdlc_tx_preamble(&tx, 40);
|
|
318 /* Don't push an initial message so we should get an underflow after the preamble. */
|
|
319 /* Lie for the first message, as there isn't really one */
|
|
320 frame_handled = TRUE;
|
|
321 frames_sent = 0;
|
|
322 bytes_sent = 0;
|
|
323 ref_len = 0;
|
|
324 for (i = 0; i < 1000000; i++)
|
|
325 {
|
|
326 nextbyte = hdlc_tx_get_byte(&tx);
|
|
327 hdlc_rx_put_byte(&rx, nextbyte);
|
|
328 if (underflow_reported)
|
|
329 {
|
|
330 underflow_reported = FALSE;
|
|
331 nextbyte = hdlc_tx_get_byte(&tx);
|
|
332 hdlc_rx_put_byte(&rx, nextbyte);
|
|
333 if (ref_len)
|
|
334 {
|
|
335 frames_sent++;
|
|
336 bytes_sent += ref_len;
|
|
337 }
|
|
338 if (!frame_handled)
|
|
339 {
|
|
340 printf("Frame not received.\n");
|
|
341 printf("Tests failed.\n");
|
|
342 exit(2);
|
|
343 }
|
|
344 ref_len = cook_up_msg(buf);
|
|
345 hdlc_tx_frame(&tx, buf, ref_len);
|
|
346 frame_handled = FALSE;
|
|
347 }
|
|
348 }
|
|
349 end = rdtscll();
|
|
350 check_result();
|
|
351
|
|
352 /* Now try progressive mode with CRC-16 */
|
|
353 printf("Testing progressive mode with CRC-16 (byte by byte)\n");
|
|
354 frame_len_errors = 0;
|
|
355 frame_data_errors = 0;
|
|
356 hdlc_tx_init(&tx, TRUE, 1, TRUE, underflow_handler, NULL);
|
|
357 hdlc_rx_init(&rx, TRUE, FALSE, 1, frame_handler, NULL);
|
|
358 underflow_reported = FALSE;
|
|
359
|
|
360 start = rdtscll();
|
|
361 hdlc_tx_preamble(&tx, 40);
|
|
362 /* Don't push an initial message so we should get an underflow after the preamble. */
|
|
363 /* Lie for the first message, as there isn't really one */
|
|
364 frame_handled = TRUE;
|
|
365 progress = 9999;
|
|
366 progress_delay = 9999;
|
|
367 frames_sent = 0;
|
|
368 bytes_sent = 0;
|
|
369 ref_len = 0;
|
|
370 for (i = 0; i < 1000000; i++)
|
|
371 {
|
|
372 nextbyte = hdlc_tx_get_byte(&tx);
|
|
373 hdlc_rx_put_byte(&rx, nextbyte);
|
|
374 if (underflow_reported)
|
|
375 {
|
|
376 underflow_reported = FALSE;
|
|
377 nextbyte = hdlc_tx_get_byte(&tx);
|
|
378 hdlc_rx_put_byte(&rx, nextbyte);
|
|
379 if (ref_len)
|
|
380 {
|
|
381 frames_sent++;
|
|
382 bytes_sent += ref_len;
|
|
383 }
|
|
384 if (!frame_handled)
|
|
385 {
|
|
386 printf("Frame not received.\n");
|
|
387 printf("Tests failed.\n");
|
|
388 exit(2);
|
|
389 }
|
|
390 ref_len = cook_up_msg(buf);
|
|
391 hdlc_tx_frame(&tx, buf, 10);
|
|
392 progress = 10;
|
|
393 progress_delay = 8;
|
|
394 frame_handled = FALSE;
|
|
395 }
|
|
396 if (progress < ref_len && progress_delay-- <= 0)
|
|
397 {
|
|
398 if (hdlc_tx_frame(&tx, buf + progress, (progress + 10 <= ref_len) ? 10 : ref_len - progress) < 0)
|
|
399 {
|
|
400 printf("Failed to add progressively\n");
|
|
401 exit(2);
|
|
402 }
|
|
403 progress += 10;
|
|
404 progress_delay = 8;
|
|
405 }
|
|
406 }
|
|
407 end = rdtscll();
|
|
408 check_result();
|
|
409
|
|
410 printf("Tests passed.\n");
|
|
411 return 0;
|
|
412 }
|
|
413 /*- End of function --------------------------------------------------------*/
|
|
414 /*- End of file ------------------------------------------------------------*/
|