Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 1 | /* |
Joey Armstrong | 2c03936 | 2024-02-04 18:51:52 -0500 | [diff] [blame^] | 2 | * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 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 | |
| 17 | package eapol |
| 18 | |
| 19 | import ( |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 20 | "errors" |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 21 | "fmt" |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 22 | "net" |
| 23 | "testing" |
| 24 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 25 | "github.com/google/gopacket" |
| 26 | "github.com/google/gopacket/layers" |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 27 | "github.com/looplab/fsm" |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 28 | "github.com/opencord/bbsim/internal/bbsim/types" |
David K. Bainbridge | c415efe | 2021-08-19 13:05:21 +0000 | [diff] [blame] | 29 | "github.com/opencord/voltha-protos/v5/go/openolt" |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 30 | "google.golang.org/grpc" |
| 31 | "gotest.tools/assert" |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 32 | ) |
| 33 | |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 34 | // MOCKS |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 35 | |
| 36 | var eapolStateMachine = fsm.NewFSM( |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 37 | StateAuthStarted, |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 38 | fsm.Events{ |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 39 | {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 Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 44 | }, |
| 45 | fsm.Callbacks{}, |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 46 | ) |
| 47 | |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 48 | // params for the function under test |
| 49 | var onuId uint32 = 1 |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 50 | var gemPortId uint32 = 1 |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 51 | var ponPortId uint32 = 0 |
Matteo Scandolo | 8a57481 | 2021-05-20 15:18:53 -0700 | [diff] [blame] | 52 | var uniId uint32 = 0 |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 53 | var serialNumber string = "BBSM00000001" |
| 54 | var macAddress = net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03} |
| 55 | var portNo uint32 = 16 |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 56 | var serviceId uint32 = 0 |
| 57 | var oltId int = 0 |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 58 | |
| 59 | type mockStream struct { |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 60 | grpc.ServerStream |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 61 | CallCount int |
| 62 | Calls map[int]*openolt.PacketIndication |
| 63 | fail bool |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 64 | } |
| 65 | |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 66 | func (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 Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 72 | return nil |
| 73 | } |
| 74 | |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 75 | // TESTS |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 76 | |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 77 | func TestSendEapStartSuccess(t *testing.T) { |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 78 | eapolStateMachine.SetState(StateAuthStarted) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 79 | |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 80 | stream := &mockStream{ |
| 81 | Calls: make(map[int]*openolt.PacketIndication), |
| 82 | fail: false, |
| 83 | } |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 84 | |
Matteo Scandolo | 8a57481 | 2021-05-20 15:18:53 -0700 | [diff] [blame] | 85 | if err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, gemPortId, uniId, eapolStateMachine, stream); err != nil { |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 86 | t.Errorf("SendEapStart returned an error: %v", err) |
| 87 | t.Fail() |
| 88 | } |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 89 | |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 90 | 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 Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 95 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 96 | assert.Equal(t, eapolStateMachine.Current(), StateStartSent) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 97 | |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 98 | } |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 99 | |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 100 | func TestSendEapStartFailStreamError(t *testing.T) { |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 101 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 102 | eapolStateMachine.SetState(StateAuthStarted) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 103 | |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 104 | stream := &mockStream{ |
| 105 | Calls: make(map[int]*openolt.PacketIndication), |
| 106 | fail: true, |
| 107 | } |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 108 | |
Matteo Scandolo | 8a57481 | 2021-05-20 15:18:53 -0700 | [diff] [blame] | 109 | err := SendEapStart(onuId, ponPortId, serialNumber, portNo, macAddress, gemPortId, uniId, eapolStateMachine, stream) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 110 | if err == nil { |
| 111 | t.Errorf("SendEapStart did not return an error") |
| 112 | t.Fail() |
| 113 | } |
| 114 | |
Matteo Scandolo | 2742870 | 2019-10-11 16:21:16 -0700 | [diff] [blame] | 115 | assert.Equal(t, err.Error(), "fake-error") |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 116 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 117 | assert.Equal(t, eapolStateMachine.Current(), StateAuthFailed) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | // TODO test eapol.HandleNextPacket |
| 121 | |
| 122 | func TestUpdateAuthFailed(t *testing.T) { |
| 123 | |
| 124 | var onuId uint32 = 1 |
| 125 | var ponPortId uint32 = 0 |
| 126 | var serialNumber string = "BBSM00000001" |
| 127 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 128 | eapolStateMachine.SetState(StateAuthStarted) |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 129 | _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 130 | assert.Equal(t, eapolStateMachine.Current(), "auth_failed") |
| 131 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 132 | eapolStateMachine.SetState(StateStartSent) |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 133 | _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 134 | assert.Equal(t, eapolStateMachine.Current(), "auth_failed") |
| 135 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 136 | eapolStateMachine.SetState(StateResponseIdentitySent) |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 137 | _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 138 | assert.Equal(t, eapolStateMachine.Current(), "auth_failed") |
| 139 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 140 | eapolStateMachine.SetState(StateResponseChallengeSent) |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 141 | _ = updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 142 | assert.Equal(t, eapolStateMachine.Current(), "auth_failed") |
| 143 | |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 144 | eapolStateMachine.SetState(StateResponseSuccessReceived) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 145 | err := updateAuthFailed(onuId, ponPortId, serialNumber, eapolStateMachine) |
| 146 | if err == nil { |
| 147 | t.Errorf("updateAuthFailed did not return an error") |
| 148 | t.Fail() |
| 149 | } |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 150 | assert.Equal(t, err.Error(), fmt.Sprintf("event %s inappropriate in current state %s", EventAuthFailed, StateResponseSuccessReceived)) |
Matteo Scandolo | 075b189 | 2019-10-07 12:11:07 -0700 | [diff] [blame] | 151 | |
Matteo Scandolo | 4b3fc7e | 2019-09-17 16:49:54 -0700 | [diff] [blame] | 152 | } |
Elia Battiston | 536a22b | 2022-01-10 10:33:15 +0100 | [diff] [blame] | 153 | |
| 154 | func 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 | |
| 159 | func handleTestEAPOLPkt(pkt gopacket.Packet, stream types.Stream) { |
| 160 | HandleNextPacket(onuId, ponPortId, gemPortId, serialNumber, portNo, uniId, serviceId, oltId, eapolStateMachine, pkt, stream, nil) |
| 161 | } |
| 162 | |
| 163 | func 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 | } |