]>
Commit | Line | Data |
---|---|---|
ead573d8 | 1 | # Test cases for MACsec/MKA |
b21540e6 | 2 | # Copyright (c) 2018-2019, Jouni Malinen <j@w1.fi> |
ead573d8 JM |
3 | # |
4 | # This software may be distributed under the terms of the BSD license. | |
5 | # See README for more details. | |
6 | ||
7 | import logging | |
8 | logger = logging.getLogger() | |
e1810300 | 9 | import binascii |
ead573d8 JM |
10 | import os |
11 | import signal | |
12 | import subprocess | |
13 | import time | |
14 | ||
41bca926 | 15 | import hostapd |
ead573d8 JM |
16 | from wpasupplicant import WpaSupplicant |
17 | import hwsim_utils | |
344929a9 | 18 | from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger |
ead573d8 JM |
19 | |
20 | def cleanup_macsec(): | |
b21540e6 | 21 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) |
ead573d8 JM |
22 | wpas.interface_remove("veth0") |
23 | wpas.interface_remove("veth1") | |
b21540e6 | 24 | del wpas |
ead573d8 JM |
25 | subprocess.call(["ip", "link", "del", "veth0"], |
26 | stderr=open('/dev/null', 'w')) | |
27 | ||
28 | def test_macsec_psk(dev, apdev, params): | |
29 | """MACsec PSK""" | |
30 | try: | |
31 | run_macsec_psk(dev, apdev, params, "macsec_psk") | |
32 | finally: | |
33 | cleanup_macsec() | |
34 | ||
35 | def test_macsec_psk_mka_life_time(dev, apdev, params): | |
36 | """MACsec PSK - MKA life time""" | |
37 | try: | |
38 | run_macsec_psk(dev, apdev, params, "macsec_psk_mka_life_time") | |
b21540e6 | 39 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) |
ead573d8 | 40 | wpas.interface_remove("veth1") |
b21540e6 | 41 | del wpas |
ead573d8 JM |
42 | # Wait for live peer to be removed on veth0 |
43 | time.sleep(6.1) | |
44 | finally: | |
45 | cleanup_macsec() | |
46 | ||
47 | def test_macsec_psk_integ_only(dev, apdev, params): | |
48 | """MACsec PSK (integrity only)""" | |
49 | try: | |
50 | run_macsec_psk(dev, apdev, params, "macsec_psk_integ_only", | |
51 | integ_only=True) | |
52 | finally: | |
53 | cleanup_macsec() | |
54 | ||
55 | def test_macsec_psk_port(dev, apdev, params): | |
56 | """MACsec PSK (port)""" | |
57 | try: | |
58 | run_macsec_psk(dev, apdev, params, "macsec_psk_port", | |
59 | port0=65534, port1=65534) | |
60 | finally: | |
61 | cleanup_macsec() | |
62 | ||
63 | def test_macsec_psk_different_ports(dev, apdev, params): | |
64 | """MACsec PSK (different ports)""" | |
65 | try: | |
66 | run_macsec_psk(dev, apdev, params, "macsec_psk_different_ports", | |
67 | port0=2, port1=3) | |
68 | finally: | |
69 | cleanup_macsec() | |
70 | ||
71 | def test_macsec_psk_shorter_ckn(dev, apdev, params): | |
72 | """MACsec PSK (shorter CKN)""" | |
73 | try: | |
74 | ckn = "11223344" | |
75 | run_macsec_psk(dev, apdev, params, "macsec_psk_shorter_ckn", | |
76 | ckn0=ckn, ckn1=ckn) | |
77 | finally: | |
78 | cleanup_macsec() | |
79 | ||
80 | def test_macsec_psk_shorter_ckn2(dev, apdev, params): | |
81 | """MACsec PSK (shorter CKN, unaligned)""" | |
82 | try: | |
83 | ckn = "112233" | |
84 | run_macsec_psk(dev, apdev, params, "macsec_psk_shorter_ckn2", | |
85 | ckn0=ckn, ckn1=ckn) | |
86 | finally: | |
87 | cleanup_macsec() | |
88 | ||
89 | def test_macsec_psk_ckn_mismatch(dev, apdev, params): | |
90 | """MACsec PSK (CKN mismatch)""" | |
91 | try: | |
92 | ckn0 = "11223344" | |
93 | ckn1 = "1122334455667788" | |
94 | run_macsec_psk(dev, apdev, params, "macsec_psk_ckn_mismatch", | |
95 | ckn0=ckn0, ckn1=ckn1, expect_failure=True) | |
96 | finally: | |
97 | cleanup_macsec() | |
98 | ||
99 | def test_macsec_psk_cak_mismatch(dev, apdev, params): | |
100 | """MACsec PSK (CAK mismatch)""" | |
101 | try: | |
102 | cak0 = 16*"11" | |
103 | cak1 = 16*"22" | |
104 | run_macsec_psk(dev, apdev, params, "macsec_psk_cak_mismatch", | |
105 | cak0=cak0, cak1=cak1, expect_failure=True) | |
106 | finally: | |
107 | cleanup_macsec() | |
108 | ||
109 | def test_macsec_psk_256(dev, apdev, params): | |
110 | """MACsec PSK with 256-bit keys""" | |
111 | try: | |
112 | cak = "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" | |
113 | run_macsec_psk(dev, apdev, params, "macsec_psk_256", cak0=cak, cak1=cak) | |
114 | finally: | |
115 | cleanup_macsec() | |
116 | ||
117 | def set_mka_psk_config(dev, mka_priority=None, integ_only=False, port=None, | |
118 | ckn=None, cak=None): | |
119 | dev.set("eapol_version", "3") | |
120 | dev.set("ap_scan", "0") | |
121 | dev.set("fast_reauth", "1") | |
122 | ||
123 | id = dev.add_network() | |
124 | dev.set_network(id, "key_mgmt", "NONE") | |
125 | if cak is None: | |
126 | cak = "000102030405060708090a0b0c0d0e0f" | |
127 | dev.set_network(id, "mka_cak", cak) | |
128 | if ckn is None: | |
129 | ckn = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" | |
130 | dev.set_network(id, "mka_ckn", ckn) | |
131 | dev.set_network(id, "eapol_flags", "0") | |
132 | dev.set_network(id, "macsec_policy", "1") | |
133 | if integ_only: | |
134 | dev.set_network(id, "macsec_integ_only", "1") | |
135 | if mka_priority is not None: | |
136 | dev.set_network(id, "mka_priority", str(mka_priority)) | |
137 | if port is not None: | |
138 | dev.set_network(id, "macsec_port", str(port)) | |
139 | ||
140 | dev.select_network(id) | |
141 | ||
41bca926 JM |
142 | def set_mka_eap_config(dev, mka_priority=None, integ_only=False, port=None): |
143 | dev.set("eapol_version", "3") | |
144 | dev.set("ap_scan", "0") | |
145 | dev.set("fast_reauth", "1") | |
146 | ||
147 | id = dev.add_network() | |
148 | dev.set_network(id, "key_mgmt", "NONE") | |
149 | dev.set_network(id, "eapol_flags", "0") | |
150 | dev.set_network(id, "macsec_policy", "1") | |
151 | if integ_only: | |
152 | dev.set_network(id, "macsec_integ_only", "1") | |
153 | if mka_priority is not None: | |
154 | dev.set_network(id, "mka_priority", str(mka_priority)) | |
155 | if port is not None: | |
156 | dev.set_network(id, "macsec_port", str(port)) | |
157 | ||
158 | dev.set_network(id, "key_mgmt", "IEEE8021X") | |
159 | dev.set_network(id, "eap", "TTLS") | |
160 | dev.set_network_quoted(id, "ca_cert", "auth_serv/ca.pem") | |
161 | dev.set_network_quoted(id, "phase2", "auth=MSCHAPV2") | |
162 | dev.set_network_quoted(id, "anonymous_identity", "ttls") | |
163 | dev.set_network_quoted(id, "identity", "DOMAIN\mschapv2 user") | |
164 | dev.set_network_quoted(id, "password", "password") | |
165 | ||
166 | dev.select_network(id) | |
167 | ||
ead573d8 | 168 | def log_ip_macsec(): |
fab49f61 | 169 | cmd = subprocess.Popen(["ip", "macsec", "show"], |
ead573d8 JM |
170 | stdout=subprocess.PIPE, |
171 | stderr=open('/dev/null', 'w')) | |
1c48c9bc | 172 | res = cmd.stdout.read().decode() |
ead573d8 JM |
173 | cmd.stdout.close() |
174 | logger.info("ip macsec:\n" + res) | |
175 | ||
176 | def log_ip_link(): | |
fab49f61 | 177 | cmd = subprocess.Popen(["ip", "link", "show"], |
ead573d8 | 178 | stdout=subprocess.PIPE) |
1c48c9bc | 179 | res = cmd.stdout.read().decode() |
ead573d8 JM |
180 | cmd.stdout.close() |
181 | logger.info("ip link:\n" + res) | |
182 | ||
344929a9 | 183 | def add_veth(): |
ead573d8 | 184 | try: |
fab49f61 JM |
185 | subprocess.check_call(["ip", "link", "add", "veth0", "type", "veth", |
186 | "peer", "name", "veth1"]) | |
ead573d8 JM |
187 | except subprocess.CalledProcessError: |
188 | raise HwsimSkip("veth not supported (kernel CONFIG_VETH)") | |
189 | ||
344929a9 JM |
190 | def add_wpas_interfaces(count=2): |
191 | wpa = [] | |
192 | try: | |
193 | for i in range(count): | |
194 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') | |
195 | wpas.interface_add("veth%d" % i, driver="macsec_linux") | |
196 | wpa.append(wpas) | |
bab493b9 | 197 | except Exception as e: |
344929a9 | 198 | if "Failed to add a dynamic wpa_supplicant interface" in str(e): |
3281c159 | 199 | raise HwsimSkip("macsec supported (wpa_supplicant CONFIG_MACSEC, CONFIG_DRIVER_MACSEC_LINUX; kernel CONFIG_MACSEC)") |
344929a9 JM |
200 | raise |
201 | ||
202 | return wpa | |
203 | ||
0d09bd08 JM |
204 | def lower_addr(addr1, addr2): |
205 | a1 = addr1.split(':') | |
206 | a2 = addr2.split(':') | |
207 | for i in range(6): | |
e1810300 | 208 | if binascii.unhexlify(a1[i]) < binascii.unhexlify(a2[i]): |
0d09bd08 | 209 | return True |
e1810300 | 210 | if binascii.unhexlify(a1[i]) > binascii.unhexlify(a2[i]): |
0d09bd08 JM |
211 | return False |
212 | return False | |
213 | ||
41bca926 | 214 | def wait_mka_done(wpa, expect_failure=False, hostapd=False): |
344929a9 JM |
215 | max_iter = 14 if expect_failure else 40 |
216 | for i in range(max_iter): | |
0d09bd08 JM |
217 | done = True |
218 | for w in wpa: | |
219 | secured = w.get_status_field("Secured") | |
41bca926 JM |
220 | live_peers = w.get_status_field("live_peers") |
221 | peers = int(live_peers) if live_peers else 0 | |
0d09bd08 JM |
222 | if expect_failure and (secured == "Yes" or peers > 0): |
223 | raise Exception("MKA completed unexpectedly") | |
41bca926 JM |
224 | expect_peers = len(wpa) - 1 |
225 | if hostapd: | |
226 | expect_peers += 1 | |
227 | if peers != expect_peers or secured != "Yes": | |
0d09bd08 JM |
228 | done = False |
229 | break | |
230 | w.dump_monitor() | |
231 | if done: | |
232 | break | |
344929a9 JM |
233 | time.sleep(0.5) |
234 | ||
235 | if expect_failure: | |
344929a9 JM |
236 | return |
237 | ||
0d09bd08 JM |
238 | if not done: |
239 | raise Exception("MKA not completed successfully") | |
240 | ||
41bca926 JM |
241 | if hostapd: |
242 | # TODO: check that hostapd is the key server | |
243 | return | |
244 | ||
0d09bd08 JM |
245 | key_server = None |
246 | ks_prio = 999 | |
247 | for w in wpa: | |
248 | logger.info("%s STATUS:\n%s" % (w.ifname, w.request("STATUS"))) | |
249 | addr = w.get_status_field("address") | |
250 | prio = int(w.get_status_field("Actor Priority")) | |
251 | if key_server is None or prio < ks_prio or \ | |
252 | (prio == ks_prio and lower_addr(addr, ks_addr)): | |
253 | key_server = w | |
254 | ks_addr = addr | |
255 | ks_prio = prio | |
256 | ||
257 | logger.info("Expected key server: " + key_server.ifname) | |
258 | if key_server.get_status_field("is_key_server") != "Yes": | |
259 | raise Exception("Expected key server was not elected") | |
260 | for w in wpa: | |
261 | if w != key_server and w.get_status_field("is_key_server") == "Yes": | |
262 | raise Exception("Unexpected key server") | |
344929a9 JM |
263 | |
264 | def run_macsec_psk(dev, apdev, params, prefix, integ_only=False, port0=None, | |
265 | port1=None, ckn0=None, ckn1=None, cak0=None, cak1=None, | |
266 | expect_failure=False): | |
267 | add_veth() | |
268 | ||
ead573d8 JM |
269 | cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") |
270 | cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") | |
271 | cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") | |
272 | cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") | |
273 | ||
274 | for i in range(2): | |
fab49f61 | 275 | subprocess.check_call(["ip", "link", "set", "dev", "veth%d" % i, "up"]) |
ead573d8 JM |
276 | |
277 | cmd = {} | |
278 | cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'veth0', | |
279 | '-w', cap_veth0, '-s', '2000', | |
280 | '--immediate-mode'], | |
281 | stderr=open('/dev/null', 'w')) | |
282 | cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'veth1', | |
283 | '-w', cap_veth1, '-s', '2000', | |
284 | '--immediate-mode'], | |
285 | stderr=open('/dev/null', 'w')) | |
286 | ||
344929a9 JM |
287 | wpa = add_wpas_interfaces() |
288 | wpas0 = wpa[0] | |
289 | wpas1 = wpa[1] | |
ead573d8 JM |
290 | |
291 | set_mka_psk_config(wpas0, integ_only=integ_only, port=port0, ckn=ckn0, | |
292 | cak=cak0) | |
293 | set_mka_psk_config(wpas1, mka_priority=100, integ_only=integ_only, | |
294 | port=port1, ckn=ckn1, cak=cak1) | |
295 | ||
296 | log_ip_macsec() | |
297 | log_ip_link() | |
298 | ||
299 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
300 | logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) | |
301 | logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) | |
302 | logger.info("wpas1 STATUS-DRIVER:\n" + wpas1.request("STATUS-DRIVER")) | |
303 | macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") | |
304 | macsec_ifname1 = wpas1.get_driver_status_field("parent_ifname") | |
305 | ||
0d09bd08 | 306 | wait_mka_done(wpa, expect_failure=expect_failure) |
ead573d8 JM |
307 | |
308 | if expect_failure: | |
ead573d8 JM |
309 | for i in range(len(cmd)): |
310 | cmd[i].terminate() | |
311 | return | |
312 | ||
313 | cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', macsec_ifname0, | |
314 | '-w', cap_macsec0, '-s', '2000', | |
315 | '--immediate-mode'], | |
316 | stderr=open('/dev/null', 'w')) | |
317 | cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', macsec_ifname1, | |
318 | '-w', cap_macsec1, '-s', '2000', | |
319 | '--immediate-mode'], | |
320 | stderr=open('/dev/null', 'w')) | |
321 | time.sleep(0.5) | |
322 | ||
90eb910e JM |
323 | mi0 = wpas0.get_status_field("mi") |
324 | mi1 = wpas1.get_status_field("mi") | |
325 | sci0 = wpas0.get_status_field("actor_sci") | |
326 | sci1 = wpas1.get_status_field("actor_sci") | |
327 | logger.info("wpas0 MIB:\n" + wpas0.request("MIB")) | |
328 | logger.info("wpas1 MIB:\n" + wpas1.request("MIB")) | |
329 | mib0 = wpas0.get_mib() | |
330 | mib1 = wpas1.get_mib() | |
331 | ||
332 | if mib0['ieee8021XKayMkaPeerListMI'] != mi1: | |
333 | raise Exception("Unexpected ieee8021XKayMkaPeerListMI value (0)") | |
334 | if mib0['ieee8021XKayMkaPeerListType'] != "1": | |
335 | raise Exception("Unexpected ieee8021XKayMkaPeerListType value (0)") | |
336 | if mib0['ieee8021XKayMkaPeerListSCI'] != sci1: | |
337 | raise Exception("Unexpected ieee8021XKayMkaPeerListSCI value (0)") | |
338 | if mib1['ieee8021XKayMkaPeerListMI'] != mi0: | |
339 | raise Exception("Unexpected ieee8021XKayMkaPeerListMI value (1)") | |
340 | if mib1['ieee8021XKayMkaPeerListType'] != "1": | |
341 | raise Exception("Unexpected ieee8021XKayMkaPeerListType value (1)") | |
342 | if mib1['ieee8021XKayMkaPeerListSCI'] != sci0: | |
343 | raise Exception("Unexpected ieee8021XKayMkaPeerListSCI value (1)") | |
344 | ||
ead573d8 JM |
345 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) |
346 | logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) | |
347 | log_ip_macsec() | |
348 | hwsim_utils.test_connectivity(wpas0, wpas1, | |
349 | ifname1=macsec_ifname0, | |
350 | ifname2=macsec_ifname1, | |
351 | send_len=1400) | |
352 | log_ip_macsec() | |
353 | ||
354 | time.sleep(1) | |
355 | for i in range(len(cmd)): | |
356 | cmd[i].terminate() | |
357 | ||
a2acadf6 | 358 | def cleanup_macsec_br(count): |
b21540e6 | 359 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) |
a2acadf6 JM |
360 | for i in range(count): |
361 | wpas.interface_remove("veth%d" % i) | |
362 | subprocess.call(["ip", "link", "del", "veth%d" % i], | |
363 | stderr=open('/dev/null', 'w')) | |
fe5400dd | 364 | del wpas |
a2acadf6 JM |
365 | subprocess.call(["ip", "link", "set", "brveth", "down"]) |
366 | subprocess.call(["brctl", "delbr", "brveth"]) | |
367 | ||
368 | def test_macsec_psk_br2(dev, apdev): | |
369 | """MACsec PSK (bridge; 2 devices)""" | |
370 | try: | |
371 | run_macsec_psk_br(dev, apdev, 2, [10, 20]) | |
372 | finally: | |
373 | cleanup_macsec_br(count=2) | |
374 | ||
375 | def test_macsec_psk_br2_same_prio(dev, apdev): | |
376 | """MACsec PSK (bridge; 2 devices, same mka_priority)""" | |
377 | try: | |
378 | run_macsec_psk_br(dev, apdev, 2, [None, None]) | |
379 | finally: | |
380 | cleanup_macsec_br(count=2) | |
381 | ||
382 | def test_macsec_psk_br3(dev, apdev): | |
383 | """MACsec PSK (bridge; 3 devices)""" | |
384 | try: | |
385 | run_macsec_psk_br(dev, apdev, 3, [10, 20, 30]) | |
386 | finally: | |
387 | cleanup_macsec_br(count=3) | |
388 | ||
389 | def test_macsec_psk_br3_same_prio(dev, apdev): | |
390 | """MACsec PSK (bridge; 3 devices, same mka_priority)""" | |
391 | try: | |
392 | run_macsec_psk_br(dev, apdev, 3, [None, None, None]) | |
393 | finally: | |
394 | cleanup_macsec_br(count=3) | |
395 | ||
396 | def run_macsec_psk_br(dev, apdev, count, mka_priority): | |
397 | subprocess.check_call(["brctl", "addbr", "brveth"]) | |
398 | subprocess.call(["echo 8 > /sys/devices/virtual/net/brveth/bridge/group_fwd_mask"], | |
399 | shell=True) | |
400 | ||
401 | try: | |
402 | for i in range(count): | |
fab49f61 JM |
403 | subprocess.check_call(["ip", "link", "add", "veth%d" % i, |
404 | "type", "veth", | |
405 | "peer", "name", "vethbr%d" % i]) | |
a2acadf6 | 406 | subprocess.check_call(["ip", "link", "set", "vethbr%d" % i, "up"]) |
fab49f61 JM |
407 | subprocess.check_call(["brctl", "addif", "brveth", |
408 | "vethbr%d" % i]) | |
a2acadf6 JM |
409 | except subprocess.CalledProcessError: |
410 | raise HwsimSkip("veth not supported (kernel CONFIG_VETH)") | |
411 | ||
412 | subprocess.check_call(["ip", "link", "set", "brveth", "up"]) | |
413 | ||
414 | log_ip_link() | |
415 | ||
416 | wpa = add_wpas_interfaces(count=count) | |
417 | for i in range(count): | |
418 | set_mka_psk_config(wpa[i], mka_priority=mka_priority[i]) | |
419 | wpa[i].dump_monitor() | |
420 | wait_mka_done(wpa) | |
421 | ||
422 | macsec_ifname = [] | |
423 | for i in range(count): | |
424 | macsec_ifname.append(wpa[i].get_driver_status_field("parent_ifname")) | |
425 | ||
426 | timeout = 2 | |
427 | max_tries = 2 if count > 2 else 1 | |
428 | success_seen = False | |
429 | failure_seen = False | |
430 | for i in range(1, count): | |
431 | try: | |
432 | hwsim_utils.test_connectivity(wpa[0], wpa[i], | |
433 | ifname1=macsec_ifname[0], | |
434 | ifname2=macsec_ifname[i], | |
435 | send_len=1400, | |
436 | timeout=timeout, max_tries=max_tries) | |
437 | success_seen = True | |
438 | logger.info("Traffic test %d<->%d success" % (0, i)) | |
439 | except: | |
440 | failure_seen = True | |
441 | logger.info("Traffic test %d<->%d failure" % (0, i)) | |
442 | for i in range(2, count): | |
443 | try: | |
444 | hwsim_utils.test_connectivity(wpa[1], wpa[i], | |
445 | ifname1=macsec_ifname[1], | |
446 | ifname2=macsec_ifname[i], | |
447 | send_len=1400, | |
448 | timeout=timeout, max_tries=max_tries) | |
449 | success_seen = True | |
450 | logger.info("Traffic test %d<->%d success" % (1, i)) | |
451 | except: | |
452 | failure_seen = True | |
453 | logger.info("Traffic test %d<->%d failure" % (1, i)) | |
454 | ||
455 | if not success_seen: | |
456 | raise Exception("None of the data traffic tests succeeded") | |
457 | ||
458 | # Something seems to be failing with three device tests semi-regularly, so | |
459 | # do not report this as a failed test case until the real reason behind | |
460 | # those failures have been determined. | |
461 | if failure_seen: | |
462 | if count < 3: | |
463 | raise Exception("Data traffic test failed") | |
464 | else: | |
465 | logger.info("Data traffic test failed - ignore for now for >= 3 device cases") | |
466 | ||
fe5400dd | 467 | for i in range(count): |
b21540e6 | 468 | wpa[i].close_monitor() |
fe5400dd | 469 | for i in range(count): |
b21540e6 | 470 | wpa[0].close_control() |
fe5400dd JM |
471 | del wpa[0] |
472 | ||
ead573d8 JM |
473 | def test_macsec_psk_ns(dev, apdev, params): |
474 | """MACsec PSK (netns)""" | |
475 | try: | |
476 | run_macsec_psk_ns(dev, apdev, params) | |
477 | finally: | |
478 | prefix = "macsec_psk_ns" | |
479 | pidfile = os.path.join(params['logdir'], prefix + ".pid") | |
480 | for i in range(2): | |
481 | was_running = False | |
482 | if os.path.exists(pidfile + str(i)): | |
483 | with open(pidfile + str(i), 'r') as f: | |
484 | pid = int(f.read().strip()) | |
485 | logger.info("wpa_supplicant for wpas%d still running with pid %d - kill it" % (i, pid)) | |
486 | was_running = True | |
487 | os.kill(pid, signal.SIGTERM) | |
488 | if was_running: | |
489 | time.sleep(1) | |
490 | ||
491 | subprocess.call(["ip", "netns", "exec", "ns0", | |
492 | "ip", "link", "del", "veth0"], | |
493 | stderr=open('/dev/null', 'w')) | |
494 | subprocess.call(["ip", "link", "del", "veth0"], | |
495 | stderr=open('/dev/null', 'w')) | |
496 | log_ip_link_ns() | |
497 | subprocess.call(["ip", "netns", "delete", "ns0"], | |
498 | stderr=open('/dev/null', 'w')) | |
499 | subprocess.call(["ip", "netns", "delete", "ns1"], | |
500 | stderr=open('/dev/null', 'w')) | |
501 | ||
502 | def log_ip_macsec_ns(): | |
fab49f61 | 503 | cmd = subprocess.Popen(["ip", "macsec", "show"], |
ead573d8 JM |
504 | stdout=subprocess.PIPE, |
505 | stderr=open('/dev/null', 'w')) | |
1c48c9bc | 506 | res = cmd.stdout.read().decode() |
ead573d8 JM |
507 | cmd.stdout.close() |
508 | logger.info("ip macsec show:\n" + res) | |
509 | ||
fab49f61 JM |
510 | cmd = subprocess.Popen(["ip", "netns", "exec", "ns0", |
511 | "ip", "macsec", "show"], | |
ead573d8 JM |
512 | stdout=subprocess.PIPE, |
513 | stderr=open('/dev/null', 'w')) | |
1c48c9bc | 514 | res = cmd.stdout.read().decode() |
ead573d8 JM |
515 | cmd.stdout.close() |
516 | logger.info("ip macsec show (ns0):\n" + res) | |
517 | ||
fab49f61 JM |
518 | cmd = subprocess.Popen(["ip", "netns", "exec", "ns1", |
519 | "ip", "macsec", "show"], | |
ead573d8 JM |
520 | stdout=subprocess.PIPE, |
521 | stderr=open('/dev/null', 'w')) | |
1c48c9bc | 522 | res = cmd.stdout.read().decode() |
ead573d8 JM |
523 | cmd.stdout.close() |
524 | logger.info("ip macsec show (ns1):\n" + res) | |
525 | ||
526 | def log_ip_link_ns(): | |
fab49f61 | 527 | cmd = subprocess.Popen(["ip", "link", "show"], |
ead573d8 | 528 | stdout=subprocess.PIPE) |
1c48c9bc | 529 | res = cmd.stdout.read().decode() |
ead573d8 JM |
530 | cmd.stdout.close() |
531 | logger.info("ip link:\n" + res) | |
532 | ||
fab49f61 JM |
533 | cmd = subprocess.Popen(["ip", "netns", "exec", "ns0", |
534 | "ip", "link", "show"], | |
ead573d8 JM |
535 | stdout=subprocess.PIPE, |
536 | stderr=open('/dev/null', 'w')) | |
1c48c9bc | 537 | res = cmd.stdout.read().decode() |
ead573d8 JM |
538 | cmd.stdout.close() |
539 | logger.info("ip link show (ns0):\n" + res) | |
540 | ||
fab49f61 JM |
541 | cmd = subprocess.Popen(["ip", "netns", "exec", "ns1", |
542 | "ip", "link", "show"], | |
ead573d8 JM |
543 | stdout=subprocess.PIPE, |
544 | stderr=open('/dev/null', 'w')) | |
1c48c9bc | 545 | res = cmd.stdout.read().decode() |
ead573d8 JM |
546 | cmd.stdout.close() |
547 | logger.info("ip link show (ns1):\n" + res) | |
548 | ||
549 | def write_conf(conffile, mka_priority=None): | |
550 | with open(conffile, 'w') as f: | |
551 | f.write("ctrl_interface=DIR=/var/run/wpa_supplicant\n") | |
552 | f.write("eapol_version=3\n") | |
553 | f.write("ap_scan=0\n") | |
554 | f.write("fast_reauth=1\n") | |
555 | f.write("network={\n") | |
26b0c290 MH |
556 | f.write(" key_mgmt=NONE\n") |
557 | f.write(" mka_cak=000102030405060708090a0b0c0d0e0f\n") | |
558 | f.write(" mka_ckn=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\n") | |
ead573d8 JM |
559 | if mka_priority is not None: |
560 | f.write(" mka_priority=%d\n" % mka_priority) | |
26b0c290 MH |
561 | f.write(" eapol_flags=0\n") |
562 | f.write(" macsec_policy=1\n") | |
ead573d8 JM |
563 | f.write("}\n") |
564 | ||
565 | def run_macsec_psk_ns(dev, apdev, params): | |
566 | try: | |
fab49f61 JM |
567 | subprocess.check_call(["ip", "link", "add", "veth0", "type", "veth", |
568 | "peer", "name", "veth1"]) | |
ead573d8 JM |
569 | except subprocess.CalledProcessError: |
570 | raise HwsimSkip("veth not supported (kernel CONFIG_VETH)") | |
571 | ||
572 | prefix = "macsec_psk_ns" | |
573 | conffile = os.path.join(params['logdir'], prefix + ".conf") | |
574 | pidfile = os.path.join(params['logdir'], prefix + ".pid") | |
575 | logfile0 = os.path.join(params['logdir'], prefix + ".veth0.log") | |
576 | logfile1 = os.path.join(params['logdir'], prefix + ".veth1.log") | |
577 | cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") | |
578 | cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") | |
579 | cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") | |
580 | cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") | |
581 | ||
582 | for i in range(2): | |
583 | try: | |
fab49f61 | 584 | subprocess.check_call(["ip", "netns", "add", "ns%d" % i]) |
ead573d8 JM |
585 | except subprocess.CalledProcessError: |
586 | raise HwsimSkip("network namespace not supported (kernel CONFIG_NAMESPACES, CONFIG_NET_NS)") | |
fab49f61 JM |
587 | subprocess.check_call(["ip", "link", "set", "veth%d" % i, |
588 | "netns", "ns%d" %i]) | |
589 | subprocess.check_call(["ip", "netns", "exec", "ns%d" % i, | |
590 | "ip", "link", "set", "dev", "veth%d" % i, | |
591 | "up"]) | |
ead573d8 JM |
592 | |
593 | cmd = {} | |
594 | cmd[0] = subprocess.Popen(['ip', 'netns', 'exec', 'ns0', | |
595 | 'tcpdump', '-p', '-U', '-i', 'veth0', | |
596 | '-w', cap_veth0, '-s', '2000', | |
597 | '--immediate-mode'], | |
598 | stderr=open('/dev/null', 'w')) | |
599 | cmd[1] = subprocess.Popen(['ip', 'netns', 'exec', 'ns1', | |
600 | 'tcpdump', '-p', '-U', '-i', 'veth1', | |
601 | '-w', cap_veth1, '-s', '2000', | |
602 | '--immediate-mode'], | |
603 | stderr=open('/dev/null', 'w')) | |
604 | ||
605 | write_conf(conffile + '0') | |
606 | write_conf(conffile + '1', mka_priority=100) | |
607 | ||
608 | prg = os.path.join(params['logdir'], | |
609 | 'alt-wpa_supplicant/wpa_supplicant/wpa_supplicant') | |
610 | if not os.path.exists(prg): | |
611 | prg = '../../wpa_supplicant/wpa_supplicant' | |
612 | ||
fab49f61 JM |
613 | arg = ["ip", "netns", "exec", "ns0", |
614 | prg, '-BdddtKW', '-P', pidfile + '0', '-f', logfile0, | |
615 | '-g', '/tmp/wpas-veth0', | |
616 | '-Dmacsec_linux', '-c', conffile + '0', '-i', "veth0"] | |
ead573d8 JM |
617 | logger.info("Start wpa_supplicant: " + str(arg)) |
618 | try: | |
619 | subprocess.check_call(arg) | |
620 | except subprocess.CalledProcessError: | |
3281c159 | 621 | raise HwsimSkip("macsec supported (wpa_supplicant CONFIG_MACSEC, CONFIG_DRIVER_MACSEC_LINUX; kernel CONFIG_MACSEC)") |
ead573d8 JM |
622 | |
623 | if os.path.exists("wpa_supplicant-macsec2"): | |
624 | logger.info("Use alternative wpa_supplicant binary for one of the macsec devices") | |
625 | prg = "wpa_supplicant-macsec2" | |
626 | ||
fab49f61 JM |
627 | arg = ["ip", "netns", "exec", "ns1", |
628 | prg, '-BdddtKW', '-P', pidfile + '1', '-f', logfile1, | |
629 | '-g', '/tmp/wpas-veth1', | |
630 | '-Dmacsec_linux', '-c', conffile + '1', '-i', "veth1"] | |
ead573d8 JM |
631 | logger.info("Start wpa_supplicant: " + str(arg)) |
632 | subprocess.check_call(arg) | |
633 | ||
634 | wpas0 = WpaSupplicant('veth0', '/tmp/wpas-veth0') | |
635 | wpas1 = WpaSupplicant('veth1', '/tmp/wpas-veth1') | |
636 | ||
637 | log_ip_macsec_ns() | |
638 | log_ip_link_ns() | |
639 | ||
640 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
641 | logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) | |
642 | logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) | |
643 | logger.info("wpas1 STATUS-DRIVER:\n" + wpas1.request("STATUS-DRIVER")) | |
ead573d8 JM |
644 | |
645 | for i in range(10): | |
658ed3ba JM |
646 | macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") |
647 | macsec_ifname1 = wpas1.get_driver_status_field("parent_ifname") | |
648 | if "Number of Keys" in wpas0.request("STATUS"): | |
649 | key_tx0 = int(wpas0.get_status_field("Number of Keys Distributed")) | |
650 | key_rx0 = int(wpas0.get_status_field("Number of Keys Received")) | |
651 | else: | |
652 | key_tx0 = 0 | |
653 | key_rx0 = 0 | |
654 | if "Number of Keys" in wpas1.request("STATUS"): | |
655 | key_tx1 = int(wpas1.get_status_field("Number of Keys Distributed")) | |
656 | key_rx1 = int(wpas1.get_status_field("Number of Keys Received")) | |
657 | else: | |
658 | key_tx1 = 0 | |
659 | key_rx1 = 0 | |
ead573d8 JM |
660 | if key_rx0 > 0 and key_tx1 > 0: |
661 | break | |
662 | time.sleep(1) | |
663 | ||
664 | cmd[2] = subprocess.Popen(['ip', 'netns', 'exec', 'ns0', | |
665 | 'tcpdump', '-p', '-U', '-i', macsec_ifname0, | |
666 | '-w', cap_macsec0, '-s', '2000', | |
667 | '--immediate-mode'], | |
668 | stderr=open('/dev/null', 'w')) | |
669 | cmd[3] = subprocess.Popen(['ip', 'netns', 'exec', 'ns0', | |
670 | 'tcpdump', '-p', '-U', '-i', macsec_ifname1, | |
671 | '-w', cap_macsec1, '-s', '2000', | |
672 | '--immediate-mode'], | |
673 | stderr=open('/dev/null', 'w')) | |
674 | time.sleep(0.5) | |
675 | ||
676 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
677 | logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) | |
678 | log_ip_macsec_ns() | |
679 | hwsim_utils.test_connectivity(wpas0, wpas1, | |
680 | ifname1=macsec_ifname0, | |
681 | ifname2=macsec_ifname1, | |
682 | send_len=1400) | |
683 | log_ip_macsec_ns() | |
684 | ||
685 | subprocess.check_call(['ip', 'netns', 'exec', 'ns0', | |
686 | 'ip', 'addr', 'add', '192.168.248.17/30', | |
687 | 'dev', macsec_ifname0]) | |
688 | subprocess.check_call(['ip', 'netns', 'exec', 'ns1', | |
689 | 'ip', 'addr', 'add', '192.168.248.18/30', | |
690 | 'dev', macsec_ifname1]) | |
691 | c = subprocess.Popen(['ip', 'netns', 'exec', 'ns0', | |
692 | 'ping', '-c', '2', '192.168.248.18'], | |
693 | stdout=subprocess.PIPE) | |
1c48c9bc | 694 | res = c.stdout.read().decode() |
ead573d8 JM |
695 | c.stdout.close() |
696 | logger.info("ping:\n" + res) | |
697 | if "2 packets transmitted, 2 received" not in res: | |
698 | raise Exception("ping did not work") | |
699 | ||
b21540e6 | 700 | wpas0.close_monitor() |
ead573d8 | 701 | wpas0.request("TERMINATE") |
b21540e6 | 702 | wpas0.close_control() |
ead573d8 | 703 | del wpas0 |
b21540e6 | 704 | wpas1.close_monitor() |
ead573d8 | 705 | wpas1.request("TERMINATE") |
b21540e6 | 706 | wpas1.close_control() |
ead573d8 JM |
707 | del wpas1 |
708 | ||
709 | time.sleep(1) | |
710 | for i in range(len(cmd)): | |
711 | cmd[i].terminate() | |
344929a9 JM |
712 | |
713 | def test_macsec_psk_fail_cp(dev, apdev): | |
714 | """MACsec PSK local failures in CP state machine""" | |
715 | try: | |
716 | add_veth() | |
717 | wpa = add_wpas_interfaces() | |
718 | set_mka_psk_config(wpa[0]) | |
719 | with alloc_fail(wpa[0], 1, "sm_CP_RECEIVE_Enter"): | |
720 | set_mka_psk_config(wpa[1]) | |
721 | wait_fail_trigger(wpa[0], "GET_ALLOC_FAIL", max_iter=100) | |
722 | ||
0d09bd08 | 723 | wait_mka_done(wpa) |
344929a9 JM |
724 | finally: |
725 | cleanup_macsec() | |
726 | ||
727 | def test_macsec_psk_fail_cp2(dev, apdev): | |
728 | """MACsec PSK local failures in CP state machine (2)""" | |
729 | try: | |
730 | add_veth() | |
731 | wpa = add_wpas_interfaces() | |
732 | set_mka_psk_config(wpa[0]) | |
733 | with alloc_fail(wpa[1], 1, "ieee802_1x_cp_sm_init"): | |
734 | set_mka_psk_config(wpa[1]) | |
735 | wait_fail_trigger(wpa[1], "GET_ALLOC_FAIL", max_iter=100) | |
736 | ||
0d09bd08 | 737 | wait_mka_done(wpa) |
344929a9 JM |
738 | finally: |
739 | cleanup_macsec() | |
41bca926 JM |
740 | |
741 | def cleanup_macsec_hostapd(): | |
742 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) | |
743 | wpas.interface_remove("veth0") | |
744 | del wpas | |
745 | hapd = hostapd.HostapdGlobal() | |
746 | hapd.remove('veth1') | |
747 | subprocess.call(["ip", "link", "del", "veth0"], | |
748 | stderr=open('/dev/null', 'w')) | |
749 | log_ip_link() | |
750 | ||
751 | def test_macsec_hostapd_psk(dev, apdev, params): | |
752 | """MACsec PSK with hostapd""" | |
753 | try: | |
754 | run_macsec_hostapd_psk(dev, apdev, params, "macsec_hostapd_psk") | |
755 | finally: | |
756 | cleanup_macsec_hostapd() | |
757 | ||
758 | def run_macsec_hostapd_psk(dev, apdev, params, prefix, integ_only=False, | |
759 | port0=None, port1=None, ckn0=None, ckn1=None, | |
760 | cak0=None, cak1=None, expect_failure=False): | |
761 | add_veth() | |
762 | ||
763 | cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") | |
764 | cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") | |
765 | cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") | |
766 | cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") | |
767 | ||
768 | for i in range(2): | |
769 | subprocess.check_call(["ip", "link", "set", "dev", "veth%d" % i, "up"]) | |
770 | ||
771 | cmd = {} | |
772 | cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'veth0', | |
773 | '-w', cap_veth0, '-s', '2000', | |
774 | '--immediate-mode'], | |
775 | stderr=open('/dev/null', 'w')) | |
776 | cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'veth1', | |
777 | '-w', cap_veth1, '-s', '2000', | |
778 | '--immediate-mode'], | |
779 | stderr=open('/dev/null', 'w')) | |
780 | ||
781 | wpa = add_wpas_interfaces(count=1) | |
782 | wpas0 = wpa[0] | |
783 | ||
784 | set_mka_psk_config(wpas0, integ_only=integ_only, port=port0, ckn=ckn0, | |
785 | cak=cak0, mka_priority=100) | |
786 | ||
787 | if cak1 is None: | |
788 | cak1 = "000102030405060708090a0b0c0d0e0f" | |
789 | if ckn1 is None: | |
790 | ckn1 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" | |
791 | params = {"driver": "macsec_linux", | |
792 | "interface": "veth1", | |
793 | "eapol_version": "3", | |
794 | "mka_cak": cak1, | |
795 | "mka_ckn": ckn1, | |
796 | "macsec_policy": "1", | |
797 | "mka_priority": "1"} | |
798 | if integ_only: | |
799 | params["macsec_integ_only"] = "1" | |
800 | if port1 is not None: | |
801 | params["macsec_port"] = str(port1) | |
802 | apdev = {'ifname': 'veth1'} | |
803 | try: | |
804 | hapd = hostapd.add_ap(apdev, params, driver="macsec_linux") | |
805 | except: | |
806 | raise HwsimSkip("No CONFIG_MACSEC=y in hostapd") | |
807 | ||
808 | log_ip_macsec() | |
809 | log_ip_link() | |
810 | ||
811 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
812 | logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) | |
813 | ||
814 | wait_mka_done(wpa, expect_failure=expect_failure, hostapd=True) | |
815 | log_ip_link() | |
816 | ||
817 | if expect_failure: | |
818 | for i in range(len(cmd)): | |
819 | cmd[i].terminate() | |
820 | return | |
821 | ||
822 | macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") | |
823 | macsec_ifname1 = hapd.get_driver_status_field("parent_ifname") | |
824 | ||
825 | cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', macsec_ifname0, | |
826 | '-w', cap_macsec0, '-s', '2000', | |
827 | '--immediate-mode'], | |
828 | stderr=open('/dev/null', 'w')) | |
829 | cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', macsec_ifname1, | |
830 | '-w', cap_macsec1, '-s', '2000', | |
831 | '--immediate-mode'], | |
832 | stderr=open('/dev/null', 'w')) | |
833 | time.sleep(0.5) | |
834 | ||
835 | logger.info("wpas0 MIB:\n" + wpas0.request("MIB")) | |
836 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
837 | log_ip_macsec() | |
838 | hwsim_utils.test_connectivity(wpas0, hapd, | |
839 | ifname1=macsec_ifname0, | |
840 | ifname2=macsec_ifname1, | |
841 | send_len=1400) | |
842 | log_ip_macsec() | |
843 | ||
844 | time.sleep(1) | |
845 | for i in range(len(cmd)): | |
846 | cmd[i].terminate() | |
847 | ||
848 | def test_macsec_hostapd_eap(dev, apdev, params): | |
849 | """MACsec EAP with hostapd""" | |
850 | try: | |
851 | run_macsec_hostapd_eap(dev, apdev, params, "macsec_hostapd_eap") | |
852 | finally: | |
853 | cleanup_macsec_hostapd() | |
854 | ||
855 | def run_macsec_hostapd_eap(dev, apdev, params, prefix, integ_only=False, | |
856 | port0=None, port1=None, expect_failure=False): | |
857 | add_veth() | |
858 | ||
859 | cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") | |
860 | cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") | |
861 | cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") | |
862 | cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") | |
863 | ||
864 | for i in range(2): | |
865 | subprocess.check_call(["ip", "link", "set", "dev", "veth%d" % i, "up"]) | |
866 | ||
867 | cmd = {} | |
868 | cmd[0] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'veth0', | |
869 | '-w', cap_veth0, '-s', '2000', | |
870 | '--immediate-mode'], | |
871 | stderr=open('/dev/null', 'w')) | |
872 | cmd[1] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', 'veth1', | |
873 | '-w', cap_veth1, '-s', '2000', | |
874 | '--immediate-mode'], | |
875 | stderr=open('/dev/null', 'w')) | |
876 | ||
877 | wpa = add_wpas_interfaces(count=1) | |
878 | wpas0 = wpa[0] | |
879 | ||
880 | set_mka_eap_config(wpas0, integ_only=integ_only, port=port0, | |
881 | mka_priority=100) | |
882 | ||
883 | params = {"driver": "macsec_linux", | |
884 | "interface": "veth1", | |
885 | "eapol_version": "3", | |
886 | "macsec_policy": "1", | |
887 | "mka_priority": "1", | |
888 | "ieee8021x": "1", | |
889 | "auth_server_addr": "127.0.0.1", | |
890 | "auth_server_port": "1812", | |
891 | "auth_server_shared_secret": "radius", | |
892 | "nas_identifier": "nas.w1.fi"} | |
893 | if integ_only: | |
894 | params["macsec_integ_only"] = "1" | |
895 | if port1 is not None: | |
896 | params["macsec_port"] = str(port1) | |
897 | apdev = {'ifname': 'veth1'} | |
898 | try: | |
899 | hapd = hostapd.add_ap(apdev, params, driver="macsec_linux") | |
900 | except: | |
901 | raise HwsimSkip("No CONFIG_MACSEC=y in hostapd") | |
902 | ||
903 | log_ip_macsec() | |
904 | log_ip_link() | |
905 | ||
906 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
907 | logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) | |
908 | ||
909 | wait_mka_done(wpa, expect_failure=expect_failure, hostapd=True) | |
910 | log_ip_link() | |
911 | ||
912 | if expect_failure: | |
913 | for i in range(len(cmd)): | |
914 | cmd[i].terminate() | |
915 | return | |
916 | ||
917 | macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") | |
918 | macsec_ifname1 = hapd.get_driver_status_field("parent_ifname") | |
919 | ||
920 | cmd[2] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', macsec_ifname0, | |
921 | '-w', cap_macsec0, '-s', '2000', | |
922 | '--immediate-mode'], | |
923 | stderr=open('/dev/null', 'w')) | |
924 | cmd[3] = subprocess.Popen(['tcpdump', '-p', '-U', '-i', macsec_ifname1, | |
925 | '-w', cap_macsec1, '-s', '2000', | |
926 | '--immediate-mode'], | |
927 | stderr=open('/dev/null', 'w')) | |
928 | time.sleep(0.5) | |
929 | ||
930 | logger.info("wpas0 MIB:\n" + wpas0.request("MIB")) | |
931 | logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) | |
932 | log_ip_macsec() | |
933 | hwsim_utils.test_connectivity(wpas0, hapd, | |
934 | ifname1=macsec_ifname0, | |
935 | ifname2=macsec_ifname1, | |
936 | send_len=1400) | |
937 | log_ip_macsec() | |
938 | ||
939 | time.sleep(1) | |
940 | for i in range(len(cmd)): | |
941 | cmd[i].terminate() |