netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / tests / test-aa.c
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 check_received_port(struct lldpd_port *sport,
44                     struct lldpd_port *rport)
45 {
46     assert(rport->p_id_subtype == sport->p_id_subtype);
47     assert(rport->p_id_len == sport->p_id_len);
48     assert(strncmp(rport->p_id, sport->p_id, sport->p_id_len) == 0);
49     assert(strcmp(rport->p_descr, sport->p_descr) == 0);
50
51     return;
52 }
53
54
55 /*
56  * Helper function to validate chassis info
57  */
58 static void
59 check_received_chassis(struct lldpd_chassis *schassis,
60                        struct lldpd_chassis *rchassis)
61 {
62     assert(rchassis->c_id_subtype == schassis->c_id_subtype);
63     assert(rchassis->c_id_len == schassis->c_id_len);
64     assert(memcmp(rchassis->c_id, schassis->c_id, schassis->c_id_len) == 0);
65     assert(strcmp(rchassis->c_name, schassis->c_name) == 0);
66     assert(strcmp(rchassis->c_descr, schassis->c_descr) == 0);
67     assert(rchassis->c_cap_available == schassis->c_cap_available);
68     assert(rchassis->c_cap_enabled == schassis->c_cap_enabled);
69
70     return;
71 }
72
73
74 /*
75  * Helper function to validate auto-attach info
76  */
77 static void
78 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     int i = 0;
84
85     assert(rport->p_element.type == sport->p_element.type);
86     assert(rport->p_element.mgmt_vlan == sport->p_element.mgmt_vlan);
87     assert(eth_addr_equals(rport->p_element.system_id.system_mac,
88                            sport->p_element.system_id.system_mac));
89     assert(rport->p_element.system_id.conn_type ==
90            sport->p_element.system_id.conn_type);
91     assert(rport->p_element.system_id.rsvd ==
92            sport->p_element.system_id.rsvd);
93     assert(rport->p_element.system_id.rsvd2[0] ==
94            sport->p_element.system_id.rsvd2[0]);
95     assert(rport->p_element.system_id.rsvd2[1] ==
96            sport->p_element.system_id.rsvd2[1]);
97
98     /* Should receive 2 mappings */
99     assert(!list_is_empty(&rport->p_isid_vlan_maps));
100
101     /* For each received isid/vlan mapping */
102     LIST_FOR_EACH (received_map, m_entries, &rport->p_isid_vlan_maps) {
103
104         /* Validate against mapping sent */
105         assert(smap[i].isid_vlan_data.status ==
106                received_map->isid_vlan_data.status);
107         assert(smap[i].isid_vlan_data.vlan ==
108                received_map->isid_vlan_data.vlan);
109         assert(smap[i].isid_vlan_data.isid ==
110                received_map->isid_vlan_data.isid);
111
112         /* Next mapping sent */
113         i++;
114     }
115     assert(i == 2);
116
117     return;
118 }
119
120
121 /*
122  * Validate basic send/receive processing
123  */
124 static int
125 test_aa_send(void)
126 {
127     struct lldp           *lldp;
128     struct lldpd_hardware hardware;
129     struct lldpd_chassis  chassis;
130
131     struct lldpd_chassis *nchassis = NULL;
132     struct lldpd_port    *nport = NULL;
133
134     struct lldpd_hardware *hw = NULL;
135     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     hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
147     hardware.h_lport.p_id = "FastEthernet 1/5";
148     hardware.h_lport.p_id_len = strlen(hardware.h_lport.p_id);
149     hardware.h_lport.p_descr = "Fake port description";
150     hardware.h_lport.p_mfs = 1516;
151
152     /* Auto attach element discovery info */
153     hardware.h_lport.p_element.type =
154         LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH;
155     hardware.h_lport.p_element.mgmt_vlan = 0xCDC;
156     eth_addr_from_uint64(0x010203040506ULL,
157                          &hardware.h_lport.p_element.system_id.system_mac);
158
159     hardware.h_lport.p_element.system_id.conn_type = 0x5;
160     hardware.h_lport.p_element.system_id.rsvd = 0x3CC;
161     hardware.h_lport.p_element.system_id.rsvd2[0] = 0xB;
162     hardware.h_lport.p_element.system_id.rsvd2[1] = 0xE;
163
164     /* Local chassis info */
165     chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
166     chassis.c_id = CONST_CAST(uint8_t *, chassis_mac.ea);
167     chassis.c_id_len = ETH_ADDR_LEN;
168     chassis.c_name = "Dummy chassis";
169     chassis.c_descr = "Long dummy chassis description";
170     chassis.c_cap_available = LLDP_CAP_BRIDGE;
171     chassis.c_cap_enabled = LLDP_CAP_BRIDGE;
172
173     /* ISID/VLAN mappings */
174     map_init[0].isid_vlan_data.status  = 0xC;
175     map_init[0].isid_vlan_data.vlan    = 0x64;
176     map_init[0].isid_vlan_data.isid    = 0x010203;
177
178     map_init[1].isid_vlan_data.status  = 0xD;
179     map_init[1].isid_vlan_data.vlan    = 0xF;
180     map_init[1].isid_vlan_data.isid    = 0x040506;
181
182     /* Prepare an empty packet buffer */
183     dp_packet_use_stub(&packet, stub, sizeof stub);
184     dp_packet_clear(&packet);
185
186     /* Create a dummy lldp instance */
187     lldp = lldp_create_dummy();
188     if ((lldp == NULL) ||
189         (lldp->lldpd == NULL) ||
190         list_is_empty(&lldp->lldpd->g_hardware)) {
191         printf("Error: unable to create dummy lldp instance");
192         return 1;
193     }
194
195     /* Populate instance with local chassis info */
196     hw = lldpd_first_hardware(lldp->lldpd);
197     ch = hw->h_lport.p_chassis;
198     ch->c_id_subtype = chassis.c_id_subtype;
199     ch->c_id = chassis.c_id;
200     ch->c_id_len = chassis.c_id_len;
201     ch->c_name = chassis.c_name;
202     ch->c_descr = chassis.c_descr;
203     ch->c_cap_available = chassis.c_cap_available;
204     ch->c_cap_enabled = chassis.c_cap_enabled;
205
206     /* Populate instance with local port info */
207     hw->h_lport.p_id_subtype = hardware.h_lport.p_id_subtype;
208     hw->h_lport.p_id = hardware.h_lport.p_id;
209     hw->h_lport.p_id_len = strlen(hw->h_lport.p_id);
210     hw->h_lport.p_descr = hardware.h_lport.p_descr;
211     hw->h_lport.p_mfs = hardware.h_lport.p_mfs;
212
213     /* Populate instance with auto attach element discovery info */
214
215     hw->h_lport.p_element.type = hardware.h_lport.p_element.type;
216     hw->h_lport.p_element.mgmt_vlan = hardware.h_lport.p_element.mgmt_vlan;
217     hw->h_lport.p_element.system_id.system_mac =
218         hardware.h_lport.p_element.system_id.system_mac;
219
220     hw->h_lport.p_element.system_id.conn_type =
221         hardware.h_lport.p_element.system_id.conn_type;
222     hw->h_lport.p_element.system_id.rsvd =
223         hardware.h_lport.p_element.system_id.rsvd;
224     hw->h_lport.p_element.system_id.rsvd2[0] =
225         hardware.h_lport.p_element.system_id.rsvd2[0];
226     hw->h_lport.p_element.system_id.rsvd2[1] =
227         hardware.h_lport.p_element.system_id.rsvd2[1];
228
229     /* Populate instance with two auto attach isid/vlan mappings */
230     map[0].isid_vlan_data.status  = map_init[0].isid_vlan_data.status;
231     map[0].isid_vlan_data.vlan    = map_init[0].isid_vlan_data.vlan;
232     map[0].isid_vlan_data.isid    = map_init[0].isid_vlan_data.isid;
233
234     map[1].isid_vlan_data.status  = map_init[1].isid_vlan_data.status;
235     map[1].isid_vlan_data.vlan    = map_init[1].isid_vlan_data.vlan;
236     map[1].isid_vlan_data.isid    = map_init[1].isid_vlan_data.isid;
237
238     list_init(&hw->h_lport.p_isid_vlan_maps);
239     list_push_back(&hw->h_lport.p_isid_vlan_maps, &map[0].m_entries);
240     list_push_back(&hw->h_lport.p_isid_vlan_maps, &map[1].m_entries);
241
242     /* Construct LLDPPDU (including Ethernet header) */
243     eth_compose(&packet, eth_addr_lldp, eth_src, ETH_TYPE_LLDP, 0);
244     n = lldp_send(lldp->lldpd, hw, &packet);
245
246     if (n == 0) {
247         printf("Error: unable to build packet\n");
248         return 1;
249     }
250
251     /* Decode the constructed LLDPPDU */
252     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     if (!nchassis || !nport) {
257         printf("Error: unable to decode packet");
258         return 1;
259     }
260
261     /* Verify chassis values */
262     check_received_chassis(&chassis, nchassis);
263
264     /* Verify port values */
265     check_received_port(&hardware.h_lport, nport);
266
267     /* Verify auto attach values */
268     check_received_aa(&hardware.h_lport, nport, map_init);
269
270     lldpd_chassis_cleanup(nchassis, true);
271     lldpd_port_cleanup(nport, true);
272     free(nport);
273     lldp_destroy_dummy(lldp);
274
275     return 0;
276 }
277
278
279 static void
280 test_aa_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
281 {
282     int num_errors = 0;
283
284     /* Make sure we emit valid auto-attach LLDPPDUs */
285     num_tests++;
286     num_errors += test_aa_send();
287
288     /* Add more tests here */
289
290     printf("executed %d tests, %d errors\n", num_tests, num_errors);
291
292     exit(num_errors != 0);
293 }
294
295 OVSTEST_REGISTER("test-aa", test_aa_main);