Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015 Avaya, Inc.
3 : : *
4 : : * Permission to use, copy, modify, and/or distribute this software for any
5 : : * purpose with or without fee is hereby granted, provided that the above
6 : : * copyright notice and this permission notice appear in all copies.
7 : : *
8 : : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 : : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 : : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 : : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 : : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 : : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 : : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 : : */
16 : :
17 : : #include <config.h>
18 : : #undef NDEBUG
19 : : #include <assert.h>
20 : : #include <stdio.h>
21 : : #include <stdlib.h>
22 : : #include <string.h>
23 : : #include "ovs-lldp.h"
24 : : #include "ovstest.h"
25 : :
26 : : #define ETH_TYPE_LLDP 0x88cc
27 : :
28 : : /* Dummy MAC addresses */
29 : : static const struct eth_addr chassis_mac = { { { 0x5e, 0x10, 0x8e, 0xe7, 0x84, 0xad } } };
30 : : static const struct eth_addr eth_src = { { { 0x5e, 0x10, 0x8e, 0xe7, 0x84, 0xad } } };
31 : :
32 : : /* LLDP multicast address */
33 : : static const struct eth_addr eth_addr_lldp = { { { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0e } } };
34 : :
35 : : /* Count of tests run */
36 : : static int num_tests = 0;
37 : :
38 : :
39 : : /*
40 : : * Helper function to validate port info
41 : : */
42 : : static void
43 : 1 : check_received_port(struct lldpd_port *sport,
44 : : struct lldpd_port *rport)
45 : : {
46 [ - + ]: 1 : assert(rport->p_id_subtype == sport->p_id_subtype);
47 [ - + ]: 1 : assert(rport->p_id_len == sport->p_id_len);
48 [ - + ]: 1 : assert(strncmp(rport->p_id, sport->p_id, sport->p_id_len) == 0);
49 [ - + ]: 1 : assert(strcmp(rport->p_descr, sport->p_descr) == 0);
50 : :
51 : 1 : return;
52 : : }
53 : :
54 : :
55 : : /*
56 : : * Helper function to validate chassis info
57 : : */
58 : : static void
59 : 1 : check_received_chassis(struct lldpd_chassis *schassis,
60 : : struct lldpd_chassis *rchassis)
61 : : {
62 [ - + ]: 1 : assert(rchassis->c_id_subtype == schassis->c_id_subtype);
63 [ - + ]: 1 : assert(rchassis->c_id_len == schassis->c_id_len);
64 [ - + ]: 1 : assert(memcmp(rchassis->c_id, schassis->c_id, schassis->c_id_len) == 0);
65 [ - + ]: 1 : assert(strcmp(rchassis->c_name, schassis->c_name) == 0);
66 [ - + ]: 1 : assert(strcmp(rchassis->c_descr, schassis->c_descr) == 0);
67 [ - + ]: 1 : assert(rchassis->c_cap_available == schassis->c_cap_available);
68 [ - + ]: 1 : assert(rchassis->c_cap_enabled == schassis->c_cap_enabled);
69 : :
70 : 1 : return;
71 : : }
72 : :
73 : :
74 : : /*
75 : : * Helper function to validate auto-attach info
76 : : */
77 : : static void
78 : 1 : check_received_aa(struct lldpd_port *sport,
79 : : struct lldpd_port *rport,
80 : : struct lldpd_aa_isid_vlan_maps_tlv *smap)
81 : : {
82 : : struct lldpd_aa_isid_vlan_maps_tlv *received_map;
83 : 1 : int i = 0;
84 : :
85 [ - + ]: 1 : assert(rport->p_element.type == sport->p_element.type);
86 [ - + ]: 1 : assert(rport->p_element.mgmt_vlan == sport->p_element.mgmt_vlan);
87 [ - + ]: 1 : assert(eth_addr_equals(rport->p_element.system_id.system_mac,
88 : : sport->p_element.system_id.system_mac));
89 [ - + ]: 1 : assert(rport->p_element.system_id.conn_type ==
90 : : sport->p_element.system_id.conn_type);
91 [ - + ]: 1 : assert(rport->p_element.system_id.rsvd ==
92 : : sport->p_element.system_id.rsvd);
93 [ - + ]: 1 : assert(rport->p_element.system_id.rsvd2[0] ==
94 : : sport->p_element.system_id.rsvd2[0]);
95 [ - + ]: 1 : assert(rport->p_element.system_id.rsvd2[1] ==
96 : : sport->p_element.system_id.rsvd2[1]);
97 : :
98 : : /* Should receive 2 mappings */
99 [ - + ]: 1 : assert(!ovs_list_is_empty(&rport->p_isid_vlan_maps));
100 : :
101 : : /* For each received isid/vlan mapping */
102 [ + + ]: 3 : LIST_FOR_EACH (received_map, m_entries, &rport->p_isid_vlan_maps) {
103 : :
104 : : /* Validate against mapping sent */
105 [ - + ]: 2 : assert(smap[i].isid_vlan_data.status ==
106 : : received_map->isid_vlan_data.status);
107 [ - + ]: 2 : assert(smap[i].isid_vlan_data.vlan ==
108 : : received_map->isid_vlan_data.vlan);
109 [ - + ]: 2 : assert(smap[i].isid_vlan_data.isid ==
110 : : received_map->isid_vlan_data.isid);
111 : :
112 : : /* Next mapping sent */
113 : 2 : i++;
114 : : }
115 [ - + ]: 1 : assert(i == 2);
116 : :
117 : 1 : return;
118 : : }
119 : :
120 : :
121 : : /*
122 : : * Validate basic send/receive processing
123 : : */
124 : : static int
125 : 1 : test_aa_send(void)
126 : : {
127 : : struct lldp *lldp;
128 : : struct lldpd_hardware hardware;
129 : : struct lldpd_chassis chassis;
130 : :
131 : 1 : struct lldpd_chassis *nchassis = NULL;
132 : 1 : struct lldpd_port *nport = NULL;
133 : :
134 : 1 : struct lldpd_hardware *hw = NULL;
135 : 1 : struct lldpd_chassis *ch = NULL;
136 : :
137 : : struct lldpd_aa_isid_vlan_maps_tlv map_init[2];
138 : : struct lldpd_aa_isid_vlan_maps_tlv map[2];
139 : :
140 : : uint32_t stub[512 / 4];
141 : : struct dp_packet packet;
142 : :
143 : : int n;
144 : :
145 : : /* Prepare data used to construct and validate LLDPPDU */
146 : 1 : hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
147 : 1 : hardware.h_lport.p_id = "FastEthernet 1/5";
148 : 1 : hardware.h_lport.p_id_len = strlen(hardware.h_lport.p_id);
149 : 1 : hardware.h_lport.p_descr = "Fake port description";
150 : 1 : hardware.h_lport.p_mfs = 1516;
151 : :
152 : : /* Auto attach element discovery info */
153 : 1 : hardware.h_lport.p_element.type =
154 : : LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH;
155 : 1 : hardware.h_lport.p_element.mgmt_vlan = 0xCDC;
156 : 1 : eth_addr_from_uint64(0x010203040506ULL,
157 : : &hardware.h_lport.p_element.system_id.system_mac);
158 : :
159 : 1 : hardware.h_lport.p_element.system_id.conn_type = 0x5;
160 : 1 : hardware.h_lport.p_element.system_id.rsvd = 0x3CC;
161 : 1 : hardware.h_lport.p_element.system_id.rsvd2[0] = 0xB;
162 : 1 : hardware.h_lport.p_element.system_id.rsvd2[1] = 0xE;
163 : :
164 : : /* Local chassis info */
165 : 1 : chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
166 : 1 : chassis.c_id = CONST_CAST(uint8_t *, chassis_mac.ea);
167 : 1 : chassis.c_id_len = ETH_ADDR_LEN;
168 : 1 : chassis.c_name = "Dummy chassis";
169 : 1 : chassis.c_descr = "Long dummy chassis description";
170 : 1 : chassis.c_cap_available = LLDP_CAP_BRIDGE;
171 : 1 : chassis.c_cap_enabled = LLDP_CAP_BRIDGE;
172 : :
173 : : /* ISID/VLAN mappings */
174 : 1 : map_init[0].isid_vlan_data.status = 0xC;
175 : 1 : map_init[0].isid_vlan_data.vlan = 0x64;
176 : 1 : map_init[0].isid_vlan_data.isid = 0x010203;
177 : :
178 : 1 : map_init[1].isid_vlan_data.status = 0xD;
179 : 1 : map_init[1].isid_vlan_data.vlan = 0xF;
180 : 1 : map_init[1].isid_vlan_data.isid = 0x040506;
181 : :
182 : : /* Prepare an empty packet buffer */
183 : 1 : dp_packet_use_stub(&packet, stub, sizeof stub);
184 : 1 : dp_packet_clear(&packet);
185 : :
186 : : /* Create a dummy lldp instance */
187 : 1 : lldp = lldp_create_dummy();
188 [ + - ][ + - ]: 1 : if ((lldp == NULL) ||
189 [ - + ]: 1 : (lldp->lldpd == NULL) ||
190 : 1 : ovs_list_is_empty(&lldp->lldpd->g_hardware)) {
191 : 0 : printf("Error: unable to create dummy lldp instance");
192 : 0 : return 1;
193 : : }
194 : :
195 : : /* Populate instance with local chassis info */
196 : 1 : hw = lldpd_first_hardware(lldp->lldpd);
197 : 1 : ch = hw->h_lport.p_chassis;
198 : 1 : ch->c_id_subtype = chassis.c_id_subtype;
199 : 1 : ch->c_id = chassis.c_id;
200 : 1 : ch->c_id_len = chassis.c_id_len;
201 : 1 : ch->c_name = chassis.c_name;
202 : 1 : ch->c_descr = chassis.c_descr;
203 : 1 : ch->c_cap_available = chassis.c_cap_available;
204 : 1 : ch->c_cap_enabled = chassis.c_cap_enabled;
205 : :
206 : : /* Populate instance with local port info */
207 : 1 : hw->h_lport.p_id_subtype = hardware.h_lport.p_id_subtype;
208 : 1 : hw->h_lport.p_id = hardware.h_lport.p_id;
209 : 1 : hw->h_lport.p_id_len = strlen(hw->h_lport.p_id);
210 : 1 : hw->h_lport.p_descr = hardware.h_lport.p_descr;
211 : 1 : hw->h_lport.p_mfs = hardware.h_lport.p_mfs;
212 : :
213 : : /* Populate instance with auto attach element discovery info */
214 : :
215 : 1 : hw->h_lport.p_element.type = hardware.h_lport.p_element.type;
216 : 1 : hw->h_lport.p_element.mgmt_vlan = hardware.h_lport.p_element.mgmt_vlan;
217 : 1 : hw->h_lport.p_element.system_id.system_mac =
218 : : hardware.h_lport.p_element.system_id.system_mac;
219 : :
220 : 1 : hw->h_lport.p_element.system_id.conn_type =
221 : 1 : hardware.h_lport.p_element.system_id.conn_type;
222 : 1 : hw->h_lport.p_element.system_id.rsvd =
223 : 1 : hardware.h_lport.p_element.system_id.rsvd;
224 : 1 : hw->h_lport.p_element.system_id.rsvd2[0] =
225 : 1 : hardware.h_lport.p_element.system_id.rsvd2[0];
226 : 1 : hw->h_lport.p_element.system_id.rsvd2[1] =
227 : 1 : hardware.h_lport.p_element.system_id.rsvd2[1];
228 : :
229 : : /* Populate instance with two auto attach isid/vlan mappings */
230 : 1 : map[0].isid_vlan_data.status = map_init[0].isid_vlan_data.status;
231 : 1 : map[0].isid_vlan_data.vlan = map_init[0].isid_vlan_data.vlan;
232 : 1 : map[0].isid_vlan_data.isid = map_init[0].isid_vlan_data.isid;
233 : :
234 : 1 : map[1].isid_vlan_data.status = map_init[1].isid_vlan_data.status;
235 : 1 : map[1].isid_vlan_data.vlan = map_init[1].isid_vlan_data.vlan;
236 : 1 : map[1].isid_vlan_data.isid = map_init[1].isid_vlan_data.isid;
237 : :
238 : 1 : ovs_list_init(&hw->h_lport.p_isid_vlan_maps);
239 : 1 : ovs_list_push_back(&hw->h_lport.p_isid_vlan_maps, &map[0].m_entries);
240 : 1 : ovs_list_push_back(&hw->h_lport.p_isid_vlan_maps, &map[1].m_entries);
241 : :
242 : : /* Construct LLDPPDU (including Ethernet header) */
243 : 1 : eth_compose(&packet, eth_addr_lldp, eth_src, ETH_TYPE_LLDP, 0);
244 : 1 : n = lldp_send(lldp->lldpd, hw, &packet);
245 : :
246 [ - + ]: 1 : if (n == 0) {
247 : 0 : printf("Error: unable to build packet\n");
248 : 0 : return 1;
249 : : }
250 : :
251 : : /* Decode the constructed LLDPPDU */
252 [ - + ]: 1 : assert(lldp_decode(NULL, dp_packet_data(&packet), dp_packet_size(&packet), hw,
253 : : &nchassis, &nport) != -1);
254 : :
255 : : /* Expecting returned pointers to allocated structures */
256 [ + - ][ - + ]: 1 : if (!nchassis || !nport) {
257 : 0 : printf("Error: unable to decode packet");
258 : 0 : return 1;
259 : : }
260 : :
261 : : /* Verify chassis values */
262 : 1 : check_received_chassis(&chassis, nchassis);
263 : :
264 : : /* Verify port values */
265 : 1 : check_received_port(&hardware.h_lport, nport);
266 : :
267 : : /* Verify auto attach values */
268 : 1 : check_received_aa(&hardware.h_lport, nport, map_init);
269 : :
270 : 1 : lldpd_chassis_cleanup(nchassis, true);
271 : 1 : lldpd_port_cleanup(nport, true);
272 : 1 : free(nport);
273 : 1 : lldp_destroy_dummy(lldp);
274 : :
275 : 1 : return 0;
276 : : }
277 : :
278 : :
279 : : static void
280 : 1 : test_aa_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
281 : : {
282 : 1 : int num_errors = 0;
283 : :
284 : : /* Make sure we emit valid auto-attach LLDPPDUs */
285 : 1 : num_tests++;
286 : 1 : num_errors += test_aa_send();
287 : :
288 : : /* Add more tests here */
289 : :
290 : 1 : printf("executed %d tests, %d errors\n", num_tests, num_errors);
291 : :
292 : 1 : exit(num_errors != 0);
293 : : }
294 : :
295 : 1175 : OVSTEST_REGISTER("test-aa", test_aa_main);
|