blob: 0c4ab2bf0bc908c3be81d14d868f51cd08b6ff48 [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 Scandoloadc72a82020-09-08 18:46:08 -070040func (s *mockService) HandleDhcp(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 Scandolo75ed5b92020-09-03 09:03:16 -070062 0, 0, 0, 0)
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 Scandoloadc72a82020-09-08 18:46:08 -0700146 s.HandleDhcp(900)
147 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 Scandoloadc72a82020-09-08 18:46:08 -0700168 s.HandleDhcp(800)
169 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
177// make sure that if the service does need DHCP we're sending any packet
178func TestService_HandleDhcp_needed(t *testing.T) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700179 s, err := createTestService(false, true)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700180
181 assert.Nil(t, err)
182
183 stream := &mockStream{
184 Calls: make(map[int]*openolt.Indication),
185 }
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700186 s.Initialize(stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700187
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700188 s.HandleDhcp(900)
189 time.Sleep(1 * time.Second)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700190
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700191 assert.Equal(t, 1, stream.CallCount)
192 assert.Equal(t, "dhcp_discovery_sent", s.DHCPState.Current())
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700193}
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700194
195// Test that if the EAPOL state machine doesn't complete in 30 seconds we
196// move it to EAPOL failed
197func TestService_EAPOLFailed(t *testing.T) {
198 // override the default wait time
199 eapolWaitTime = 500 * time.Millisecond
200 s, err := createTestService(true, false)
201
202 assert.Nil(t, err)
203
204 stream := &mockStream{
205 Calls: make(map[int]*openolt.Indication),
206 }
207 s.Initialize(stream)
208
209 // set to failed if timeout occurs
210 _ = s.EapolState.Event("start_auth")
211 time.Sleep(1 * time.Second)
212 assert.Equal(t, "auth_failed", s.EapolState.Current())
213
214 // do not set to failed if succeeded
215 s.EapolState.SetState("created")
216 _ = s.EapolState.Event("start_auth")
217 s.EapolState.SetState("eap_response_success_received")
218 time.Sleep(1 * time.Second)
219 assert.Equal(t, "eap_response_success_received", s.EapolState.Current())
220
221}
222
223// Test that if the DHCP state machine doesn't complete in 30 seconds we
224// move it to DHCP failed
225func TestService_DHCPFailed(t *testing.T) {
226 // override the default wait time
227 dhcpWaitTime = 100 * time.Millisecond
228 s, err := createTestService(false, true)
229
230 assert.Nil(t, err)
231
232 stream := &mockStream{
233 Calls: make(map[int]*openolt.Indication),
234 }
235 s.Initialize(stream)
236
237 // set to failed if timeout occurs
238 _ = s.DHCPState.Event("start_dhcp")
239 time.Sleep(1 * time.Second)
240 assert.Equal(t, "dhcp_failed", s.DHCPState.Current())
241
242 // do not set to failed if succeeded
243 s.DHCPState.SetState("created")
244 _ = s.DHCPState.Event("start_dhcp")
245 s.DHCPState.SetState("dhcp_ack_received")
246 time.Sleep(1 * time.Second)
247 assert.Equal(t, "dhcp_ack_received", s.DHCPState.Current())
248}