blob: e8fa4517a3d812b86ef004df041f68cde8c8454f [file] [log] [blame]
Matteo Scandolo813402b2019-10-23 19:24:52 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package devices
18
19import (
Matteo Scandolo813402b2019-10-23 19:24:52 -070020 "github.com/google/gopacket/layers"
21 "github.com/looplab/fsm"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080022 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolo813402b2019-10-23 19:24:52 -070023 "gotest.tools/assert"
Matteo Scandolo813402b2019-10-23 19:24:52 -070024 "testing"
25)
26
Matteo Scandolo813402b2019-10-23 19:24:52 -070027func Test_Onu_SendEapolFlow(t *testing.T) {
Matteo Scandoloc1147092019-10-29 09:38:33 -070028 onu := createMockOnu(1, 1, 900, 900, false, false)
Matteo Scandolo813402b2019-10-23 19:24:52 -070029
30 client := &mockClient{
31 FlowAddSpy: FlowAddSpy{
32 Calls: make(map[int]*openolt.Flow),
33 },
34 fail: false,
35 }
36
37 onu.sendEapolFlow(client)
38 assert.Equal(t, client.FlowAddSpy.CallCount, 1)
39
40 assert.Equal(t, client.FlowAddSpy.Calls[1].AccessIntfId, int32(onu.PonPortID))
41 assert.Equal(t, client.FlowAddSpy.Calls[1].OnuId, int32(onu.ID))
42 assert.Equal(t, client.FlowAddSpy.Calls[1].UniId, int32(0))
43 assert.Equal(t, client.FlowAddSpy.Calls[1].FlowId, onu.ID)
44 assert.Equal(t, client.FlowAddSpy.Calls[1].FlowType, "downstream")
45 assert.Equal(t, client.FlowAddSpy.Calls[1].PortNo, onu.ID)
46}
47
48// validates that when an ONU receives an EAPOL flow for UNI 0
49// it transition to auth_started state
50func Test_HandleFlowUpdateEapolFromGem(t *testing.T) {
51
Matteo Scandoloc1147092019-10-29 09:38:33 -070052 onu := createMockOnu(1, 1, 900, 900, true, false)
Matteo Scandolo813402b2019-10-23 19:24:52 -070053
54 onu.InternalState = fsm.NewFSM(
55 "gem_port_added",
56 fsm.Events{
57 {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
58 },
59 fsm.Callbacks{},
60 )
61
62 flow := openolt.Flow{
63 AccessIntfId: int32(onu.PonPortID),
64 OnuId: int32(onu.ID),
65 UniId: int32(0),
66 FlowId: uint32(onu.ID),
67 FlowType: "downstream",
68 AllocId: int32(0),
69 NetworkIntfId: int32(0),
70 Classifier: &openolt.Classifier{
71 EthType: uint32(layers.EthernetTypeEAPOL),
72 OVid: 4091,
73 },
74 Action: &openolt.Action{},
75 Priority: int32(100),
76 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
77 }
78
79 msg := OnuFlowUpdateMessage{
80 PonPortID: 1,
81 OnuID: 1,
82 Flow: &flow,
83 }
84
85 onu.handleFlowUpdate(msg)
86 assert.Equal(t, onu.InternalState.Current(), "auth_started")
87}
88
89// validates that when an ONU receives an EAPOL flow for UNI that is not 0
90// no action is taken
91func Test_HandleFlowUpdateEapolFromGemIgnore(t *testing.T) {
92
Matteo Scandoloc1147092019-10-29 09:38:33 -070093 onu := createMockOnu(1, 1, 900, 900, false, false)
Matteo Scandolo813402b2019-10-23 19:24:52 -070094
95 onu.InternalState = fsm.NewFSM(
96 "gem_port_added",
97 fsm.Events{
98 {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
99 },
100 fsm.Callbacks{},
101 )
102
103 flow := openolt.Flow{
104 AccessIntfId: int32(onu.PonPortID),
105 OnuId: int32(onu.ID),
106 UniId: int32(1),
107 FlowId: uint32(onu.ID),
108 FlowType: "downstream",
109 AllocId: int32(0),
110 NetworkIntfId: int32(0),
111 Classifier: &openolt.Classifier{
112 EthType: uint32(layers.EthernetTypeEAPOL),
113 OVid: 4091,
114 },
115 Action: &openolt.Action{},
116 Priority: int32(100),
117 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
118 }
119
120 msg := OnuFlowUpdateMessage{
121 PonPortID: 1,
122 OnuID: 1,
123 Flow: &flow,
124 }
125
126 onu.handleFlowUpdate(msg)
127 assert.Equal(t, onu.InternalState.Current(), "gem_port_added")
128}
129
130// validates that when an ONU receives an EAPOL flow for UNI 0
131// it transition to auth_started state
132func Test_HandleFlowUpdateEapolFromEnabled(t *testing.T) {
133
Matteo Scandoloc1147092019-10-29 09:38:33 -0700134 onu := createMockOnu(1, 1, 900, 900, false, false)
Matteo Scandolo813402b2019-10-23 19:24:52 -0700135
136 onu.InternalState = fsm.NewFSM(
137 "enabled",
138 fsm.Events{
139 {Name: "receive_eapol_flow", Src: []string{"enabled", "gem_port_added"}, Dst: "eapol_flow_received"},
140 },
141 fsm.Callbacks{},
142 )
143
144 flow := openolt.Flow{
145 AccessIntfId: int32(onu.PonPortID),
146 OnuId: int32(onu.ID),
147 UniId: int32(0),
148 FlowId: uint32(onu.ID),
149 FlowType: "downstream",
150 AllocId: int32(0),
151 NetworkIntfId: int32(0),
152 Classifier: &openolt.Classifier{
153 EthType: uint32(layers.EthernetTypeEAPOL),
154 OVid: 4091,
155 },
156 Action: &openolt.Action{},
157 Priority: int32(100),
158 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
159 }
160
161 msg := OnuFlowUpdateMessage{
162 PonPortID: 1,
163 OnuID: 1,
164 Flow: &flow,
165 }
166
167 onu.handleFlowUpdate(msg)
168 assert.Equal(t, onu.InternalState.Current(), "eapol_flow_received")
169}
170
171// validates that when an ONU receives an EAPOL flow for UNI that is not 0
172// no action is taken
173func Test_HandleFlowUpdateEapolFromEnabledIgnore(t *testing.T) {
174
Matteo Scandoloc1147092019-10-29 09:38:33 -0700175 onu := createMockOnu(1, 1, 900, 900, false, false)
Matteo Scandolo813402b2019-10-23 19:24:52 -0700176
177 onu.InternalState = fsm.NewFSM(
178 "enabled",
179 fsm.Events{
180 {Name: "receive_eapol_flow", Src: []string{"enabled", "gem_port_added"}, Dst: "eapol_flow_received"},
181 },
182 fsm.Callbacks{},
183 )
184
185 flow := openolt.Flow{
186 AccessIntfId: int32(onu.PonPortID),
187 OnuId: int32(onu.ID),
188 UniId: int32(1),
189 FlowId: uint32(onu.ID),
190 FlowType: "downstream",
191 AllocId: int32(0),
192 NetworkIntfId: int32(0),
193 Classifier: &openolt.Classifier{
194 EthType: uint32(layers.EthernetTypeEAPOL),
195 OVid: 4091,
196 },
197 Action: &openolt.Action{},
198 Priority: int32(100),
199 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
200 }
201
202 msg := OnuFlowUpdateMessage{
203 PonPortID: 1,
204 OnuID: 1,
205 Flow: &flow,
206 }
207
208 onu.handleFlowUpdate(msg)
209 assert.Equal(t, onu.InternalState.Current(), "enabled")
210}
211
Matteo Scandoloc1147092019-10-29 09:38:33 -0700212// validates that when an ONU receives an EAPOL flow for UNI 0
213// but the noAuth bit is set no action is taken
214func Test_HandleFlowUpdateEapolNoAuth(t *testing.T) {
215 onu := createMockOnu(1, 1, 900, 900, false, false)
216
217 onu.InternalState = fsm.NewFSM(
218 "gem_port_added",
219 fsm.Events{
220 {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
221 },
222 fsm.Callbacks{},
223 )
224
225 flow := openolt.Flow{
226 AccessIntfId: int32(onu.PonPortID),
227 OnuId: int32(onu.ID),
228 UniId: int32(0),
229 FlowId: uint32(onu.ID),
230 FlowType: "downstream",
231 AllocId: int32(0),
232 NetworkIntfId: int32(0),
233 Classifier: &openolt.Classifier{
234 EthType: uint32(layers.EthernetTypeEAPOL),
235 OVid: 4091,
236 },
237 Action: &openolt.Action{},
238 Priority: int32(100),
239 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
240 }
241
242 msg := OnuFlowUpdateMessage{
243 PonPortID: 1,
244 OnuID: 1,
245 Flow: &flow,
246 }
247
248 onu.handleFlowUpdate(msg)
249 assert.Equal(t, onu.InternalState.Current(), "gem_port_added")
250}
251
252func Test_HandleFlowUpdateDhcp(t *testing.T) {
253 onu := createMockOnu(1, 1, 900, 900, false, true)
254
255 onu.InternalState = fsm.NewFSM(
256 "eap_response_success_received",
257 fsm.Events{
258 {Name: "start_dhcp", Src: []string{"eap_response_success_received"}, Dst: "dhcp_started"},
259 },
260 fsm.Callbacks{},
261 )
262
263 flow := openolt.Flow{
264 AccessIntfId: int32(onu.PonPortID),
265 OnuId: int32(onu.ID),
266 UniId: int32(0),
267 FlowId: uint32(onu.ID),
268 FlowType: "downstream",
269 AllocId: int32(0),
270 NetworkIntfId: int32(0),
271 Classifier: &openolt.Classifier{
272 EthType: uint32(layers.EthernetTypeIPv4),
273 SrcPort: uint32(68),
274 DstPort: uint32(67),
Matteo Scandolod74abba2020-04-16 16:36:44 -0700275 OPbits: 0,
Matteo Scandoloc1147092019-10-29 09:38:33 -0700276 },
277 Action: &openolt.Action{},
278 Priority: int32(100),
279 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
280 }
281
282 msg := OnuFlowUpdateMessage{
283 PonPortID: 1,
284 OnuID: 1,
285 Flow: &flow,
286 }
287
288 onu.handleFlowUpdate(msg)
289 assert.Equal(t, onu.InternalState.Current(), "dhcp_started")
290 assert.Equal(t, onu.DhcpFlowReceived, true)
291}
292
Matteo Scandolod74abba2020-04-16 16:36:44 -0700293func Test_HandleFlowUpdateDhcpPBit255(t *testing.T) {
294 onu := createMockOnu(1, 1, 900, 900, false, true)
295
296 onu.InternalState = fsm.NewFSM(
297 "eap_response_success_received",
298 fsm.Events{
299 {Name: "start_dhcp", Src: []string{"eap_response_success_received"}, Dst: "dhcp_started"},
300 },
301 fsm.Callbacks{},
302 )
303
304 flow := openolt.Flow{
305 AccessIntfId: int32(onu.PonPortID),
306 OnuId: int32(onu.ID),
307 UniId: int32(0),
308 FlowId: uint32(onu.ID),
309 FlowType: "downstream",
310 AllocId: int32(0),
311 NetworkIntfId: int32(0),
312 Classifier: &openolt.Classifier{
313 EthType: uint32(layers.EthernetTypeIPv4),
314 SrcPort: uint32(68),
315 DstPort: uint32(67),
316 OPbits: 0,
317 },
318 Action: &openolt.Action{},
319 Priority: int32(100),
320 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
321 }
322
323 msg := OnuFlowUpdateMessage{
324 PonPortID: 1,
325 OnuID: 1,
326 Flow: &flow,
327 }
328
329 onu.handleFlowUpdate(msg)
330 assert.Equal(t, onu.InternalState.Current(), "dhcp_started")
331 assert.Equal(t, onu.DhcpFlowReceived, true)
332}
333
334func Test_HandleFlowUpdateDhcpIgnoreByPbit(t *testing.T) {
335 onu := createMockOnu(1, 1, 900, 900, false, true)
336
337 onu.InternalState = fsm.NewFSM(
338 "eap_response_success_received",
339 fsm.Events{
340 {Name: "start_dhcp", Src: []string{"eap_response_success_received"}, Dst: "dhcp_started"},
341 },
342 fsm.Callbacks{},
343 )
344
345 flow := openolt.Flow{
346 AccessIntfId: int32(onu.PonPortID),
347 OnuId: int32(onu.ID),
348 UniId: int32(0),
349 FlowId: uint32(onu.ID),
350 FlowType: "downstream",
351 AllocId: int32(0),
352 NetworkIntfId: int32(0),
353 Classifier: &openolt.Classifier{
354 EthType: uint32(layers.EthernetTypeIPv4),
355 SrcPort: uint32(68),
356 DstPort: uint32(67),
357 OPbits: 1,
358 },
359 Action: &openolt.Action{},
360 Priority: int32(100),
361 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
362 }
363
364 msg := OnuFlowUpdateMessage{
365 PonPortID: 1,
366 OnuID: 1,
367 Flow: &flow,
368 }
369
370 onu.handleFlowUpdate(msg)
371 assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
372 assert.Equal(t, onu.DhcpFlowReceived, false)
373}
374
Matteo Scandoloc1147092019-10-29 09:38:33 -0700375func Test_HandleFlowUpdateDhcpNoDhcp(t *testing.T) {
376 onu := createMockOnu(1, 1, 900, 900, false, false)
377
378 onu.InternalState = fsm.NewFSM(
379 "eap_response_success_received",
380 fsm.Events{
381 {Name: "start_dhcp", Src: []string{"eap_response_success_received"}, Dst: "dhcp_started"},
382 },
383 fsm.Callbacks{},
384 )
385
386 flow := openolt.Flow{
387 AccessIntfId: int32(onu.PonPortID),
388 OnuId: int32(onu.ID),
389 UniId: int32(0),
390 FlowId: uint32(onu.ID),
391 FlowType: "downstream",
392 AllocId: int32(0),
393 NetworkIntfId: int32(0),
394 Classifier: &openolt.Classifier{
395 EthType: uint32(layers.EthernetTypeIPv4),
396 SrcPort: uint32(68),
397 DstPort: uint32(67),
398 },
399 Action: &openolt.Action{},
400 Priority: int32(100),
401 PortNo: uint32(onu.ID), // NOTE we are using this to map an incoming packetIndication to an ONU
402 }
403
404 msg := OnuFlowUpdateMessage{
405 PonPortID: 1,
406 OnuID: 1,
407 Flow: &flow,
408 }
409
410 onu.handleFlowUpdate(msg)
411 assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
Matteo Scandolod74abba2020-04-16 16:36:44 -0700412 assert.Equal(t, onu.DhcpFlowReceived, false)
Matteo Scandoloc1147092019-10-29 09:38:33 -0700413}