[VOL-3583] Reject unexpected EAPOL packets
Change-Id: I7c164fb2815e2ab573ab3f466a373cb75c61ac86
diff --git a/internal/bbsim/devices/onu_state_machine_test.go b/internal/bbsim/devices/onu_state_machine_test.go
index ab32dd0..c1f6d8e 100644
--- a/internal/bbsim/devices/onu_state_machine_test.go
+++ b/internal/bbsim/devices/onu_state_machine_test.go
@@ -17,9 +17,11 @@
package devices
import (
+ "testing"
+
+ "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
omcilib "github.com/opencord/bbsim/internal/common/omci"
me "github.com/opencord/omci-lib-go/v2/generated"
- "testing"
"gotest.tools/assert"
)
@@ -121,7 +123,7 @@
assert.Equal(t, onu.InternalState.Current(), OnuStateEnabled)
// fail as no EapolFlow has been received
- err := onu.InternalState.Event("start_auth")
+ err := onu.InternalState.Event(eapol.EventStartAuth)
if err == nil {
t.Fatal("can't start EAPOL without EapolFlow")
}
@@ -137,7 +139,7 @@
assert.Equal(t, onu.InternalState.Current(), OnuStateEnabled)
// fail has no GemPort has been set
- err := onu.InternalState.Event("start_auth")
+ err := onu.InternalState.Event(eapol.EventStartAuth)
if err == nil {
t.Fatal("can't start EAPOL without GemPort")
}
@@ -154,33 +156,33 @@
assert.Equal(t, onu.InternalState.Current(), OnuStateEnabled)
// succeed
- _ = onu.InternalState.Event("start_auth")
- assert.Equal(t, onu.InternalState.Current(), "auth_started")
+ _ = onu.InternalState.Event(eapol.EventStartAuth)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateAuthStarted)
}
func Test_Onu_StateMachine_eapol_states(t *testing.T) {
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.InternalState.SetState("auth_started")
+ onu.InternalState.SetState(eapol.StateAuthStarted)
- assert.Equal(t, onu.InternalState.Current(), "auth_started")
- _ = onu.InternalState.Event("eap_start_sent")
- assert.Equal(t, onu.InternalState.Current(), "eap_start_sent")
- _ = onu.InternalState.Event("eap_response_identity_sent")
- assert.Equal(t, onu.InternalState.Current(), "eap_response_identity_sent")
- _ = onu.InternalState.Event("eap_response_challenge_sent")
- assert.Equal(t, onu.InternalState.Current(), "eap_response_challenge_sent")
- _ = onu.InternalState.Event("eap_response_success_received")
- assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateAuthStarted)
+ _ = onu.InternalState.Event(eapol.EventStartSent)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateStartSent)
+ _ = onu.InternalState.Event(eapol.EventResponseIdentitySent)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseIdentitySent)
+ _ = onu.InternalState.Event(eapol.EventResponseChallengeSent)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseChallengeSent)
+ _ = onu.InternalState.Event(eapol.EventResponseSuccessReceived)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseSuccessReceived)
// test that we can retrigger EAPOL
- states := []string{"eap_start_sent", "eap_response_identity_sent", "eap_response_challenge_sent", "eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}
+ states := []string{eapol.StateStartSent, eapol.StateResponseIdentitySent, eapol.StateResponseChallengeSent, eapol.StateResponseSuccessReceived, eapol.StateAuthFailed, "dhcp_ack_received", "dhcp_failed"}
for _, state := range states {
onu.InternalState.SetState(state)
- err := onu.InternalState.Event("start_auth")
+ err := onu.InternalState.Event(eapol.EventStartAuth)
assert.Equal(t, err, nil)
- assert.Equal(t, onu.InternalState.Current(), "auth_started")
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateAuthStarted)
}
}
@@ -205,14 +207,14 @@
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.InternalState.SetState("eap_response_success_received")
- assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+ onu.InternalState.SetState(eapol.StateResponseSuccessReceived)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseSuccessReceived)
err := onu.InternalState.Event("start_dhcp")
if err == nil {
t.Fail()
}
- assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseSuccessReceived)
assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-dhcp-started-as-dhcp-flow-is-missing")
}
@@ -221,14 +223,14 @@
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.InternalState.SetState("eap_response_success_received")
- assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+ onu.InternalState.SetState(eapol.StateResponseSuccessReceived)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseSuccessReceived)
err := onu.InternalState.Event("start_dhcp")
if err == nil {
t.Fail()
}
- assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseSuccessReceived)
assert.Equal(t, err.Error(), "transition canceled with error: cannot-go-to-dhcp-started-as-gemport-is-missing")
}
@@ -236,8 +238,8 @@
t.Skip("Needs to be moved in the Service struct")
onu := createTestOnu()
- onu.InternalState.SetState("eap_response_success_received")
- assert.Equal(t, onu.InternalState.Current(), "eap_response_success_received")
+ onu.InternalState.SetState(eapol.StateResponseSuccessReceived)
+ assert.Equal(t, onu.InternalState.Current(), eapol.StateResponseSuccessReceived)
// default transition
_ = onu.InternalState.Event("start_dhcp")
@@ -259,7 +261,7 @@
assert.Equal(t, onu.InternalState.Current(), "dhcp_ack_received")
// test that we can retrigger DHCP
- states := []string{"eap_response_success_received", "dhcp_discovery_sent", "dhcp_request_sent", "dhcp_ack_received", "dhcp_failed"}
+ states := []string{eapol.StateResponseSuccessReceived, "dhcp_discovery_sent", "dhcp_request_sent", "dhcp_ack_received", "dhcp_failed"}
for _, state := range states {
onu.InternalState.SetState(state)
err := onu.InternalState.Event("start_dhcp")
diff --git a/internal/bbsim/devices/service_test.go b/internal/bbsim/devices/service_test.go
index 3285021..12ea230 100644
--- a/internal/bbsim/devices/service_test.go
+++ b/internal/bbsim/devices/service_test.go
@@ -18,13 +18,15 @@
import (
"context"
+ "net"
+ "testing"
+ "time"
+
+ "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
"github.com/opencord/bbsim/internal/bbsim/types"
"github.com/opencord/bbsim/internal/common"
"github.com/opencord/voltha-protos/v5/go/openolt"
"github.com/stretchr/testify/assert"
- "net"
- "testing"
- "time"
)
type mockService struct {
@@ -80,12 +82,12 @@
assert.NotNil(t, s.Channel)
// set EAPOL and DHCP states to something else
- s.EapolState.SetState("eap_response_success_received")
+ s.EapolState.SetState(eapol.StateResponseSuccessReceived)
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, eapol.StateCreated, s.EapolState.Current())
assert.Equal(t, "created", s.DHCPState.Current())
// make sure the channel have been closed
@@ -112,7 +114,7 @@
assert.Equal(t, stream.CallCount, 0)
// state should not change
- assert.Equal(t, s.EapolState.Current(), "created")
+ assert.Equal(t, s.EapolState.Current(), eapol.StateCreated)
}
// make sure that if the service does need EAPOL we're sending any packet
@@ -133,7 +135,7 @@
assert.Equal(t, stream.CallCount, 1)
// state should not change
- assert.Equal(t, s.EapolState.Current(), "eap_start_sent")
+ assert.Equal(t, s.EapolState.Current(), eapol.StateStartSent)
}
// make sure that if the service does not need DHCP we're not sending any packet
@@ -259,16 +261,16 @@
s.Initialize(stream)
// set to failed if timeout occurs
- _ = s.EapolState.Event("start_auth")
+ _ = s.EapolState.Event(eapol.EventStartAuth)
time.Sleep(1 * time.Second)
- assert.Equal(t, "auth_failed", s.EapolState.Current())
+ assert.Equal(t, eapol.StateAuthFailed, 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")
+ s.EapolState.SetState(eapol.StateCreated)
+ _ = s.EapolState.Event(eapol.EventStartAuth)
+ s.EapolState.SetState(eapol.StateResponseSuccessReceived)
time.Sleep(1 * time.Second)
- assert.Equal(t, "eap_response_success_received", s.EapolState.Current())
+ assert.Equal(t, eapol.StateResponseSuccessReceived, s.EapolState.Current())
}
@@ -291,11 +293,11 @@
s.Initialize(stream)
// set to failed if timeout occurs
- _ = s.EapolState.Event("start_auth")
+ _ = s.EapolState.Event(eapol.EventStartAuth)
// after a second EAPOL should have failed and restarted
time.Sleep(1 * time.Second)
- assert.Equal(t, "eap_start_sent", s.EapolState.Current())
+ assert.Equal(t, eapol.StateStartSent, s.EapolState.Current())
}
// Test that if the DHCP state machine doesn't complete in 30 seconds we
diff --git a/internal/bbsim/devices/services.go b/internal/bbsim/devices/services.go
index 4b94ecf..3546e91 100644
--- a/internal/bbsim/devices/services.go
+++ b/internal/bbsim/devices/services.go
@@ -19,6 +19,9 @@
import (
"encoding/hex"
"fmt"
+ "net"
+ "time"
+
"github.com/looplab/fsm"
"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
"github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
@@ -27,8 +30,6 @@
bbsimTypes "github.com/opencord/bbsim/internal/bbsim/types"
"github.com/opencord/bbsim/internal/common"
log "github.com/sirupsen/logrus"
- "net"
- "time"
)
var serviceLogger = log.WithFields(log.Fields{
@@ -138,7 +139,7 @@
},
fmt.Sprintf("enter_%s", ServiceStateDisabled): func(e *fsm.Event) {
// reset the state machines
- service.EapolState.SetState("created")
+ service.EapolState.SetState(eapol.StateCreated)
service.DHCPState.SetState("created")
// stop listening for packets
@@ -152,26 +153,26 @@
)
service.EapolState = fsm.NewFSM(
- "created",
+ eapol.StateCreated,
fsm.Events{
- {Name: "start_auth", Src: []string{"created", "eap_response_success_received", "auth_failed"}, Dst: "auth_started"},
- {Name: "eap_start_sent", Src: []string{"auth_started"}, Dst: "eap_start_sent"},
- {Name: "eap_response_identity_sent", Src: []string{"eap_start_sent"}, Dst: "eap_response_identity_sent"},
- {Name: "eap_response_challenge_sent", Src: []string{"eap_response_identity_sent"}, Dst: "eap_response_challenge_sent"},
- {Name: "eap_response_success_received", Src: []string{"eap_response_challenge_sent"}, Dst: "eap_response_success_received"},
- {Name: "auth_failed", Src: []string{"auth_started", "eap_start_sent", "eap_response_identity_sent", "eap_response_challenge_sent"}, Dst: "auth_failed"},
+ {Name: eapol.EventStartAuth, Src: []string{eapol.StateCreated, eapol.StateResponseSuccessReceived, eapol.StateAuthFailed}, Dst: eapol.StateAuthStarted},
+ {Name: eapol.EventStartSent, Src: []string{eapol.StateAuthStarted}, Dst: eapol.StateStartSent},
+ {Name: eapol.EventResponseIdentitySent, Src: []string{eapol.StateStartSent}, Dst: eapol.StateResponseIdentitySent},
+ {Name: eapol.EventResponseChallengeSent, Src: []string{eapol.StateResponseIdentitySent}, Dst: eapol.StateResponseChallengeSent},
+ {Name: eapol.EventResponseSuccessReceived, Src: []string{eapol.StateResponseChallengeSent}, Dst: eapol.StateResponseSuccessReceived},
+ {Name: eapol.EventAuthFailed, Src: []string{eapol.StateAuthStarted, eapol.StateStartSent, eapol.StateResponseIdentitySent, eapol.StateResponseChallengeSent}, Dst: eapol.StateAuthFailed},
},
fsm.Callbacks{
"enter_state": func(e *fsm.Event) {
service.logStateChange("EapolState", e.Src, e.Dst)
},
- "before_start_auth": func(e *fsm.Event) {
+ fmt.Sprintf("before_%s", eapol.EventStartAuth): func(e *fsm.Event) {
msg := bbsimTypes.Message{
Type: bbsimTypes.StartEAPOL,
}
service.Channel <- msg
},
- "enter_auth_started": func(e *fsm.Event) {
+ fmt.Sprintf("enter_%s", eapol.StateAuthStarted): func(e *fsm.Event) {
go func() {
for {
@@ -180,7 +181,7 @@
// if the OLT is disabled, then cancel
return
case <-time.After(eapolWaitTime):
- if service.EapolState.Current() != "eap_response_success_received" {
+ if service.EapolState.Current() != eapol.StateResponseSuccessReceived {
serviceLogger.WithFields(log.Fields{
"OnuId": service.UniPort.Onu.ID,
"IntfId": service.UniPort.Onu.PonPortID,
@@ -191,9 +192,9 @@
"EapolState": service.EapolState.Current(),
}).Warn("EAPOL failed, resetting EAPOL State")
- _ = service.EapolState.Event("auth_failed")
+ _ = service.EapolState.Event(eapol.EventAuthFailed)
if common.Config.BBSim.AuthRetry {
- _ = service.EapolState.Event("start_auth")
+ _ = service.EapolState.Event(eapol.EventStartAuth)
}
return
@@ -325,7 +326,7 @@
return
}
- if err := s.EapolState.Event("start_auth"); err != nil {
+ if err := s.EapolState.Event(eapol.EventStartAuth); err != nil {
serviceLogger.WithFields(log.Fields{
"OnuId": s.UniPort.Onu.ID,
"IntfId": s.UniPort.Onu.PonPortID,
@@ -467,7 +468,7 @@
"Name": s.Name,
"err": err,
}).Error("Error while sending EapolStart packet")
- _ = s.EapolState.Event("auth_failed")
+ _ = s.EapolState.Event(eapol.EventAuthFailed)
}
case bbsimTypes.StartDHCP:
if err := s.handleDHCPStart(s.Stream); err != nil {
diff --git a/internal/bbsim/responders/eapol/eapol.go b/internal/bbsim/responders/eapol/eapol.go
index e341cef..afaee68 100644
--- a/internal/bbsim/responders/eapol/eapol.go
+++ b/internal/bbsim/responders/eapol/eapol.go
@@ -36,6 +36,24 @@
var eapolVersion uint8 = 1
+// constants for the EAPOL state machine states and events
+const (
+ StateCreated = "created"
+ StateAuthStarted = "auth_started"
+ StateStartSent = "eap_start_sent"
+ StateResponseIdentitySent = "eap_response_identity_sent"
+ StateResponseChallengeSent = "eap_response_challenge_sent"
+ StateResponseSuccessReceived = "eap_response_success_received"
+ StateAuthFailed = "auth_failed"
+
+ EventStartAuth = "start_auth"
+ EventStartSent = "eap_start_sent"
+ EventResponseIdentitySent = "eap_response_identity_sent"
+ EventResponseChallengeSent = "eap_response_challenge_sent"
+ EventResponseSuccessReceived = "eap_response_success_received"
+ EventAuthFailed = "auth_failed"
+)
+
func sendEapolPktIn(msg bbsim.ByteMsg, portNo uint32, gemid uint32, stream bbsim.Stream) error {
// FIXME unify sendDHCPPktIn and sendEapolPktIn methods
@@ -181,7 +199,7 @@
}
func updateAuthFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
- if err := onuStateMachine.Event("auth_failed"); err != nil {
+ if err := onuStateMachine.Event(EventAuthFailed); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
@@ -253,7 +271,7 @@
"GemPortId": gemPort,
}).Debug("Sent EapStart packet")
- if err := stateMachine.Event("eap_start_sent"); err != nil {
+ if err := stateMachine.Event(EventStartSent); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
@@ -327,6 +345,21 @@
}).Infof("Sent EAPIdentityRequest packet")
return
} else if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeIdentity {
+ if state := stateMachine.Current(); state != StateStartSent {
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "PortNo": portNo,
+ "UniId": uniId,
+ }).Errorf("Received EAPIdentityRequest packet while in state %q, dropped", state)
+
+ if state := stateMachine.Current(); state != StateAuthFailed && state != StateResponseSuccessReceived {
+ _ = updateAuthFailed(onuId, ponPortId, serialNumber, stateMachine)
+ }
+ return
+ }
+
reseap := createEAPIdentityResponse(eap.Id)
pkt := createEAPOLPkt(reseap, serviceId, uniId, onuId, ponPortId, oltId)
@@ -337,7 +370,7 @@
}
if err := sendEapolPktIn(msg, portNo, gemPortId, stream); err != nil {
- _ = stateMachine.Event("auth_failed")
+ _ = updateAuthFailed(onuId, ponPortId, serialNumber, stateMachine)
return
}
eapolLogger.WithFields(log.Fields{
@@ -347,7 +380,7 @@
"PortNo": portNo,
"UniId": uniId,
}).Debugf("Sent EAPIdentityResponse packet")
- if err := stateMachine.Event("eap_response_identity_sent"); err != nil {
+ if err := stateMachine.Event(EventResponseIdentitySent); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
@@ -381,6 +414,21 @@
}).Infof("Sent EAPChallengeRequest packet")
return
} else if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeOTP {
+ if state := stateMachine.Current(); state != StateResponseIdentitySent {
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "PortNo": portNo,
+ "UniId": uniId,
+ }).Errorf("Received EAPChallengeRequest packet while in state %q, dropped", state)
+
+ if state := stateMachine.Current(); state != StateAuthFailed && state != StateResponseSuccessReceived {
+ _ = updateAuthFailed(onuId, ponPortId, serialNumber, stateMachine)
+ }
+ return
+ }
+
senddata := getMD5Data(eap)
senddata = append([]byte{0x10}, senddata...)
sendeap := createEAPChallengeResponse(eap.Id, senddata)
@@ -393,7 +441,7 @@
}
if err := sendEapolPktIn(msg, portNo, gemPortId, stream); err != nil {
- _ = stateMachine.Event("auth_failed")
+ _ = updateAuthFailed(onuId, ponPortId, serialNumber, stateMachine)
return
}
eapolLogger.WithFields(log.Fields{
@@ -403,7 +451,7 @@
"PortNo": portNo,
"UniId": uniId,
}).Debugf("Sent EAPChallengeResponse packet")
- if err := stateMachine.Event("eap_response_challenge_sent"); err != nil {
+ if err := stateMachine.Event(EventResponseChallengeSent); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
@@ -442,6 +490,21 @@
}).Errorf("Error while transitioning ONU State %v", err)
}
} else if eap.Code == layers.EAPCodeSuccess && eap.Type == layers.EAPTypeNone {
+ if state := stateMachine.Current(); state != StateResponseChallengeSent {
+ log.WithFields(log.Fields{
+ "OnuId": onuId,
+ "IntfId": ponPortId,
+ "OnuSn": serialNumber,
+ "PortNo": portNo,
+ "UniId": uniId,
+ }).Errorf("Received EAP Success packet while in state %q, dropped", state)
+
+ if state := stateMachine.Current(); state != StateAuthFailed && state != StateResponseSuccessReceived {
+ _ = updateAuthFailed(onuId, ponPortId, serialNumber, stateMachine)
+ }
+ return
+ }
+
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
@@ -449,7 +512,7 @@
"PortNo": portNo,
"UniId": uniId,
}).Debugf("Received EAPSuccess packet")
- if err := stateMachine.Event("eap_response_success_received"); err != nil {
+ if err := stateMachine.Event(EventResponseSuccessReceived); err != nil {
eapolLogger.WithFields(log.Fields{
"OnuId": onuId,
"IntfId": ponPortId,
diff --git a/internal/bbsim/responders/eapol/eapol_test.go b/internal/bbsim/responders/eapol/eapol_test.go
index 21ca86b..d2f861d 100644
--- a/internal/bbsim/responders/eapol/eapol_test.go
+++ b/internal/bbsim/responders/eapol/eapol_test.go
@@ -18,10 +18,14 @@
import (
"errors"
+ "fmt"
"net"
"testing"
+ "github.com/google/gopacket"
+ "github.com/google/gopacket/layers"
"github.com/looplab/fsm"
+ "github.com/opencord/bbsim/internal/bbsim/types"
"github.com/opencord/voltha-protos/v5/go/openolt"
"google.golang.org/grpc"
"gotest.tools/assert"
@@ -30,13 +34,13 @@
// MOCKS
var eapolStateMachine = fsm.NewFSM(
- "auth_started",
+ StateAuthStarted,
fsm.Events{
- {Name: "eap_start_sent", Src: []string{"auth_started"}, Dst: "eap_start_sent"},
- {Name: "eap_response_identity_sent", Src: []string{"eap_start_sent"}, Dst: "eap_response_identity_sent"},
- {Name: "eap_response_challenge_sent", Src: []string{"eap_response_identity_sent"}, Dst: "eap_response_challenge_sent"},
- {Name: "eap_response_success_received", Src: []string{"eap_response_challenge_sent"}, Dst: "eap_response_success_received"},
- {Name: "auth_failed", Src: []string{"auth_started", "eap_start_sent", "eap_response_identity_sent", "eap_response_challenge_sent"}, Dst: "auth_failed"},
+ {Name: EventStartSent, Src: []string{StateAuthStarted}, Dst: StateStartSent},
+ {Name: EventResponseIdentitySent, Src: []string{StateStartSent}, Dst: StateResponseIdentitySent},
+ {Name: EventResponseChallengeSent, Src: []string{StateResponseIdentitySent}, Dst: StateResponseChallengeSent},
+ {Name: EventResponseSuccessReceived, Src: []string{StateResponseChallengeSent}, Dst: StateResponseSuccessReceived},
+ {Name: EventAuthFailed, Src: []string{StateAuthStarted, StateStartSent, StateResponseIdentitySent, StateResponseChallengeSent}, Dst: StateAuthFailed},
},
fsm.Callbacks{},
)
@@ -49,6 +53,8 @@
var serialNumber string = "BBSM00000001"
var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03}
var portNo uint32 = 16
+var serviceId uint32 = 0
+var oltId int = 0
type mockStream struct {
grpc.ServerStream
@@ -69,7 +75,7 @@
// TESTS
func TestSendEapStartSuccess(t *testing.T) {
- eapolStateMachine.SetState("auth_started")
+ eapolStateMachine.SetState(StateAuthStarted)
stream := &mockStream{
Calls: make(map[int]*openolt.PacketIndication),
@@ -87,13 +93,13 @@
assert.Equal(t, stream.Calls[1].IntfType, "pon")
assert.Equal(t, stream.Calls[1].GemportId, uint32(gemPortId))
- assert.Equal(t, eapolStateMachine.Current(), "eap_start_sent")
+ assert.Equal(t, eapolStateMachine.Current(), StateStartSent)
}
func TestSendEapStartFailStreamError(t *testing.T) {
- eapolStateMachine.SetState("auth_started")
+ eapolStateMachine.SetState(StateAuthStarted)
stream := &mockStream{
Calls: make(map[int]*openolt.PacketIndication),
@@ -108,7 +114,7 @@
assert.Equal(t, err.Error(), "fake-error")
- assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
+ assert.Equal(t, eapolStateMachine.Current(), StateAuthFailed)
}
// TODO test eapol.HandleNextPacket
@@ -119,28 +125,84 @@
var ponPortId uint32 = 0
var serialNumber string = "BBSM00000001"
- eapolStateMachine.SetState("auth_started")
+ eapolStateMachine.SetState(StateAuthStarted)
_ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
- eapolStateMachine.SetState("eap_start_sent")
+ eapolStateMachine.SetState(StateStartSent)
_ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
- eapolStateMachine.SetState("eap_response_identity_sent")
+ eapolStateMachine.SetState(StateResponseIdentitySent)
_ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
- eapolStateMachine.SetState("eap_response_challenge_sent")
+ eapolStateMachine.SetState(StateResponseChallengeSent)
_ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
- eapolStateMachine.SetState("eap_response_success_received")
+ eapolStateMachine.SetState(StateResponseSuccessReceived)
err := updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
if err == nil {
t.Errorf("updateAuthFailed did not return an error")
t.Fail()
}
- assert.Equal(t, err.Error(), "event auth_failed inappropriate in current state eap_response_success_received")
+ assert.Equal(t, err.Error(), fmt.Sprintf("event %s inappropriate in current state %s", EventAuthFailed, StateResponseSuccessReceived))
}
+
+func createTestEAPOLPkt(eap *layers.EAP) gopacket.Packet {
+ bytes := createEAPOLPkt(eap, serviceId, uniId, onuId, ponPortId, oltId)
+ return gopacket.NewPacket(bytes, layers.LayerTypeEthernet, gopacket.Default)
+}
+
+func handleTestEAPOLPkt(pkt gopacket.Packet, stream types.Stream) {
+ HandleNextPacket(onuId, ponPortId, gemPortId, serialNumber, portNo, uniId, serviceId, oltId, eapolStateMachine, pkt, stream, nil)
+}
+
+func TestDropUnexpectedPackets(t *testing.T) {
+ stream := &mockStream{
+ Calls: make(map[int]*openolt.PacketIndication),
+ }
+
+ const eapId uint8 = 1
+
+ //Create test packets
+ identityRequest := createEAPIdentityRequest(eapId)
+ challangeRequest := createEAPChallengeRequest(eapId, []byte{0x10})
+ success := createEAPSuccess(eapId)
+
+ identityPkt := createTestEAPOLPkt(identityRequest)
+ challangePkt := createTestEAPOLPkt(challangeRequest)
+ successPkt := createTestEAPOLPkt(success)
+
+ testStates := map[string]struct {
+ packets []gopacket.Packet
+ destinationState string
+ }{
+ //All packet should be dropped in state auth_started
+ StateAuthStarted: {[]gopacket.Packet{identityPkt, challangePkt, successPkt}, StateAuthFailed},
+ //Only the identity request packet should be handled in state eap_start_sent
+ StateStartSent: {[]gopacket.Packet{challangePkt, successPkt}, StateAuthFailed},
+ //Only the challange request packet should be handled in state eap_response_identity_sent
+ StateResponseIdentitySent: {[]gopacket.Packet{identityPkt, successPkt}, StateAuthFailed},
+ //Only the success packet should be handled in state eap_response_challenge_sent
+ StateResponseChallengeSent: {[]gopacket.Packet{identityPkt, challangePkt}, StateAuthFailed},
+ //All packet should be dropped in state eap_response_success_received
+ StateResponseSuccessReceived: {[]gopacket.Packet{identityPkt, challangePkt, successPkt}, StateResponseSuccessReceived},
+ //All packet should be dropped in state auth_failed
+ StateAuthFailed: {[]gopacket.Packet{identityPkt, challangePkt}, StateAuthFailed},
+ }
+
+ for s, info := range testStates {
+ for _, p := range info.packets {
+ eapolStateMachine.SetState(s)
+ handleTestEAPOLPkt(p, stream)
+
+ //No response should be sent
+ assert.Equal(t, stream.CallCount, 0)
+ //The state machine should transition to the failed state
+ assert.Equal(t, eapolStateMachine.Current(), info.destinationState)
+ }
+ }
+}