blob: e601120bb791e969212e1ffb1307147a6a346230 [file] [log] [blame]
Matteo Scandolo4a036262020-08-17 15:56:13 -07001/*
Joey Armstrong2c039362024-02-04 18:51:52 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo4a036262020-08-17 15:56:13 -07003
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package devices
18
19import (
Matteo Scandolo8a574812021-05-20 15:18:53 -070020 "fmt"
Elia Battiston536a22b2022-01-10 10:33:15 +010021 "net"
22 "time"
23
Matteo Scandolo4a036262020-08-17 15:56:13 -070024 "github.com/looplab/fsm"
25 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
26 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
27 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
Matteo Scandolo618a6582020-09-09 12:21:29 -070028 "github.com/opencord/bbsim/internal/bbsim/responders/igmp"
Matteo Scandolo4a036262020-08-17 15:56:13 -070029 bbsimTypes "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo76c3ff62020-09-24 18:03:01 -070030 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4a036262020-08-17 15:56:13 -070031 log "github.com/sirupsen/logrus"
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"
Elia Battistondebd4ce2022-03-08 13:38:38 +010050
51 fttbDpuMgmtServiceName = "DPU_MGMT_TRAFFIC"
Matteo Scandolo8a574812021-05-20 15:18:53 -070052)
53
Matteo Scandolo4a036262020-08-17 15:56:13 -070054type ServiceIf interface {
Elia Battistondebd4ce2022-03-08 13:38:38 +010055 HandlePackets() // start listening on the PacketCh
56 HandleAuth() // Sends the EapoStart packet
57 HandleDhcp(oPbit uint8, oVid int) // Sends the DHCPDiscover packet
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070058
Matteo Scandoloadc72a82020-09-08 18:46:08 -070059 Initialize(stream bbsimTypes.Stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -070060 UpdateStream(stream bbsimTypes.Stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070061 Disable()
Matteo Scandolo4a036262020-08-17 15:56:13 -070062}
63
64type Service struct {
Matteo Scandolo8a574812021-05-20 15:18:53 -070065 Id uint32
Matteo Scandolo4a036262020-08-17 15:56:13 -070066 Name string
67 HwAddress net.HardwareAddr
Matteo Scandolo8a574812021-05-20 15:18:53 -070068 UniPort *UniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -070069 CTag int
70 STag int
71 NeedsEapol bool
72 NeedsDhcp bool
73 NeedsIgmp bool
Andrea Campanella29890452022-02-03 16:00:19 +010074 NeedsPPPoE bool
Matteo Scandolo4a036262020-08-17 15:56:13 -070075 TechnologyProfileID int
76 UniTagMatch int
77 ConfigureMacAddress bool
Andrea Campanella29890452022-02-03 16:00:19 +010078 EnableMacLearning bool
Matteo Scandolo8d281372020-09-03 16:23:37 -070079 UsPonCTagPriority uint8
80 UsPonSTagPriority uint8
81 DsPonCTagPriority uint8
82 DsPonSTagPriority uint8
Matteo Scandolo4a036262020-08-17 15:56:13 -070083
Baris Ertas53ab13c2023-05-25 16:31:48 +030084 // gem port received in flow add requests
85 GemPort uint32
86 // Multicast addresses joined with the ctag
87 groupAddresses map[string]int
88
Matteo Scandolo4a036262020-08-17 15:56:13 -070089 // state
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070090 InternalState *fsm.FSM
91 EapolState *fsm.FSM
92 DHCPState *fsm.FSM
Matteo Scandolo618a6582020-09-09 12:21:29 -070093 IGMPState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080094 Channel chan bbsimTypes.Message // drive Service lifecycle
95 PacketCh chan bbsimTypes.OnuPacketMessage // handle packets
96 Stream bbsimTypes.Stream // the gRPC stream to communicate with the adapter, created in the initialize transition
Matteo Scandolo4a036262020-08-17 15:56:13 -070097}
98
Matteo Scandolo8a574812021-05-20 15:18:53 -070099func NewService(id uint32, name string, hwAddress net.HardwareAddr, uni *UniPort, cTag int, sTag int,
Andrea Campanella29890452022-02-03 16:00:19 +0100100 needsEapol bool, needsDchp bool, needsIgmp bool, needsPPPoE bool, tpID int, uniTagMatch int, configMacAddress bool,
101 enableMacLearning bool, usPonCTagPriority uint8, usPonSTagPriority uint8, dsPonCTagPriority uint8,
102 dsPonSTagPriority uint8) (*Service, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700103
104 service := Service{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700105 Id: id,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700106 Name: name,
107 HwAddress: hwAddress,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700108 UniPort: uni,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700109 CTag: cTag,
110 STag: sTag,
111 NeedsEapol: needsEapol,
112 NeedsDhcp: needsDchp,
113 NeedsIgmp: needsIgmp,
Andrea Campanella29890452022-02-03 16:00:19 +0100114 NeedsPPPoE: needsPPPoE,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700115 TechnologyProfileID: tpID,
116 UniTagMatch: uniTagMatch,
117 ConfigureMacAddress: configMacAddress,
Andrea Campanella29890452022-02-03 16:00:19 +0100118 EnableMacLearning: enableMacLearning,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700119 UsPonCTagPriority: usPonCTagPriority,
120 UsPonSTagPriority: usPonSTagPriority,
121 DsPonCTagPriority: dsPonCTagPriority,
122 DsPonSTagPriority: dsPonSTagPriority,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700123 }
124
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700125 service.InternalState = fsm.NewFSM(
Matteo Scandolo8a574812021-05-20 15:18:53 -0700126 ServiceStateCreated,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700127 fsm.Events{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700128 {Name: ServiceTxInitialize, Src: []string{ServiceStateCreated, ServiceStateDisabled}, Dst: ServiceStateInitialized},
129 {Name: ServiceTxDisable, Src: []string{ServiceStateInitialized}, Dst: ServiceStateDisabled},
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700130 },
131 fsm.Callbacks{
132 "enter_state": func(e *fsm.Event) {
133 service.logStateChange("InternalState", e.Src, e.Dst)
134 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700135 fmt.Sprintf("enter_%s", ServiceStateInitialized): func(e *fsm.Event) {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700136
137 stream, ok := e.Args[0].(bbsimTypes.Stream)
138 if !ok {
139 serviceLogger.Fatal("initialize invoke with wrong arguments")
140 }
141
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700142 service.UpdateStream(stream)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700143
Matteo Scandolof9d43412021-01-12 11:11:34 -0800144 service.PacketCh = make(chan bbsimTypes.OnuPacketMessage)
145 service.Channel = make(chan bbsimTypes.Message)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700146
147 go service.HandlePackets()
148 go service.HandleChannel()
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700149 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700150 fmt.Sprintf("enter_%s", ServiceStateDisabled): func(e *fsm.Event) {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700151 // reset the state machines
Elia Battiston536a22b2022-01-10 10:33:15 +0100152 service.EapolState.SetState(eapol.StateCreated)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700153 service.DHCPState.SetState("created")
154
155 // stop listening for packets
156 close(service.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700157 close(service.Channel)
158
159 service.PacketCh = nil
160 service.Channel = nil
Baris Ertas53ab13c2023-05-25 16:31:48 +0300161
162 service.GemPort = 0
163 service.groupAddresses = nil
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700164 },
165 },
166 )
167
Matteo Scandolo4a036262020-08-17 15:56:13 -0700168 service.EapolState = fsm.NewFSM(
Elia Battiston536a22b2022-01-10 10:33:15 +0100169 eapol.StateCreated,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700170 fsm.Events{
Elia Battiston536a22b2022-01-10 10:33:15 +0100171 {Name: eapol.EventStartAuth, Src: []string{eapol.StateCreated, eapol.StateResponseSuccessReceived, eapol.StateAuthFailed}, Dst: eapol.StateAuthStarted},
172 {Name: eapol.EventStartSent, Src: []string{eapol.StateAuthStarted}, Dst: eapol.StateStartSent},
173 {Name: eapol.EventResponseIdentitySent, Src: []string{eapol.StateStartSent}, Dst: eapol.StateResponseIdentitySent},
174 {Name: eapol.EventResponseChallengeSent, Src: []string{eapol.StateResponseIdentitySent}, Dst: eapol.StateResponseChallengeSent},
175 {Name: eapol.EventResponseSuccessReceived, Src: []string{eapol.StateResponseChallengeSent}, Dst: eapol.StateResponseSuccessReceived},
176 {Name: eapol.EventAuthFailed, Src: []string{eapol.StateAuthStarted, eapol.StateStartSent, eapol.StateResponseIdentitySent, eapol.StateResponseChallengeSent}, Dst: eapol.StateAuthFailed},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700177 },
178 fsm.Callbacks{
179 "enter_state": func(e *fsm.Event) {
180 service.logStateChange("EapolState", e.Src, e.Dst)
181 },
Elia Battiston536a22b2022-01-10 10:33:15 +0100182 fmt.Sprintf("before_%s", eapol.EventStartAuth): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800183 msg := bbsimTypes.Message{
184 Type: bbsimTypes.StartEAPOL,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700185 }
186 service.Channel <- msg
187 },
Elia Battiston536a22b2022-01-10 10:33:15 +0100188 fmt.Sprintf("enter_%s", eapol.StateAuthStarted): func(e *fsm.Event) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700189 go func() {
190
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700191 for {
192 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700193 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Elia Battistonda45f6e2022-02-24 11:12:16 +0100194 serviceLogger.WithFields(log.Fields{
195 "context": service.UniPort.Onu.PonPort.Olt.enableContext,
196 }).Debug("EAPOL cancelled, OLT is disabled")
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700197 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700198 case <-time.After(eapolWaitTime):
Elia Battiston536a22b2022-01-10 10:33:15 +0100199 if service.EapolState.Current() != eapol.StateResponseSuccessReceived {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700200 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700201 "OnuId": service.UniPort.Onu.ID,
202 "IntfId": service.UniPort.Onu.PonPortID,
203 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700204 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700205 "PortNo": service.UniPort.PortNo,
206 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700207 "EapolState": service.EapolState.Current(),
208 }).Warn("EAPOL failed, resetting EAPOL State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700209
Elia Battiston536a22b2022-01-10 10:33:15 +0100210 _ = service.EapolState.Event(eapol.EventAuthFailed)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700211 if common.Config.BBSim.AuthRetry {
Elia Battiston536a22b2022-01-10 10:33:15 +0100212 _ = service.EapolState.Event(eapol.EventStartAuth)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700213 }
214
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700215 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700216 }
217 }
218
219 }
220 }()
221 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700222 },
223 )
224
225 service.DHCPState = fsm.NewFSM(
226 "created",
227 fsm.Events{
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700228 {Name: "start_dhcp", Src: []string{"created", "dhcp_ack_received", "dhcp_failed"}, Dst: "dhcp_started"},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700229 {Name: "dhcp_discovery_sent", Src: []string{"dhcp_started"}, Dst: "dhcp_discovery_sent"},
230 {Name: "dhcp_request_sent", Src: []string{"dhcp_discovery_sent"}, Dst: "dhcp_request_sent"},
231 {Name: "dhcp_ack_received", Src: []string{"dhcp_request_sent"}, Dst: "dhcp_ack_received"},
232 {Name: "dhcp_failed", Src: []string{"dhcp_started", "dhcp_discovery_sent", "dhcp_request_sent"}, Dst: "dhcp_failed"},
233 },
234 fsm.Callbacks{
235 "enter_state": func(e *fsm.Event) {
236 service.logStateChange("DHCPState", e.Src, e.Dst)
237 },
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700238 "before_start_dhcp": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800239 msg := bbsimTypes.Message{
240 Type: bbsimTypes.StartDHCP,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700241 }
242 service.Channel <- msg
243 },
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700244 "enter_dhcp_started": func(e *fsm.Event) {
245 go func() {
246
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700247 for {
248 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700249 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Elia Battistonda45f6e2022-02-24 11:12:16 +0100250 serviceLogger.WithFields(log.Fields{
251 "context": service.UniPort.Onu.PonPort.Olt.enableContext,
252 }).Debug("DHCP cancelled, OLT is disabled")
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700253 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700254 case <-time.After(dhcpWaitTime):
255 if service.DHCPState.Current() != "dhcp_ack_received" {
256 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700257 "OnuId": service.UniPort.Onu.ID,
258 "IntfId": service.UniPort.Onu.PonPortID,
259 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700260 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700261 "PortNo": service.UniPort.PortNo,
262 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700263 "DHCPState": service.DHCPState.Current(),
264 }).Warn("DHCP failed, resetting DHCP State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700265
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700266 _ = service.DHCPState.Event("dhcp_failed")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700267 if common.Config.BBSim.DhcpRetry {
268 _ = service.DHCPState.Event("start_dhcp")
269 }
270
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700271 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700272 }
273 }
274
275 }
276 }()
277 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700278 },
279 )
280
Matteo Scandolo618a6582020-09-09 12:21:29 -0700281 service.IGMPState = fsm.NewFSM(
282 "created",
283 fsm.Events{
284 {Name: "igmp_join_start", Src: []string{"created", "igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
285 {Name: "igmp_join_startv3", Src: []string{"igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
286 {Name: "igmp_join_error", Src: []string{"igmp_join_started"}, Dst: "igmp_join_error"},
287 {Name: "igmp_leave", Src: []string{"igmp_join_started"}, Dst: "igmp_left"},
288 },
289 fsm.Callbacks{
290 "igmp_join_start": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800291 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
292 msg := bbsimTypes.Message{
293 Type: bbsimTypes.IGMPMembershipReportV2,
294 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000295 GroupAddress: igmpInfo.GroupAddress,
296 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700297 }
298 service.Channel <- msg
299 },
300 "igmp_leave": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800301 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
302 msg := bbsimTypes.Message{
303 Type: bbsimTypes.IGMPLeaveGroup,
304 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000305 GroupAddress: igmpInfo.GroupAddress,
306 },
307 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700308 service.Channel <- msg
309 },
310 "igmp_join_startv3": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800311 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
312 msg := bbsimTypes.Message{
313 Type: bbsimTypes.IGMPMembershipReportV3,
314 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000315 GroupAddress: igmpInfo.GroupAddress,
316 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700317 }
318 service.Channel <- msg
319 },
320 },
321 )
322
Matteo Scandolo4a036262020-08-17 15:56:13 -0700323 return &service, nil
324}
325
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700326func (s *Service) UpdateStream(stream bbsimTypes.Stream) {
327 s.Stream = stream
328}
329
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700330// HandleAuth is used to start EAPOL for a particular Service when the corresponding flow is received
331func (s *Service) HandleAuth() {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700332
333 if !s.NeedsEapol {
334 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700335 "OnuId": s.UniPort.Onu.ID,
336 "IntfId": s.UniPort.Onu.PonPortID,
337 "OnuSn": s.UniPort.Onu.Sn(),
338 "PortNo": s.UniPort.PortNo,
339 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700340 "Name": s.Name,
341 "NeedsEapol": s.NeedsEapol,
342 }).Debug("Won't start authentication as EAPOL is not required")
343 return
344 }
345
Elia Battistonda45f6e2022-02-24 11:12:16 +0100346 serviceLogger.WithFields(log.Fields{
347 "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 "NeedsEapol": s.NeedsEapol,
354 }).Debug("Starting EAPOL for the service")
Elia Battiston536a22b2022-01-10 10:33:15 +0100355 if err := s.EapolState.Event(eapol.EventStartAuth); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700356 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700357 "OnuId": s.UniPort.Onu.ID,
358 "IntfId": s.UniPort.Onu.PonPortID,
359 "OnuSn": s.UniPort.Onu.Sn(),
360 "PortNo": s.UniPort.PortNo,
361 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700362 "Name": s.Name,
363 "err": err.Error(),
364 }).Error("Can't start auth for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700365 }
366}
367
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700368// HandleDhcp is used to start DHCP for a particular Service when the corresponding flow is received
Elia Battistondebd4ce2022-03-08 13:38:38 +0100369func (s *Service) HandleDhcp(oPbit uint8, oVid int) {
370 var compareTag int
371 var comparePbits uint8
Matteo Scandolo4a036262020-08-17 15:56:13 -0700372
Elia Battistondebd4ce2022-03-08 13:38:38 +0100373 if s.Name == fttbDpuMgmtServiceName {
374 compareTag = s.STag
375 comparePbits = s.UsPonSTagPriority
376 } else {
377 compareTag = s.CTag
378 comparePbits = s.UsPonCTagPriority
379 }
380
381 if compareTag != oVid || (comparePbits != oPbit && oPbit != 255) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700382 serviceLogger.WithFields(log.Fields{
Elia Battistondebd4ce2022-03-08 13:38:38 +0100383 "OnuId": s.UniPort.Onu.ID,
384 "IntfId": s.UniPort.Onu.PonPortID,
385 "OnuSn": s.UniPort.Onu.Sn(),
386 "PortNo": s.UniPort.PortNo,
387 "UniId": s.UniPort.ID,
388 "Name": s.Name,
389 "compareTag": compareTag,
390 "comparePbits": comparePbits,
391 "oVid": oVid,
392 "oPbit": oPbit,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700393 }).Debug("DHCP flow is not for this service, ignoring")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700394 return
395 }
396
Matteo Scandolo4a036262020-08-17 15:56:13 -0700397 if !s.NeedsDhcp {
398 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700399 "OnuId": s.UniPort.Onu.ID,
400 "IntfId": s.UniPort.Onu.PonPortID,
401 "OnuSn": s.UniPort.Onu.Sn(),
402 "PortNo": s.UniPort.PortNo,
403 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700404 "Name": s.Name,
405 "NeedsDhcp": s.NeedsDhcp,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700406 }).Trace("Won't start DHCP as it is not required")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700407 return
408 }
409
Elia Battistonda45f6e2022-02-24 11:12:16 +0100410 serviceLogger.WithFields(log.Fields{
411 "OnuId": s.UniPort.Onu.ID,
412 "IntfId": s.UniPort.Onu.PonPortID,
413 "OnuSn": s.UniPort.Onu.Sn(),
414 "PortNo": s.UniPort.PortNo,
415 "UniId": s.UniPort.ID,
416 "Name": s.Name,
417 "NeedsEapol": s.NeedsEapol,
418 }).Debug("Starting DHCP for the service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700419 if err := s.DHCPState.Event("start_dhcp"); err != nil {
420 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700421 "OnuId": s.UniPort.Onu.ID,
422 "IntfId": s.UniPort.Onu.PonPortID,
423 "OnuSn": s.UniPort.Onu.Sn(),
424 "PortNo": s.UniPort.PortNo,
425 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700426 "Name": s.Name,
427 "err": err.Error(),
428 }).Error("Can't start DHCP for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700429 }
430}
431
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700432func (s *Service) HandlePackets() {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700433 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700434 "OnuId": s.UniPort.Onu.ID,
435 "IntfId": s.UniPort.Onu.PonPortID,
436 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700437 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700438 "PortNo": s.UniPort.PortNo,
439 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700440 "Name": s.Name,
441 }).Debug("Listening on Service Packet Channel")
442
443 defer func() {
444 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700445 "OnuId": s.UniPort.Onu.ID,
446 "IntfId": s.UniPort.Onu.PonPortID,
447 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700448 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700449 "PortNo": s.UniPort.PortNo,
450 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700451 "Name": s.Name,
452 }).Debug("Done Listening on Service Packet Channel")
453 }()
454
455 for msg := range s.PacketCh {
456 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700457 "OnuId": s.UniPort.Onu.ID,
458 "IntfId": s.UniPort.Onu.PonPortID,
459 "OnuSn": s.UniPort.Onu.Sn(),
460 "GemPortId": s.GemPort,
461 "PortNo": s.UniPort.PortNo,
462 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700463 "Name": s.Name,
464 "messageType": msg.Type,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700465 }).Trace("Received message on Service Packet Channel")
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700466
467 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700468 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 -0700469 } else if msg.Type == packetHandlers.DHCP {
Elia Battistona9666542022-03-17 15:45:45 +0100470 tag := int(s.CTag)
471 priority := s.UsPonCTagPriority
472 if s.Name == fttbDpuMgmtServiceName {
473 tag = int(s.STag)
474 priority = s.UsPonSTagPriority
475 }
476
477 _ = dhcp.HandleNextPacket(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.Name, s.UniPort.Onu.Sn(), s.UniPort.PortNo, tag, s.GemPort, s.UniPort.ID, s.HwAddress, s.DHCPState, msg.Packet, priority, s.Stream)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700478 } else if msg.Type == packetHandlers.IGMP {
Baris Ertas53ab13c2023-05-25 16:31:48 +0300479 _ = igmp.HandleNextPacket(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.groupAddresses, s.Stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700480 }
481 }
482}
483
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700484func (s *Service) HandleChannel() {
485 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700486 "OnuId": s.UniPort.Onu.ID,
487 "IntfId": s.UniPort.Onu.PonPortID,
488 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700489 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700490 "PortNo": s.UniPort.PortNo,
491 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700492 "Name": s.Name,
493 }).Debug("Listening on Service Channel")
494
495 defer func() {
496 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700497 "OnuId": s.UniPort.Onu.ID,
498 "IntfId": s.UniPort.Onu.PonPortID,
499 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700500 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700501 "PortNo": s.UniPort.PortNo,
502 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700503 "Name": s.Name,
504 }).Debug("Done Listening on Service Channel")
505 }()
506 for msg := range s.Channel {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700507 switch msg.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800508 case bbsimTypes.StartEAPOL:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700509 if err := s.handleEapolStart(s.Stream); err != nil {
510 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700511 "OnuId": s.UniPort.Onu.ID,
512 "IntfId": s.UniPort.Onu.PonPortID,
513 "OnuSn": s.UniPort.Onu.Sn(),
514 "GemPortId": s.GemPort,
515 "PortNo": s.UniPort.PortNo,
516 "UniId": s.UniPort.ID,
517 "Name": s.Name,
518 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700519 }).Error("Error while sending EapolStart packet")
Elia Battiston536a22b2022-01-10 10:33:15 +0100520 _ = s.EapolState.Event(eapol.EventAuthFailed)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700521 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800522 case bbsimTypes.StartDHCP:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700523 if err := s.handleDHCPStart(s.Stream); err != nil {
524 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700525 "OnuId": s.UniPort.Onu.ID,
526 "IntfId": s.UniPort.Onu.PonPortID,
527 "OnuSn": s.UniPort.Onu.Sn(),
528 "GemPortId": s.GemPort,
529 "PortNo": s.UniPort.PortNo,
530 "UniId": s.UniPort.ID,
531 "Name": s.Name,
532 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700533 }).Error("Error while sending DHCPDiscovery packet")
534 _ = s.DHCPState.Event("dhcp_failed")
Matteo Scandolo618a6582020-09-09 12:21:29 -0700535
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700536 }
Baris Ertas53ab13c2023-05-25 16:31:48 +0300537 // IGMP block is not in use since the event mechanism is disable for IGMP
Matteo Scandolof9d43412021-01-12 11:11:34 -0800538 case bbsimTypes.IGMPMembershipReportV2:
539 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700540 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700541 "OnuId": s.UniPort.Onu.ID,
542 "IntfId": s.UniPort.Onu.PonPortID,
543 "OnuSn": s.UniPort.Onu.Sn(),
544 "GemPortId": s.GemPort,
545 "PortNo": s.UniPort.PortNo,
546 "UniId": s.UniPort.ID,
547 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000548 }).Debug("Received IGMPMembershipReportV2 message on ONU channel")
Baris Ertas0ce2f7c2023-04-11 11:44:24 +0300549 _ = igmp.SendIGMPMembershipReportV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800550 case bbsimTypes.IGMPLeaveGroup:
551 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700552 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700553 "OnuId": s.UniPort.Onu.ID,
554 "IntfId": s.UniPort.Onu.PonPortID,
555 "OnuSn": s.UniPort.Onu.Sn(),
556 "GemPortId": s.GemPort,
557 "PortNo": s.UniPort.PortNo,
558 "UniId": s.UniPort.ID,
559 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000560 }).Debug("Received IGMPLeaveGroupV2 message on ONU channel")
Baris Ertas53ab13c2023-05-25 16:31:48 +0300561 s.RemoveGroupAddress(igmpInfo.GroupAddress)
Baris Ertas0ce2f7c2023-04-11 11:44:24 +0300562 _ = igmp.SendIGMPLeaveGroupV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800563 case bbsimTypes.IGMPMembershipReportV3:
564 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700565 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700566 "OnuId": s.UniPort.Onu.ID,
567 "IntfId": s.UniPort.Onu.PonPortID,
568 "OnuSn": s.UniPort.Onu.Sn(),
569 "GemPortId": s.GemPort,
570 "PortNo": s.UniPort.PortNo,
571 "UniId": s.UniPort.ID,
572 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000573 }).Debug("Received IGMPMembershipReportV3 message on ONU channel")
Baris Ertas0ce2f7c2023-04-11 11:44:24 +0300574 _ = igmp.SendIGMPMembershipReportV3(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700575
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700576 }
577 }
578}
579
580func (s *Service) Initialize(stream bbsimTypes.Stream) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700581 if err := s.InternalState.Event(ServiceTxInitialize, stream); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700582 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700583 "OnuId": s.UniPort.Onu.ID,
584 "IntfId": s.UniPort.Onu.PonPortID,
585 "OnuSn": s.UniPort.Onu.Sn(),
586 "GemPortId": s.GemPort,
587 "PortNo": s.UniPort.PortNo,
588 "UniId": s.UniPort.ID,
589 "Name": s.Name,
590 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700591 }).Error("Cannot initialize service")
592 }
593}
594
595func (s *Service) Disable() {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700596 if err := s.InternalState.Event(ServiceTxDisable); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -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(),
601 "GemPortId": s.GemPort,
602 "PortNo": s.UniPort.PortNo,
603 "UniId": s.UniPort.ID,
604 "Name": s.Name,
605 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700606 }).Error("Cannot disable service")
607 }
608}
609
Matteo Scandolo4a036262020-08-17 15:56:13 -0700610func (s *Service) handleEapolStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700611 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700612 "OnuId": s.UniPort.Onu.ID,
613 "IntfId": s.UniPort.Onu.PonPortID,
614 "OnuSn": s.UniPort.Onu.Sn(),
615 "GemPortId": s.GemPort,
616 "PortNo": s.UniPort.PortNo,
617 "UniId": s.UniPort.ID,
618 "GemPort": s.GemPort,
619 "Name": s.Name,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700620 }).Trace("handleEapolStart")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700621
Matteo Scandolo8a574812021-05-20 15:18:53 -0700622 if err := eapol.SendEapStart(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.UniPort.Onu.Sn(), s.UniPort.PortNo,
623 s.HwAddress, s.GemPort, s.UniPort.ID, s.EapolState, stream); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700624 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700625 "OnuId": s.UniPort.Onu.ID,
626 "IntfId": s.UniPort.Onu.PonPortID,
627 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700628 "GemPort": s.GemPort,
629 "Name": s.Name,
630 }).Error("handleEapolStart")
631 return err
632 }
633 return nil
634}
635
636func (s *Service) handleDHCPStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700637 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700638 "OnuId": s.UniPort.Onu.ID,
639 "IntfId": s.UniPort.Onu.PonPortID,
640 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700641 "Name": s.Name,
642 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700643 "PortNo": s.UniPort.PortNo,
644 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700645 }).Debugf("HandleDHCPStart")
646
Elia Battistona9666542022-03-17 15:45:45 +0100647 tag := int(s.CTag)
648 priority := s.UsPonCTagPriority
649 if s.Name == fttbDpuMgmtServiceName {
650 tag = int(s.STag)
651 priority = s.UsPonSTagPriority
652 }
653
654 if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, tag, s.GemPort,
655 s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.DHCPState, s.HwAddress, priority, stream); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700656 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700657 "OnuId": s.UniPort.Onu.ID,
658 "IntfId": s.UniPort.Onu.PonPortID,
659 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700660 "Name": s.Name,
661 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700662 "PortNo": s.UniPort.PortNo,
663 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700664 }).Error("HandleDHCPStart")
665 return err
666 }
667 return nil
668}
669
Matteo Scandolo4a036262020-08-17 15:56:13 -0700670func (s *Service) logStateChange(stateMachine string, src string, dst string) {
671 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700672 "OnuId": s.UniPort.Onu.ID,
673 "IntfId": s.UniPort.Onu.PonPortID,
674 "OnuSn": s.UniPort.Onu.Sn(),
675 "GemPortId": s.GemPort,
676 "PortNo": s.UniPort.PortNo,
677 "UniId": s.UniPort.ID,
678 "Name": s.Name,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700679 }).Debugf("Changing Service.%s InternalState from %s to %s", stateMachine, src, dst)
680}
Baris Ertas53ab13c2023-05-25 16:31:48 +0300681
682func (s *Service) AddGroupAddress(addr string, ctag int) {
683 if s.groupAddresses == nil {
684 s.groupAddresses = make(map[string]int)
685 }
686 s.groupAddresses[addr] = ctag
687}
688
689func (s *Service) RemoveGroupAddress(addr string) {
690 if s.groupAddresses == nil {
691 return
692 }
693 delete(s.groupAddresses, addr)
694}