blob: a2b720d433d7370c79e2c14fd0b0e8b9854dcb64 [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"
Matteo Scandolo4a036262020-08-17 15:56:13 -070021 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo618a6582020-09-09 12:21:29 -070022 "github.com/opencord/voltha-protos/v3/go/openolt"
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070023 "github.com/stretchr/testify/assert"
Matteo Scandolo4a036262020-08-17 15:56:13 -070024 "net"
25 "testing"
Matteo Scandoloadc72a82020-09-08 18:46:08 -070026 "time"
Matteo Scandolo4a036262020-08-17 15:56:13 -070027)
28
29type mockService struct {
30 Name string
31 HandleAuthCallCount int
32 HandleDhcpCallCount int
33 HandlePacketsCallCount int
34}
35
Matteo Scandoloadc72a82020-09-08 18:46:08 -070036func (s *mockService) HandleAuth() {
Matteo Scandolo4a036262020-08-17 15:56:13 -070037 s.HandleAuthCallCount = s.HandleAuthCallCount + 1
38}
39
Matteo Scandolobd875b32020-09-18 17:46:31 -070040func (s *mockService) HandleDhcp(pbit uint8, cTag int) {
Matteo Scandolo4a036262020-08-17 15:56:13 -070041 s.HandleDhcpCallCount = s.HandleDhcpCallCount + 1
42}
43
Matteo Scandoloadc72a82020-09-08 18:46:08 -070044func (s *mockService) HandlePackets() {
Matteo Scandolo4a036262020-08-17 15:56:13 -070045 s.HandlePacketsCallCount = s.HandlePacketsCallCount + 1
46}
47
Matteo Scandoloadc72a82020-09-08 18:46:08 -070048func (s *mockService) Initialize(stream types.Stream) {}
49func (s *mockService) Disable() {}
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070050
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070051func createTestService(needsEapol bool, needsDchp bool) (*Service, error) {
52
53 enableContext := context.TODO()
54
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070055 mac := net.HardwareAddr{0x2e, 0x60, byte(1), byte(1), byte(1), byte(1)}
56 onu := createMockOnu(1, 1)
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070057 onu.PonPort = &PonPort{}
58 onu.PonPort.Olt = &OltDevice{}
59 onu.PonPort.Olt.enableContext = enableContext
60 return NewService("testService", mac, onu, 900, 900,
61 needsEapol, needsDchp, false, 64, 0, false,
Matteo Scandolobd875b32020-09-18 17:46:31 -070062 7, 7, 7, 7)
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070063}
64
65// test the internalState transitions
66func TestService_InternalState(t *testing.T) {
67 s, err := createTestService(false, false)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070068
69 assert.Nil(t, err)
70
71 assert.Empty(t, s.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -070072 s.Initialize(&mockStream{})
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070073
Matteo Scandoloadc72a82020-09-08 18:46:08 -070074 // check that channels have been created
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070075 assert.NotNil(t, s.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -070076 assert.NotNil(t, s.Channel)
77
78 // set EAPOL and DHCP states to something else
79 s.EapolState.SetState("eap_response_success_received")
80 s.DHCPState.SetState("dhcp_ack_received")
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070081
82 s.Disable()
Matteo Scandoloadc72a82020-09-08 18:46:08 -070083 // make sure the EAPOL and DHCP states have been reset after disable
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070084 assert.Equal(t, "created", s.EapolState.Current())
85 assert.Equal(t, "created", s.DHCPState.Current())
Matteo Scandoloadc72a82020-09-08 18:46:08 -070086
87 // make sure the channel have been closed
88 assert.Nil(t, s.Channel)
89 assert.Nil(t, s.PacketCh)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070090}
91
92// make sure that if the service does not need EAPOL we're not sending any packet
Matteo Scandolo4a036262020-08-17 15:56:13 -070093func TestService_HandleAuth_noEapol(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070094 s, err := createTestService(false, false)
Matteo Scandolo4a036262020-08-17 15:56:13 -070095
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070096 assert.Nil(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -070097
98 stream := &mockStream{
99 Calls: make(map[int]*openolt.Indication),
100 channel: make(chan int, 10),
101 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700102 s.Initialize(stream)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700103
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700104 s.HandleAuth()
105 time.Sleep(1 * time.Second)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700106
107 // if the service does not need EAPOL we don't expect any packet to be generated
108 assert.Equal(t, stream.CallCount, 0)
109
110 // state should not change
111 assert.Equal(t, s.EapolState.Current(), "created")
112}
113
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700114// make sure that if the service does need EAPOL we're sending any packet
Matteo Scandolo4a036262020-08-17 15:56:13 -0700115func TestService_HandleAuth_withEapol(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700116 s, err := createTestService(true, false)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700117
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700118 assert.Nil(t, err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700119
120 stream := &mockStream{
121 Calls: make(map[int]*openolt.Indication),
122 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700123 s.Initialize(stream)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700124
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700125 s.HandleAuth()
126 time.Sleep(1 * time.Second)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700127
128 // if the service does not need EAPOL we don't expect any packet to be generated
129 assert.Equal(t, stream.CallCount, 1)
130
131 // state should not change
132 assert.Equal(t, s.EapolState.Current(), "eap_start_sent")
133}
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700134
135// make sure that if the service does not need DHCP we're not sending any packet
136func TestService_HandleDhcp_not_needed(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700137 s, err := createTestService(false, false)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700138
139 assert.Nil(t, err)
140
141 stream := &mockStream{
142 Calls: make(map[int]*openolt.Indication),
143 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700144 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700145
Matteo Scandolobd875b32020-09-18 17:46:31 -0700146 s.HandleDhcp(7, 900)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700147 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700148
149 assert.Equal(t, stream.CallCount, 0)
150
151 // state should not change
152 assert.Equal(t, s.DHCPState.Current(), "created")
153}
154
155// when we receive a DHCP flow we call HandleDhcp an all the ONU Services
156// each service device whether the tag matches it's own configuration
157func TestService_HandleDhcp_different_c_Tag(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700158 s, err := createTestService(false, true)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700159
160 assert.Nil(t, err)
161
162 stream := &mockStream{
163 Calls: make(map[int]*openolt.Indication),
164 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700165 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700166
167 // NOTE that the c_tag is different from the one configured in the service
Matteo Scandolobd875b32020-09-18 17:46:31 -0700168 s.HandleDhcp(7, 800)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700169 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700170
171 assert.Equal(t, stream.CallCount, 0)
172
173 // state should not change
174 assert.Equal(t, s.DHCPState.Current(), "created")
175}
176
Matteo Scandolobd875b32020-09-18 17:46:31 -0700177// when we receive a DHCP flow we call HandleDhcp an all the ONU Services
178// each service device whether the tag matches it's own configuration
179func TestService_HandleDhcp_different_pbit(t *testing.T) {
180 s, err := createTestService(false, true)
181
182 assert.Nil(t, err)
183
184 stream := &mockStream{
185 Calls: make(map[int]*openolt.Indication),
186 }
187 s.Initialize(stream)
188
189 // NOTE that the c_tag is different from the one configured in the service
190 s.HandleDhcp(5, 900)
191 time.Sleep(1 * time.Second)
192
193 assert.Equal(t, stream.CallCount, 0)
194
195 // state should not change
196 assert.Equal(t, s.DHCPState.Current(), "created")
197}
198
199// if PBIT is 255 it means all of them, so start DHCP if the C_TAG matches
200func TestService_HandleDhcp_pbit_255(t *testing.T) {
201 s, err := createTestService(false, true)
202
203 assert.Nil(t, err)
204
205 stream := &mockStream{
206 Calls: make(map[int]*openolt.Indication),
207 }
208 s.Initialize(stream)
209
210 // NOTE that the c_tag is different from the one configured in the service
211 s.HandleDhcp(255, 900)
212 time.Sleep(1 * time.Second)
213
214 assert.Equal(t, 1, stream.CallCount)
215 assert.Equal(t, s.DHCPState.Current(), "dhcp_discovery_sent")
216}
217
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700218// make sure that if the service does need DHCP we're sending any packet
219func TestService_HandleDhcp_needed(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700220 s, err := createTestService(false, true)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700221
222 assert.Nil(t, err)
223
224 stream := &mockStream{
225 Calls: make(map[int]*openolt.Indication),
226 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700227 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700228
Matteo Scandolobd875b32020-09-18 17:46:31 -0700229 s.HandleDhcp(7, 900)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700230 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700231
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700232 assert.Equal(t, 1, stream.CallCount)
233 assert.Equal(t, "dhcp_discovery_sent", s.DHCPState.Current())
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700234}
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700235
236// Test that if the EAPOL state machine doesn't complete in 30 seconds we
237// move it to EAPOL failed
238func TestService_EAPOLFailed(t *testing.T) {
239 // override the default wait time
240 eapolWaitTime = 500 * time.Millisecond
241 s, err := createTestService(true, false)
242
243 assert.Nil(t, err)
244
245 stream := &mockStream{
246 Calls: make(map[int]*openolt.Indication),
247 }
248 s.Initialize(stream)
249
250 // set to failed if timeout occurs
251 _ = s.EapolState.Event("start_auth")
252 time.Sleep(1 * time.Second)
253 assert.Equal(t, "auth_failed", s.EapolState.Current())
254
255 // do not set to failed if succeeded
256 s.EapolState.SetState("created")
257 _ = s.EapolState.Event("start_auth")
258 s.EapolState.SetState("eap_response_success_received")
259 time.Sleep(1 * time.Second)
260 assert.Equal(t, "eap_response_success_received", s.EapolState.Current())
261
262}
263
264// Test that if the DHCP state machine doesn't complete in 30 seconds we
265// move it to DHCP failed
266func TestService_DHCPFailed(t *testing.T) {
267 // override the default wait time
268 dhcpWaitTime = 100 * time.Millisecond
269 s, err := createTestService(false, true)
270
271 assert.Nil(t, err)
272
273 stream := &mockStream{
274 Calls: make(map[int]*openolt.Indication),
275 }
276 s.Initialize(stream)
277
278 // set to failed if timeout occurs
279 _ = s.DHCPState.Event("start_dhcp")
280 time.Sleep(1 * time.Second)
281 assert.Equal(t, "dhcp_failed", s.DHCPState.Current())
282
283 // do not set to failed if succeeded
284 s.DHCPState.SetState("created")
285 _ = s.DHCPState.Event("start_dhcp")
286 s.DHCPState.SetState("dhcp_ack_received")
287 time.Sleep(1 * time.Second)
288 assert.Equal(t, "dhcp_ack_received", s.DHCPState.Current())
289}