blob: 3546e914ac50b8e33cf15fda513045ef5597ef0f [file] [log] [blame]
Matteo Scandolo4a036262020-08-17 15:56:13 -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
17package devices
18
19import (
Matteo Scandolo618a6582020-09-09 12:21:29 -070020 "encoding/hex"
Matteo Scandolo8a574812021-05-20 15:18:53 -070021 "fmt"
Elia Battiston536a22b2022-01-10 10:33:15 +010022 "net"
23 "time"
24
Matteo Scandolo4a036262020-08-17 15:56:13 -070025 "github.com/looplab/fsm"
26 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
27 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
28 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
Matteo Scandolo618a6582020-09-09 12:21:29 -070029 "github.com/opencord/bbsim/internal/bbsim/responders/igmp"
Matteo Scandolo4a036262020-08-17 15:56:13 -070030 bbsimTypes "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo76c3ff62020-09-24 18:03:01 -070031 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4a036262020-08-17 15:56:13 -070032 log "github.com/sirupsen/logrus"
Matteo Scandolo4a036262020-08-17 15:56:13 -070033)
34
35var serviceLogger = log.WithFields(log.Fields{
36 "module": "SERVICE",
37})
38
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070039// time to wait before fail EAPOL/DHCP
40// (it's a variable and not a constant so it can be overridden in the tests)
Matteo Scandolo24a88c42020-09-17 14:55:28 -070041var eapolWaitTime = 60 * time.Second
42var dhcpWaitTime = 60 * time.Second
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070043
Matteo Scandolo8a574812021-05-20 15:18:53 -070044const (
45 ServiceStateCreated = "created"
46 ServiceStateInitialized = "initialized"
47 ServiceStateDisabled = "disabled"
48
49 ServiceTxInitialize = "initialize"
50 ServiceTxDisable = "disable"
51)
52
Matteo Scandolo4a036262020-08-17 15:56:13 -070053type ServiceIf interface {
Matteo Scandolobd875b32020-09-18 17:46:31 -070054 HandlePackets() // start listening on the PacketCh
55 HandleAuth() // Sends the EapoStart packet
56 HandleDhcp(pbit uint8, cTag int) // Sends the DHCPDiscover packet
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070057
Matteo Scandoloadc72a82020-09-08 18:46:08 -070058 Initialize(stream bbsimTypes.Stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -070059 UpdateStream(stream bbsimTypes.Stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070060 Disable()
Matteo Scandolo4a036262020-08-17 15:56:13 -070061}
62
63type Service struct {
Matteo Scandolo8a574812021-05-20 15:18:53 -070064 Id uint32
Matteo Scandolo4a036262020-08-17 15:56:13 -070065 Name string
66 HwAddress net.HardwareAddr
Matteo Scandolo8a574812021-05-20 15:18:53 -070067 UniPort *UniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -070068 CTag int
69 STag int
70 NeedsEapol bool
71 NeedsDhcp bool
72 NeedsIgmp bool
73 TechnologyProfileID int
74 UniTagMatch int
75 ConfigureMacAddress bool
Matteo Scandolo8d281372020-09-03 16:23:37 -070076 UsPonCTagPriority uint8
77 UsPonSTagPriority uint8
78 DsPonCTagPriority uint8
79 DsPonSTagPriority uint8
Matteo Scandolo4a036262020-08-17 15:56:13 -070080
81 // state
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070082 GemPort uint32
83 InternalState *fsm.FSM
84 EapolState *fsm.FSM
85 DHCPState *fsm.FSM
Matteo Scandolo618a6582020-09-09 12:21:29 -070086 IGMPState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080087 Channel chan bbsimTypes.Message // drive Service lifecycle
88 PacketCh chan bbsimTypes.OnuPacketMessage // handle packets
89 Stream bbsimTypes.Stream // the gRPC stream to communicate with the adapter, created in the initialize transition
Matteo Scandolo4a036262020-08-17 15:56:13 -070090}
91
Matteo Scandolo8a574812021-05-20 15:18:53 -070092func NewService(id uint32, name string, hwAddress net.HardwareAddr, uni *UniPort, cTag int, sTag int,
Matteo Scandolo4a036262020-08-17 15:56:13 -070093 needsEapol bool, needsDchp bool, needsIgmp bool, tpID int, uniTagMatch int, configMacAddress bool,
Matteo Scandolo8d281372020-09-03 16:23:37 -070094 usPonCTagPriority uint8, usPonSTagPriority uint8, dsPonCTagPriority uint8, dsPonSTagPriority uint8) (*Service, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -070095
96 service := Service{
Matteo Scandolo8a574812021-05-20 15:18:53 -070097 Id: id,
Matteo Scandolo4a036262020-08-17 15:56:13 -070098 Name: name,
99 HwAddress: hwAddress,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700100 UniPort: uni,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700101 CTag: cTag,
102 STag: sTag,
103 NeedsEapol: needsEapol,
104 NeedsDhcp: needsDchp,
105 NeedsIgmp: needsIgmp,
106 TechnologyProfileID: tpID,
107 UniTagMatch: uniTagMatch,
108 ConfigureMacAddress: configMacAddress,
109 UsPonCTagPriority: usPonCTagPriority,
110 UsPonSTagPriority: usPonSTagPriority,
111 DsPonCTagPriority: dsPonCTagPriority,
112 DsPonSTagPriority: dsPonSTagPriority,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700113 }
114
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700115 service.InternalState = fsm.NewFSM(
Matteo Scandolo8a574812021-05-20 15:18:53 -0700116 ServiceStateCreated,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700117 fsm.Events{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700118 {Name: ServiceTxInitialize, Src: []string{ServiceStateCreated, ServiceStateDisabled}, Dst: ServiceStateInitialized},
119 {Name: ServiceTxDisable, Src: []string{ServiceStateInitialized}, Dst: ServiceStateDisabled},
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700120 },
121 fsm.Callbacks{
122 "enter_state": func(e *fsm.Event) {
123 service.logStateChange("InternalState", e.Src, e.Dst)
124 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700125 fmt.Sprintf("enter_%s", ServiceStateInitialized): func(e *fsm.Event) {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700126
127 stream, ok := e.Args[0].(bbsimTypes.Stream)
128 if !ok {
129 serviceLogger.Fatal("initialize invoke with wrong arguments")
130 }
131
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700132 service.UpdateStream(stream)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700133
Matteo Scandolof9d43412021-01-12 11:11:34 -0800134 service.PacketCh = make(chan bbsimTypes.OnuPacketMessage)
135 service.Channel = make(chan bbsimTypes.Message)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700136
137 go service.HandlePackets()
138 go service.HandleChannel()
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700139 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700140 fmt.Sprintf("enter_%s", ServiceStateDisabled): func(e *fsm.Event) {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700141 // reset the state machines
Elia Battiston536a22b2022-01-10 10:33:15 +0100142 service.EapolState.SetState(eapol.StateCreated)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700143 service.DHCPState.SetState("created")
144
145 // stop listening for packets
146 close(service.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700147 close(service.Channel)
148
149 service.PacketCh = nil
150 service.Channel = nil
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700151 },
152 },
153 )
154
Matteo Scandolo4a036262020-08-17 15:56:13 -0700155 service.EapolState = fsm.NewFSM(
Elia Battiston536a22b2022-01-10 10:33:15 +0100156 eapol.StateCreated,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700157 fsm.Events{
Elia Battiston536a22b2022-01-10 10:33:15 +0100158 {Name: eapol.EventStartAuth, Src: []string{eapol.StateCreated, eapol.StateResponseSuccessReceived, eapol.StateAuthFailed}, Dst: eapol.StateAuthStarted},
159 {Name: eapol.EventStartSent, Src: []string{eapol.StateAuthStarted}, Dst: eapol.StateStartSent},
160 {Name: eapol.EventResponseIdentitySent, Src: []string{eapol.StateStartSent}, Dst: eapol.StateResponseIdentitySent},
161 {Name: eapol.EventResponseChallengeSent, Src: []string{eapol.StateResponseIdentitySent}, Dst: eapol.StateResponseChallengeSent},
162 {Name: eapol.EventResponseSuccessReceived, Src: []string{eapol.StateResponseChallengeSent}, Dst: eapol.StateResponseSuccessReceived},
163 {Name: eapol.EventAuthFailed, Src: []string{eapol.StateAuthStarted, eapol.StateStartSent, eapol.StateResponseIdentitySent, eapol.StateResponseChallengeSent}, Dst: eapol.StateAuthFailed},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700164 },
165 fsm.Callbacks{
166 "enter_state": func(e *fsm.Event) {
167 service.logStateChange("EapolState", e.Src, e.Dst)
168 },
Elia Battiston536a22b2022-01-10 10:33:15 +0100169 fmt.Sprintf("before_%s", eapol.EventStartAuth): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800170 msg := bbsimTypes.Message{
171 Type: bbsimTypes.StartEAPOL,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700172 }
173 service.Channel <- msg
174 },
Elia Battiston536a22b2022-01-10 10:33:15 +0100175 fmt.Sprintf("enter_%s", eapol.StateAuthStarted): func(e *fsm.Event) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700176 go func() {
177
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700178 for {
179 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700180 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700181 // if the OLT is disabled, then cancel
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700182 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700183 case <-time.After(eapolWaitTime):
Elia Battiston536a22b2022-01-10 10:33:15 +0100184 if service.EapolState.Current() != eapol.StateResponseSuccessReceived {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700185 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700186 "OnuId": service.UniPort.Onu.ID,
187 "IntfId": service.UniPort.Onu.PonPortID,
188 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700189 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700190 "PortNo": service.UniPort.PortNo,
191 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700192 "EapolState": service.EapolState.Current(),
193 }).Warn("EAPOL failed, resetting EAPOL State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700194
Elia Battiston536a22b2022-01-10 10:33:15 +0100195 _ = service.EapolState.Event(eapol.EventAuthFailed)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700196 if common.Config.BBSim.AuthRetry {
Elia Battiston536a22b2022-01-10 10:33:15 +0100197 _ = service.EapolState.Event(eapol.EventStartAuth)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700198 }
199
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700200 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700201 }
202 }
203
204 }
205 }()
206 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700207 },
208 )
209
210 service.DHCPState = fsm.NewFSM(
211 "created",
212 fsm.Events{
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700213 {Name: "start_dhcp", Src: []string{"created", "dhcp_ack_received", "dhcp_failed"}, Dst: "dhcp_started"},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700214 {Name: "dhcp_discovery_sent", Src: []string{"dhcp_started"}, Dst: "dhcp_discovery_sent"},
215 {Name: "dhcp_request_sent", Src: []string{"dhcp_discovery_sent"}, Dst: "dhcp_request_sent"},
216 {Name: "dhcp_ack_received", Src: []string{"dhcp_request_sent"}, Dst: "dhcp_ack_received"},
217 {Name: "dhcp_failed", Src: []string{"dhcp_started", "dhcp_discovery_sent", "dhcp_request_sent"}, Dst: "dhcp_failed"},
218 },
219 fsm.Callbacks{
220 "enter_state": func(e *fsm.Event) {
221 service.logStateChange("DHCPState", e.Src, e.Dst)
222 },
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700223 "before_start_dhcp": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800224 msg := bbsimTypes.Message{
225 Type: bbsimTypes.StartDHCP,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700226 }
227 service.Channel <- msg
228 },
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700229 "enter_dhcp_started": func(e *fsm.Event) {
230 go func() {
231
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700232 for {
233 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700234 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700235 // if the OLT is disabled, then cancel
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700236 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700237 case <-time.After(dhcpWaitTime):
238 if service.DHCPState.Current() != "dhcp_ack_received" {
239 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700240 "OnuId": service.UniPort.Onu.ID,
241 "IntfId": service.UniPort.Onu.PonPortID,
242 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700243 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700244 "PortNo": service.UniPort.PortNo,
245 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700246 "DHCPState": service.DHCPState.Current(),
247 }).Warn("DHCP failed, resetting DHCP State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700248
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700249 _ = service.DHCPState.Event("dhcp_failed")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700250 if common.Config.BBSim.DhcpRetry {
251 _ = service.DHCPState.Event("start_dhcp")
252 }
253
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700254 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700255 }
256 }
257
258 }
259 }()
260 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700261 },
262 )
263
Matteo Scandolo618a6582020-09-09 12:21:29 -0700264 service.IGMPState = fsm.NewFSM(
265 "created",
266 fsm.Events{
267 {Name: "igmp_join_start", Src: []string{"created", "igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
268 {Name: "igmp_join_startv3", Src: []string{"igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
269 {Name: "igmp_join_error", Src: []string{"igmp_join_started"}, Dst: "igmp_join_error"},
270 {Name: "igmp_leave", Src: []string{"igmp_join_started"}, Dst: "igmp_left"},
271 },
272 fsm.Callbacks{
273 "igmp_join_start": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800274 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
275 msg := bbsimTypes.Message{
276 Type: bbsimTypes.IGMPMembershipReportV2,
277 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000278 GroupAddress: igmpInfo.GroupAddress,
279 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700280 }
281 service.Channel <- msg
282 },
283 "igmp_leave": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800284 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
285 msg := bbsimTypes.Message{
286 Type: bbsimTypes.IGMPLeaveGroup,
287 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000288 GroupAddress: igmpInfo.GroupAddress,
289 },
290 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700291 service.Channel <- msg
292 },
293 "igmp_join_startv3": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800294 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
295 msg := bbsimTypes.Message{
296 Type: bbsimTypes.IGMPMembershipReportV3,
297 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000298 GroupAddress: igmpInfo.GroupAddress,
299 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700300 }
301 service.Channel <- msg
302 },
303 },
304 )
305
Matteo Scandolo4a036262020-08-17 15:56:13 -0700306 return &service, nil
307}
308
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700309func (s *Service) UpdateStream(stream bbsimTypes.Stream) {
310 s.Stream = stream
311}
312
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700313// HandleAuth is used to start EAPOL for a particular Service when the corresponding flow is received
314func (s *Service) HandleAuth() {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700315
316 if !s.NeedsEapol {
317 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700318 "OnuId": s.UniPort.Onu.ID,
319 "IntfId": s.UniPort.Onu.PonPortID,
320 "OnuSn": s.UniPort.Onu.Sn(),
321 "PortNo": s.UniPort.PortNo,
322 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700323 "Name": s.Name,
324 "NeedsEapol": s.NeedsEapol,
325 }).Debug("Won't start authentication as EAPOL is not required")
326 return
327 }
328
Elia Battiston536a22b2022-01-10 10:33:15 +0100329 if err := s.EapolState.Event(eapol.EventStartAuth); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700330 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700331 "OnuId": s.UniPort.Onu.ID,
332 "IntfId": s.UniPort.Onu.PonPortID,
333 "OnuSn": s.UniPort.Onu.Sn(),
334 "PortNo": s.UniPort.PortNo,
335 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700336 "Name": s.Name,
337 "err": err.Error(),
338 }).Error("Can't start auth for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700339 }
340}
341
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700342// HandleDhcp is used to start DHCP for a particular Service when the corresponding flow is received
Matteo Scandolobd875b32020-09-18 17:46:31 -0700343func (s *Service) HandleDhcp(pbit uint8, cTag int) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700344
Matteo Scandolobd875b32020-09-18 17:46:31 -0700345 if s.CTag != cTag || (s.UsPonCTagPriority != pbit && pbit != 255) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700346 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700347 "OnuId": s.UniPort.Onu.ID,
348 "IntfId": s.UniPort.Onu.PonPortID,
349 "OnuSn": s.UniPort.Onu.Sn(),
350 "PortNo": s.UniPort.PortNo,
351 "UniId": s.UniPort.ID,
352 "Name": s.Name,
353 "Service.CTag": s.CTag,
354 "Service.UsPonCTagPriority": s.UsPonCTagPriority,
355 "cTag": cTag,
356 "pbit": pbit,
357 }).Debug("DHCP flow is not for this service, ignoring")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700358 return
359 }
360
Matteo Scandolo4a036262020-08-17 15:56:13 -0700361 if !s.NeedsDhcp {
362 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700363 "OnuId": s.UniPort.Onu.ID,
364 "IntfId": s.UniPort.Onu.PonPortID,
365 "OnuSn": s.UniPort.Onu.Sn(),
366 "PortNo": s.UniPort.PortNo,
367 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700368 "Name": s.Name,
369 "NeedsDhcp": s.NeedsDhcp,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700370 }).Trace("Won't start DHCP as it is not required")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700371 return
372 }
373
Matteo Scandolo8a574812021-05-20 15:18:53 -0700374 // TODO check if the DHCP flow was received before starting DHCP
Matteo Scandolo4a036262020-08-17 15:56:13 -0700375
376 if err := s.DHCPState.Event("start_dhcp"); err != nil {
377 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700378 "OnuId": s.UniPort.Onu.ID,
379 "IntfId": s.UniPort.Onu.PonPortID,
380 "OnuSn": s.UniPort.Onu.Sn(),
381 "PortNo": s.UniPort.PortNo,
382 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700383 "Name": s.Name,
384 "err": err.Error(),
385 }).Error("Can't start DHCP for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700386 }
387}
388
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700389func (s *Service) HandlePackets() {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700390 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700391 "OnuId": s.UniPort.Onu.ID,
392 "IntfId": s.UniPort.Onu.PonPortID,
393 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700394 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700395 "PortNo": s.UniPort.PortNo,
396 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700397 "Name": s.Name,
398 }).Debug("Listening on Service Packet Channel")
399
400 defer func() {
401 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700402 "OnuId": s.UniPort.Onu.ID,
403 "IntfId": s.UniPort.Onu.PonPortID,
404 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700405 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700406 "PortNo": s.UniPort.PortNo,
407 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700408 "Name": s.Name,
409 }).Debug("Done Listening on Service Packet Channel")
410 }()
411
412 for msg := range s.PacketCh {
413 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700414 "OnuId": s.UniPort.Onu.ID,
415 "IntfId": s.UniPort.Onu.PonPortID,
416 "OnuSn": s.UniPort.Onu.Sn(),
417 "GemPortId": s.GemPort,
418 "PortNo": s.UniPort.PortNo,
419 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700420 "Name": s.Name,
421 "messageType": msg.Type,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700422 }).Trace("Received message on Service Packet Channel")
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700423
424 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700425 eapol.HandleNextPacket(msg.OnuId, msg.IntfId, s.GemPort, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.Id, s.UniPort.Onu.PonPort.Olt.ID, s.EapolState, msg.Packet, s.Stream, nil)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700426 } else if msg.Type == packetHandlers.DHCP {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700427 _ = dhcp.HandleNextPacket(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.Name, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.CTag, s.GemPort, s.UniPort.ID, s.HwAddress, s.DHCPState, msg.Packet, s.UsPonCTagPriority, s.Stream)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700428 } else if msg.Type == packetHandlers.IGMP {
429 log.Warn(hex.EncodeToString(msg.Packet.Data()))
Matteo Scandolo8a574812021-05-20 15:18:53 -0700430 _ = igmp.HandleNextPacket(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.Stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700431 }
432 }
433}
434
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700435func (s *Service) HandleChannel() {
436 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700437 "OnuId": s.UniPort.Onu.ID,
438 "IntfId": s.UniPort.Onu.PonPortID,
439 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700440 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700441 "PortNo": s.UniPort.PortNo,
442 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700443 "Name": s.Name,
444 }).Debug("Listening on Service Channel")
445
446 defer func() {
447 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700448 "OnuId": s.UniPort.Onu.ID,
449 "IntfId": s.UniPort.Onu.PonPortID,
450 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700451 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700452 "PortNo": s.UniPort.PortNo,
453 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700454 "Name": s.Name,
455 }).Debug("Done Listening on Service Channel")
456 }()
457 for msg := range s.Channel {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700458 switch msg.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800459 case bbsimTypes.StartEAPOL:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700460 if err := s.handleEapolStart(s.Stream); err != nil {
461 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700462 "OnuId": s.UniPort.Onu.ID,
463 "IntfId": s.UniPort.Onu.PonPortID,
464 "OnuSn": s.UniPort.Onu.Sn(),
465 "GemPortId": s.GemPort,
466 "PortNo": s.UniPort.PortNo,
467 "UniId": s.UniPort.ID,
468 "Name": s.Name,
469 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700470 }).Error("Error while sending EapolStart packet")
Elia Battiston536a22b2022-01-10 10:33:15 +0100471 _ = s.EapolState.Event(eapol.EventAuthFailed)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700472 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800473 case bbsimTypes.StartDHCP:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700474 if err := s.handleDHCPStart(s.Stream); err != nil {
475 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700476 "OnuId": s.UniPort.Onu.ID,
477 "IntfId": s.UniPort.Onu.PonPortID,
478 "OnuSn": s.UniPort.Onu.Sn(),
479 "GemPortId": s.GemPort,
480 "PortNo": s.UniPort.PortNo,
481 "UniId": s.UniPort.ID,
482 "Name": s.Name,
483 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700484 }).Error("Error while sending DHCPDiscovery packet")
485 _ = s.DHCPState.Event("dhcp_failed")
Matteo Scandolo618a6582020-09-09 12:21:29 -0700486
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700487 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800488 case bbsimTypes.IGMPMembershipReportV2:
489 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700490 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700491 "OnuId": s.UniPort.Onu.ID,
492 "IntfId": s.UniPort.Onu.PonPortID,
493 "OnuSn": s.UniPort.Onu.Sn(),
494 "GemPortId": s.GemPort,
495 "PortNo": s.UniPort.PortNo,
496 "UniId": s.UniPort.ID,
497 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000498 }).Debug("Received IGMPMembershipReportV2 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700499 _ = igmp.SendIGMPMembershipReportV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800500 case bbsimTypes.IGMPLeaveGroup:
501 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700502 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700503 "OnuId": s.UniPort.Onu.ID,
504 "IntfId": s.UniPort.Onu.PonPortID,
505 "OnuSn": s.UniPort.Onu.Sn(),
506 "GemPortId": s.GemPort,
507 "PortNo": s.UniPort.PortNo,
508 "UniId": s.UniPort.ID,
509 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000510 }).Debug("Received IGMPLeaveGroupV2 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700511 _ = igmp.SendIGMPLeaveGroupV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800512 case bbsimTypes.IGMPMembershipReportV3:
513 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700514 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700515 "OnuId": s.UniPort.Onu.ID,
516 "IntfId": s.UniPort.Onu.PonPortID,
517 "OnuSn": s.UniPort.Onu.Sn(),
518 "GemPortId": s.GemPort,
519 "PortNo": s.UniPort.PortNo,
520 "UniId": s.UniPort.ID,
521 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000522 }).Debug("Received IGMPMembershipReportV3 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700523 _ = igmp.SendIGMPMembershipReportV3(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700524
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700525 }
526 }
527}
528
529func (s *Service) Initialize(stream bbsimTypes.Stream) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700530 if err := s.InternalState.Event(ServiceTxInitialize, stream); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700531 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700532 "OnuId": s.UniPort.Onu.ID,
533 "IntfId": s.UniPort.Onu.PonPortID,
534 "OnuSn": s.UniPort.Onu.Sn(),
535 "GemPortId": s.GemPort,
536 "PortNo": s.UniPort.PortNo,
537 "UniId": s.UniPort.ID,
538 "Name": s.Name,
539 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700540 }).Error("Cannot initialize service")
541 }
542}
543
544func (s *Service) Disable() {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700545 if err := s.InternalState.Event(ServiceTxDisable); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700546 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700547 "OnuId": s.UniPort.Onu.ID,
548 "IntfId": s.UniPort.Onu.PonPortID,
549 "OnuSn": s.UniPort.Onu.Sn(),
550 "GemPortId": s.GemPort,
551 "PortNo": s.UniPort.PortNo,
552 "UniId": s.UniPort.ID,
553 "Name": s.Name,
554 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700555 }).Error("Cannot disable service")
556 }
557}
558
Matteo Scandolo4a036262020-08-17 15:56:13 -0700559func (s *Service) handleEapolStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700560 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700561 "OnuId": s.UniPort.Onu.ID,
562 "IntfId": s.UniPort.Onu.PonPortID,
563 "OnuSn": s.UniPort.Onu.Sn(),
564 "GemPortId": s.GemPort,
565 "PortNo": s.UniPort.PortNo,
566 "UniId": s.UniPort.ID,
567 "GemPort": s.GemPort,
568 "Name": s.Name,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700569 }).Trace("handleEapolStart")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700570
Matteo Scandolo8a574812021-05-20 15:18:53 -0700571 if err := eapol.SendEapStart(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.UniPort.Onu.Sn(), s.UniPort.PortNo,
572 s.HwAddress, s.GemPort, s.UniPort.ID, s.EapolState, stream); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700573 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700574 "OnuId": s.UniPort.Onu.ID,
575 "IntfId": s.UniPort.Onu.PonPortID,
576 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700577 "GemPort": s.GemPort,
578 "Name": s.Name,
579 }).Error("handleEapolStart")
580 return err
581 }
582 return nil
583}
584
585func (s *Service) handleDHCPStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700586 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700587 "OnuId": s.UniPort.Onu.ID,
588 "IntfId": s.UniPort.Onu.PonPortID,
589 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700590 "Name": s.Name,
591 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700592 "PortNo": s.UniPort.PortNo,
593 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700594 }).Debugf("HandleDHCPStart")
595
Matteo Scandolo8a574812021-05-20 15:18:53 -0700596 if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, int(s.CTag), s.GemPort,
597 s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.DHCPState, s.HwAddress, s.UsPonCTagPriority, stream); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700598 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700599 "OnuId": s.UniPort.Onu.ID,
600 "IntfId": s.UniPort.Onu.PonPortID,
601 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700602 "Name": s.Name,
603 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700604 "PortNo": s.UniPort.PortNo,
605 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700606 }).Error("HandleDHCPStart")
607 return err
608 }
609 return nil
610}
611
Matteo Scandolo4a036262020-08-17 15:56:13 -0700612func (s *Service) logStateChange(stateMachine string, src string, dst string) {
613 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700614 "OnuId": s.UniPort.Onu.ID,
615 "IntfId": s.UniPort.Onu.PonPortID,
616 "OnuSn": s.UniPort.Onu.Sn(),
617 "GemPortId": s.GemPort,
618 "PortNo": s.UniPort.PortNo,
619 "UniId": s.UniPort.ID,
620 "Name": s.Name,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700621 }).Debugf("Changing Service.%s InternalState from %s to %s", stateMachine, src, dst)
622}