blob: 58b18e5fd4c9a3eb9cc304c3961a87a8ed6df5bf [file] [log] [blame]
Takahiro Suzukid7bf8202020-12-17 20:21:59 +09001/*
2 * Copyright 2020-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
17//Package core provides the utility for olt devices, flows and statistics
18package core
19
20import (
21 "context"
22 "sync"
23 "time"
24
25 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
26 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
27 "github.com/opencord/voltha-lib-go/v3/pkg/log"
28 "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
29 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
30 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
31 "github.com/opencord/voltha-protos/v3/go/openflow_13"
32 "github.com/opencord/voltha-protos/v3/go/voltha"
33)
34
35//OpenOLT structure holds the OLT information
36type OpenOLT struct {
37 deviceHandlers map[string]*DeviceHandler
38 coreProxy adapterif.CoreProxy
39 adapterProxy adapterif.AdapterProxy
40 eventProxy adapterif.EventProxy
41 kafkaICProxy kafka.InterContainerProxy
42 config *config.AdapterFlags
43 numOnus int
44 KVStoreAddress string
45 KVStoreType string
46 exitChannel chan int
47 HeartbeatCheckInterval time.Duration
48 HeartbeatFailReportInterval time.Duration
49 GrpcTimeoutInterval time.Duration
50 lockDeviceHandlersMap sync.RWMutex
51}
52
53//NewOpenOLT returns a new instance of OpenOLT
54func NewOpenOLT(ctx context.Context, kafkaICProxy kafka.InterContainerProxy,
55 coreProxy adapterif.CoreProxy, adapterProxy adapterif.AdapterProxy,
56 eventProxy adapterif.EventProxy, cfg *config.AdapterFlags) *OpenOLT {
57 var openOLT OpenOLT
58 openOLT.exitChannel = make(chan int, 1)
59 openOLT.deviceHandlers = make(map[string]*DeviceHandler)
60 openOLT.kafkaICProxy = kafkaICProxy
61 openOLT.config = cfg
62 openOLT.numOnus = cfg.OnuNumber
63 openOLT.coreProxy = coreProxy
64 openOLT.adapterProxy = adapterProxy
65 openOLT.eventProxy = eventProxy
66 openOLT.KVStoreAddress = cfg.KVStoreAddress
67 openOLT.KVStoreType = cfg.KVStoreType
68 openOLT.HeartbeatCheckInterval = cfg.HeartbeatCheckInterval
69 openOLT.HeartbeatFailReportInterval = cfg.HeartbeatFailReportInterval
70 openOLT.GrpcTimeoutInterval = cfg.GrpcTimeoutInterval
71 openOLT.lockDeviceHandlersMap = sync.RWMutex{}
72 return &openOLT
73}
74
75//Start starts (logs) the device manager
76func (oo *OpenOLT) Start(ctx context.Context) error {
77 logger.Info(ctx, "starting-device-manager")
78 logger.Info(ctx, "device-manager-started")
79 return nil
80}
81
82//Stop terminates the session
83func (oo *OpenOLT) Stop(ctx context.Context) error {
84 logger.Info(ctx, "stopping-device-manager")
85 oo.exitChannel <- 1
86 logger.Info(ctx, "device-manager-stopped")
87 return nil
88}
89
90func (oo *OpenOLT) addDeviceHandlerToMap(agent *DeviceHandler) {
91 oo.lockDeviceHandlersMap.Lock()
92 defer oo.lockDeviceHandlersMap.Unlock()
93 if _, exist := oo.deviceHandlers[agent.device.Id]; !exist {
94 oo.deviceHandlers[agent.device.Id] = agent
95 }
96}
97
98func (oo *OpenOLT) deleteDeviceHandlerToMap(agent *DeviceHandler) {
99 oo.lockDeviceHandlersMap.Lock()
100 defer oo.lockDeviceHandlersMap.Unlock()
101 delete(oo.deviceHandlers, agent.device.Id)
102}
103
104func (oo *OpenOLT) getDeviceHandler(deviceID string) *DeviceHandler {
105 oo.lockDeviceHandlersMap.Lock()
106 defer oo.lockDeviceHandlersMap.Unlock()
107 if agent, ok := oo.deviceHandlers[deviceID]; ok {
108 return agent
109 }
110 return nil
111}
112
113// Adopt_device creates a new device handler if not present already and then adopts the device
114func (oo *OpenOLT) Adopt_device(ctx context.Context, device *voltha.Device) error {
115 if device == nil {
116 return olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil).Log()
117 }
118 logger.Infow(ctx, "adopt-device", log.Fields{"deviceId": device.Id})
119 var handler *DeviceHandler
120 if handler = oo.getDeviceHandler(device.Id); handler == nil {
121 handler := NewDeviceHandler(oo.coreProxy, oo.adapterProxy, oo.eventProxy, device, oo)
122 oo.addDeviceHandlerToMap(handler)
123 go handler.AdoptDevice(ctx, device)
124 // Launch the creation of the device topic
125 // go oo.createDeviceTopic(device)
126 }
127 return nil
128}
129
130//Get_ofp_device_info returns OFP information for the given device
131func (oo *OpenOLT) Get_ofp_device_info(ctx context.Context, device *voltha.Device) (*ic.SwitchCapability, error) {
132 logger.Infow(ctx, "Get_ofp_device_info", log.Fields{"deviceId": device.Id})
133 if handler := oo.getDeviceHandler(device.Id); handler != nil {
134 return handler.GetOfpDeviceInfo(device)
135 }
136 return nil, olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
137}
138
139//Process_inter_adapter_message sends messages to a target device (between adapters)
140func (oo *OpenOLT) Process_inter_adapter_message(ctx context.Context, msg *ic.InterAdapterMessage) error {
141 logger.Debugw(ctx, "Process_inter_adapter_message", log.Fields{"msgId": msg.Header.Id})
142 targetDevice := msg.Header.ProxyDeviceId // Request?
143 if targetDevice == "" && msg.Header.ToDeviceId != "" {
144 // Typical response
145 targetDevice = msg.Header.ToDeviceId
146 }
147 if handler := oo.getDeviceHandler(targetDevice); handler != nil {
148 return handler.ProcessInterAdapterMessage(ctx, msg)
149 }
150 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": targetDevice}, nil)
151}
152
153//Adapter_descriptor not implemented
154func (oo *OpenOLT) Adapter_descriptor(ctx context.Context) error {
155 return olterrors.ErrNotImplemented
156}
157
158//Device_types unimplemented
159func (oo *OpenOLT) Device_types(ctx context.Context) (*voltha.DeviceTypes, error) {
160 return nil, olterrors.ErrNotImplemented
161}
162
163//Health returns unimplemented
164func (oo *OpenOLT) Health(ctx context.Context) (*voltha.HealthStatus, error) {
165 return nil, olterrors.ErrNotImplemented
166}
167
168//Reconcile_device unimplemented
169func (oo *OpenOLT) Reconcile_device(ctx context.Context, device *voltha.Device) error {
170 if device == nil {
171 return olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
172 }
173 logger.Infow(ctx, "reconcile-device", log.Fields{"deviceId": device.Id})
174 var handler *DeviceHandler
175 if handler = oo.getDeviceHandler(device.Id); handler == nil {
176 handler := NewDeviceHandler(oo.coreProxy, oo.adapterProxy, oo.eventProxy, device, oo)
177 oo.addDeviceHandlerToMap(handler)
178 handler.transitionMap = NewTransitionMap(handler)
179 handler.transitionMap.Handle(ctx, DeviceInit)
180 }
181 return nil
182}
183
184//Abandon_device unimplemented
185func (oo *OpenOLT) Abandon_device(ctx context.Context, device *voltha.Device) error {
186 return olterrors.ErrNotImplemented
187}
188
189//Disable_device disables the given device
190func (oo *OpenOLT) Disable_device(ctx context.Context, device *voltha.Device) error {
191 logger.Infow(ctx, "disable-device", log.Fields{"deviceId": device.Id})
192 if handler := oo.getDeviceHandler(device.Id); handler != nil {
193 return handler.DisableDevice(ctx, device)
194 }
195 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
196}
197
198//Reenable_device enables the olt device after disable
199func (oo *OpenOLT) Reenable_device(ctx context.Context, device *voltha.Device) error {
200 logger.Infow(ctx, "reenable-device", log.Fields{"deviceId": device.Id})
201 if handler := oo.getDeviceHandler(device.Id); handler != nil {
202 return handler.ReenableDevice(ctx, device)
203 }
204 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
205}
206
207//Reboot_device reboots the given device
208func (oo *OpenOLT) Reboot_device(ctx context.Context, device *voltha.Device) error {
209 logger.Infow(ctx, "reboot-device", log.Fields{"deviceId": device.Id})
210 if handler := oo.getDeviceHandler(device.Id); handler != nil {
211 return handler.RebootDevice(ctx, device)
212 }
213 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
214}
215
216//Self_test_device unimplented
217func (oo *OpenOLT) Self_test_device(ctx context.Context, device *voltha.Device) error {
218 return olterrors.ErrNotImplemented
219}
220
221//Delete_device unimplemented
222func (oo *OpenOLT) Delete_device(ctx context.Context, device *voltha.Device) error {
223 logger.Infow(ctx, "delete-device", log.Fields{"deviceId": device.Id})
224 if handler := oo.getDeviceHandler(device.Id); handler != nil {
225 if err := handler.DeleteDevice(ctx, device); err != nil {
226 logger.Errorw(ctx, "failed-to-handle-delete-device", log.Fields{"device-id": device.Id})
227 }
228 oo.deleteDeviceHandlerToMap(handler)
229 return nil
230 }
231 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
232}
233
234//Get_device_details unimplemented
235func (oo *OpenOLT) Get_device_details(ctx context.Context, device *voltha.Device) error {
236 return olterrors.ErrNotImplemented
237}
238
239//Update_flows_bulk returns
240func (oo *OpenOLT) Update_flows_bulk(ctx context.Context, device *voltha.Device, flows *voltha.Flows, groups *voltha.FlowGroups, flowMetadata *voltha.FlowMetadata) error {
241 return olterrors.ErrNotImplemented
242}
243
244//Update_flows_incrementally updates (add/remove) the flows on a given device
245func (oo *OpenOLT) Update_flows_incrementally(ctx context.Context, device *voltha.Device, flows *openflow_13.FlowChanges, groups *openflow_13.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
246 logger.Debugw(ctx, "Update_flows_incrementally", log.Fields{"deviceId": device.Id, "flows": flows, "flowMetadata": flowMetadata})
247 if handler := oo.getDeviceHandler(device.Id); handler != nil {
248 return handler.UpdateFlowsIncrementally(ctx, device, flows, groups, flowMetadata)
249 }
250 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
251}
252
253//Update_pm_config returns PmConfigs nil or error
254func (oo *OpenOLT) Update_pm_config(ctx context.Context, device *voltha.Device, pmConfigs *voltha.PmConfigs) error {
255 logger.Debugw(ctx, "Update_pm_config", log.Fields{"device-id": device.Id, "pm-configs": pmConfigs})
256 if handler := oo.getDeviceHandler(device.Id); handler != nil {
257 handler.UpdatePmConfig(ctx, pmConfigs)
258 return nil
259 }
260 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
261}
262
263//Receive_packet_out sends packet out to the device
264func (oo *OpenOLT) Receive_packet_out(ctx context.Context, deviceID string, egressPortNo int, packet *openflow_13.OfpPacketOut) error {
265 logger.Debugw(ctx, "Receive_packet_out", log.Fields{"deviceId": deviceID, "egress_port_no": egressPortNo, "pkt": packet})
266 if handler := oo.getDeviceHandler(deviceID); handler != nil {
267 return handler.PacketOut(ctx, egressPortNo, packet)
268 }
269 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": deviceID}, nil)
270}
271
272//Suppress_event unimplemented
273func (oo *OpenOLT) Suppress_event(ctx context.Context, filter *voltha.EventFilter) error {
274 return olterrors.ErrNotImplemented
275}
276
277//Unsuppress_event unimplemented
278func (oo *OpenOLT) Unsuppress_event(ctx context.Context, filter *voltha.EventFilter) error {
279 return olterrors.ErrNotImplemented
280}
281
282//Download_image unimplemented
283func (oo *OpenOLT) Download_image(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
284 return nil, olterrors.ErrNotImplemented
285}
286
287//Get_image_download_status unimplemented
288func (oo *OpenOLT) Get_image_download_status(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
289 return nil, olterrors.ErrNotImplemented
290}
291
292//Cancel_image_download unimplemented
293func (oo *OpenOLT) Cancel_image_download(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
294 return nil, olterrors.ErrNotImplemented
295}
296
297//Activate_image_update unimplemented
298func (oo *OpenOLT) Activate_image_update(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
299 return nil, olterrors.ErrNotImplemented
300}
301
302//Revert_image_update unimplemented
303func (oo *OpenOLT) Revert_image_update(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
304 return nil, olterrors.ErrNotImplemented
305}
306
307// Enable_port to Enable PON/NNI interface
308func (oo *OpenOLT) Enable_port(ctx context.Context, deviceID string, port *voltha.Port) error {
309 logger.Infow(ctx, "Enable_port", log.Fields{"deviceId": deviceID, "port": port})
310 return oo.enableDisablePort(ctx, deviceID, port, true)
311}
312
313// Disable_port to Disable pon/nni interface
314func (oo *OpenOLT) Disable_port(ctx context.Context, deviceID string, port *voltha.Port) error {
315 logger.Infow(ctx, "Disable_port", log.Fields{"deviceId": deviceID, "port": port})
316 return oo.enableDisablePort(ctx, deviceID, port, false)
317}
318
319// enableDisablePort to Disable pon or Enable PON interface
320func (oo *OpenOLT) enableDisablePort(ctx context.Context, deviceID string, port *voltha.Port, enablePort bool) error {
321 logger.Infow(ctx, "enableDisablePort", log.Fields{"deviceId": deviceID, "port": port})
322 if port == nil {
323 return olterrors.NewErrInvalidValue(log.Fields{
324 "reason": "port cannot be nil",
325 "device-id": deviceID,
326 "port": nil}, nil)
327 }
328 if handler := oo.getDeviceHandler(deviceID); handler != nil {
329 logger.Debugw(ctx, "Enable_Disable_Port", log.Fields{"deviceId": deviceID, "port": port})
330 if enablePort {
331 if err := handler.EnablePort(ctx, port); err != nil {
332 return olterrors.NewErrAdapter("error-occurred-during-enable-port", log.Fields{"deviceID": deviceID, "port": port}, err)
333 }
334 } else {
335 if err := handler.DisablePort(ctx, port); err != nil {
336 return olterrors.NewErrAdapter("error-occurred-during-disable-port", log.Fields{"deviceID": deviceID, "port": port}, err)
337 }
338 }
339 }
340 return nil
341}
342
343//Child_device_lost deletes the ONU and its references from PONResources
344func (oo *OpenOLT) Child_device_lost(ctx context.Context, deviceID string, pPortNo uint32, onuID uint32) error {
345 logger.Infow(ctx, "Child-device-lost", log.Fields{"parentId": deviceID})
346 if handler := oo.getDeviceHandler(deviceID); handler != nil {
347 return handler.ChildDeviceLost(ctx, pPortNo, onuID)
348 }
349 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": deviceID}, nil).Log()
350}
351
352//Start_omci_test not implemented
353func (oo *OpenOLT) Start_omci_test(ctx context.Context, device *voltha.Device, request *voltha.OmciTestRequest) (*voltha.TestResponse, error) {
354 return nil, olterrors.ErrNotImplemented
355}
356
357//Get_ext_value retrieves a value on a particular ONU
358func (oo *OpenOLT) Get_ext_value(ctx context.Context, deviceID string, device *voltha.Device, valueparam voltha.ValueType_Type) (*voltha.ReturnValues, error) {
359 var err error
360 resp := new(voltha.ReturnValues)
361 logger.Infow(ctx, "Get_ext_value", log.Fields{"device-id": deviceID, "onu-id": device.Id})
362 if handler := oo.getDeviceHandler(deviceID); handler != nil {
363 if resp, err = handler.getExtValue(ctx, device, valueparam); err != nil {
364 logger.Errorw(ctx, "error-occurred-during-get-ext-value", log.Fields{"device-id": deviceID, "onu-id": device.Id,
365 "error": err})
366 return nil, err
367 }
368 }
369 return resp, nil
370}
371
372func (oo *OpenOLT) Simulate_alarm(ctx context.Context, device *voltha.Device, request *voltha.SimulateAlarmRequest) error {
373 logger.Infow(ctx, "Simulate_alarm", log.Fields{"deviceId": device.Id})
374 if handler := oo.getDeviceHandler(device.Id); handler != nil {
375 logger.Infow(ctx, "Simulate_alarm", log.Fields{"request": request})
376 return handler.L2oamCmdRequest(ctx, device, request)
377 }
378 return olterrors.NewErrNotFound("device-handler", log.Fields{"device-id": device.Id}, nil)
379}