blob: 4b94ecf8aef4e6d830815f225ddd1f98f3cca203 [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"
Matteo Scandolo4a036262020-08-17 15:56:13 -070022 "github.com/looplab/fsm"
23 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
24 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
25 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
Matteo Scandolo618a6582020-09-09 12:21:29 -070026 "github.com/opencord/bbsim/internal/bbsim/responders/igmp"
Matteo Scandolo4a036262020-08-17 15:56:13 -070027 bbsimTypes "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo76c3ff62020-09-24 18:03:01 -070028 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4a036262020-08-17 15:56:13 -070029 log "github.com/sirupsen/logrus"
30 "net"
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070031 "time"
Matteo Scandolo4a036262020-08-17 15:56:13 -070032)
33
34var serviceLogger = log.WithFields(log.Fields{
35 "module": "SERVICE",
36})
37
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070038// time to wait before fail EAPOL/DHCP
39// (it's a variable and not a constant so it can be overridden in the tests)
Matteo Scandolo24a88c42020-09-17 14:55:28 -070040var eapolWaitTime = 60 * time.Second
41var dhcpWaitTime = 60 * time.Second
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -070042
Matteo Scandolo8a574812021-05-20 15:18:53 -070043const (
44 ServiceStateCreated = "created"
45 ServiceStateInitialized = "initialized"
46 ServiceStateDisabled = "disabled"
47
48 ServiceTxInitialize = "initialize"
49 ServiceTxDisable = "disable"
50)
51
Matteo Scandolo4a036262020-08-17 15:56:13 -070052type ServiceIf interface {
Matteo Scandolobd875b32020-09-18 17:46:31 -070053 HandlePackets() // start listening on the PacketCh
54 HandleAuth() // Sends the EapoStart packet
55 HandleDhcp(pbit uint8, cTag int) // Sends the DHCPDiscover packet
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070056
Matteo Scandoloadc72a82020-09-08 18:46:08 -070057 Initialize(stream bbsimTypes.Stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -070058 UpdateStream(stream bbsimTypes.Stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070059 Disable()
Matteo Scandolo4a036262020-08-17 15:56:13 -070060}
61
62type Service struct {
Matteo Scandolo8a574812021-05-20 15:18:53 -070063 Id uint32
Matteo Scandolo4a036262020-08-17 15:56:13 -070064 Name string
65 HwAddress net.HardwareAddr
Matteo Scandolo8a574812021-05-20 15:18:53 -070066 UniPort *UniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -070067 CTag int
68 STag int
69 NeedsEapol bool
70 NeedsDhcp bool
71 NeedsIgmp bool
72 TechnologyProfileID int
73 UniTagMatch int
74 ConfigureMacAddress bool
Matteo Scandolo8d281372020-09-03 16:23:37 -070075 UsPonCTagPriority uint8
76 UsPonSTagPriority uint8
77 DsPonCTagPriority uint8
78 DsPonSTagPriority uint8
Matteo Scandolo4a036262020-08-17 15:56:13 -070079
80 // state
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070081 GemPort uint32
82 InternalState *fsm.FSM
83 EapolState *fsm.FSM
84 DHCPState *fsm.FSM
Matteo Scandolo618a6582020-09-09 12:21:29 -070085 IGMPState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080086 Channel chan bbsimTypes.Message // drive Service lifecycle
87 PacketCh chan bbsimTypes.OnuPacketMessage // handle packets
88 Stream bbsimTypes.Stream // the gRPC stream to communicate with the adapter, created in the initialize transition
Matteo Scandolo4a036262020-08-17 15:56:13 -070089}
90
Matteo Scandolo8a574812021-05-20 15:18:53 -070091func NewService(id uint32, name string, hwAddress net.HardwareAddr, uni *UniPort, cTag int, sTag int,
Matteo Scandolo4a036262020-08-17 15:56:13 -070092 needsEapol bool, needsDchp bool, needsIgmp bool, tpID int, uniTagMatch int, configMacAddress bool,
Matteo Scandolo8d281372020-09-03 16:23:37 -070093 usPonCTagPriority uint8, usPonSTagPriority uint8, dsPonCTagPriority uint8, dsPonSTagPriority uint8) (*Service, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -070094
95 service := Service{
Matteo Scandolo8a574812021-05-20 15:18:53 -070096 Id: id,
Matteo Scandolo4a036262020-08-17 15:56:13 -070097 Name: name,
98 HwAddress: hwAddress,
Matteo Scandolo8a574812021-05-20 15:18:53 -070099 UniPort: uni,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700100 CTag: cTag,
101 STag: sTag,
102 NeedsEapol: needsEapol,
103 NeedsDhcp: needsDchp,
104 NeedsIgmp: needsIgmp,
105 TechnologyProfileID: tpID,
106 UniTagMatch: uniTagMatch,
107 ConfigureMacAddress: configMacAddress,
108 UsPonCTagPriority: usPonCTagPriority,
109 UsPonSTagPriority: usPonSTagPriority,
110 DsPonCTagPriority: dsPonCTagPriority,
111 DsPonSTagPriority: dsPonSTagPriority,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700112 }
113
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700114 service.InternalState = fsm.NewFSM(
Matteo Scandolo8a574812021-05-20 15:18:53 -0700115 ServiceStateCreated,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700116 fsm.Events{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700117 {Name: ServiceTxInitialize, Src: []string{ServiceStateCreated, ServiceStateDisabled}, Dst: ServiceStateInitialized},
118 {Name: ServiceTxDisable, Src: []string{ServiceStateInitialized}, Dst: ServiceStateDisabled},
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700119 },
120 fsm.Callbacks{
121 "enter_state": func(e *fsm.Event) {
122 service.logStateChange("InternalState", e.Src, e.Dst)
123 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700124 fmt.Sprintf("enter_%s", ServiceStateInitialized): func(e *fsm.Event) {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700125
126 stream, ok := e.Args[0].(bbsimTypes.Stream)
127 if !ok {
128 serviceLogger.Fatal("initialize invoke with wrong arguments")
129 }
130
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700131 service.UpdateStream(stream)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700132
Matteo Scandolof9d43412021-01-12 11:11:34 -0800133 service.PacketCh = make(chan bbsimTypes.OnuPacketMessage)
134 service.Channel = make(chan bbsimTypes.Message)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700135
136 go service.HandlePackets()
137 go service.HandleChannel()
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700138 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700139 fmt.Sprintf("enter_%s", ServiceStateDisabled): func(e *fsm.Event) {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700140 // reset the state machines
141 service.EapolState.SetState("created")
142 service.DHCPState.SetState("created")
143
144 // stop listening for packets
145 close(service.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700146 close(service.Channel)
147
148 service.PacketCh = nil
149 service.Channel = nil
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700150 },
151 },
152 )
153
Matteo Scandolo4a036262020-08-17 15:56:13 -0700154 service.EapolState = fsm.NewFSM(
155 "created",
156 fsm.Events{
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700157 {Name: "start_auth", Src: []string{"created", "eap_response_success_received", "auth_failed"}, Dst: "auth_started"},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700158 {Name: "eap_start_sent", Src: []string{"auth_started"}, Dst: "eap_start_sent"},
159 {Name: "eap_response_identity_sent", Src: []string{"eap_start_sent"}, Dst: "eap_response_identity_sent"},
160 {Name: "eap_response_challenge_sent", Src: []string{"eap_response_identity_sent"}, Dst: "eap_response_challenge_sent"},
161 {Name: "eap_response_success_received", Src: []string{"eap_response_challenge_sent"}, Dst: "eap_response_success_received"},
162 {Name: "auth_failed", Src: []string{"auth_started", "eap_start_sent", "eap_response_identity_sent", "eap_response_challenge_sent"}, Dst: "auth_failed"},
163 },
164 fsm.Callbacks{
165 "enter_state": func(e *fsm.Event) {
166 service.logStateChange("EapolState", e.Src, e.Dst)
167 },
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700168 "before_start_auth": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800169 msg := bbsimTypes.Message{
170 Type: bbsimTypes.StartEAPOL,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700171 }
172 service.Channel <- msg
173 },
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700174 "enter_auth_started": func(e *fsm.Event) {
175 go func() {
176
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700177 for {
178 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700179 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700180 // if the OLT is disabled, then cancel
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700181 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700182 case <-time.After(eapolWaitTime):
183 if service.EapolState.Current() != "eap_response_success_received" {
184 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700185 "OnuId": service.UniPort.Onu.ID,
186 "IntfId": service.UniPort.Onu.PonPortID,
187 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700188 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700189 "PortNo": service.UniPort.PortNo,
190 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700191 "EapolState": service.EapolState.Current(),
192 }).Warn("EAPOL failed, resetting EAPOL State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700193
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700194 _ = service.EapolState.Event("auth_failed")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700195 if common.Config.BBSim.AuthRetry {
196 _ = service.EapolState.Event("start_auth")
197 }
198
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700199 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700200 }
201 }
202
203 }
204 }()
205 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 },
207 )
208
209 service.DHCPState = fsm.NewFSM(
210 "created",
211 fsm.Events{
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700212 {Name: "start_dhcp", Src: []string{"created", "dhcp_ack_received", "dhcp_failed"}, Dst: "dhcp_started"},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700213 {Name: "dhcp_discovery_sent", Src: []string{"dhcp_started"}, Dst: "dhcp_discovery_sent"},
214 {Name: "dhcp_request_sent", Src: []string{"dhcp_discovery_sent"}, Dst: "dhcp_request_sent"},
215 {Name: "dhcp_ack_received", Src: []string{"dhcp_request_sent"}, Dst: "dhcp_ack_received"},
216 {Name: "dhcp_failed", Src: []string{"dhcp_started", "dhcp_discovery_sent", "dhcp_request_sent"}, Dst: "dhcp_failed"},
217 },
218 fsm.Callbacks{
219 "enter_state": func(e *fsm.Event) {
220 service.logStateChange("DHCPState", e.Src, e.Dst)
221 },
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700222 "before_start_dhcp": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800223 msg := bbsimTypes.Message{
224 Type: bbsimTypes.StartDHCP,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700225 }
226 service.Channel <- msg
227 },
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700228 "enter_dhcp_started": func(e *fsm.Event) {
229 go func() {
230
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700231 for {
232 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700233 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700234 // if the OLT is disabled, then cancel
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700235 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700236 case <-time.After(dhcpWaitTime):
237 if service.DHCPState.Current() != "dhcp_ack_received" {
238 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700239 "OnuId": service.UniPort.Onu.ID,
240 "IntfId": service.UniPort.Onu.PonPortID,
241 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700242 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700243 "PortNo": service.UniPort.PortNo,
244 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700245 "DHCPState": service.DHCPState.Current(),
246 }).Warn("DHCP failed, resetting DHCP State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700247
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700248 _ = service.DHCPState.Event("dhcp_failed")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700249 if common.Config.BBSim.DhcpRetry {
250 _ = service.DHCPState.Event("start_dhcp")
251 }
252
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700253 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700254 }
255 }
256
257 }
258 }()
259 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700260 },
261 )
262
Matteo Scandolo618a6582020-09-09 12:21:29 -0700263 service.IGMPState = fsm.NewFSM(
264 "created",
265 fsm.Events{
266 {Name: "igmp_join_start", Src: []string{"created", "igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
267 {Name: "igmp_join_startv3", Src: []string{"igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
268 {Name: "igmp_join_error", Src: []string{"igmp_join_started"}, Dst: "igmp_join_error"},
269 {Name: "igmp_leave", Src: []string{"igmp_join_started"}, Dst: "igmp_left"},
270 },
271 fsm.Callbacks{
272 "igmp_join_start": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800273 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
274 msg := bbsimTypes.Message{
275 Type: bbsimTypes.IGMPMembershipReportV2,
276 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000277 GroupAddress: igmpInfo.GroupAddress,
278 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700279 }
280 service.Channel <- msg
281 },
282 "igmp_leave": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800283 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
284 msg := bbsimTypes.Message{
285 Type: bbsimTypes.IGMPLeaveGroup,
286 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000287 GroupAddress: igmpInfo.GroupAddress,
288 },
289 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700290 service.Channel <- msg
291 },
292 "igmp_join_startv3": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800293 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
294 msg := bbsimTypes.Message{
295 Type: bbsimTypes.IGMPMembershipReportV3,
296 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000297 GroupAddress: igmpInfo.GroupAddress,
298 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700299 }
300 service.Channel <- msg
301 },
302 },
303 )
304
Matteo Scandolo4a036262020-08-17 15:56:13 -0700305 return &service, nil
306}
307
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700308func (s *Service) UpdateStream(stream bbsimTypes.Stream) {
309 s.Stream = stream
310}
311
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700312// HandleAuth is used to start EAPOL for a particular Service when the corresponding flow is received
313func (s *Service) HandleAuth() {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700314
315 if !s.NeedsEapol {
316 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700317 "OnuId": s.UniPort.Onu.ID,
318 "IntfId": s.UniPort.Onu.PonPortID,
319 "OnuSn": s.UniPort.Onu.Sn(),
320 "PortNo": s.UniPort.PortNo,
321 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700322 "Name": s.Name,
323 "NeedsEapol": s.NeedsEapol,
324 }).Debug("Won't start authentication as EAPOL is not required")
325 return
326 }
327
Matteo Scandolo4a036262020-08-17 15:56:13 -0700328 if err := s.EapolState.Event("start_auth"); err != nil {
329 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700330 "OnuId": s.UniPort.Onu.ID,
331 "IntfId": s.UniPort.Onu.PonPortID,
332 "OnuSn": s.UniPort.Onu.Sn(),
333 "PortNo": s.UniPort.PortNo,
334 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700335 "Name": s.Name,
336 "err": err.Error(),
337 }).Error("Can't start auth for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700338 }
339}
340
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700341// HandleDhcp is used to start DHCP for a particular Service when the corresponding flow is received
Matteo Scandolobd875b32020-09-18 17:46:31 -0700342func (s *Service) HandleDhcp(pbit uint8, cTag int) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700343
Matteo Scandolobd875b32020-09-18 17:46:31 -0700344 if s.CTag != cTag || (s.UsPonCTagPriority != pbit && pbit != 255) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700345 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700346 "OnuId": s.UniPort.Onu.ID,
347 "IntfId": s.UniPort.Onu.PonPortID,
348 "OnuSn": s.UniPort.Onu.Sn(),
349 "PortNo": s.UniPort.PortNo,
350 "UniId": s.UniPort.ID,
351 "Name": s.Name,
352 "Service.CTag": s.CTag,
353 "Service.UsPonCTagPriority": s.UsPonCTagPriority,
354 "cTag": cTag,
355 "pbit": pbit,
356 }).Debug("DHCP flow is not for this service, ignoring")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700357 return
358 }
359
Matteo Scandolo4a036262020-08-17 15:56:13 -0700360 if !s.NeedsDhcp {
361 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700362 "OnuId": s.UniPort.Onu.ID,
363 "IntfId": s.UniPort.Onu.PonPortID,
364 "OnuSn": s.UniPort.Onu.Sn(),
365 "PortNo": s.UniPort.PortNo,
366 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700367 "Name": s.Name,
368 "NeedsDhcp": s.NeedsDhcp,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700369 }).Trace("Won't start DHCP as it is not required")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700370 return
371 }
372
Matteo Scandolo8a574812021-05-20 15:18:53 -0700373 // TODO check if the DHCP flow was received before starting DHCP
Matteo Scandolo4a036262020-08-17 15:56:13 -0700374
375 if err := s.DHCPState.Event("start_dhcp"); err != nil {
376 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700377 "OnuId": s.UniPort.Onu.ID,
378 "IntfId": s.UniPort.Onu.PonPortID,
379 "OnuSn": s.UniPort.Onu.Sn(),
380 "PortNo": s.UniPort.PortNo,
381 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700382 "Name": s.Name,
383 "err": err.Error(),
384 }).Error("Can't start DHCP for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700385 }
386}
387
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700388func (s *Service) HandlePackets() {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700389 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700390 "OnuId": s.UniPort.Onu.ID,
391 "IntfId": s.UniPort.Onu.PonPortID,
392 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700393 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700394 "PortNo": s.UniPort.PortNo,
395 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700396 "Name": s.Name,
397 }).Debug("Listening on Service Packet Channel")
398
399 defer func() {
400 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700401 "OnuId": s.UniPort.Onu.ID,
402 "IntfId": s.UniPort.Onu.PonPortID,
403 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700404 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700405 "PortNo": s.UniPort.PortNo,
406 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700407 "Name": s.Name,
408 }).Debug("Done Listening on Service Packet Channel")
409 }()
410
411 for msg := range s.PacketCh {
412 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700413 "OnuId": s.UniPort.Onu.ID,
414 "IntfId": s.UniPort.Onu.PonPortID,
415 "OnuSn": s.UniPort.Onu.Sn(),
416 "GemPortId": s.GemPort,
417 "PortNo": s.UniPort.PortNo,
418 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700419 "Name": s.Name,
420 "messageType": msg.Type,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700421 }).Trace("Received message on Service Packet Channel")
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700422
423 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700424 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 -0700425 } else if msg.Type == packetHandlers.DHCP {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700426 _ = 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 -0700427 } else if msg.Type == packetHandlers.IGMP {
428 log.Warn(hex.EncodeToString(msg.Packet.Data()))
Matteo Scandolo8a574812021-05-20 15:18:53 -0700429 _ = 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 -0700430 }
431 }
432}
433
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700434func (s *Service) HandleChannel() {
435 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700436 "OnuId": s.UniPort.Onu.ID,
437 "IntfId": s.UniPort.Onu.PonPortID,
438 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700439 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700440 "PortNo": s.UniPort.PortNo,
441 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700442 "Name": s.Name,
443 }).Debug("Listening on Service Channel")
444
445 defer func() {
446 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700447 "OnuId": s.UniPort.Onu.ID,
448 "IntfId": s.UniPort.Onu.PonPortID,
449 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700450 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700451 "PortNo": s.UniPort.PortNo,
452 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700453 "Name": s.Name,
454 }).Debug("Done Listening on Service Channel")
455 }()
456 for msg := range s.Channel {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700457 switch msg.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800458 case bbsimTypes.StartEAPOL:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700459 if err := s.handleEapolStart(s.Stream); err != nil {
460 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700461 "OnuId": s.UniPort.Onu.ID,
462 "IntfId": s.UniPort.Onu.PonPortID,
463 "OnuSn": s.UniPort.Onu.Sn(),
464 "GemPortId": s.GemPort,
465 "PortNo": s.UniPort.PortNo,
466 "UniId": s.UniPort.ID,
467 "Name": s.Name,
468 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700469 }).Error("Error while sending EapolStart packet")
470 _ = s.EapolState.Event("auth_failed")
471 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800472 case bbsimTypes.StartDHCP:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700473 if err := s.handleDHCPStart(s.Stream); err != nil {
474 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700475 "OnuId": s.UniPort.Onu.ID,
476 "IntfId": s.UniPort.Onu.PonPortID,
477 "OnuSn": s.UniPort.Onu.Sn(),
478 "GemPortId": s.GemPort,
479 "PortNo": s.UniPort.PortNo,
480 "UniId": s.UniPort.ID,
481 "Name": s.Name,
482 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700483 }).Error("Error while sending DHCPDiscovery packet")
484 _ = s.DHCPState.Event("dhcp_failed")
Matteo Scandolo618a6582020-09-09 12:21:29 -0700485
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700486 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800487 case bbsimTypes.IGMPMembershipReportV2:
488 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700489 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700490 "OnuId": s.UniPort.Onu.ID,
491 "IntfId": s.UniPort.Onu.PonPortID,
492 "OnuSn": s.UniPort.Onu.Sn(),
493 "GemPortId": s.GemPort,
494 "PortNo": s.UniPort.PortNo,
495 "UniId": s.UniPort.ID,
496 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000497 }).Debug("Received IGMPMembershipReportV2 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700498 _ = 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 -0800499 case bbsimTypes.IGMPLeaveGroup:
500 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700501 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700502 "OnuId": s.UniPort.Onu.ID,
503 "IntfId": s.UniPort.Onu.PonPortID,
504 "OnuSn": s.UniPort.Onu.Sn(),
505 "GemPortId": s.GemPort,
506 "PortNo": s.UniPort.PortNo,
507 "UniId": s.UniPort.ID,
508 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000509 }).Debug("Received IGMPLeaveGroupV2 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700510 _ = 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 -0800511 case bbsimTypes.IGMPMembershipReportV3:
512 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700513 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700514 "OnuId": s.UniPort.Onu.ID,
515 "IntfId": s.UniPort.Onu.PonPortID,
516 "OnuSn": s.UniPort.Onu.Sn(),
517 "GemPortId": s.GemPort,
518 "PortNo": s.UniPort.PortNo,
519 "UniId": s.UniPort.ID,
520 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000521 }).Debug("Received IGMPMembershipReportV3 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700522 _ = 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 -0700523
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700524 }
525 }
526}
527
528func (s *Service) Initialize(stream bbsimTypes.Stream) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700529 if err := s.InternalState.Event(ServiceTxInitialize, stream); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700530 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700531 "OnuId": s.UniPort.Onu.ID,
532 "IntfId": s.UniPort.Onu.PonPortID,
533 "OnuSn": s.UniPort.Onu.Sn(),
534 "GemPortId": s.GemPort,
535 "PortNo": s.UniPort.PortNo,
536 "UniId": s.UniPort.ID,
537 "Name": s.Name,
538 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700539 }).Error("Cannot initialize service")
540 }
541}
542
543func (s *Service) Disable() {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700544 if err := s.InternalState.Event(ServiceTxDisable); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700545 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700546 "OnuId": s.UniPort.Onu.ID,
547 "IntfId": s.UniPort.Onu.PonPortID,
548 "OnuSn": s.UniPort.Onu.Sn(),
549 "GemPortId": s.GemPort,
550 "PortNo": s.UniPort.PortNo,
551 "UniId": s.UniPort.ID,
552 "Name": s.Name,
553 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700554 }).Error("Cannot disable service")
555 }
556}
557
Matteo Scandolo4a036262020-08-17 15:56:13 -0700558func (s *Service) handleEapolStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700559 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700560 "OnuId": s.UniPort.Onu.ID,
561 "IntfId": s.UniPort.Onu.PonPortID,
562 "OnuSn": s.UniPort.Onu.Sn(),
563 "GemPortId": s.GemPort,
564 "PortNo": s.UniPort.PortNo,
565 "UniId": s.UniPort.ID,
566 "GemPort": s.GemPort,
567 "Name": s.Name,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700568 }).Trace("handleEapolStart")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700569
Matteo Scandolo8a574812021-05-20 15:18:53 -0700570 if err := eapol.SendEapStart(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.UniPort.Onu.Sn(), s.UniPort.PortNo,
571 s.HwAddress, s.GemPort, s.UniPort.ID, s.EapolState, stream); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700572 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700573 "OnuId": s.UniPort.Onu.ID,
574 "IntfId": s.UniPort.Onu.PonPortID,
575 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700576 "GemPort": s.GemPort,
577 "Name": s.Name,
578 }).Error("handleEapolStart")
579 return err
580 }
581 return nil
582}
583
584func (s *Service) handleDHCPStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700585 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700586 "OnuId": s.UniPort.Onu.ID,
587 "IntfId": s.UniPort.Onu.PonPortID,
588 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700589 "Name": s.Name,
590 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700591 "PortNo": s.UniPort.PortNo,
592 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700593 }).Debugf("HandleDHCPStart")
594
Matteo Scandolo8a574812021-05-20 15:18:53 -0700595 if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, int(s.CTag), s.GemPort,
596 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 -0700597 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700598 "OnuId": s.UniPort.Onu.ID,
599 "IntfId": s.UniPort.Onu.PonPortID,
600 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700601 "Name": s.Name,
602 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700603 "PortNo": s.UniPort.PortNo,
604 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700605 }).Error("HandleDHCPStart")
606 return err
607 }
608 return nil
609}
610
Matteo Scandolo4a036262020-08-17 15:56:13 -0700611func (s *Service) logStateChange(stateMachine string, src string, dst string) {
612 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700613 "OnuId": s.UniPort.Onu.ID,
614 "IntfId": s.UniPort.Onu.PonPortID,
615 "OnuSn": s.UniPort.Onu.Sn(),
616 "GemPortId": s.GemPort,
617 "PortNo": s.UniPort.PortNo,
618 "UniId": s.UniPort.ID,
619 "Name": s.Name,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700620 }).Debugf("Changing Service.%s InternalState from %s to %s", stateMachine, src, dst)
621}