1# Test cases for SCS
2# Copyright (c) 2021, Jouni Malinen <j@w1.fi>
3# Copyright (c) 2021, The Linux Foundation
4#
5# This software may be distributed under the terms of the BSD license.
6# See README for more details.
7
8import struct
9import time
10
11import hostapd
12from utils import *
13
14def register_scs_req(hapd):
15    type = 0x00d0
16    match = "1300"
17    if "OK" not in hapd.request("REGISTER_FRAME %04x %s" % (type, match)):
18        raise Exception("Could not register frame reception for Robust AV Streaming")
19
20def handle_scs_req(hapd, wrong_dialog=False, status_code=0, twice=False,
21                   short=False, scsid=1):
22    msg = hapd.mgmt_rx()
23    if msg['subtype'] != 13:
24        logger.info("RX:" + str(msg))
25        raise Exception("Received unexpected Management frame")
26    categ, act, dialog_token = struct.unpack('BBB', msg['payload'][0:3])
27    if categ != 19 or act != 0:
28        logger.info("RX:" + str(msg))
29        raise Exception("Received unexpected Action frame")
30
31    if wrong_dialog:
32        dialog_token = (dialog_token + 1) % 256
33    msg['da'] = msg['sa']
34    msg['sa'] = hapd.own_addr()
35    count = 1
36    if short:
37        resp = struct.pack('BBB', 19, 1, dialog_token)
38    else:
39        resp = struct.pack('BBBB', 19, 1, dialog_token, count)
40        resp += struct.pack('<BH', scsid, status_code)
41    msg['payload'] = resp
42    hapd.mgmt_tx(msg)
43    ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
44    if ev is None or "stype=13 ok=1" not in ev:
45        raise Exception("No TX status reported")
46    if twice:
47        hapd.mgmt_tx(msg)
48        ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
49        if ev is None or "stype=13 ok=1" not in ev:
50            raise Exception("No TX status reported")
51
52def wait_scs_result(dev, expect_status="0"):
53    ev = dev.wait_event(["CTRL-EVENT-SCS-RESULT"], timeout=2)
54    if ev is None:
55        raise Exception("No SCS result reported")
56    if "status_code=%s" % expect_status not in ev:
57        raise Exception("Unexpected SCS result: " + ev)
58
59def test_scs_invalid_params(dev, apdev):
60    """SCS command invalid parameters"""
61    tests = ["",
62             "scs_id=1",
63             "scs_id=1 foo",
64             "scs_id=1 add ",
65             "scs_id=1 add scs_up=8",
66             "scs_id=1 add scs_up=7",
67             "scs_id=1 add scs_up=7 classifier_type=1",
68             "scs_id=1 add scs_up=7 classifier_type=4",
69             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv4",
70             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv4 src_ip=q",
71             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv4 dst_ip=q",
72             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv4 src_port=q",
73             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv4 dst_port=q",
74             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv4 protocol=foo",
75             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv6 protocol=foo",
76             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv6 next_header=foo",
77             "scs_id=1 add scs_up=7 classifier_type=4 ip_version=ipv6 flow_label=ffffff",
78             "scs_id=1 add scs_up=7 classifier_type=10",
79             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1",
80             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp",
81             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344",
82             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=qq",
83             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffff",
84             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=qqqqqqqq",
85             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffffff",
86             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=foo filter_value=11223344 filter_mask=ffffffff",
87             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11 filter_mask=ee classifier_type=10 prot_instance=2 prot_number=udp filter_value=22 filter_mask=ff",
88             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11 filter_mask=ee classifier_type=10 prot_instance=2 prot_number=udp filter_value=22 filter_mask=ff tclas_processing=2",
89             "scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11 filter_mask=ee classifier_type=10 prot_instance=2 prot_number=udp filter_value=22 filter_mask=ff tclas_processing=0",
90             "scs_id=1 add scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp scs_id=1 add scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=tcp"
91             "scs_id=1 remove",
92             "scs_id=1 change "]
93    for t in tests:
94        if "FAIL" not in dev[0].request("SCS " + t):
95            raise Exception("Invalid SCS parameters accepted: " + t)
96
97def test_scs_request(dev, apdev):
98    """SCS Request"""
99    params = {"ssid": "scs",
100              "ext_capa": 6*"00" + "40"}
101    hapd = hostapd.add_ap(apdev[0], params)
102    run_scs_request(dev, hapd, False)
103
104def test_scs_request_wfa(dev, apdev):
105    """SCS Request (WFA capability)"""
106    params = {"ssid": "scs",
107              "ext_capa": 6*"00" + "40",
108              "vendor_elements": "dd06506f9a230104"}
109    hapd = hostapd.add_ap(apdev[0], params)
110    run_scs_request(dev, hapd, True)
111
112def run_scs_request(dev, hapd, wfa):
113    register_scs_req(hapd)
114
115    dev[0].connect("scs", key_mgmt="NONE", scan_freq="2412")
116
117    hapd.dump_monitor()
118    hapd.set("ext_mgmt_frame_handling", "1")
119
120    cmd = "SCS scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffffff"
121    if "OK" not in dev[0].request(cmd):
122        raise Exception("SCS add failed")
123
124    handle_scs_req(hapd)
125    wait_scs_result(dev[0])
126
127    cmd = "SCS scs_id=2 add scs_up=5 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffffff"
128    if "OK" not in dev[0].request(cmd):
129        raise Exception("SCS add failed")
130
131    handle_scs_req(hapd, wrong_dialog=True)
132    ev = dev[0].wait_event(["CTRL-EVENT-SCS-RESULT"], timeout=2)
133    if ev is None:
134        raise Exception("No SCS result reported")
135    if "status_code=timedout" not in ev:
136        raise Exception("Timeout not reported: " + ev)
137
138    cmd = "SCS scs_id=1 add scs_up=5 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffffff"
139    if "FAIL" not in dev[0].request(cmd):
140        raise Exception("SCS add for already configured scs_id did not fail")
141
142    cmd = "SCS scs_id=1 remove"
143    if "OK" not in dev[0].request(cmd):
144        raise Exception("SCS remove failed")
145    handle_scs_req(hapd)
146    wait_scs_result(dev[0])
147
148    tests = ["scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp",
149             "scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=tcp",
150             "scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=esp",
151             "scs_up=6 classifier_type=4 ip_version=ipv6 src_ip=::1 dst_ip=::1 src_port=12345 dst_port=23456 dscp=5 next_header=udp",
152             "scs_up=6 classifier_type=4 ip_version=ipv6 src_ip=::1 dst_ip=::1 src_port=12345 dst_port=23456 dscp=5 next_header=tcp",
153             "scs_up=6 classifier_type=4 ip_version=ipv6 src_ip=::1 dst_ip=::1 src_port=12345 dst_port=23456 dscp=5 next_header=esp flow_label=012345",
154             "scs_up=6 classifier_type=10 prot_instance=1 prot_number=tcp filter_value=11223344 filter_mask=ffffffff",
155             "scs_up=6 classifier_type=10 prot_instance=1 prot_number=esp filter_value=11223344 filter_mask=ffffffff",
156             "scs_up=6 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffffff",
157             "scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=tcp tclas_processing=1",
158             "scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp scs_id=10 add scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=tcp"]
159    qos_char = "scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp qos_characteristics=direct min_si=1 max_si=9 min_data_rate=123 delay_bound=1234 max_msdu=12345 service_start_time=123456 service_start_time_link_id=0 mean_data_rate=1 burst_size=1234 msdu_lifetime=1234 msdu_delivery_info=1 medium_time=2"
160    if wfa:
161        tests.append(qos_char)
162    for t in tests:
163        cmd = "SCS scs_id=1 change " + t
164        if "OK" not in dev[0].request(cmd):
165            raise Exception("SCS change failed: " + t)
166        handle_scs_req(hapd)
167        wait_scs_result(dev[0])
168        if "scs_id=" in t:
169            wait_scs_result(dev[0], expect_status="response_not_received")
170
171    if not wfa:
172        cmd = "SCS scs_id=1 change " + qos_char
173        if "OK" in dev[0].request(cmd):
174            raise Exception("SCS change with QoS characteristics accepted unexpectedly")
175
176    cmd = "SCS scs_id=1 change scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp"
177    if "OK" not in dev[0].request(cmd):
178        raise Exception("SCS change failed: " + t)
179    if "FAIL" not in dev[0].request(cmd):
180        raise Exception("SCS change failed: " + t)
181    handle_scs_req(hapd, twice=True)
182    wait_scs_result(dev[0])
183    ev = dev[0].wait_event(["CTRL-EVENT-SCS-RESULT"], timeout=0.1)
184    if ev is not None:
185        raise Exception("Unexpected SCS result reported(1)")
186
187    if "OK" not in dev[0].request(cmd):
188        raise Exception("SCS change failed: " + t)
189    handle_scs_req(hapd, short=True)
190    ev = dev[0].wait_event(["CTRL-EVENT-SCS-RESULT"], timeout=3)
191    if ev is not None:
192        raise Exception("Unexpected SCS result reported(2)")
193
194    cmd = "SCS scs_id=123 add scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp"
195    if "OK" not in dev[0].request(cmd):
196        raise Exception("SCS add failed: " + t)
197    handle_scs_req(hapd, scsid=34)
198    wait_scs_result(dev[0], expect_status="response_not_received")
199
200    cmd = "SCS scs_id=33 add scs_up=6 classifier_type=4 ip_version=ipv4 src_ip=1.2.3.4 dst_ip=5.6.7.8 src_port=12345 dst_port=23456 dscp=5 protocol=udp"
201    if "OK" not in dev[0].request(cmd):
202        raise Exception("SCS add failed: " + t)
203    handle_scs_req(hapd, scsid=33, status_code=123)
204    wait_scs_result(dev[0], expect_status="123")
205
206def test_scs_request_without_ap_capa(dev, apdev):
207    """SCS Request without AP capability"""
208    params = {"ssid": "scs"}
209    hapd = hostapd.add_ap(apdev[0], params)
210
211    dev[0].connect("scs", key_mgmt="NONE", scan_freq="2412")
212
213    cmd = "SCS scs_id=1 add scs_up=7 classifier_type=10 prot_instance=1 prot_number=udp filter_value=11223344 filter_mask=ffffffff"
214    if "FAIL" not in dev[0].request(cmd):
215        raise Exception("SCS add accepted")
216