blob: 64c405c6e886e1f92762d13062e802774c8fe10a [file] [log] [blame]
Zsolt Haraszti66862032016-11-28 14:28:39 -08001from time import time, sleep
2
3from google.protobuf.json_format import MessageToDict
4
5from voltha.core.flow_decomposer import *
6from voltha.protos.device_pb2 import Device
7from voltha.protos.common_pb2 import AdminState, OperStatus
8from voltha.protos import openflow_13_pb2 as ofp
9from tests.itests.voltha.rest_base import RestBase
10
11
12class TestColdActivationSequence(RestBase):
13
14 def wait_till(self, msg, predicate, interval=0.1, timeout=5.0):
15 deadline = time() + timeout
16 while time() < deadline:
17 if predicate():
18 return
19 sleep(interval)
20 self.fail('Timed out while waiting for condition: {}'.format(msg))
21
22 def test_cold_activation_sequence(self):
23 """Complex test-case to cover device activation sequence"""
24
25 self.verify_prerequisites()
26 olt_id = self.add_olt_device()
27 self.verify_device_preprovisioned_state(olt_id)
28 self.activate_device(olt_id)
29 ldev_id = self.wait_for_logical_device(olt_id)
30 onu_ids = self.wait_for_onu_discovery(olt_id)
31 self.verify_logical_ports(ldev_id)
32 self.simulate_eapol_flow_install(ldev_id, olt_id, onu_ids)
33 self.verify_olt_eapol_flow(olt_id)
34 self.verify_onu_forwarding_flows(onu_ids)
35 self.simulate_eapol_start()
36 self.simulate_eapol_request_identity()
37 self.simulate_eapol_response_identity()
38 self.simulate_eapol_request()
39 self.simulate_eapol_response()
40 self.simulate_eapol_success()
41 self.install_and_verify_dhcp_flows()
42 self.install_and_verify_igmp_flows()
43 self.install_and_verifyunicast_flows()
44
45 def verify_prerequisites(self):
46 # all we care is that Voltha is available via REST using the base uri
47 self.get('/api/v1')
48
49 def add_olt_device(self):
50 device = Device(
51 type='simulated_olt',
52 mac_address='00:00:00:00:00:01'
53 )
54 device = self.post('/api/v1/devices', MessageToDict(device),
55 expected_code=200)
56 return device['id']
57
58 def verify_device_preprovisioned_state(self, olt_id):
59 # we also check that so far what we read back is same as what we get
60 # back on create
61 device = self.get('/api/v1/devices/{}'.format(olt_id))
62 self.assertNotEqual(device['id'], '')
63 self.assertEqual(device['adapter'], 'simulated_olt')
64 self.assertEqual(device['admin_state'], 'PREPROVISIONED')
65 self.assertEqual(device['oper_status'], 'UNKNOWN')
66
67 def activate_device(self, olt_id):
68 path = '/api/v1/devices/{}'.format(olt_id)
Khen Nursimulu29e75502017-03-07 17:26:50 -050069 self.post(path + '/enable', expected_code=200)
Zsolt Haraszti66862032016-11-28 14:28:39 -080070 device = self.get(path)
71 self.assertEqual(device['admin_state'], 'ENABLED')
72
73 self.wait_till(
74 'admin state moves to ACTIVATING or ACTIVE',
75 lambda: self.get(path)['oper_status'] in ('ACTIVATING', 'ACTIVE'),
76 timeout=0.5)
77
78 # eventually, it shall move to active state and by then we shall have
79 # device details filled, connect_state set, and device ports created
80 self.wait_till(
81 'admin state ACTIVE',
82 lambda: self.get(path)['oper_status'] == 'ACTIVE',
83 timeout=0.5)
84 device = self.get(path)
85 self.assertNotEqual(device['software_version'], '')
86 self.assertEqual(device['connect_status'], 'REACHABLE')
87
88 ports = self.get(path + '/ports')['items']
89 self.assertEqual(len(ports), 2)
90
91 def wait_for_logical_device(self, olt_id):
92 # we shall find the logical device id from the parent_id of the olt
93 # (root) device
94 device = self.get(
95 '/api/v1/devices/{}'.format(olt_id))
96 self.assertNotEqual(device['parent_id'], '')
97 logical_device = self.get(
98 '/api/v1/logical_devices/{}'.format(device['parent_id']))
99
100 # the logical device shall be linked back to the hard device,
101 # its ports too
102 self.assertEqual(logical_device['root_device_id'], device['id'])
103
104 logical_ports = self.get(
105 '/api/v1/logical_devices/{}/ports'.format(
106 logical_device['id'])
107 )['items']
108 self.assertGreaterEqual(len(logical_ports), 1)
109 logical_port = logical_ports[0]
110 self.assertEqual(logical_port['id'], 'nni')
111 self.assertEqual(logical_port['ofp_port']['name'], 'nni')
112 self.assertEqual(logical_port['ofp_port']['port_no'], 129)
113 self.assertEqual(logical_port['device_id'], device['id'])
114 self.assertEqual(logical_port['device_port_no'], 2)
115 return logical_device['id']
116
117 def wait_for_onu_discovery(self, olt_id):
118 # shortly after we shall see the discovery of four new onus, linked to
119 # the olt device
120 def find_our_onus():
121 devices = self.get('/api/v1/devices')['items']
122 return [
123 d for d in devices
124 if d['parent_id'] == olt_id
125 ]
126 self.wait_till(
127 'find four ONUs linked to the olt device',
128 lambda: len(find_our_onus()) >= 4,
129 2
130 )
131
132 # verify that they are properly set
133 onus = find_our_onus()
134 for onu in onus:
135 self.assertEqual(onu['admin_state'], 'ENABLED')
136 self.assertEqual(onu['oper_status'], 'ACTIVE')
137
138 return [onu['id'] for onu in onus]
139
140 def verify_logical_ports(self, ldev_id):
141
142 # at this point we shall see at least 5 logical ports on the
143 # logical device
144 logical_ports = self.get(
145 '/api/v1/logical_devices/{}/ports'.format(ldev_id)
146 )['items']
147 self.assertGreaterEqual(len(logical_ports), 5)
148
149 # verify that all logical ports are LIVE (state=4)
150 for lport in logical_ports:
151 self.assertEqual(lport['ofp_port']['state'], 4)
152
153 def simulate_eapol_flow_install(self, ldev_id, olt_id, onu_ids):
154
155 # emulate the flow mod requests that shall arrive from the SDN
156 # controller, one for each ONU
157 lports = self.get(
158 '/api/v1/logical_devices/{}/ports'.format(ldev_id)
159 )['items']
160
161 # device_id -> logical port map, which we will use to construct
162 # our flows
163 lport_map = dict((lp['device_id'], lp) for lp in lports)
164 for onu_id in onu_ids:
165 # if eth_type == 0x888e => send to controller
166 _in_port = lport_map[onu_id]['ofp_port']['port_no']
167 req = ofp.FlowTableUpdate(
168 id='simulated1',
169 flow_mod=mk_simple_flow_mod(
170 match_fields=[
171 in_port(_in_port),
172 vlan_vid(ofp.OFPVID_PRESENT | 0),
173 eth_type(0x888e)],
174 actions=[
175 output(ofp.OFPP_CONTROLLER)
176 ],
177 priority=1000
178 )
179 )
180 res = self.post('/api/v1/logical_devices/{}/flows'.format(ldev_id),
181 MessageToDict(req,
182 preserving_proto_field_name=True),
183 expected_code=200)
184
185 # for sanity, verify that flows are in flow table of logical device
186 flows = self.get(
187 '/api/v1/logical_devices/{}/flows'.format(ldev_id))['items']
188 self.assertGreaterEqual(len(flows), 4)
189
190 def verify_olt_eapol_flow(self, olt_id):
191 # olt shall have two flow rules, one is the default and the
192 # second is the result of eapol forwarding with rule:
193 # if eth_type == 0x888e => push vlan(1000); out_port=nni_port
194 flows = self.get('/api/v1/devices/{}/flows'.format(olt_id))['items']
195 self.assertEqual(len(flows), 2)
196 flow = flows[1]
197 self.assertEqual(flow['table_id'], 0)
198 self.assertEqual(flow['priority'], 1000)
199
200 # TODO refine this
201 # self.assertEqual(flow['match'], {})
202 # self.assertEqual(flow['instructions'], [])
203
204 def verify_onu_forwarding_flows(self, onu_ids):
205 pass
206
207 def simulate_eapol_start(self):
208 pass
209
210 def simulate_eapol_request_identity(self):
211 pass
212
213 def simulate_eapol_response_identity(self):
214 pass
215
216 def simulate_eapol_request(self):
217 pass
218
219 def simulate_eapol_response(self):
220 pass
221
222 def simulate_eapol_success(self):
223 pass
224
225 def install_and_verify_dhcp_flows(self):
226 pass
227
228 def install_and_verify_igmp_flows(self):
229 pass
230
231 def install_and_verifyunicast_flows(self):
232 pass
233