blob: 548a14ab3b5bdfa958bf465d46138bf6802cb666 [file] [log] [blame]
/*
* Copyright 2018-present Open Networking Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package devices
import (
"context"
"github.com/opencord/bbsim/internal/bbsim/types"
"github.com/opencord/bbsim/internal/common"
"github.com/opencord/voltha-protos/v3/go/openolt"
"github.com/stretchr/testify/assert"
"net"
"testing"
"time"
)
type mockService struct {
Name string
HandleAuthCallCount int
HandleDhcpCallCount int
HandlePacketsCallCount int
}
func (s *mockService) HandleAuth() {
s.HandleAuthCallCount = s.HandleAuthCallCount + 1
}
func (s *mockService) HandleDhcp(pbit uint8, cTag int) {
s.HandleDhcpCallCount = s.HandleDhcpCallCount + 1
}
func (s *mockService) HandlePackets() {
s.HandlePacketsCallCount = s.HandlePacketsCallCount + 1
}
func (s *mockService) Initialize(stream types.Stream) {}
func (s *mockService) Disable() {}
func createTestService(needsEapol bool, needsDchp bool) (*Service, error) {
enableContext := context.TODO()
mac := net.HardwareAddr{0x2e, 0x60, byte(1), byte(1), byte(1), byte(1)}
onu := createMockOnu(1, 1)
onu.PonPort = &PonPort{}
onu.PonPort.Olt = &OltDevice{}
onu.PonPort.Olt.enableContext = enableContext
return NewService("testService", mac, onu, 900, 900,
needsEapol, needsDchp, false, 64, 0, false,
7, 7, 7, 7)
}
// test the internalState transitions
func TestService_InternalState(t *testing.T) {
s, err := createTestService(false, false)
assert.Nil(t, err)
assert.Empty(t, s.PacketCh)
s.Initialize(&mockStream{})
// check that channels have been created
assert.NotNil(t, s.PacketCh)
assert.NotNil(t, s.Channel)
// set EAPOL and DHCP states to something else
s.EapolState.SetState("eap_response_success_received")
s.DHCPState.SetState("dhcp_ack_received")
s.Disable()
// make sure the EAPOL and DHCP states have been reset after disable
assert.Equal(t, "created", s.EapolState.Current())
assert.Equal(t, "created", s.DHCPState.Current())
// make sure the channel have been closed
assert.Nil(t, s.Channel)
assert.Nil(t, s.PacketCh)
}
// make sure that if the service does not need EAPOL we're not sending any packet
func TestService_HandleAuth_noEapol(t *testing.T) {
s, err := createTestService(false, false)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
channel: make(chan int, 10),
}
s.Initialize(stream)
s.HandleAuth()
time.Sleep(1 * time.Second)
// if the service does not need EAPOL we don't expect any packet to be generated
assert.Equal(t, stream.CallCount, 0)
// state should not change
assert.Equal(t, s.EapolState.Current(), "created")
}
// make sure that if the service does need EAPOL we're sending any packet
func TestService_HandleAuth_withEapol(t *testing.T) {
s, err := createTestService(true, false)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
s.HandleAuth()
time.Sleep(1 * time.Second)
// if the service does not need EAPOL we don't expect any packet to be generated
assert.Equal(t, stream.CallCount, 1)
// state should not change
assert.Equal(t, s.EapolState.Current(), "eap_start_sent")
}
// make sure that if the service does not need DHCP we're not sending any packet
func TestService_HandleDhcp_not_needed(t *testing.T) {
s, err := createTestService(false, false)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
s.HandleDhcp(7, 900)
time.Sleep(1 * time.Second)
assert.Equal(t, stream.CallCount, 0)
// state should not change
assert.Equal(t, s.DHCPState.Current(), "created")
}
// when we receive a DHCP flow we call HandleDhcp an all the ONU Services
// each service device whether the tag matches it's own configuration
func TestService_HandleDhcp_different_c_Tag(t *testing.T) {
s, err := createTestService(false, true)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// NOTE that the c_tag is different from the one configured in the service
s.HandleDhcp(7, 800)
time.Sleep(1 * time.Second)
assert.Equal(t, stream.CallCount, 0)
// state should not change
assert.Equal(t, s.DHCPState.Current(), "created")
}
// when we receive a DHCP flow we call HandleDhcp an all the ONU Services
// each service device whether the tag matches it's own configuration
func TestService_HandleDhcp_different_pbit(t *testing.T) {
s, err := createTestService(false, true)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// NOTE that the c_tag is different from the one configured in the service
s.HandleDhcp(5, 900)
time.Sleep(1 * time.Second)
assert.Equal(t, stream.CallCount, 0)
// state should not change
assert.Equal(t, s.DHCPState.Current(), "created")
}
// if PBIT is 255 it means all of them, so start DHCP if the C_TAG matches
func TestService_HandleDhcp_pbit_255(t *testing.T) {
s, err := createTestService(false, true)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// NOTE that the c_tag is different from the one configured in the service
s.HandleDhcp(255, 900)
time.Sleep(1 * time.Second)
assert.Equal(t, 1, stream.CallCount)
assert.Equal(t, s.DHCPState.Current(), "dhcp_discovery_sent")
}
// make sure that if the service does need DHCP we're sending any packet
func TestService_HandleDhcp_needed(t *testing.T) {
s, err := createTestService(false, true)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
s.HandleDhcp(7, 900)
time.Sleep(1 * time.Second)
assert.Equal(t, 1, stream.CallCount)
assert.Equal(t, "dhcp_discovery_sent", s.DHCPState.Current())
}
// Test that if the EAPOL state machine doesn't complete in 30 seconds we
// move it to EAPOL failed
func TestService_EAPOLFailed(t *testing.T) {
common.Config = &common.GlobalConfig{
BBSim: common.BBSimConfig{
AuthRetry: false,
},
}
// override the default wait time
eapolWaitTime = 500 * time.Millisecond
s, err := createTestService(true, false)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// set to failed if timeout occurs
_ = s.EapolState.Event("start_auth")
time.Sleep(1 * time.Second)
assert.Equal(t, "auth_failed", s.EapolState.Current())
// do not set to failed if succeeded
s.EapolState.SetState("created")
_ = s.EapolState.Event("start_auth")
s.EapolState.SetState("eap_response_success_received")
time.Sleep(1 * time.Second)
assert.Equal(t, "eap_response_success_received", s.EapolState.Current())
}
func TestService_EAPOLRestart(t *testing.T) {
common.Config = &common.GlobalConfig{
BBSim: common.BBSimConfig{
AuthRetry: true,
},
}
eapolWaitTime = 500 * time.Millisecond
s, err := createTestService(true, false)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// set to failed if timeout occurs
_ = s.EapolState.Event("start_auth")
// after a second EAPOL should have failed and restarted
time.Sleep(1 * time.Second)
assert.Equal(t, "eap_start_sent", s.EapolState.Current())
}
// Test that if the DHCP state machine doesn't complete in 30 seconds we
// move it to DHCP failed
func TestService_DHCPFailed(t *testing.T) {
common.Config = &common.GlobalConfig{
BBSim: common.BBSimConfig{
DhcpRetry: false,
},
}
// override the default wait time
dhcpWaitTime = 100 * time.Millisecond
s, err := createTestService(false, true)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// set to failed if timeout occurs
_ = s.DHCPState.Event("start_dhcp")
time.Sleep(1 * time.Second)
assert.Equal(t, "dhcp_failed", s.DHCPState.Current())
// do not set to failed if succeeded
s.DHCPState.SetState("created")
_ = s.DHCPState.Event("start_dhcp")
s.DHCPState.SetState("dhcp_ack_received")
time.Sleep(1 * time.Second)
assert.Equal(t, "dhcp_ack_received", s.DHCPState.Current())
}
func TestService_DHCPRestart(t *testing.T) {
common.Config = &common.GlobalConfig{
BBSim: common.BBSimConfig{
DhcpRetry: true,
},
}
// override the default wait time
dhcpWaitTime = 100 * time.Millisecond
s, err := createTestService(false, true)
assert.Nil(t, err)
stream := &mockStream{
Calls: make(map[int]*openolt.Indication),
}
s.Initialize(stream)
// set to failed if timeout occurs
_ = s.DHCPState.Event("start_dhcp")
time.Sleep(1 * time.Second)
assert.Equal(t, "dhcp_discovery_sent", s.DHCPState.Current())
}