blob: d26f3e9f8a5f2ed8d908366c84752a149bf0a979 [file] [log] [blame]
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001/*
Joey Armstrong2c039362024-02-04 18:51:52 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07003
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 eapol
18
19import (
Matteo Scandolo075b1892019-10-07 12:11:07 -070020 "errors"
Elia Battiston536a22b2022-01-10 10:33:15 +010021 "fmt"
Shrey Baid688b4242020-07-10 20:40:10 +053022 "net"
23 "testing"
24
Elia Battiston536a22b2022-01-10 10:33:15 +010025 "github.com/google/gopacket"
26 "github.com/google/gopacket/layers"
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070027 "github.com/looplab/fsm"
Elia Battiston536a22b2022-01-10 10:33:15 +010028 "github.com/opencord/bbsim/internal/bbsim/types"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000029 "github.com/opencord/voltha-protos/v5/go/openolt"
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070030 "google.golang.org/grpc"
31 "gotest.tools/assert"
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070032)
33
Matteo Scandolo075b1892019-10-07 12:11:07 -070034// MOCKS
Matteo Scandolo075b1892019-10-07 12:11:07 -070035
36var eapolStateMachine = fsm.NewFSM(
Elia Battiston536a22b2022-01-10 10:33:15 +010037 StateAuthStarted,
Matteo Scandolo075b1892019-10-07 12:11:07 -070038 fsm.Events{
Elia Battiston536a22b2022-01-10 10:33:15 +010039 {Name: EventStartSent, Src: []string{StateAuthStarted}, Dst: StateStartSent},
40 {Name: EventResponseIdentitySent, Src: []string{StateStartSent}, Dst: StateResponseIdentitySent},
41 {Name: EventResponseChallengeSent, Src: []string{StateResponseIdentitySent}, Dst: StateResponseChallengeSent},
42 {Name: EventResponseSuccessReceived, Src: []string{StateResponseChallengeSent}, Dst: StateResponseSuccessReceived},
43 {Name: EventAuthFailed, Src: []string{StateAuthStarted, StateStartSent, StateResponseIdentitySent, StateResponseChallengeSent}, Dst: StateAuthFailed},
Matteo Scandolo075b1892019-10-07 12:11:07 -070044 },
45 fsm.Callbacks{},
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070046)
47
Matteo Scandolo27428702019-10-11 16:21:16 -070048// params for the function under test
49var onuId uint32 = 1
Matteo Scandolo4a036262020-08-17 15:56:13 -070050var gemPortId uint32 = 1
Matteo Scandolo27428702019-10-11 16:21:16 -070051var ponPortId uint32 = 0
Matteo Scandolo8a574812021-05-20 15:18:53 -070052var uniId uint32 = 0
Matteo Scandolo27428702019-10-11 16:21:16 -070053var serialNumber string = "BBSM00000001"
54var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03}
55var portNo uint32 = 16
Elia Battiston536a22b2022-01-10 10:33:15 +010056var serviceId uint32 = 0
57var oltId int = 0
Matteo Scandolo27428702019-10-11 16:21:16 -070058
59type mockStream struct {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070060 grpc.ServerStream
Matteo Scandolo27428702019-10-11 16:21:16 -070061 CallCount int
62 Calls map[int]*openolt.PacketIndication
63 fail bool
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070064}
65
Matteo Scandolo27428702019-10-11 16:21:16 -070066func (s *mockStream) Send(ind *openolt.Indication) error {
67 s.CallCount++
68 if s.fail {
69 return errors.New("fake-error")
70 }
71 s.Calls[s.CallCount] = ind.GetPktInd()
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070072 return nil
73}
74
Matteo Scandolo075b1892019-10-07 12:11:07 -070075// TESTS
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070076
Matteo Scandolo075b1892019-10-07 12:11:07 -070077func TestSendEapStartSuccess(t *testing.T) {
Elia Battiston536a22b2022-01-10 10:33:15 +010078 eapolStateMachine.SetState(StateAuthStarted)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070079
Matteo Scandolo27428702019-10-11 16:21:16 -070080 stream := &mockStream{
81 Calls: make(map[int]*openolt.PacketIndication),
82 fail: false,
83 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070084
Matteo Scandolo8a574812021-05-20 15:18:53 -070085 if err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, gemPortId, uniId, eapolStateMachine, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -070086 t.Errorf("SendEapStart returned an error: %v", err)
87 t.Fail()
88 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070089
Matteo Scandolo27428702019-10-11 16:21:16 -070090 assert.Equal(t, stream.CallCount, 1)
91 assert.Equal(t, stream.Calls[1].PortNo, portNo)
92 assert.Equal(t, stream.Calls[1].IntfId, ponPortId)
93 assert.Equal(t, stream.Calls[1].IntfType, "pon")
94 assert.Equal(t, stream.Calls[1].GemportId, uint32(gemPortId))
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070095
Elia Battiston536a22b2022-01-10 10:33:15 +010096 assert.Equal(t, eapolStateMachine.Current(), StateStartSent)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070097
Matteo Scandolo075b1892019-10-07 12:11:07 -070098}
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070099
Matteo Scandolo075b1892019-10-07 12:11:07 -0700100func TestSendEapStartFailStreamError(t *testing.T) {
Matteo Scandolo27428702019-10-11 16:21:16 -0700101
Elia Battiston536a22b2022-01-10 10:33:15 +0100102 eapolStateMachine.SetState(StateAuthStarted)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700103
Matteo Scandolo27428702019-10-11 16:21:16 -0700104 stream := &mockStream{
105 Calls: make(map[int]*openolt.PacketIndication),
106 fail: true,
107 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700108
Matteo Scandolo8a574812021-05-20 15:18:53 -0700109 err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, gemPortId, uniId, eapolStateMachine, stream)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700110 if err == nil {
111 t.Errorf("SendEapStart did not return an error")
112 t.Fail()
113 }
114
Matteo Scandolo27428702019-10-11 16:21:16 -0700115 assert.Equal(t, err.Error(), "fake-error")
Matteo Scandolo075b1892019-10-07 12:11:07 -0700116
Elia Battiston536a22b2022-01-10 10:33:15 +0100117 assert.Equal(t, eapolStateMachine.Current(), StateAuthFailed)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700118}
119
120// TODO test eapol.HandleNextPacket
121
122func TestUpdateAuthFailed(t *testing.T) {
123
124 var onuId uint32 = 1
125 var ponPortId uint32 = 0
126 var serialNumber string = "BBSM00000001"
127
Elia Battiston536a22b2022-01-10 10:33:15 +0100128 eapolStateMachine.SetState(StateAuthStarted)
Shrey Baid688b4242020-07-10 20:40:10 +0530129 _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700130 assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
131
Elia Battiston536a22b2022-01-10 10:33:15 +0100132 eapolStateMachine.SetState(StateStartSent)
Shrey Baid688b4242020-07-10 20:40:10 +0530133 _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700134 assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
135
Elia Battiston536a22b2022-01-10 10:33:15 +0100136 eapolStateMachine.SetState(StateResponseIdentitySent)
Shrey Baid688b4242020-07-10 20:40:10 +0530137 _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700138 assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
139
Elia Battiston536a22b2022-01-10 10:33:15 +0100140 eapolStateMachine.SetState(StateResponseChallengeSent)
Shrey Baid688b4242020-07-10 20:40:10 +0530141 _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700142 assert.Equal(t, eapolStateMachine.Current(), "auth_failed")
143
Elia Battiston536a22b2022-01-10 10:33:15 +0100144 eapolStateMachine.SetState(StateResponseSuccessReceived)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700145 err := updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine)
146 if err == nil {
147 t.Errorf("updateAuthFailed did not return an error")
148 t.Fail()
149 }
Elia Battiston536a22b2022-01-10 10:33:15 +0100150 assert.Equal(t, err.Error(), fmt.Sprintf("event %s inappropriate in current state %s", EventAuthFailed, StateResponseSuccessReceived))
Matteo Scandolo075b1892019-10-07 12:11:07 -0700151
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700152}
Elia Battiston536a22b2022-01-10 10:33:15 +0100153
154func createTestEAPOLPkt(eap *layers.EAP) gopacket.Packet {
155 bytes := createEAPOLPkt(eap, serviceId, uniId, onuId, ponPortId, oltId)
156 return gopacket.NewPacket(bytes, layers.LayerTypeEthernet, gopacket.Default)
157}
158
159func handleTestEAPOLPkt(pkt gopacket.Packet, stream types.Stream) {
160 HandleNextPacket(onuId, ponPortId, gemPortId, serialNumber, portNo, uniId, serviceId, oltId, eapolStateMachine, pkt, stream, nil)
161}
162
163func TestDropUnexpectedPackets(t *testing.T) {
164 stream := &mockStream{
165 Calls: make(map[int]*openolt.PacketIndication),
166 }
167
168 const eapId uint8 = 1
169
170 //Create test packets
171 identityRequest := createEAPIdentityRequest(eapId)
172 challangeRequest := createEAPChallengeRequest(eapId, []byte{0x10})
173 success := createEAPSuccess(eapId)
174
175 identityPkt := createTestEAPOLPkt(identityRequest)
176 challangePkt := createTestEAPOLPkt(challangeRequest)
177 successPkt := createTestEAPOLPkt(success)
178
179 testStates := map[string]struct {
180 packets []gopacket.Packet
181 destinationState string
182 }{
183 //All packet should be dropped in state auth_started
184 StateAuthStarted: {[]gopacket.Packet{identityPkt, challangePkt, successPkt}, StateAuthFailed},
185 //Only the identity request packet should be handled in state eap_start_sent
186 StateStartSent: {[]gopacket.Packet{challangePkt, successPkt}, StateAuthFailed},
187 //Only the challange request packet should be handled in state eap_response_identity_sent
188 StateResponseIdentitySent: {[]gopacket.Packet{identityPkt, successPkt}, StateAuthFailed},
189 //Only the success packet should be handled in state eap_response_challenge_sent
190 StateResponseChallengeSent: {[]gopacket.Packet{identityPkt, challangePkt}, StateAuthFailed},
191 //All packet should be dropped in state eap_response_success_received
192 StateResponseSuccessReceived: {[]gopacket.Packet{identityPkt, challangePkt, successPkt}, StateResponseSuccessReceived},
193 //All packet should be dropped in state auth_failed
194 StateAuthFailed: {[]gopacket.Packet{identityPkt, challangePkt}, StateAuthFailed},
195 }
196
197 for s, info := range testStates {
198 for _, p := range info.packets {
199 eapolStateMachine.SetState(s)
200 handleTestEAPOLPkt(p, stream)
201
202 //No response should be sent
203 assert.Equal(t, stream.CallCount, 0)
204 //The state machine should transition to the failed state
205 assert.Equal(t, eapolStateMachine.Current(), info.destinationState)
206 }
207 }
208}