blob: 12ea23025ebfc9c9380ddee47c4b6270562b0e54 [file] [log] [blame]
Matteo Scandolo4a036262020-08-17 15:56:13 -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 Scandoloe9f5a6b2020-09-16 15:54:38 -070020 "context"
Elia Battiston536a22b2022-01-10 10:33:15 +010021 "net"
22 "testing"
23 "time"
24
25 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
Matteo Scandolo4a036262020-08-17 15:56:13 -070026 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo76c3ff62020-09-24 18:03:01 -070027 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000028 "github.com/opencord/voltha-protos/v5/go/openolt"
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070029 "github.com/stretchr/testify/assert"
Matteo Scandolo4a036262020-08-17 15:56:13 -070030)
31
32type mockService struct {
33 Name string
34 HandleAuthCallCount int
35 HandleDhcpCallCount int
36 HandlePacketsCallCount int
37}
38
Matteo Scandoloadc72a82020-09-08 18:46:08 -070039func (s *mockService) HandleAuth() {
Matteo Scandolo4a036262020-08-17 15:56:13 -070040 s.HandleAuthCallCount = s.HandleAuthCallCount + 1
41}
42
Matteo Scandolobd875b32020-09-18 17:46:31 -070043func (s *mockService) HandleDhcp(pbit uint8, cTag int) {
Matteo Scandolo4a036262020-08-17 15:56:13 -070044 s.HandleDhcpCallCount = s.HandleDhcpCallCount + 1
45}
46
Matteo Scandoloadc72a82020-09-08 18:46:08 -070047func (s *mockService) HandlePackets() {
Matteo Scandolo4a036262020-08-17 15:56:13 -070048 s.HandlePacketsCallCount = s.HandlePacketsCallCount + 1
49}
50
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -070051func (s *mockService) Initialize(stream types.Stream) {}
52func (s *mockService) UpdateStream(stream types.Stream) {}
53func (s *mockService) Disable() {}
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070054
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070055func createTestService(needsEapol bool, needsDchp bool) (*Service, error) {
56
57 enableContext := context.TODO()
58
Matteo Scandolo8a574812021-05-20 15:18:53 -070059 mac := net.HardwareAddr{0x2e, byte(1), byte(1), byte(1), byte(1), byte(1)}
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070060 onu := createMockOnu(1, 1)
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070061 onu.PonPort = &PonPort{}
62 onu.PonPort.Olt = &OltDevice{}
63 onu.PonPort.Olt.enableContext = enableContext
Matteo Scandolo8a574812021-05-20 15:18:53 -070064
65 uni := UniPort{ID: 1, Onu: onu}
66 return NewService(0, "testService", mac, &uni, 900, 900,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070067 needsEapol, needsDchp, false, 64, 0, false,
Matteo Scandolobd875b32020-09-18 17:46:31 -070068 7, 7, 7, 7)
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070069}
70
71// test the internalState transitions
72func TestService_InternalState(t *testing.T) {
73 s, err := createTestService(false, false)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070074
75 assert.Nil(t, err)
76
77 assert.Empty(t, s.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -070078 s.Initialize(&mockStream{})
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070079
Matteo Scandoloadc72a82020-09-08 18:46:08 -070080 // check that channels have been created
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070081 assert.NotNil(t, s.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -070082 assert.NotNil(t, s.Channel)
83
84 // set EAPOL and DHCP states to something else
Elia Battiston536a22b2022-01-10 10:33:15 +010085 s.EapolState.SetState(eapol.StateResponseSuccessReceived)
Matteo Scandoloadc72a82020-09-08 18:46:08 -070086 s.DHCPState.SetState("dhcp_ack_received")
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070087
88 s.Disable()
Matteo Scandoloadc72a82020-09-08 18:46:08 -070089 // make sure the EAPOL and DHCP states have been reset after disable
Elia Battiston536a22b2022-01-10 10:33:15 +010090 assert.Equal(t, eapol.StateCreated, s.EapolState.Current())
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070091 assert.Equal(t, "created", s.DHCPState.Current())
Matteo Scandoloadc72a82020-09-08 18:46:08 -070092
93 // make sure the channel have been closed
94 assert.Nil(t, s.Channel)
95 assert.Nil(t, s.PacketCh)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070096}
97
98// make sure that if the service does not need EAPOL we're not sending any packet
Matteo Scandolo4a036262020-08-17 15:56:13 -070099func TestService_HandleAuth_noEapol(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700100 s, err := createTestService(false, false)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700101
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700102 assert.Nil(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700103
104 stream := &mockStream{
105 Calls: make(map[int]*openolt.Indication),
106 channel: make(chan int, 10),
107 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700108 s.Initialize(stream)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700109
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700110 s.HandleAuth()
111 time.Sleep(1 * time.Second)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700112
113 // if the service does not need EAPOL we don't expect any packet to be generated
114 assert.Equal(t, stream.CallCount, 0)
115
116 // state should not change
Elia Battiston536a22b2022-01-10 10:33:15 +0100117 assert.Equal(t, s.EapolState.Current(), eapol.StateCreated)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700118}
119
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700120// make sure that if the service does need EAPOL we're sending any packet
Matteo Scandolo4a036262020-08-17 15:56:13 -0700121func TestService_HandleAuth_withEapol(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700122 s, err := createTestService(true, false)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700123
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700124 assert.Nil(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700125
126 stream := &mockStream{
127 Calls: make(map[int]*openolt.Indication),
128 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700129 s.Initialize(stream)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700130
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700131 s.HandleAuth()
132 time.Sleep(1 * time.Second)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700133
134 // if the service does not need EAPOL we don't expect any packet to be generated
135 assert.Equal(t, stream.CallCount, 1)
136
137 // state should not change
Elia Battiston536a22b2022-01-10 10:33:15 +0100138 assert.Equal(t, s.EapolState.Current(), eapol.StateStartSent)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700139}
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700140
141// make sure that if the service does not need DHCP we're not sending any packet
142func TestService_HandleDhcp_not_needed(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700143 s, err := createTestService(false, false)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700144
145 assert.Nil(t, err)
146
147 stream := &mockStream{
148 Calls: make(map[int]*openolt.Indication),
149 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700150 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700151
Matteo Scandolobd875b32020-09-18 17:46:31 -0700152 s.HandleDhcp(7, 900)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700153 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700154
155 assert.Equal(t, stream.CallCount, 0)
156
157 // state should not change
158 assert.Equal(t, s.DHCPState.Current(), "created")
159}
160
161// when we receive a DHCP flow we call HandleDhcp an all the ONU Services
162// each service device whether the tag matches it's own configuration
163func TestService_HandleDhcp_different_c_Tag(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700164 s, err := createTestService(false, true)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700165
166 assert.Nil(t, err)
167
168 stream := &mockStream{
169 Calls: make(map[int]*openolt.Indication),
170 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700171 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700172
173 // NOTE that the c_tag is different from the one configured in the service
Matteo Scandolobd875b32020-09-18 17:46:31 -0700174 s.HandleDhcp(7, 800)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700175 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700176
177 assert.Equal(t, stream.CallCount, 0)
178
179 // state should not change
180 assert.Equal(t, s.DHCPState.Current(), "created")
181}
182
Matteo Scandolobd875b32020-09-18 17:46:31 -0700183// when we receive a DHCP flow we call HandleDhcp an all the ONU Services
184// each service device whether the tag matches it's own configuration
185func TestService_HandleDhcp_different_pbit(t *testing.T) {
186 s, err := createTestService(false, true)
187
188 assert.Nil(t, err)
189
190 stream := &mockStream{
191 Calls: make(map[int]*openolt.Indication),
192 }
193 s.Initialize(stream)
194
195 // NOTE that the c_tag is different from the one configured in the service
196 s.HandleDhcp(5, 900)
197 time.Sleep(1 * time.Second)
198
199 assert.Equal(t, stream.CallCount, 0)
200
201 // state should not change
202 assert.Equal(t, s.DHCPState.Current(), "created")
203}
204
205// if PBIT is 255 it means all of them, so start DHCP if the C_TAG matches
206func TestService_HandleDhcp_pbit_255(t *testing.T) {
207 s, err := createTestService(false, true)
208
209 assert.Nil(t, err)
210
211 stream := &mockStream{
212 Calls: make(map[int]*openolt.Indication),
213 }
214 s.Initialize(stream)
215
216 // NOTE that the c_tag is different from the one configured in the service
217 s.HandleDhcp(255, 900)
218 time.Sleep(1 * time.Second)
219
220 assert.Equal(t, 1, stream.CallCount)
221 assert.Equal(t, s.DHCPState.Current(), "dhcp_discovery_sent")
222}
223
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700224// make sure that if the service does need DHCP we're sending any packet
225func TestService_HandleDhcp_needed(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700226 s, err := createTestService(false, true)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700227
228 assert.Nil(t, err)
229
230 stream := &mockStream{
231 Calls: make(map[int]*openolt.Indication),
232 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700233 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700234
Matteo Scandolobd875b32020-09-18 17:46:31 -0700235 s.HandleDhcp(7, 900)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700236 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700237
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700238 assert.Equal(t, 1, stream.CallCount)
239 assert.Equal(t, "dhcp_discovery_sent", s.DHCPState.Current())
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700240}
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700241
242// Test that if the EAPOL state machine doesn't complete in 30 seconds we
243// move it to EAPOL failed
244func TestService_EAPOLFailed(t *testing.T) {
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700245
246 common.Config = &common.GlobalConfig{
247 BBSim: common.BBSimConfig{
248 AuthRetry: false,
249 },
250 }
251
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700252 // override the default wait time
253 eapolWaitTime = 500 * time.Millisecond
254 s, err := createTestService(true, false)
255
256 assert.Nil(t, err)
257
258 stream := &mockStream{
259 Calls: make(map[int]*openolt.Indication),
260 }
261 s.Initialize(stream)
262
263 // set to failed if timeout occurs
Elia Battiston536a22b2022-01-10 10:33:15 +0100264 _ = s.EapolState.Event(eapol.EventStartAuth)
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700265 time.Sleep(1 * time.Second)
Elia Battiston536a22b2022-01-10 10:33:15 +0100266 assert.Equal(t, eapol.StateAuthFailed, s.EapolState.Current())
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700267
268 // do not set to failed if succeeded
Elia Battiston536a22b2022-01-10 10:33:15 +0100269 s.EapolState.SetState(eapol.StateCreated)
270 _ = s.EapolState.Event(eapol.EventStartAuth)
271 s.EapolState.SetState(eapol.StateResponseSuccessReceived)
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700272 time.Sleep(1 * time.Second)
Elia Battiston536a22b2022-01-10 10:33:15 +0100273 assert.Equal(t, eapol.StateResponseSuccessReceived, s.EapolState.Current())
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700274
275}
276
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700277func TestService_EAPOLRestart(t *testing.T) {
278
279 common.Config = &common.GlobalConfig{
280 BBSim: common.BBSimConfig{
281 AuthRetry: true,
282 },
283 }
284
285 eapolWaitTime = 500 * time.Millisecond
286 s, err := createTestService(true, false)
287
288 assert.Nil(t, err)
289
290 stream := &mockStream{
291 Calls: make(map[int]*openolt.Indication),
292 }
293 s.Initialize(stream)
294
295 // set to failed if timeout occurs
Elia Battiston536a22b2022-01-10 10:33:15 +0100296 _ = s.EapolState.Event(eapol.EventStartAuth)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700297
298 // after a second EAPOL should have failed and restarted
299 time.Sleep(1 * time.Second)
Elia Battiston536a22b2022-01-10 10:33:15 +0100300 assert.Equal(t, eapol.StateStartSent, s.EapolState.Current())
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700301}
302
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700303// Test that if the DHCP state machine doesn't complete in 30 seconds we
304// move it to DHCP failed
305func TestService_DHCPFailed(t *testing.T) {
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700306
307 common.Config = &common.GlobalConfig{
308 BBSim: common.BBSimConfig{
309 DhcpRetry: false,
310 },
311 }
312
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700313 // override the default wait time
314 dhcpWaitTime = 100 * time.Millisecond
315 s, err := createTestService(false, true)
316
317 assert.Nil(t, err)
318
319 stream := &mockStream{
320 Calls: make(map[int]*openolt.Indication),
321 }
322 s.Initialize(stream)
323
324 // set to failed if timeout occurs
325 _ = s.DHCPState.Event("start_dhcp")
326 time.Sleep(1 * time.Second)
327 assert.Equal(t, "dhcp_failed", s.DHCPState.Current())
328
329 // do not set to failed if succeeded
330 s.DHCPState.SetState("created")
331 _ = s.DHCPState.Event("start_dhcp")
332 s.DHCPState.SetState("dhcp_ack_received")
333 time.Sleep(1 * time.Second)
334 assert.Equal(t, "dhcp_ack_received", s.DHCPState.Current())
335}
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700336
337func TestService_DHCPRestart(t *testing.T) {
338 common.Config = &common.GlobalConfig{
339 BBSim: common.BBSimConfig{
340 DhcpRetry: true,
341 },
342 }
343
344 // override the default wait time
345 dhcpWaitTime = 100 * time.Millisecond
346 s, err := createTestService(false, true)
347
348 assert.Nil(t, err)
349
350 stream := &mockStream{
351 Calls: make(map[int]*openolt.Indication),
352 }
353 s.Initialize(stream)
354
355 // set to failed if timeout occurs
356 _ = s.DHCPState.Event("start_dhcp")
357 time.Sleep(1 * time.Second)
358 assert.Equal(t, "dhcp_discovery_sent", s.DHCPState.Current())
359}