~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/tests/tcpip_test.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License as
 
6
 * published by the Free Software Foundation; either version 2 of the
 
7
 * License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
 * 02110-1301, USA.
 
18
 *
 
19
 * You can also choose to distribute this program under the terms of
 
20
 * the Unmodified Binary Distribution Licence (as given in the file
 
21
 * COPYING.UBDL), provided that you have satisfied its requirements.
 
22
 */
 
23
 
 
24
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
25
 
 
26
/** @file
 
27
 *
 
28
 * TCP/IP self-tests
 
29
 *
 
30
 */
 
31
 
 
32
/* Forcibly enable assertions */
 
33
#undef NDEBUG
 
34
 
 
35
#include <stdint.h>
 
36
#include <stdlib.h>
 
37
#include <string.h>
 
38
#include <assert.h>
 
39
#include <ipxe/test.h>
 
40
#include <ipxe/profile.h>
 
41
#include <ipxe/tcpip.h>
 
42
 
 
43
/** Number of sample iterations for profiling */
 
44
#define PROFILE_COUNT 16
 
45
 
 
46
/** A TCP/IP fixed-data test */
 
47
struct tcpip_test {
 
48
        /** Data */
 
49
        const void *data;
 
50
        /** Length of data */
 
51
        size_t len;
 
52
};
 
53
 
 
54
/** A TCP/IP pseudorandom-data test */
 
55
struct tcpip_random_test {
 
56
        /** Seed */
 
57
        unsigned int seed;
 
58
        /** Length of data */
 
59
        size_t len;
 
60
        /** Alignment offset */
 
61
        size_t offset;
 
62
};
 
63
 
 
64
/** Define inline data */
 
65
#define DATA(...) { __VA_ARGS__ }
 
66
 
 
67
/** Define a TCP/IP fixed-data test */
 
68
#define TCPIP_TEST( name, DATA )                                        \
 
69
        static const uint8_t __attribute__ (( aligned ( 16 ) ))         \
 
70
                name ## _data[] = DATA;                                 \
 
71
        static struct tcpip_test name = {                               \
 
72
                .data = name ## _data,                                  \
 
73
                .len = sizeof ( name ## _data ),                        \
 
74
        }
 
75
 
 
76
/** Define a TCP/IP pseudorandom-data test */
 
77
#define TCPIP_RANDOM_TEST( name, SEED, LEN, OFFSET )                    \
 
78
        static struct tcpip_random_test name = {                        \
 
79
                .seed = SEED,                                           \
 
80
                .len = LEN,                                             \
 
81
                .offset = OFFSET,                                       \
 
82
        }
 
83
 
 
84
/** Buffer for pseudorandom-data tests */
 
85
static uint8_t __attribute__ (( aligned ( 16 ) ))
 
86
        tcpip_data[ 4096 + 7 /* offset */ ];
 
87
 
 
88
/** Empty data */
 
89
TCPIP_TEST ( empty, DATA() );
 
90
 
 
91
/** Single byte */
 
92
TCPIP_TEST ( one_byte, DATA ( 0xeb ) );
 
93
 
 
94
/** Double byte */
 
95
TCPIP_TEST ( two_bytes, DATA ( 0xba, 0xbe ) );
 
96
 
 
97
/** Positive zero data */
 
98
TCPIP_TEST ( positive_zero, DATA ( 0x00, 0x00 ) );
 
99
 
 
100
/** Negative zero data */
 
101
TCPIP_TEST ( negative_zero, DATA ( 0xff, 0xff ) );
 
102
 
 
103
/** Final wrap-around carry (big-endian) */
 
104
TCPIP_TEST ( final_carry_big,
 
105
             DATA ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ) );
 
106
 
 
107
/** Final wrap-around carry (little-endian) */
 
108
TCPIP_TEST ( final_carry_little,
 
109
             DATA ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 ) );
 
110
 
 
111
/** Random data (aligned) */
 
112
TCPIP_RANDOM_TEST ( random_aligned, 0x12345678UL, 4096, 0 );
 
113
 
 
114
/** Random data (unaligned, +1) */
 
115
TCPIP_RANDOM_TEST ( random_unaligned_1, 0x12345678UL, 4096, 1 );
 
116
 
 
117
/** Random data (unaligned, +2) */
 
118
TCPIP_RANDOM_TEST ( random_unaligned_2, 0x12345678UL, 4096, 2 );
 
119
 
 
120
/** Random data (aligned, truncated) */
 
121
TCPIP_RANDOM_TEST ( random_aligned_truncated, 0x12345678UL, 4095, 0 );
 
122
 
 
123
/** Random data (unaligned start and finish) */
 
124
TCPIP_RANDOM_TEST ( partial, 0xcafebabe, 121, 5 );
 
125
 
 
126
/**
 
127
 * Calculate TCP/IP checksum
 
128
 *
 
129
 * @v data              Data to sum
 
130
 * @v len               Length of data
 
131
 * @ret cksum           Checksum
 
132
 *
 
133
 * This is a reference implementation taken from RFC1071 (and modified
 
134
 * to fix compilation without warnings under gcc).
 
135
 *
 
136
 * The initial value of the one's complement @c sum is changed from
 
137
 * positive zero (0x0000) to negative zero (0xffff).  This ensures
 
138
 * that the return value will always use the positive representation
 
139
 * of zero (0x0000).  Without this change, the return value would use
 
140
 * negative zero (0xffff) if the input data is zero length (or all
 
141
 * zeros) but positive zero (0x0000) for any other data which sums to
 
142
 * zero.
 
143
 */
 
