Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2023 Stephen Hemminger
3 : : */
4 : :
5 : : #include <rte_ether.h>
6 : : #include <rte_mbuf.h>
7 : : #include <rte_mempool.h>
8 : :
9 : : #include <rte_test.h>
10 : : #include "test.h"
11 : :
12 : : #define N 1000000
13 : :
14 : : static const struct rte_ether_addr zero_ea;
15 : : static const struct rte_ether_addr bcast_ea = {
16 : : .addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
17 : : };
18 : :
19 : : static struct rte_mempool *net_ether_test_pool;
20 : :
21 : : static int
22 : 1 : test_ether_addr(void)
23 : : {
24 : 1 : struct rte_ether_addr rand_ea = { };
25 : : unsigned int i;
26 : :
27 : : RTE_TEST_ASSERT(rte_is_zero_ether_addr(&zero_ea), "Zero address is not zero");
28 : : RTE_TEST_ASSERT(!rte_is_zero_ether_addr(&bcast_ea), "Broadcast is zero");
29 : :
30 [ + + ]: 1000001 : for (i = 0; i < N; i++) {
31 : 1000000 : rte_eth_random_addr(rand_ea.addr_bytes);
32 [ - + ]: 1000000 : RTE_TEST_ASSERT(!rte_is_zero_ether_addr(&rand_ea),
33 : : "Random address is zero");
34 [ - + ]: 1000000 : RTE_TEST_ASSERT(rte_is_unicast_ether_addr(&rand_ea),
35 : : "Random address is not unicast");
36 [ - + ]: 1000000 : RTE_TEST_ASSERT(rte_is_local_admin_ether_addr(&rand_ea),
37 : : "Random address is not local admin");
38 : : }
39 : :
40 : : return 0;
41 : : }
42 : :
43 : : static int
44 : 1 : test_format_addr(void)
45 : : {
46 : 1 : struct rte_ether_addr rand_ea = { };
47 : : char buf[RTE_ETHER_ADDR_FMT_SIZE];
48 : : unsigned int i;
49 : :
50 [ + + ]: 1000001 : for (i = 0; i < N; i++) {
51 : 1000000 : struct rte_ether_addr result = { };
52 : : int ret;
53 : :
54 : 1000000 : rte_eth_random_addr(rand_ea.addr_bytes);
55 : :
56 : 1000000 : rte_ether_format_addr(buf, sizeof(buf), &rand_ea);
57 : :
58 : 1000000 : ret = rte_ether_unformat_addr(buf, &result);
59 [ - + ]: 1000000 : if (ret != 0) {
60 : 0 : fprintf(stderr, "rte_ether_unformat_addr(%s) failed\n", buf);
61 : 0 : return -1;
62 : : }
63 [ - + ]: 1000000 : RTE_TEST_ASSERT(rte_is_same_ether_addr(&rand_ea, &result),
64 : : "rte_ether_format/unformat mismatch");
65 : : }
66 : : return 0;
67 : :
68 : : }
69 : :
70 : : static int
71 : 1 : test_unformat_addr(void)
72 : : {
73 : : const struct rte_ether_addr expected = {
74 : : .addr_bytes = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc },
75 : : };
76 : : const struct rte_ether_addr nozero_ea = {
77 : : .addr_bytes = { 1, 2, 3, 4, 5, 6 },
78 : : };
79 : : struct rte_ether_addr result;
80 : : int ret;
81 : :
82 : : /* Test IETF format */
83 : : memset(&result, 0, sizeof(result));
84 : 1 : ret = rte_ether_unformat_addr("12:34:56:78:9a:bc", &result);
85 [ - + ]: 1 : RTE_TEST_ASSERT(ret == 0, "IETF unformat failed");
86 [ - + ]: 1 : RTE_TEST_ASSERT(rte_is_same_ether_addr(&expected, &result),
87 : : "IETF unformat mismatch");
88 : :
89 : : /* Test IEEE format */
90 : : memset(&result, 0, sizeof(result));
91 : 1 : ret = rte_ether_unformat_addr("12-34-56-78-9A-BC", &result);
92 [ - + ]: 1 : RTE_TEST_ASSERT(ret == 0, "IEEE unformat failed");
93 [ - + ]: 1 : RTE_TEST_ASSERT(rte_is_same_ether_addr(&expected, &result),
94 : : "IEEE unformat mismatch");
95 : :
96 : : /* Test Cisco format */
97 : : memset(&result, 0, sizeof(result));
98 : 1 : ret = rte_ether_unformat_addr("1234.5678.9ABC", &result);
99 [ - + ]: 1 : RTE_TEST_ASSERT(ret == 0, "Cisco unformat failed");
100 [ - + ]: 1 : RTE_TEST_ASSERT(rte_is_same_ether_addr(&expected, &result),
101 : : "Cisco unformat mismatch");
102 : :
103 : : /* Test no leading zeros - IETF */
104 : : memset(&result, 0, sizeof(result));
105 : 1 : ret = rte_ether_unformat_addr("1:2:3:4:5:6", &result);
106 [ - + ]: 1 : RTE_TEST_ASSERT(ret == 0, "IETF leading zero failed");
107 [ - + ]: 1 : RTE_TEST_ASSERT(rte_is_same_ether_addr(&nozero_ea, &result),
108 : : "IETF leading zero mismatch");
109 : :
110 : : /* Test no-leading zero - IEEE format */
111 : : memset(&result, 0, sizeof(result));
112 : 1 : ret = rte_ether_unformat_addr("1-2-3-4-5-6", &result);
113 [ - + ]: 1 : RTE_TEST_ASSERT(ret == 0, "IEEE leading zero failed");
114 [ - + ]: 1 : RTE_TEST_ASSERT(rte_is_same_ether_addr(&nozero_ea, &result),
115 : : "IEEE leading zero mismatch");
116 : :
117 : :
118 : : return 0;
119 : : }
120 : :
121 : : static int
122 : 1 : test_invalid_addr(void)
123 : : {
124 : : static const char * const invalid[] = {
125 : : "123",
126 : : "123:456",
127 : : "12:34:56:78:9a:gh",
128 : : "12:34:56:78:9a",
129 : : "100:34:56:78:9a:bc",
130 : : "34-56-78-9a-bc",
131 : : "12:34:56-78:9a:bc",
132 : : "12:34:56.78:9a:bc",
133 : : "123:456:789:abc",
134 : : "NOT.AN.ADDRESS",
135 : : "102.304.506",
136 : : "",
137 : : };
138 : : struct rte_ether_addr result;
139 : : unsigned int i;
140 : :
141 [ + + ]: 13 : for (i = 0; i < RTE_DIM(invalid); ++i) {
142 [ - + ]: 12 : if (!rte_ether_unformat_addr(invalid[i], &result)) {
143 : 0 : fprintf(stderr, "rte_ether_unformat_addr(%s) succeeded!\n",
144 : : invalid[i]);
145 : 0 : return -1;
146 : : }
147 : : }
148 : : return 0;
149 : : }
150 : :
151 : : /*
152 : : * Build a minimal Ethernet frame in an mbuf: Ethernet header with the given
153 : : * ether_type followed by payload_len bytes of padding.
154 : : */
155 : : static struct rte_mbuf *
156 : 2 : alloc_frame(struct rte_mempool *mp, uint16_t ether_type, uint16_t payload_len)
157 : : {
158 : : struct rte_ether_hdr *eh;
159 : : struct rte_mbuf *m;
160 : :
161 : 2 : m = rte_pktmbuf_alloc(mp);
162 [ + - ]: 2 : if (m == NULL)
163 : : return NULL;
164 : :
165 : : eh = (struct rte_ether_hdr *)rte_pktmbuf_append(m,
166 : 2 : sizeof(*eh) + payload_len);
167 [ - + ]: 2 : if (eh == NULL) {
168 : 0 : rte_pktmbuf_free(m);
169 : 0 : return NULL;
170 : : }
171 : :
172 [ - + ]: 2 : memset(eh->dst_addr.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN);
173 : 2 : memset(eh->src_addr.addr_bytes, 0x00, RTE_ETHER_ADDR_LEN);
174 [ - + ]: 2 : eh->ether_type = rte_cpu_to_be_16(ether_type);
175 : :
176 : 2 : return m;
177 : : }
178 : :
179 : : static int
180 : 1 : test_vlan_insert_8021q(void)
181 : : {
182 : : struct rte_ether_hdr *eh;
183 : : struct rte_vlan_hdr *vh;
184 : : struct rte_mbuf *m;
185 : : int ret;
186 : :
187 : 1 : m = alloc_frame(net_ether_test_pool, RTE_ETHER_TYPE_IPV4, 46);
188 [ - + ]: 1 : TEST_ASSERT_NOT_NULL(m, "Failed to allocate mbuf");
189 : :
190 : 1 : m->vlan_tci = 100;
191 : 1 : m->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
192 : :
193 : : ret = rte_vlan_insert(&m);
194 [ - + ]: 1 : TEST_ASSERT_SUCCESS(ret, "rte_vlan_insert failed");
195 : :
196 : 1 : eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
197 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(eh->ether_type), RTE_ETHER_TYPE_VLAN,
- - ]
198 : : "Expected 802.1Q TPID 0x%04x, got 0x%04x",
199 : : RTE_ETHER_TYPE_VLAN, rte_be_to_cpu_16(eh->ether_type));
200 : :
201 : : vh = (struct rte_vlan_hdr *)(eh + 1);
202 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(vh->vlan_tci), 100,
- - ]
203 : : "Expected VID 100, got %u", rte_be_to_cpu_16(vh->vlan_tci));
204 : :
205 : 1 : rte_pktmbuf_free(m);
206 : 1 : return TEST_SUCCESS;
207 : : }
208 : :
209 : : static int
210 : 1 : test_vlan_insert_tpid(void)
211 : : {
212 : : struct rte_ether_hdr *eh;
213 : : struct rte_vlan_hdr *vh;
214 : : struct rte_mbuf *m;
215 : : int ret;
216 : :
217 : 1 : m = alloc_frame(net_ether_test_pool, RTE_ETHER_TYPE_VLAN, sizeof(*vh) + 46);
218 [ - + ]: 1 : TEST_ASSERT_NOT_NULL(m, "Failed to allocate mbuf");
219 : :
220 : 1 : vh = (struct rte_vlan_hdr *)(rte_pktmbuf_mtod(m, struct rte_ether_hdr *) + 1);
221 : 1 : vh->vlan_tci = rte_cpu_to_be_16(200);
222 : 1 : vh->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
223 : :
224 : 1 : m->vlan_tci = 50;
225 : 1 : m->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
226 : :
227 : : ret = rte_vlan_insert_tpid(&m, RTE_ETHER_TYPE_QINQ);
228 [ - + ]: 1 : TEST_ASSERT_SUCCESS(ret, "rte_vlan_insert_tpid failed");
229 : :
230 : 1 : eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
231 : :
232 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(eh->ether_type), RTE_ETHER_TYPE_QINQ,
- - ]
233 : : "Outer TPID: expected 0x%04x (802.1ad) got 0x%04x",
234 : : RTE_ETHER_TYPE_QINQ, rte_be_to_cpu_16(eh->ether_type));
235 : :
236 : : vh = (struct rte_vlan_hdr *)(eh + 1);
237 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(vh->vlan_tci), 50,
- - ]
238 : : "Outer VID: expected 50, got %u",
239 : : rte_be_to_cpu_16(vh->vlan_tci));
240 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(vh->eth_proto), RTE_ETHER_TYPE_VLAN,
- - ]
241 : : "Outer eth_proto: expected 0x%04x (802.1Q), got 0x%04x",
242 : : RTE_ETHER_TYPE_VLAN, rte_be_to_cpu_16(vh->eth_proto));
243 : :
244 : : vh = vh + 1;
245 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(vh->vlan_tci), 200,
- - ]
246 : : "Inner VID: expected 200, got %u",
247 : : rte_be_to_cpu_16(vh->vlan_tci));
248 [ - + - + : 2 : TEST_ASSERT_EQUAL(rte_be_to_cpu_16(vh->eth_proto), RTE_ETHER_TYPE_IPV4,
- - ]
249 : : "Inner eth_proto: expected 0x%04x (IPv4), got 0x%04x",
250 : : RTE_ETHER_TYPE_IPV4, rte_be_to_cpu_16(vh->eth_proto));
251 : :
252 : 1 : rte_pktmbuf_free(m);
253 : 1 : return TEST_SUCCESS;
254 : : }
255 : :
256 : : static int
257 : 1 : net_ether_testsuite_setup(void)
258 : : {
259 : 1 : net_ether_test_pool = rte_pktmbuf_pool_create("net_ether_test_pool", 64, 0, 0,
260 : : RTE_MBUF_DEFAULT_BUF_SIZE, SOCKET_ID_ANY);
261 [ - + ]: 1 : TEST_ASSERT_NOT_NULL(net_ether_test_pool, "Failed to create mempool");
262 : :
263 : : return TEST_SUCCESS;
264 : : }
265 : :
266 : : static void
267 : 1 : net_ether_testsuite_teardown(void)
268 : : {
269 : 1 : rte_mempool_free(net_ether_test_pool);
270 : 1 : net_ether_test_pool = NULL;
271 : 1 : }
272 : :
273 : : static struct unit_test_suite net_ether_testsuite = {
274 : : .suite_name = "net_ether autotest",
275 : : .setup = net_ether_testsuite_setup,
276 : : .teardown = net_ether_testsuite_teardown,
277 : : .unit_test_cases = {
278 : : TEST_CASE(test_ether_addr),
279 : : TEST_CASE(test_format_addr),
280 : : TEST_CASE(test_unformat_addr),
281 : : TEST_CASE(test_invalid_addr),
282 : : TEST_CASE(test_vlan_insert_8021q),
283 : : TEST_CASE(test_vlan_insert_tpid),
284 : : TEST_CASES_END()
285 : : }
286 : : };
287 : :
288 : : static int
289 : 1 : test_net_ether(void)
290 : : {
291 : 1 : return unit_test_suite_runner(&net_ether_testsuite);
292 : : }
293 : :
294 : 302 : REGISTER_FAST_TEST(net_ether_autotest, NOHUGE_OK, ASAN_OK, test_net_ether);
|