blob: 45876206b4bd70978203a18354b058f61d2cb62a [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -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
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
Matteo Scandolo3bc73742019-08-20 14:04:04 -070020 "fmt"
Matteo Scandolo3bc73742019-08-20 14:04:04 -070021 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070022 "github.com/looplab/fsm"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070023 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
24 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
25 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandoloc559ef12019-08-20 13:24:21 -070026 omci "github.com/opencord/omci-sim"
Matteo Scandolo3bc73742019-08-20 14:04:04 -070027 "github.com/opencord/voltha-protos/go/openolt"
Matteo Scandolo4747d292019-08-05 11:50:18 -070028 log "github.com/sirupsen/logrus"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070029 "net"
Matteo Scandolo4747d292019-08-05 11:50:18 -070030)
31
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070032var onuLogger = log.WithFields(log.Fields{
33 "module": "ONU",
34})
35
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070036func CreateONU(olt OltDevice, pon PonPort, id uint32, sTag int, cTag int) Onu {
Matteo Scandolo4747d292019-08-05 11:50:18 -070037
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070038 o := Onu{
39 ID: id,
40 PonPortID: pon.ID,
41 PonPort: pon,
42 STag: sTag,
43 CTag: cTag,
44 HwAddress: net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(pon.ID), byte(id)},
Matteo Scandolo10f965c2019-09-24 10:40:46 -070045 // NOTE can we combine everything in a single Channel?
46 Channel: make(chan Message, 2048),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070047 eapolPktOutCh: make(chan *bbsim.ByteMsg, 1024),
48 dhcpPktOutCh: make(chan *bbsim.ByteMsg, 1024),
49 }
50 o.SerialNumber = o.NewSN(olt.ID, pon.ID, o.ID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070051
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070052 // NOTE this state machine is used to track the operational
53 // state as requested by VOLTHA
54 o.OperState = getOperStateFSM(func(e *fsm.Event) {
55 onuLogger.WithFields(log.Fields{
56 "ID": o.ID,
57 }).Debugf("Changing ONU OperState from %s to %s", e.Src, e.Dst)
58 })
59
60 // NOTE this state machine is used to activate the OMCI, EAPOL and DHCP clients
61 o.InternalState = fsm.NewFSM(
62 "created",
63 fsm.Events{
Matteo Scandolo10f965c2019-09-24 10:40:46 -070064 // DEVICE Lifecycle
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070065 {Name: "discover", Src: []string{"created"}, Dst: "discovered"},
Matteo Scandolo10f965c2019-09-24 10:40:46 -070066 {Name: "enable", Src: []string{"discovered", "disabled"}, Dst: "enabled"},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070067 {Name: "receive_eapol_flow", Src: []string{"enabled", "gem_port_added"}, Dst: "eapol_flow_received"},
68 {Name: "add_gem_port", Src: []string{"enabled", "eapol_flow_received"}, Dst: "gem_port_added"},
Matteo Scandolo10f965c2019-09-24 10:40:46 -070069 // NOTE should disabled state be diffente for oper_disabled (emulating an error) and admin_disabled (received a disabled call via VOLTHA)?
70 {Name: "disable", Src: []string{"eap_response_success_received", "auth_failed", "dhcp_ack_received", "dhcp_failed"}, Dst: "disabled"},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070071 // EAPOL
72 {Name: "start_auth", Src: []string{"eapol_flow_received", "gem_port_added"}, Dst: "auth_started"},
73 {Name: "eap_start_sent", Src: []string{"auth_started"}, Dst: "eap_start_sent"},
74 {Name: "eap_response_identity_sent", Src: []string{"eap_start_sent"}, Dst: "eap_response_identity_sent"},
75 {Name: "eap_response_challenge_sent", Src: []string{"eap_response_identity_sent"}, Dst: "eap_response_challenge_sent"},
76 {Name: "eap_response_success_received", Src: []string{"eap_response_challenge_sent"}, Dst: "eap_response_success_received"},
77 {Name: "auth_failed", Src: []string{"auth_started", "eap_start_sent", "eap_response_identity_sent", "eap_response_challenge_sent"}, Dst: "auth_failed"},
78 // DHCP
79 {Name: "start_dhcp", Src: []string{"eap_response_success_received"}, Dst: "dhcp_started"},
80 {Name: "dhcp_discovery_sent", Src: []string{"dhcp_started"}, Dst: "dhcp_discovery_sent"},
81 {Name: "dhcp_request_sent", Src: []string{"dhcp_discovery_sent"}, Dst: "dhcp_request_sent"},
82 {Name: "dhcp_ack_received", Src: []string{"dhcp_request_sent"}, Dst: "dhcp_ack_received"},
83 {Name: "dhcp_failed", Src: []string{"dhcp_started", "dhcp_discovery_sent", "dhcp_request_sent"}, Dst: "dhcp_failed"},
84 },
85 fsm.Callbacks{
86 "enter_state": func(e *fsm.Event) {
87 o.logStateChange(e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -070088 },
Matteo Scandolo10f965c2019-09-24 10:40:46 -070089 "enter_enabled": func(event *fsm.Event) {
90 msg := Message{
91 Type: OnuIndication,
92 Data: OnuIndicationMessage{
93 OnuSN: o.SerialNumber,
94 PonPortID: o.PonPortID,
95 OperState: UP,
96 },
97 }
98 o.Channel <- msg
99 },
100 "enter_disabled": func(event *fsm.Event) {
101 msg := Message{
102 Type: OnuIndication,
103 Data: OnuIndicationMessage{
104 OnuSN: o.SerialNumber,
105 PonPortID: o.PonPortID,
106 OperState: DOWN,
107 },
108 }
109 o.Channel <- msg
110 },
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700111 "enter_auth_started": func(e *fsm.Event) {
112 o.logStateChange(e.Src, e.Dst)
113 msg := Message{
114 Type: StartEAPOL,
115 Data: PacketMessage{
116 PonPortID: o.PonPortID,
117 OnuID: o.ID,
118 },
119 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700120 o.Channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700121 },
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700122 "enter_auth_failed": func(e *fsm.Event) {
123 onuLogger.WithFields(log.Fields{
124 "OnuId": o.ID,
125 "IntfId": o.PonPortID,
126 "OnuSn": o.Sn(),
127 }).Errorf("ONU failed to authenticate!")
128 },
129 "enter_dhcp_started": func(e *fsm.Event) {
130 msg := Message{
131 Type: StartDHCP,
132 Data: PacketMessage{
133 PonPortID: o.PonPortID,
134 OnuID: o.ID,
135 },
136 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700137 o.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700138 },
139 "enter_dhcp_failed": func(e *fsm.Event) {
140 onuLogger.WithFields(log.Fields{
141 "OnuId": o.ID,
142 "IntfId": o.PonPortID,
143 "OnuSn": o.Sn(),
144 }).Errorf("ONU failed to DHCP!")
145 },
146 },
147 )
148 return o
Matteo Scandolo4747d292019-08-05 11:50:18 -0700149}
150
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700151func (o Onu) logStateChange(src string, dst string) {
152 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700153 "OnuId": o.ID,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700154 "IntfId": o.PonPortID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700155 "OnuSn": o.Sn(),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700156 }).Debugf("Changing ONU InternalState from %s to %s", src, dst)
157}
158
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700159func (o Onu) processOnuMessages(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700160 onuLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700161 "onuID": o.ID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700162 "onuSN": o.Sn(),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700163 }).Debug("Started ONU Indication Channel")
164
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700165 for message := range o.Channel {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700166 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700167 "onuID": o.ID,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700168 "onuSN": o.Sn(),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700169 "messageType": message.Type,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700170 }).Tracef("Received message on ONU Channel")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700171
172 switch message.Type {
173 case OnuDiscIndication:
174 msg, _ := message.Data.(OnuDiscIndicationMessage)
175 o.sendOnuDiscIndication(msg, stream)
176 case OnuIndication:
177 msg, _ := message.Data.(OnuIndicationMessage)
178 o.sendOnuIndication(msg, stream)
179 case OMCI:
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700180 msg, _ := message.Data.(OmciMessage)
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700181 o.handleOmciMessage(msg, stream)
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700182 case FlowUpdate:
183 msg, _ := message.Data.(OnuFlowUpdateMessage)
184 o.handleFlowUpdate(msg, stream)
185 case StartEAPOL:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700186 log.Infof("Receive StartEAPOL message on ONU Channel")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700187 go func() {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700188 // TODO kill this thread
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700189 eapol.CreateWPASupplicant(
190 o.ID,
191 o.PonPortID,
192 o.Sn(),
193 o.InternalState,
194 stream,
195 o.eapolPktOutCh,
196 )
197 }()
198 case StartDHCP:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700199 log.Infof("Receive StartDHCP message on ONU Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700200 go func() {
201 // TODO kill this thread
202 dhcp.CreateDHCPClient(
203 o.ID,
204 o.PonPortID,
205 o.Sn(),
206 o.HwAddress,
207 o.CTag,
208 o.InternalState,
209 stream,
210 o.dhcpPktOutCh,
211 )
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700212 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700213
214 case DyingGaspIndication:
215 msg, _ := message.Data.(DyingGaspIndicationMessage)
216 o.sendDyingGaspInd(msg, stream)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700217 default:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700218 onuLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700219 }
220 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700221}
222
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700223func (o Onu) processOmciMessages(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700224 ch := omci.GetChannel()
225
226 onuLogger.WithFields(log.Fields{
227 "onuID": o.ID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700228 "onuSN": o.Sn(),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700229 }).Debug("Started OMCI Indication Channel")
230
231 for message := range ch {
232 switch message.Type {
233 case omci.GemPortAdded:
234 log.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700235 "OnuId": message.Data.OnuId,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700236 "IntfId": message.Data.IntfId,
237 }).Infof("GemPort Added")
238
239 // NOTE if we receive the GemPort but we don't have EAPOL flows
240 // go an intermediate state, otherwise start auth
241 if o.InternalState.Is("enabled") {
242 if err := o.InternalState.Event("add_gem_port"); err != nil {
243 log.Errorf("Can't go to gem_port_added: %v", err)
244 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700245 } else if o.InternalState.Is("eapol_flow_received") {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700246 if err := o.InternalState.Event("start_auth"); err != nil {
247 log.Errorf("Can't go to auth_started: %v", err)
248 }
249 }
250 }
251 }
252}
253
Matteo Scandolo4747d292019-08-05 11:50:18 -0700254func (o Onu) NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
255
256 sn := new(openolt.SerialNumber)
257
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700258 //sn = new(openolt.SerialNumber)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700259 sn.VendorId = []byte("BBSM")
260 sn.VendorSpecific = []byte{0, byte(oltid % 256), byte(intfid), byte(onuid)}
261
262 return sn
263}
264
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700265// NOTE handle_/process methods can change the ONU internal state as they are receiving messages
266// send method should not change the ONU state
267
268func (o Onu) sendDyingGaspInd(msg DyingGaspIndicationMessage, stream openolt.Openolt_EnableIndicationServer) error {
269 alarmData := &openolt.AlarmIndication_DyingGaspInd{
270 DyingGaspInd: &openolt.DyingGaspIndication{
271 IntfId: msg.PonPortID,
272 OnuId: msg.OnuID,
273 Status: "on",
274 },
275 }
276 data := &openolt.Indication_AlarmInd{AlarmInd: &openolt.AlarmIndication{Data: alarmData}}
277
278 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
279 onuLogger.Errorf("Failed to send DyingGaspInd : %v", err)
280 return err
281 }
282 onuLogger.WithFields(log.Fields{
283 "IntfId": msg.PonPortID,
284 "OnuSn": o.Sn(),
285 "OnuId": msg.OnuID,
286 }).Info("sendDyingGaspInd")
287 return nil
288}
289
Matteo Scandolo4747d292019-08-05 11:50:18 -0700290func (o Onu) sendOnuDiscIndication(msg OnuDiscIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
291 discoverData := &openolt.Indication_OnuDiscInd{OnuDiscInd: &openolt.OnuDiscIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700292 IntfId: msg.Onu.PonPortID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700293 SerialNumber: msg.Onu.SerialNumber,
294 }}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700295
Matteo Scandolo4747d292019-08-05 11:50:18 -0700296 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700297 log.Errorf("Failed to send Indication_OnuDiscInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700298 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700299
300 if err := o.InternalState.Event("discover"); err != nil {
301 oltLogger.WithFields(log.Fields{
302 "IntfId": o.PonPortID,
303 "OnuSn": o.Sn(),
304 "OnuId": o.ID,
305 }).Infof("Failed to transition ONU to discovered state: %s", err.Error())
306 }
307
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700308 onuLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700309 "IntfId": msg.Onu.PonPortID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700310 "OnuSn": msg.Onu.Sn(),
311 "OnuId": o.ID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700312 }).Debug("Sent Indication_OnuDiscInd")
313}
314
315func (o Onu) sendOnuIndication(msg OnuIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
316 // NOTE voltha returns an ID, but if we use that ID then it complains:
317 // expected_onu_id: 1, received_onu_id: 1024, event: ONU-id-mismatch, can happen if both voltha and the olt rebooted
318 // so we're using the internal ID that is 1
319 // o.ID = msg.OnuID
Matteo Scandolo4747d292019-08-05 11:50:18 -0700320
321 indData := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700322 IntfId: o.PonPortID,
323 OnuId: o.ID,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700324 OperState: msg.OperState.String(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700325 AdminState: o.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700326 SerialNumber: o.SerialNumber,
327 }}
328 if err := stream.Send(&openolt.Indication{Data: indData}); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700329 // TODO do we need to transition to a broken state?
Matteo Scandolo11006992019-08-28 11:29:46 -0700330 log.Errorf("Failed to send Indication_OnuInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700331 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700332 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700333 "IntfId": o.PonPortID,
334 "OnuId": o.ID,
335 "OperState": msg.OperState.String(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700336 "AdminState": msg.OperState.String(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700337 "OnuSn": o.Sn(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700338 }).Debug("Sent Indication_OnuInd")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700339
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700340}
341
342func (o Onu) handleOmciMessage(msg OmciMessage, stream openolt.Openolt_EnableIndicationServer) {
343
344 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700345 "IntfId": o.PonPortID,
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700346 "SerialNumber": o.SerialNumber,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700347 "omciPacket": msg.omciMsg.Pkt,
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700348 }).Tracef("Received OMCI message")
349
350 var omciInd openolt.OmciIndication
351 respPkt, err := omci.OmciSim(o.PonPortID, o.ID, HexDecode(msg.omciMsg.Pkt))
352 if err != nil {
353 onuLogger.Errorf("Error handling OMCI message %v", msg)
354 }
355
356 omciInd.IntfId = o.PonPortID
357 omciInd.OnuId = o.ID
358 omciInd.Pkt = respPkt
359
360 omci := &openolt.Indication_OmciInd{OmciInd: &omciInd}
361 if err := stream.Send(&openolt.Indication{Data: omci}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700362 onuLogger.Errorf("send omci indication failed: %v", err)
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700363 }
364 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700365 "IntfId": o.PonPortID,
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700366 "SerialNumber": o.SerialNumber,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700367 "omciPacket": omciInd.Pkt,
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700368 }).Tracef("Sent OMCI message")
369}
370
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700371func (o Onu) handleFlowUpdate(msg OnuFlowUpdateMessage, stream openolt.Openolt_EnableIndicationServer) {
372 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700373 "DstPort": msg.Flow.Classifier.DstPort,
374 "EthType": fmt.Sprintf("%x", msg.Flow.Classifier.EthType),
375 "FlowId": msg.Flow.FlowId,
376 "FlowType": msg.Flow.FlowType,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700377 "InnerVlan": msg.Flow.Classifier.IVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700378 "IntfId": msg.Flow.AccessIntfId,
379 "IpProto": msg.Flow.Classifier.IpProto,
380 "OnuId": msg.Flow.OnuId,
381 "OnuSn": o.Sn(),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700382 "OuterVlan": msg.Flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700383 "PortNo": msg.Flow.PortNo,
384 "SrcPort": msg.Flow.Classifier.SrcPort,
385 "UniID": msg.Flow.UniId,
386 }).Debug("ONU receives Flow")
387
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700388 if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) && msg.Flow.Classifier.OVid == 4091 {
389 // NOTE if we receive the EAPOL flows but we don't have GemPorts
390 // go an intermediate state, otherwise start auth
391 if o.InternalState.Is("enabled") {
392 if err := o.InternalState.Event("receive_eapol_flow"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700393 log.Warnf("Can't go to eapol_flow_received: %v", err)
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700394 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700395 } else if o.InternalState.Is("gem_port_added") {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700396 if err := o.InternalState.Event("start_auth"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700397 log.Warnf("Can't go to auth_started: %v", err)
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700398 }
399 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700400 } else if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeIPv4) &&
401 msg.Flow.Classifier.SrcPort == uint32(68) &&
402 msg.Flow.Classifier.DstPort == uint32(67) {
403 // NOTE we are receiving mulitple DHCP flows but we shouldn't call the transition multiple times
404 if err := o.InternalState.Event("start_dhcp"); err != nil {
405 log.Warnf("Can't go to dhcp_started: %v", err)
406 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700407 }
408}
409
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700410// HexDecode converts the hex encoding to binary
411func HexDecode(pkt []byte) []byte {
412 p := make([]byte, len(pkt)/2)
413 for i, j := 0, 0; i < len(pkt); i, j = i+2, j+1 {
414 // Go figure this ;)
415 u := (pkt[i] & 15) + (pkt[i]>>6)*9
416 l := (pkt[i+1] & 15) + (pkt[i+1]>>6)*9
417 p[j] = u<<4 + l
418 }
419 onuLogger.Tracef("Omci decoded: %x.", p)
420 return p
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700421}