144
static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) {
 
145
        unsigned long sum = 0xffff;
 
146
 
 
147
        while ( len > 1 )  {
 
148
                sum += *( ( uint16_t * ) data );
 
149
                data += 2;
 
150
                len -= 2;
 
151
        }
 
152
 
 
153
        if ( len > 0 )
 
154
                sum += *( ( uint8_t * ) data );
 
155
 
 
156
        while ( sum >> 16 )
 
157
                sum = ( ( sum & 0xffff ) + ( sum >> 16 ) );
 
158
 
 
159
        assert ( sum != 0x0000 );
 
160
        return ~sum;
 
161
}
 
162
 
 
163
/**
 
164
 * Report TCP/IP fixed-data test result
 
165
 *
 
166
 * @v test              TCP/IP test
 
167
 * @v file              Test code file
 
168
 * @v line              Test code line
 
169
 */
 
170
static void tcpip_okx ( struct tcpip_test *test, const char *file,
 
171
                        unsigned int line ) {
 
172
        uint16_t expected;
 
173
        uint16_t generic_sum;
 
174
        uint16_t sum;
 
175
 
 
176
        /* Verify generic_tcpip_continue_chksum() result */
 
177
        expected = rfc_tcpip_chksum ( test->data, test->len );
 
178
        generic_sum = generic_tcpip_continue_chksum ( TCPIP_EMPTY_CSUM,
 
179
                                                      test->data, test->len );
 
180
        okx ( generic_sum == expected, file, line );
 
181
 
 
182
        /* Verify optimised tcpip_continue_chksum() result */
 
183
        sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, test->data, test->len );
 
184
        okx ( sum == expected, file, line );
 
185
}
 
186
#define tcpip_ok( test ) tcpip_okx ( test, __FILE__, __LINE__ )
 
187
 
 
188
/**
 
189
 * Report TCP/IP pseudorandom-data test result
 
190
 *
 
191
 * @v test              TCP/IP test
 
192
 * @v file              Test code file
 
193
 * @v line              Test code line
 
194
 */
 
195
static void tcpip_random_okx ( struct tcpip_random_test *test,
 
196
                               const char *file, unsigned int line ) {
 
197
        uint8_t *data = ( tcpip_data + test->offset );
 
198
        struct profiler profiler;
 
199
        uint16_t expected;
 
200
        uint16_t generic_sum;
 
201
        uint16_t sum;
 
202
        unsigned int i;
 
203
 
 
204
        /* Sanity check */
 
205
        assert ( ( test->len + test->offset ) <= sizeof ( tcpip_data ) );
 
206
 
 
207
        /* Generate random data */
 
208
        srandom ( test->seed );
 
209
        for ( i = 0 ; i < test->len ; i++ )
 
210
                data[i] = random();
 
211
 
 
212
        /* Verify generic_tcpip_continue_chksum() result */
 
213
        expected = rfc_tcpip_chksum ( data, test->len );
 
214
        generic_sum = generic_tcpip_continue_chksum ( TCPIP_EMPTY_CSUM,
 
215
                                                      data, test->len );
 
216
        okx ( generic_sum == expected, file, line );
 
217
 
 
218
        /* Verify optimised tcpip_continue_chksum() result */
 
219
        sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, test->len );
 
220
        okx ( sum == expected, file, line );
 
221
 
 
222
        /* Profile optimised calculation */
 
223
        memset ( &profiler, 0, sizeof ( profiler ) );
 
224
        for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
 
225
                profile_start ( &profiler );
 
226
                sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data,
 
227
                                              test->len );
 
228
                profile_stop ( &profiler );
 
229
        }
 
230
        DBG ( "TCPIP checksummed %zd bytes (+%zd) in %ld +/- %ld ticks\n",
 
231
              test->len, test->offset, profile_mean ( &profiler ),
 
232
              profile_stddev ( &profiler ) );
 
233
}
 
234
#define tcpip_random_ok( test ) tcpip_random_okx ( test, __FILE__, __LINE__ )
 
235
 
 
236
/**
 
237
 * Perform TCP/IP self-tests
 
238
 *
 
239
 */
 
240
static void tcpip_test_exec ( void ) {
 
241
 
 
242
        tcpip_ok ( &empty );
 
243
        tcpip_ok ( &one_byte );
 
244
        tcpip_ok ( &two_bytes );
 
245
        tcpip_ok ( &positive_zero );
 
246
        tcpip_ok ( &negative_zero );
 
247
        tcpip_ok ( &final_carry_big );
 
248
        tcpip_ok ( &final_carry_little );
 
249
        tcpip_random_ok ( &random_aligned );
 
250
        tcpip_random_ok ( &random_unaligned_1 );
 
251
        tcpip_random_ok ( &random_unaligned_2 );
 
252
        tcpip_random_ok ( &random_aligned_truncated );
 
253
        tcpip_random_ok ( &partial );
 
254
}
 
255
 
 
256
/** TCP/IP self-test */
 
257
struct self_test tcpip_test __self_test = {
 
258
        .name = "tcpip",
 
259
        .exec = tcpip_test_exec,
 
260
};