]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-lldp.c
Merge pull request #7388 from keszybz/doc-tweak
[thirdparty/systemd.git] / src / libsystemd-network / test-lldp.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2014 Tom Gundersen
5 Copyright (C) 2014 Susant Sahani
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <arpa/inet.h>
22 #include <net/ethernet.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "sd-event.h"
28 #include "sd-lldp.h"
29
30 #include "alloc-util.h"
31 #include "fd-util.h"
32 #include "lldp-network.h"
33 #include "macro.h"
34 #include "string-util.h"
35
36 #define TEST_LLDP_PORT "em1"
37 #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
38 #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
39
40 static int test_fd[2] = { -1, -1 };
41 static int lldp_handler_calls;
42
43 int lldp_network_bind_raw_socket(int ifindex) {
44 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
45 return -errno;
46
47 return test_fd[0];
48 }
49
50 static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
51 lldp_handler_calls++;
52 }
53
54 static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *cb_data) {
55 int r;
56
57 r = sd_lldp_new(lldp);
58 if (r < 0)
59 return r;
60
61 r = sd_lldp_set_ifindex(*lldp, 42);
62 if (r < 0)
63 return r;
64
65 r = sd_lldp_set_callback(*lldp, cb, cb_data);
66 if (r < 0)
67 return r;
68
69 r = sd_lldp_attach_event(*lldp, e, 0);
70 if (r < 0)
71 return r;
72
73 r = sd_lldp_start(*lldp);
74 if (r < 0)
75 return r;
76
77 return 0;
78 }
79
80 static int stop_lldp(sd_lldp *lldp) {
81 int r;
82
83 r = sd_lldp_stop(lldp);
84 if (r < 0)
85 return r;
86
87 r = sd_lldp_detach_event(lldp);
88 if (r < 0)
89 return r;
90
91 sd_lldp_unref(lldp);
92 safe_close(test_fd[1]);
93
94 return 0;
95 }
96
97 static void test_receive_basic_packet(sd_event *e) {
98
99 static const uint8_t frame[] = {
100 /* Ethernet header */
101 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
102 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
103 0x88, 0xcc, /* Ethertype */
104 /* LLDP mandatory TLVs */
105 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */
106 0x03, 0x04, 0x05,
107 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */
108 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
109 /* LLDP optional TLVs */
110 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */
111 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */
112 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */
113 0x00, 0x00 /* End Of LLDPDU */
114 };
115
116 sd_lldp *lldp;
117 sd_lldp_neighbor **neighbors;
118 uint8_t type;
119 const void *data;
120 uint16_t ttl;
121 size_t length;
122 const char *str;
123
124 lldp_handler_calls = 0;
125 assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
126
127 assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
128 sd_event_run(e, 0);
129 assert_se(lldp_handler_calls == 1);
130 assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
131
132 assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[0], &type, &data, &length) == 0);
133 assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
134 assert_se(length == ETH_ALEN);
135 assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN));
136
137 assert_se(sd_lldp_neighbor_get_port_id(neighbors[0], &type, &data, &length) == 0);
138 assert_se(type == SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME);
139 assert_se(length == 3);
140 assert_se(strneq((char *) data, "1/3", 3));
141
142 assert_se(sd_lldp_neighbor_get_port_description(neighbors[0], &str) == 0);
143 assert_se(streq(str, "Port"));
144
145 assert_se(sd_lldp_neighbor_get_system_name(neighbors[0], &str) == 0);
146 assert_se(streq(str, "SYS"));
147
148 assert_se(sd_lldp_neighbor_get_system_description(neighbors[0], &str) == 0);
149 assert_se(streq(str, "foo"));
150
151 assert_se(sd_lldp_neighbor_get_ttl(neighbors[0], &ttl) == 0);
152 assert_se(ttl == 120);
153
154 sd_lldp_neighbor_unref(neighbors[0]);
155 free(neighbors);
156
157 assert_se(stop_lldp(lldp) == 0);
158 }
159
160 static void test_receive_incomplete_packet(sd_event *e) {
161 sd_lldp *lldp;
162 sd_lldp_neighbor **neighbors;
163 uint8_t frame[] = {
164 /* Ethernet header */
165 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
166 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
167 0x88, 0xcc, /* Ethertype */
168 /* LLDP mandatory TLVs */
169 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */
170 0x03, 0x04, 0x05,
171 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */
172 /* Missing TTL */
173 0x00, 0x00 /* End Of LLDPDU */
174 };
175
176 lldp_handler_calls = 0;
177 assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
178
179 assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
180 sd_event_run(e, 0);
181 assert_se(lldp_handler_calls == 0);
182 assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 0);
183
184 assert_se(stop_lldp(lldp) == 0);
185 }
186
187 static void test_receive_oui_packet(sd_event *e) {
188 sd_lldp *lldp;
189 sd_lldp_neighbor **neighbors;
190 uint8_t frame[] = {
191 /* Ethernet header */
192 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
193 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
194 0x88, 0xcc, /* Ethertype */
195 /* LLDP mandatory TLVs */
196 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */
197 0x03, 0x04, 0x05,
198 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port TLV: interface name, "1/3" */
199 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
200 /* LLDP optional TLVs */
201 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* Port VLAN ID: 0x1234 */
202 0x12, 0x34,
203 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* Port and protocol: flag 1, PPVID 0x7788 */
204 0x01, 0x77, 0x88,
205 0xfe, 0x0d, 0x00, 0x80, 0xc2, 0x03, /* VLAN Name: ID 0x1234, name "Vlan51" */
206 0x12, 0x34, 0x06, 0x56, 0x6c, 0x61,
207 0x6e, 0x35, 0x31,
208 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x06, /* Management VID: 0x0102 */
209 0x01, 0x02,
210 0xfe, 0x09, 0x00, 0x80, 0xc2, 0x07, /* Link aggregation: status 1, ID 0x00140012 */
211 0x01, 0x00, 0x14, 0x00, 0x12,
212 0x00, 0x00 /* End of LLDPDU */
213 };
214
215 lldp_handler_calls = 0;
216 assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
217
218 assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
219 sd_event_run(e, 0);
220 assert_se(lldp_handler_calls == 1);
221 assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
222
223 assert_se(sd_lldp_neighbor_tlv_rewind(neighbors[0]) >= 0);
224 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_CHASSIS_ID) > 0);
225 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
226 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_PORT_ID) > 0);
227 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
228 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_TTL) > 0);
229 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
230 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0);
231 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
232 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0);
233 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
234 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0);
235 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
236 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0);
237 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
238 assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
239 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
240 assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0);
241 assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0);
242
243 sd_lldp_neighbor_unref(neighbors[0]);
244 free(neighbors);
245
246 assert_se(stop_lldp(lldp) == 0);
247 }
248
249 int main(int argc, char *argv[]) {
250 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
251
252 log_set_max_level(LOG_DEBUG);
253
254 /* LLDP reception tests */
255 assert_se(sd_event_new(&e) == 0);
256 test_receive_basic_packet(e);
257 test_receive_incomplete_packet(e);
258 test_receive_oui_packet(e);
259
260 return 0;
261 }