blob: 3e4e83baabd8e22edf406a2344d866f2f2c5085f [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"
Elia Battistondebd4ce2022-03-08 13:38:38 +010051
52 fttbDpuMgmtServiceName = "DPU_MGMT_TRAFFIC"
Matteo Scandolo8a574812021-05-20 15:18:53 -070053)
54
Matteo Scandolo4a036262020-08-17 15:56:13 -070055type ServiceIf interface {
Elia Battistondebd4ce2022-03-08 13:38:38 +010056 HandlePackets() // start listening on the PacketCh
57 HandleAuth() // Sends the EapoStart packet
58 HandleDhcp(oPbit uint8, oVid int) // Sends the DHCPDiscover packet
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070059
Matteo Scandoloadc72a82020-09-08 18:46:08 -070060 Initialize(stream bbsimTypes.Stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -070061 UpdateStream(stream bbsimTypes.Stream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070062 Disable()
Matteo Scandolo4a036262020-08-17 15:56:13 -070063}
64
65type Service struct {
Matteo Scandolo8a574812021-05-20 15:18:53 -070066 Id uint32
Matteo Scandolo4a036262020-08-17 15:56:13 -070067 Name string
68 HwAddress net.HardwareAddr
Matteo Scandolo8a574812021-05-20 15:18:53 -070069 UniPort *UniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -070070 CTag int
71 STag int
72 NeedsEapol bool
73 NeedsDhcp bool
74 NeedsIgmp bool
Andrea Campanella29890452022-02-03 16:00:19 +010075 NeedsPPPoE bool
Matteo Scandolo4a036262020-08-17 15:56:13 -070076 TechnologyProfileID int
77 UniTagMatch int
78 ConfigureMacAddress bool
Andrea Campanella29890452022-02-03 16:00:19 +010079 EnableMacLearning bool
Matteo Scandolo8d281372020-09-03 16:23:37 -070080 UsPonCTagPriority uint8
81 UsPonSTagPriority uint8
82 DsPonCTagPriority uint8
83 DsPonSTagPriority uint8
Matteo Scandolo4a036262020-08-17 15:56:13 -070084
85 // state
Matteo Scandolo75ed5b92020-09-03 09:03:16 -070086 GemPort uint32
87 InternalState *fsm.FSM
88 EapolState *fsm.FSM
89 DHCPState *fsm.FSM
Matteo Scandolo618a6582020-09-09 12:21:29 -070090 IGMPState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080091 Channel chan bbsimTypes.Message // drive Service lifecycle
92 PacketCh chan bbsimTypes.OnuPacketMessage // handle packets
93 Stream bbsimTypes.Stream // the gRPC stream to communicate with the adapter, created in the initialize transition
Matteo Scandolo4a036262020-08-17 15:56:13 -070094}
95
Matteo Scandolo8a574812021-05-20 15:18:53 -070096func NewService(id uint32, name string, hwAddress net.HardwareAddr, uni *UniPort, cTag int, sTag int,
Andrea Campanella29890452022-02-03 16:00:19 +010097 needsEapol bool, needsDchp bool, needsIgmp bool, needsPPPoE bool, tpID int, uniTagMatch int, configMacAddress bool,
98 enableMacLearning bool, usPonCTagPriority uint8, usPonSTagPriority uint8, dsPonCTagPriority uint8,
99 dsPonSTagPriority uint8) (*Service, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700100
101 service := Service{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700102 Id: id,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700103 Name: name,
104 HwAddress: hwAddress,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700105 UniPort: uni,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700106 CTag: cTag,
107 STag: sTag,
108 NeedsEapol: needsEapol,
109 NeedsDhcp: needsDchp,
110 NeedsIgmp: needsIgmp,
Andrea Campanella29890452022-02-03 16:00:19 +0100111 NeedsPPPoE: needsPPPoE,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700112 TechnologyProfileID: tpID,
113 UniTagMatch: uniTagMatch,
114 ConfigureMacAddress: configMacAddress,
Andrea Campanella29890452022-02-03 16:00:19 +0100115 EnableMacLearning: enableMacLearning,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700116 UsPonCTagPriority: usPonCTagPriority,
117 UsPonSTagPriority: usPonSTagPriority,
118 DsPonCTagPriority: dsPonCTagPriority,
119 DsPonSTagPriority: dsPonSTagPriority,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700120 }
121
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700122 service.InternalState = fsm.NewFSM(
Matteo Scandolo8a574812021-05-20 15:18:53 -0700123 ServiceStateCreated,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700124 fsm.Events{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700125 {Name: ServiceTxInitialize, Src: []string{ServiceStateCreated, ServiceStateDisabled}, Dst: ServiceStateInitialized},
126 {Name: ServiceTxDisable, Src: []string{ServiceStateInitialized}, Dst: ServiceStateDisabled},
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700127 },
128 fsm.Callbacks{
129 "enter_state": func(e *fsm.Event) {
130 service.logStateChange("InternalState", e.Src, e.Dst)
131 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700132 fmt.Sprintf("enter_%s", ServiceStateInitialized): func(e *fsm.Event) {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700133
134 stream, ok := e.Args[0].(bbsimTypes.Stream)
135 if !ok {
136 serviceLogger.Fatal("initialize invoke with wrong arguments")
137 }
138
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700139 service.UpdateStream(stream)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700140
Matteo Scandolof9d43412021-01-12 11:11:34 -0800141 service.PacketCh = make(chan bbsimTypes.OnuPacketMessage)
142 service.Channel = make(chan bbsimTypes.Message)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700143
144 go service.HandlePackets()
145 go service.HandleChannel()
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700146 },
Matteo Scandolo8a574812021-05-20 15:18:53 -0700147 fmt.Sprintf("enter_%s", ServiceStateDisabled): func(e *fsm.Event) {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700148 // reset the state machines
Elia Battiston536a22b2022-01-10 10:33:15 +0100149 service.EapolState.SetState(eapol.StateCreated)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700150 service.DHCPState.SetState("created")
151
152 // stop listening for packets
153 close(service.PacketCh)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700154 close(service.Channel)
155
156 service.PacketCh = nil
157 service.Channel = nil
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700158 },
159 },
160 )
161
Matteo Scandolo4a036262020-08-17 15:56:13 -0700162 service.EapolState = fsm.NewFSM(
Elia Battiston536a22b2022-01-10 10:33:15 +0100163 eapol.StateCreated,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700164 fsm.Events{
Elia Battiston536a22b2022-01-10 10:33:15 +0100165 {Name: eapol.EventStartAuth, Src: []string{eapol.StateCreated, eapol.StateResponseSuccessReceived, eapol.StateAuthFailed}, Dst: eapol.StateAuthStarted},
166 {Name: eapol.EventStartSent, Src: []string{eapol.StateAuthStarted}, Dst: eapol.StateStartSent},
167 {Name: eapol.EventResponseIdentitySent, Src: []string{eapol.StateStartSent}, Dst: eapol.StateResponseIdentitySent},
168 {Name: eapol.EventResponseChallengeSent, Src: []string{eapol.StateResponseIdentitySent}, Dst: eapol.StateResponseChallengeSent},
169 {Name: eapol.EventResponseSuccessReceived, Src: []string{eapol.StateResponseChallengeSent}, Dst: eapol.StateResponseSuccessReceived},
170 {Name: eapol.EventAuthFailed, Src: []string{eapol.StateAuthStarted, eapol.StateStartSent, eapol.StateResponseIdentitySent, eapol.StateResponseChallengeSent}, Dst: eapol.StateAuthFailed},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700171 },
172 fsm.Callbacks{
173 "enter_state": func(e *fsm.Event) {
174 service.logStateChange("EapolState", e.Src, e.Dst)
175 },
Elia Battiston536a22b2022-01-10 10:33:15 +0100176 fmt.Sprintf("before_%s", eapol.EventStartAuth): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800177 msg := bbsimTypes.Message{
178 Type: bbsimTypes.StartEAPOL,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700179 }
180 service.Channel <- msg
181 },
Elia Battiston536a22b2022-01-10 10:33:15 +0100182 fmt.Sprintf("enter_%s", eapol.StateAuthStarted): func(e *fsm.Event) {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700183 go func() {
184
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700185 for {
186 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700187 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Elia Battistonda45f6e2022-02-24 11:12:16 +0100188 serviceLogger.WithFields(log.Fields{
189 "context": service.UniPort.Onu.PonPort.Olt.enableContext,
190 }).Debug("EAPOL cancelled, OLT is disabled")
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700191 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700192 case <-time.After(eapolWaitTime):
Elia Battiston536a22b2022-01-10 10:33:15 +0100193 if service.EapolState.Current() != eapol.StateResponseSuccessReceived {
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700194 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700195 "OnuId": service.UniPort.Onu.ID,
196 "IntfId": service.UniPort.Onu.PonPortID,
197 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700198 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700199 "PortNo": service.UniPort.PortNo,
200 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700201 "EapolState": service.EapolState.Current(),
202 }).Warn("EAPOL failed, resetting EAPOL State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700203
Elia Battiston536a22b2022-01-10 10:33:15 +0100204 _ = service.EapolState.Event(eapol.EventAuthFailed)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700205 if common.Config.BBSim.AuthRetry {
Elia Battiston536a22b2022-01-10 10:33:15 +0100206 _ = service.EapolState.Event(eapol.EventStartAuth)
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700207 }
208
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700209 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700210 }
211 }
212
213 }
214 }()
215 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700216 },
217 )
218
219 service.DHCPState = fsm.NewFSM(
220 "created",
221 fsm.Events{
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700222 {Name: "start_dhcp", Src: []string{"created", "dhcp_ack_received", "dhcp_failed"}, Dst: "dhcp_started"},
Matteo Scandolo4a036262020-08-17 15:56:13 -0700223 {Name: "dhcp_discovery_sent", Src: []string{"dhcp_started"}, Dst: "dhcp_discovery_sent"},
224 {Name: "dhcp_request_sent", Src: []string{"dhcp_discovery_sent"}, Dst: "dhcp_request_sent"},
225 {Name: "dhcp_ack_received", Src: []string{"dhcp_request_sent"}, Dst: "dhcp_ack_received"},
226 {Name: "dhcp_failed", Src: []string{"dhcp_started", "dhcp_discovery_sent", "dhcp_request_sent"}, Dst: "dhcp_failed"},
227 },
228 fsm.Callbacks{
229 "enter_state": func(e *fsm.Event) {
230 service.logStateChange("DHCPState", e.Src, e.Dst)
231 },
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700232 "before_start_dhcp": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800233 msg := bbsimTypes.Message{
234 Type: bbsimTypes.StartDHCP,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700235 }
236 service.Channel <- msg
237 },
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700238 "enter_dhcp_started": func(e *fsm.Event) {
239 go func() {
240
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700241 for {
242 select {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700243 case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
Elia Battistonda45f6e2022-02-24 11:12:16 +0100244 serviceLogger.WithFields(log.Fields{
245 "context": service.UniPort.Onu.PonPort.Olt.enableContext,
246 }).Debug("DHCP cancelled, OLT is disabled")
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700247 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700248 case <-time.After(dhcpWaitTime):
249 if service.DHCPState.Current() != "dhcp_ack_received" {
250 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700251 "OnuId": service.UniPort.Onu.ID,
252 "IntfId": service.UniPort.Onu.PonPortID,
253 "OnuSn": service.UniPort.Onu.Sn(),
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700254 "Name": service.Name,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700255 "PortNo": service.UniPort.PortNo,
256 "UniId": service.UniPort.ID,
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700257 "DHCPState": service.DHCPState.Current(),
258 }).Warn("DHCP failed, resetting DHCP State")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700259
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700260 _ = service.DHCPState.Event("dhcp_failed")
Matteo Scandolo76c3ff62020-09-24 18:03:01 -0700261 if common.Config.BBSim.DhcpRetry {
262 _ = service.DHCPState.Event("start_dhcp")
263 }
264
Matteo Scandolo6e7afb02020-09-24 11:32:18 -0700265 return
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700266 }
267 }
268
269 }
270 }()
271 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700272 },
273 )
274
Matteo Scandolo618a6582020-09-09 12:21:29 -0700275 service.IGMPState = fsm.NewFSM(
276 "created",
277 fsm.Events{
278 {Name: "igmp_join_start", Src: []string{"created", "igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
279 {Name: "igmp_join_startv3", Src: []string{"igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
280 {Name: "igmp_join_error", Src: []string{"igmp_join_started"}, Dst: "igmp_join_error"},
281 {Name: "igmp_leave", Src: []string{"igmp_join_started"}, Dst: "igmp_left"},
282 },
283 fsm.Callbacks{
284 "igmp_join_start": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800285 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
286 msg := bbsimTypes.Message{
287 Type: bbsimTypes.IGMPMembershipReportV2,
288 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000289 GroupAddress: igmpInfo.GroupAddress,
290 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700291 }
292 service.Channel <- msg
293 },
294 "igmp_leave": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800295 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
296 msg := bbsimTypes.Message{
297 Type: bbsimTypes.IGMPLeaveGroup,
298 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000299 GroupAddress: igmpInfo.GroupAddress,
300 },
301 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700302 service.Channel <- msg
303 },
304 "igmp_join_startv3": func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800305 igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
306 msg := bbsimTypes.Message{
307 Type: bbsimTypes.IGMPMembershipReportV3,
308 Data: bbsimTypes.IgmpMessage{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000309 GroupAddress: igmpInfo.GroupAddress,
310 },
Matteo Scandolo618a6582020-09-09 12:21:29 -0700311 }
312 service.Channel <- msg
313 },
314 },
315 )
316
Matteo Scandolo4a036262020-08-17 15:56:13 -0700317 return &service, nil
318}
319
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700320func (s *Service) UpdateStream(stream bbsimTypes.Stream) {
321 s.Stream = stream
322}
323
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700324// HandleAuth is used to start EAPOL for a particular Service when the corresponding flow is received
325func (s *Service) HandleAuth() {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700326
327 if !s.NeedsEapol {
328 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700329 "OnuId": s.UniPort.Onu.ID,
330 "IntfId": s.UniPort.Onu.PonPortID,
331 "OnuSn": s.UniPort.Onu.Sn(),
332 "PortNo": s.UniPort.PortNo,
333 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700334 "Name": s.Name,
335 "NeedsEapol": s.NeedsEapol,
336 }).Debug("Won't start authentication as EAPOL is not required")
337 return
338 }
339
Elia Battistonda45f6e2022-02-24 11:12:16 +0100340 serviceLogger.WithFields(log.Fields{
341 "OnuId": s.UniPort.Onu.ID,
342 "IntfId": s.UniPort.Onu.PonPortID,
343 "OnuSn": s.UniPort.Onu.Sn(),
344 "PortNo": s.UniPort.PortNo,
345 "UniId": s.UniPort.ID,
346 "Name": s.Name,
347 "NeedsEapol": s.NeedsEapol,
348 }).Debug("Starting EAPOL for the service")
Elia Battiston536a22b2022-01-10 10:33:15 +0100349 if err := s.EapolState.Event(eapol.EventStartAuth); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700350 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700351 "OnuId": s.UniPort.Onu.ID,
352 "IntfId": s.UniPort.Onu.PonPortID,
353 "OnuSn": s.UniPort.Onu.Sn(),
354 "PortNo": s.UniPort.PortNo,
355 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700356 "Name": s.Name,
357 "err": err.Error(),
358 }).Error("Can't start auth for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700359 }
360}
361
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700362// HandleDhcp is used to start DHCP for a particular Service when the corresponding flow is received
Elia Battistondebd4ce2022-03-08 13:38:38 +0100363func (s *Service) HandleDhcp(oPbit uint8, oVid int) {
364 var compareTag int
365 var comparePbits uint8
Matteo Scandolo4a036262020-08-17 15:56:13 -0700366
Elia Battistondebd4ce2022-03-08 13:38:38 +0100367 if s.Name == fttbDpuMgmtServiceName {
368 compareTag = s.STag
369 comparePbits = s.UsPonSTagPriority
370 } else {
371 compareTag = s.CTag
372 comparePbits = s.UsPonCTagPriority
373 }
374
375 if compareTag != oVid || (comparePbits != oPbit && oPbit != 255) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700376 serviceLogger.WithFields(log.Fields{
Elia Battistondebd4ce2022-03-08 13:38:38 +0100377 "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,
382 "Name": s.Name,
383 "compareTag": compareTag,
384 "comparePbits": comparePbits,
385 "oVid": oVid,
386 "oPbit": oPbit,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700387 }).Debug("DHCP flow is not for this service, ignoring")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700388 return
389 }
390
Matteo Scandolo4a036262020-08-17 15:56:13 -0700391 if !s.NeedsDhcp {
392 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700393 "OnuId": s.UniPort.Onu.ID,
394 "IntfId": s.UniPort.Onu.PonPortID,
395 "OnuSn": s.UniPort.Onu.Sn(),
396 "PortNo": s.UniPort.PortNo,
397 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700398 "Name": s.Name,
399 "NeedsDhcp": s.NeedsDhcp,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700400 }).Trace("Won't start DHCP as it is not required")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700401 return
402 }
403
Elia Battistonda45f6e2022-02-24 11:12:16 +0100404 serviceLogger.WithFields(log.Fields{
405 "OnuId": s.UniPort.Onu.ID,
406 "IntfId": s.UniPort.Onu.PonPortID,
407 "OnuSn": s.UniPort.Onu.Sn(),
408 "PortNo": s.UniPort.PortNo,
409 "UniId": s.UniPort.ID,
410 "Name": s.Name,
411 "NeedsEapol": s.NeedsEapol,
412 }).Debug("Starting DHCP for the service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700413 if err := s.DHCPState.Event("start_dhcp"); err != nil {
414 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700415 "OnuId": s.UniPort.Onu.ID,
416 "IntfId": s.UniPort.Onu.PonPortID,
417 "OnuSn": s.UniPort.Onu.Sn(),
418 "PortNo": s.UniPort.PortNo,
419 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700420 "Name": s.Name,
421 "err": err.Error(),
422 }).Error("Can't start DHCP for this Service")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700423 }
424}
425
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700426func (s *Service) HandlePackets() {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700427 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700428 "OnuId": s.UniPort.Onu.ID,
429 "IntfId": s.UniPort.Onu.PonPortID,
430 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700431 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700432 "PortNo": s.UniPort.PortNo,
433 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700434 "Name": s.Name,
435 }).Debug("Listening on Service Packet Channel")
436
437 defer func() {
438 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700439 "OnuId": s.UniPort.Onu.ID,
440 "IntfId": s.UniPort.Onu.PonPortID,
441 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700442 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700443 "PortNo": s.UniPort.PortNo,
444 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700445 "Name": s.Name,
446 }).Debug("Done Listening on Service Packet Channel")
447 }()
448
449 for msg := range s.PacketCh {
450 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700451 "OnuId": s.UniPort.Onu.ID,
452 "IntfId": s.UniPort.Onu.PonPortID,
453 "OnuSn": s.UniPort.Onu.Sn(),
454 "GemPortId": s.GemPort,
455 "PortNo": s.UniPort.PortNo,
456 "UniId": s.UniPort.ID,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700457 "Name": s.Name,
458 "messageType": msg.Type,
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700459 }).Trace("Received message on Service Packet Channel")
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700460
461 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700462 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 -0700463 } else if msg.Type == packetHandlers.DHCP {
Elia Battistona9666542022-03-17 15:45:45 +0100464 tag := int(s.CTag)
465 priority := s.UsPonCTagPriority
466 if s.Name == fttbDpuMgmtServiceName {
467 tag = int(s.STag)
468 priority = s.UsPonSTagPriority
469 }
470
471 _ = 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 -0700472 } else if msg.Type == packetHandlers.IGMP {
473 log.Warn(hex.EncodeToString(msg.Packet.Data()))
Matteo Scandolo8a574812021-05-20 15:18:53 -0700474 _ = 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 -0700475 }
476 }
477}
478
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700479func (s *Service) HandleChannel() {
480 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700481 "OnuId": s.UniPort.Onu.ID,
482 "IntfId": s.UniPort.Onu.PonPortID,
483 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700484 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700485 "PortNo": s.UniPort.PortNo,
486 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700487 "Name": s.Name,
488 }).Debug("Listening on Service Channel")
489
490 defer func() {
491 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700492 "OnuId": s.UniPort.Onu.ID,
493 "IntfId": s.UniPort.Onu.PonPortID,
494 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700495 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700496 "PortNo": s.UniPort.PortNo,
497 "UniId": s.UniPort.ID,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700498 "Name": s.Name,
499 }).Debug("Done Listening on Service Channel")
500 }()
501 for msg := range s.Channel {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700502 switch msg.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800503 case bbsimTypes.StartEAPOL:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700504 if err := s.handleEapolStart(s.Stream); err != nil {
505 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700506 "OnuId": s.UniPort.Onu.ID,
507 "IntfId": s.UniPort.Onu.PonPortID,
508 "OnuSn": s.UniPort.Onu.Sn(),
509 "GemPortId": s.GemPort,
510 "PortNo": s.UniPort.PortNo,
511 "UniId": s.UniPort.ID,
512 "Name": s.Name,
513 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700514 }).Error("Error while sending EapolStart packet")
Elia Battiston536a22b2022-01-10 10:33:15 +0100515 _ = s.EapolState.Event(eapol.EventAuthFailed)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700516 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800517 case bbsimTypes.StartDHCP:
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700518 if err := s.handleDHCPStart(s.Stream); err != nil {
519 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700520 "OnuId": s.UniPort.Onu.ID,
521 "IntfId": s.UniPort.Onu.PonPortID,
522 "OnuSn": s.UniPort.Onu.Sn(),
523 "GemPortId": s.GemPort,
524 "PortNo": s.UniPort.PortNo,
525 "UniId": s.UniPort.ID,
526 "Name": s.Name,
527 "err": err,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700528 }).Error("Error while sending DHCPDiscovery packet")
529 _ = s.DHCPState.Event("dhcp_failed")
Matteo Scandolo618a6582020-09-09 12:21:29 -0700530
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700531 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800532 case bbsimTypes.IGMPMembershipReportV2:
533 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700534 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700535 "OnuId": s.UniPort.Onu.ID,
536 "IntfId": s.UniPort.Onu.PonPortID,
537 "OnuSn": s.UniPort.Onu.Sn(),
538 "GemPortId": s.GemPort,
539 "PortNo": s.UniPort.PortNo,
540 "UniId": s.UniPort.ID,
541 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000542 }).Debug("Received IGMPMembershipReportV2 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700543 _ = 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 -0800544 case bbsimTypes.IGMPLeaveGroup:
545 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -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,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000554 }).Debug("Received IGMPLeaveGroupV2 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700555 _ = 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 -0800556 case bbsimTypes.IGMPMembershipReportV3:
557 igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700558 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700559 "OnuId": s.UniPort.Onu.ID,
560 "IntfId": s.UniPort.Onu.PonPortID,
561 "OnuSn": s.UniPort.Onu.Sn(),
562 "GemPortId": s.GemPort,
563 "PortNo": s.UniPort.PortNo,
564 "UniId": s.UniPort.ID,
565 "Name": s.Name,
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000566 }).Debug("Received IGMPMembershipReportV3 message on ONU channel")
Matteo Scandolo8a574812021-05-20 15:18:53 -0700567 _ = 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 -0700568
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700569 }
570 }
571}
572
573func (s *Service) Initialize(stream bbsimTypes.Stream) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700574 if err := s.InternalState.Event(ServiceTxInitialize, stream); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700575 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700576 "OnuId": s.UniPort.Onu.ID,
577 "IntfId": s.UniPort.Onu.PonPortID,
578 "OnuSn": s.UniPort.Onu.Sn(),
579 "GemPortId": s.GemPort,
580 "PortNo": s.UniPort.PortNo,
581 "UniId": s.UniPort.ID,
582 "Name": s.Name,
583 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700584 }).Error("Cannot initialize service")
585 }
586}
587
588func (s *Service) Disable() {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700589 if err := s.InternalState.Event(ServiceTxDisable); err != nil {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700590 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700591 "OnuId": s.UniPort.Onu.ID,
592 "IntfId": s.UniPort.Onu.PonPortID,
593 "OnuSn": s.UniPort.Onu.Sn(),
594 "GemPortId": s.GemPort,
595 "PortNo": s.UniPort.PortNo,
596 "UniId": s.UniPort.ID,
597 "Name": s.Name,
598 "Err": err,
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700599 }).Error("Cannot disable service")
600 }
601}
602
Matteo Scandolo4a036262020-08-17 15:56:13 -0700603func (s *Service) handleEapolStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700604 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700605 "OnuId": s.UniPort.Onu.ID,
606 "IntfId": s.UniPort.Onu.PonPortID,
607 "OnuSn": s.UniPort.Onu.Sn(),
608 "GemPortId": s.GemPort,
609 "PortNo": s.UniPort.PortNo,
610 "UniId": s.UniPort.ID,
611 "GemPort": s.GemPort,
612 "Name": s.Name,
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700613 }).Trace("handleEapolStart")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700614
Matteo Scandolo8a574812021-05-20 15:18:53 -0700615 if err := eapol.SendEapStart(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.UniPort.Onu.Sn(), s.UniPort.PortNo,
616 s.HwAddress, s.GemPort, s.UniPort.ID, s.EapolState, stream); err != nil {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700617 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700618 "OnuId": s.UniPort.Onu.ID,
619 "IntfId": s.UniPort.Onu.PonPortID,
620 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700621 "GemPort": s.GemPort,
622 "Name": s.Name,
623 }).Error("handleEapolStart")
624 return err
625 }
626 return nil
627}
628
629func (s *Service) handleDHCPStart(stream bbsimTypes.Stream) error {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700630 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700631 "OnuId": s.UniPort.Onu.ID,
632 "IntfId": s.UniPort.Onu.PonPortID,
633 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700634 "Name": s.Name,
635 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700636 "PortNo": s.UniPort.PortNo,
637 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700638 }).Debugf("HandleDHCPStart")
639
Elia Battistona9666542022-03-17 15:45:45 +0100640 tag := int(s.CTag)
641 priority := s.UsPonCTagPriority
642 if s.Name == fttbDpuMgmtServiceName {
643 tag = int(s.STag)
644 priority = s.UsPonSTagPriority
645 }
646
647 if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, tag, s.GemPort,
648 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 -0700649 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700650 "OnuId": s.UniPort.Onu.ID,
651 "IntfId": s.UniPort.Onu.PonPortID,
652 "OnuSn": s.UniPort.Onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -0700653 "Name": s.Name,
654 "GemPortId": s.GemPort,
Matteo Scandolo8a574812021-05-20 15:18:53 -0700655 "PortNo": s.UniPort.PortNo,
656 "UniId": s.UniPort.ID,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700657 }).Error("HandleDHCPStart")
658 return err
659 }
660 return nil
661}
662
Matteo Scandolo4a036262020-08-17 15:56:13 -0700663func (s *Service) logStateChange(stateMachine string, src string, dst string) {
664 serviceLogger.WithFields(log.Fields{
Matteo Scandolo8a574812021-05-20 15:18:53 -0700665 "OnuId": s.UniPort.Onu.ID,
666 "IntfId": s.UniPort.Onu.PonPortID,
667 "OnuSn": s.UniPort.Onu.Sn(),
668 "GemPortId": s.GemPort,
669 "PortNo": s.UniPort.PortNo,
670 "UniId": s.UniPort.ID,
671 "Name": s.Name,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700672 }).Debugf("Changing Service.%s InternalState from %s to %s", stateMachine, src, dst)
673}