blob: 4d154eb952604bd3d4da050532c9b3dc79de713c [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001/*
Joey Armstrong7a9af442024-01-03 19:26:36 -05002* Copyright 2021-2024 Open Networking Foundation (ONF) and the ONF Contributors
khenaidood948f772021-08-11 17:49:24 -04003
Joey Armstrong393daca2023-07-06 08:47:54 -04004* 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
khenaidood948f772021-08-11 17:49:24 -04007
Joey Armstrong393daca2023-07-06 08:47:54 -04008* http://www.apache.org/licenses/LICENSE-2.0
khenaidood948f772021-08-11 17:49:24 -04009
Joey Armstrong393daca2023-07-06 08:47:54 -040010* 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.
khenaidood948f772021-08-11 17:49:24 -040015 */
16package device
17
18import (
19 "context"
khenaidooa46458b2021-12-15 16:50:44 -050020 "fmt"
21 "time"
khenaidood948f772021-08-11 17:49:24 -040022
23 "github.com/golang/protobuf/ptypes/empty"
24 "github.com/opencord/voltha-go/rw_core/utils"
25 "github.com/opencord/voltha-lib-go/v7/pkg/log"
26 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoo9beaaf12021-10-19 17:32:01 -040027 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidooa46458b2021-12-15 16:50:44 -050028 "github.com/opencord/voltha-protos/v5/go/core_service"
khenaidoo25057da2021-12-08 14:40:45 -050029 "github.com/opencord/voltha-protos/v5/go/health"
khenaidood948f772021-08-11 17:49:24 -040030 "github.com/opencord/voltha-protos/v5/go/voltha"
31 "google.golang.org/grpc/codes"
32 "google.golang.org/grpc/status"
33)
34
35func (dMgr *Manager) PortCreated(ctx context.Context, port *voltha.Port) (*empty.Empty, error) {
36 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "PortCreated")
37
38 logger.Debugw(ctx, "port-created", log.Fields{"port": port})
39
40 agent := dMgr.getDeviceAgent(ctx, port.DeviceId)
41 if agent != nil {
42 if err := agent.addPort(ctx, port); err != nil {
43 return nil, err
44 }
45 // Setup peer ports in its own routine
nikesh.krishnan95142d52023-02-24 15:32:11 +053046
47 if err := dMgr.addPeerPort(ctx, port.DeviceId, port); err != nil {
48 logger.Errorw(ctx, "unable-to-add-peer-port", log.Fields{"error": err, "device-id": port.DeviceId})
49 }
50
khenaidood948f772021-08-11 17:49:24 -040051 return &empty.Empty{}, nil
52 }
53 return nil, status.Errorf(codes.NotFound, "%s", port.DeviceId)
54}
55
56func (dMgr *Manager) DeviceUpdate(ctx context.Context, device *voltha.Device) (*empty.Empty, error) {
57 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeviceUpdate")
58 logger.Debugw(ctx, "device-update", log.Fields{"device-id": device.Id, "device": device})
59
60 if agent := dMgr.getDeviceAgent(ctx, device.Id); agent != nil {
61 if err := agent.updateDeviceUsingAdapterData(ctx, device); err != nil {
62 return nil, err
63 }
64 return &empty.Empty{}, nil
65 }
66 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
67}
68
khenaidoo9beaaf12021-10-19 17:32:01 -040069func (dMgr *Manager) DeviceStateUpdate(ctx context.Context, ds *ca.DeviceStateFilter) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -040070 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeviceStateUpdate")
71 logger.Debugw(ctx, "device-state-update", log.Fields{"device-id": ds.DeviceId, "operStatus": ds.OperStatus, "connStatus": ds.ConnStatus})
72
73 if agent := dMgr.getDeviceAgent(ctx, ds.DeviceId); agent != nil {
74 if err := agent.updateDeviceStatus(ctx, ds.OperStatus, ds.ConnStatus); err != nil {
75 return nil, err
76 }
77 return &empty.Empty{}, nil
78 }
79 return nil, status.Errorf(codes.NotFound, "%s", ds.DeviceId)
80}
81
khenaidoo9beaaf12021-10-19 17:32:01 -040082func (dMgr *Manager) ChildDeviceDetected(ctx context.Context, dd *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidood948f772021-08-11 17:49:24 -040083 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildDeviceDetected")
84 logger.Debugw(ctx, "child-device-detected",
85 log.Fields{
86 "parent-device-id": dd.ParentId,
87 "parentPortNo": dd.ParentPortNo,
88 "deviceType": dd.ChildDeviceType,
89 "channelId": dd.ChannelId,
90 "vendorId": dd.VendorId,
91 "serialNumber": dd.SerialNumber,
92 "onuId": dd.OnuId,
93 })
94
95 var err error
96 if dd.ChildDeviceType == "" && dd.VendorId != "" {
97 logger.Debug(ctx, "device-type-is-nil-fetching-device-type")
98 if dd.ChildDeviceType, err = dMgr.adapterMgr.GetAdapterTypeByVendorID(dd.VendorId); err != nil {
99 return nil, err
100 }
101 }
102 //if no match found for the vendorid,report adapter with the custom error message
103 if dd.ChildDeviceType == "" {
104 logger.Errorw(ctx, "failed-to-fetch-adapter-name ", log.Fields{"vendorId": dd.VendorId})
105 return nil, status.Errorf(codes.NotFound, "%s", dd.VendorId)
106 }
107
108 // Create the ONU device
109 childDevice := &voltha.Device{}
110 childDevice.Type = dd.ChildDeviceType
111 childDevice.ParentId = dd.ParentId
112 childDevice.ParentPortNo = uint32(dd.ParentPortNo)
113 childDevice.VendorId = dd.VendorId
114 childDevice.SerialNumber = dd.SerialNumber
115 childDevice.Root = false
116
117 // Get parent device type
118 pAgent := dMgr.getDeviceAgent(ctx, dd.ParentId)
119 if pAgent == nil {
120 return nil, status.Errorf(codes.NotFound, "%s", dd.ParentId)
121 }
122 if pAgent.deviceType == "" {
123 pDevice, err := pAgent.getDeviceReadOnly(ctx)
124 logger.Errorw(ctx, "device-type-not-set", log.Fields{"parent-device": pDevice, "error": err})
125 return nil, status.Errorf(codes.FailedPrecondition, "device Type not set %s", dd.ParentId)
126 }
127
khenaidoo9beaaf12021-10-19 17:32:01 -0400128 if device, err := dMgr.GetChildDevice(ctx, &ca.ChildDeviceFilter{
khenaidood948f772021-08-11 17:49:24 -0400129 ParentId: dd.ParentId,
130 SerialNumber: dd.SerialNumber,
131 OnuId: dd.OnuId,
132 ParentPortNo: dd.ParentPortNo}); err == nil {
133 logger.Warnw(ctx, "child-device-exists", log.Fields{"parent-device-id": dd.ParentId, "serialNumber": dd.SerialNumber})
134 return device, status.Errorf(codes.AlreadyExists, "%s", dd.SerialNumber)
135 }
136
137 //Get parent endpoint
138 pEndPoint, err := dMgr.adapterMgr.GetAdapterEndpoint(ctx, pAgent.deviceID, pAgent.deviceType)
139 if err != nil {
140 logger.Errorw(ctx, "endpoint-error", log.Fields{"error": err, "parent-id": pAgent.deviceID, "parent-device-type": pAgent.deviceType})
141 return nil, status.Errorf(codes.NotFound, "parent-endpoint-%s", dd.ParentId)
142 }
143
144 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: dd.ParentId, DeviceType: pAgent.deviceType, ChannelId: dd.ChannelId, OnuId: dd.OnuId, AdapterEndpoint: pEndPoint}
145
146 // Set child device ID -- needed to get the device endpoint
147 childDevice.Id = utils.CreateDeviceID()
148
149 // Set the child adapter endpoint
150 childDevice.AdapterEndpoint, err = dMgr.adapterMgr.GetAdapterEndpoint(ctx, childDevice.Id, childDevice.Type)
151 if err != nil {
152 return nil, status.Errorf(codes.NotFound, "child-endpoint-%s", childDevice.Id)
153 }
154
155 // Create and start a device agent for that device
Himani Chawla4b4bd252021-11-08 15:59:40 +0530156 agent := newAgent(childDevice, dMgr, dMgr.dbPath, dMgr.dProxy, dMgr.internalTimeout, dMgr.rpcTimeout, dMgr.flowTimeout)
khenaidood948f772021-08-11 17:49:24 -0400157 insertedChildDevice, err := agent.start(ctx, false, childDevice)
158 if err != nil {
159 logger.Errorw(ctx, "error-starting-child-device", log.Fields{"parent-device-id": childDevice.ParentId, "child-device-id": agent.deviceID, "error": err})
160 return nil, err
161 }
162 dMgr.addDeviceAgentToMap(agent)
163
164 // Activate the child device
165 if agent = dMgr.getDeviceAgent(ctx, agent.deviceID); agent != nil {
166 go func() {
167 err := agent.enableDevice(utils.WithSpanAndRPCMetadataFromContext(ctx))
168 if err != nil {
169 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err, "device-id": agent.deviceID})
170 }
171 }()
172 }
173
174 return insertedChildDevice, nil
175}
176
khenaidoo9beaaf12021-10-19 17:32:01 -0400177func (dMgr *Manager) GetChildDevice(ctx context.Context, df *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidood948f772021-08-11 17:49:24 -0400178 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetChildDevice")
179 logger.Debugw(ctx, "get-child-device", log.Fields{"filter": df})
180
nikesh.krishnan1e3b98a2023-11-26 02:39:53 +0530181 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, df.ParentId)
khenaidood948f772021-08-11 17:49:24 -0400182 if len(childDeviceIds) == 0 {
183 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": df.ParentId, "serial-number": df.SerialNumber, "onu-id": df.OnuId})
184 return nil, status.Errorf(codes.NotFound, "%s", df.ParentId)
185 }
186
187 var foundChildDevice *voltha.Device
188 for childDeviceID := range childDeviceIds {
189 var found bool
190 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
191
192 foundOnuID := false
193 if searchDevice.ProxyAddress.OnuId == uint32(df.OnuId) {
194 if searchDevice.ParentPortNo == uint32(df.ParentPortNo) {
195 logger.Debugw(ctx, "found-child-by-onu-id", log.Fields{"parent-device-id": df.ParentId, "onuId": df.OnuId})
196 foundOnuID = true
197 }
198 }
199
200 foundSerialNumber := false
201 if searchDevice.SerialNumber == df.SerialNumber {
202 logger.Debugw(ctx, "found-child-by-serial-number", log.Fields{"parent-device-id": df.ParentId, "serialNumber": df.SerialNumber})
203 foundSerialNumber = true
204 }
205
206 // if both onuId and serialNumber are provided both must be true for the device to be found
207 // otherwise whichever one found a match is good enough
208 if df.OnuId > 0 && df.SerialNumber != "" {
209 found = foundOnuID && foundSerialNumber
210 } else {
211 found = foundOnuID || foundSerialNumber
212 }
213
214 if found {
215 foundChildDevice = searchDevice
216 break
217 }
218 }
219 }
220
221 if foundChildDevice != nil {
222 logger.Debugw(ctx, "child-device-found", log.Fields{"parent-device-id": df.ParentId, "foundChildDevice": foundChildDevice})
223 return foundChildDevice, nil
224 }
225
226 logger.Debugw(ctx, "child-device-not-found", log.Fields{"parent-device-id": df.ParentId,
227 "serialNumber": df.SerialNumber, "onuId": df.OnuId, "parentPortNo": df.ParentPortNo})
228 return nil, status.Errorf(codes.NotFound, "%s", df.ParentId)
229}
230
231// PortsStateUpdate updates the operational status of all ports on the device
khenaidoo9beaaf12021-10-19 17:32:01 -0400232func (dMgr *Manager) PortsStateUpdate(ctx context.Context, ps *ca.PortStateFilter) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400233 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "PortsStateUpdate")
234 logger.Debugw(ctx, "ports-state-update", log.Fields{"device-id": ps.DeviceId})
235
236 agent := dMgr.getDeviceAgent(ctx, ps.DeviceId)
237 if agent == nil {
238 return nil, status.Errorf(codes.NotFound, "%s", ps.DeviceId)
239 }
240 if ps.OperStatus != voltha.OperStatus_ACTIVE && ps.OperStatus != voltha.OperStatus_UNKNOWN {
241 return nil, status.Error(codes.Unimplemented, "state-change-not-implemented")
242 }
243 if err := agent.updatePortsOperState(ctx, ps.PortTypeFilter, ps.OperStatus); err != nil {
244 logger.Warnw(ctx, "ports-state-update-failed", log.Fields{"device-id": ps.DeviceId, "error": err})
245 return nil, err
246 }
247 return &empty.Empty{}, nil
248}
249
Joey Armstrong393daca2023-07-06 08:47:54 -0400250// ChildDevicesLost is invoked by an adapter to indicate that a parent device is in a state (Disabled) where it
251// cannot manage the child devices. This will trigger the Core to disable all the child devices.
khenaidood948f772021-08-11 17:49:24 -0400252func (dMgr *Manager) ChildDevicesLost(ctx context.Context, parentID *common.ID) (*empty.Empty, error) {
253 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildDevicesLost")
254 logger.Debugw(ctx, "child-devices-lost", log.Fields{"parent-id": parentID.Id})
255
256 parentDevice, err := dMgr.getDeviceReadOnly(ctx, parentID.Id)
257 if err != nil {
258 logger.Warnw(ctx, "failed-getting-device", log.Fields{"parent-device-id": parentID.Id, "error": err})
259 return nil, err
260 }
261 if err = dMgr.DisableAllChildDevices(ctx, parentDevice); err != nil {
262 return nil, err
263 }
264 return &empty.Empty{}, nil
265}
266
Joey Armstrong393daca2023-07-06 08:47:54 -0400267// ChildDevicesDetected is invoked by an adapter when child devices are found, typically after after a
khenaidood948f772021-08-11 17:49:24 -0400268// disable/enable sequence. This will trigger the Core to Enable all the child devices of that parent.
269func (dMgr *Manager) ChildDevicesDetected(ctx context.Context, parentDeviceID *common.ID) (*empty.Empty, error) {
270 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildDevicesDetected")
271 logger.Debugw(ctx, "child-devices-detected", log.Fields{"parent-device-id": parentDeviceID})
272
nikesh.krishnan1e3b98a2023-11-26 02:39:53 +0530273 var err error
274 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, parentDeviceID.Id)
khenaidood948f772021-08-11 17:49:24 -0400275 if len(childDeviceIds) == 0 {
276 logger.Debugw(ctx, "no-child-device", log.Fields{"parent-device-id": parentDeviceID.Id})
277 }
278 allChildEnableRequestSent := true
279 for childDeviceID := range childDeviceIds {
280 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
281 // Run the children re-registration in its own routine
282 go func(ctx context.Context) {
283 err = agent.enableDevice(ctx)
284 if err != nil {
285 logger.Errorw(ctx, "unable-to-enable-device", log.Fields{"error": err})
286 }
287 }(log.WithSpanFromContext(context.Background(), ctx))
288 } else {
289 err = status.Errorf(codes.Unavailable, "no agent for child device %s", childDeviceID)
290 logger.Errorw(ctx, "no-child-device-agent", log.Fields{"parent-device-id": parentDeviceID.Id, "childId": childDeviceID})
291 allChildEnableRequestSent = false
292 }
293 }
294 if !allChildEnableRequestSent {
295 return nil, err
296 }
297 return &empty.Empty{}, nil
298}
299
300// GetChildDeviceWithProxyAddress will return a device based on proxy address
301func (dMgr *Manager) GetChildDeviceWithProxyAddress(ctx context.Context, proxyAddress *voltha.Device_ProxyAddress) (*voltha.Device, error) {
302 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetChildDeviceWithProxyAddress")
303
304 logger.Debugw(ctx, "get-child-device-with-proxy-address", log.Fields{"proxyAddress": proxyAddress})
305
nikesh.krishnan1e3b98a2023-11-26 02:39:53 +0530306 childDeviceIds := dMgr.getAllChildDeviceIds(ctx, proxyAddress.DeviceId)
khenaidood948f772021-08-11 17:49:24 -0400307 if len(childDeviceIds) == 0 {
308 logger.Debugw(ctx, "no-child-devices", log.Fields{"parent-device-id": proxyAddress.DeviceId})
309 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
310 }
311
312 var foundChildDevice *voltha.Device
313 for childDeviceID := range childDeviceIds {
314 if searchDevice, err := dMgr.getDeviceReadOnly(ctx, childDeviceID); err == nil {
315 if searchDevice.ProxyAddress == proxyAddress {
316 foundChildDevice = searchDevice
317 break
318 }
319 }
320 }
321
322 if foundChildDevice != nil {
323 logger.Debugw(ctx, "child-device-found", log.Fields{"proxyAddress": proxyAddress})
324 return foundChildDevice, nil
325 }
326
327 logger.Warnw(ctx, "child-device-not-found", log.Fields{"proxyAddress": proxyAddress})
328 return nil, status.Errorf(codes.NotFound, "%s", proxyAddress)
329}
330
khenaidoo9beaaf12021-10-19 17:32:01 -0400331func (dMgr *Manager) GetPorts(ctx context.Context, pf *ca.PortFilter) (*voltha.Ports, error) {
khenaidood948f772021-08-11 17:49:24 -0400332 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetPorts")
333 logger.Debugw(ctx, "get-ports", log.Fields{"device-id": pf.DeviceId, "portType": pf.PortType})
334
335 agent := dMgr.getDeviceAgent(ctx, pf.DeviceId)
336 if agent == nil {
337 return nil, status.Errorf(codes.NotFound, "%s", pf.DeviceId)
338 }
339 return agent.getPorts(ctx, pf.PortType), nil
340}
341
342func (dMgr *Manager) GetChildDevices(ctx context.Context, parentDeviceID *common.ID) (*voltha.Devices, error) {
343 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetChildDevices")
344
345 logger.Debugw(ctx, "get-child-devices", log.Fields{"parent-device-id": parentDeviceID.Id})
346 return dMgr.getAllChildDevices(ctx, parentDeviceID.Id)
347}
348
khenaidoo9beaaf12021-10-19 17:32:01 -0400349func (dMgr *Manager) ChildrenStateUpdate(ctx context.Context, ds *ca.DeviceStateFilter) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400350 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ChildrenStateUpdate")
351 logger.Debugw(ctx, "children-state-update", log.Fields{"parent-device-id": ds.ParentDeviceId, "operStatus": ds.OperStatus, "connStatus": ds.ConnStatus})
352
nikesh.krishnan1e3b98a2023-11-26 02:39:53 +0530353 for childDeviceID := range dMgr.getAllChildDeviceIds(ctx, ds.ParentDeviceId) {
khenaidood948f772021-08-11 17:49:24 -0400354 if agent := dMgr.getDeviceAgent(ctx, childDeviceID); agent != nil {
nikesh.krishnan1e3b98a2023-11-26 02:39:53 +0530355 if err := agent.updateDeviceStatus(ctx, ds.OperStatus, ds.ConnStatus); err != nil {
khenaidood948f772021-08-11 17:49:24 -0400356 return nil, status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceID, err.Error())
357 }
358 }
359 }
360 return &empty.Empty{}, nil
361}
362
khenaidoo9beaaf12021-10-19 17:32:01 -0400363func (dMgr *Manager) PortStateUpdate(ctx context.Context, ps *ca.PortState) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400364 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "PortStateUpdate")
365 logger.Debugw(ctx, "port-state-update", log.Fields{"device-id": ps.DeviceId, "portType": ps.PortType, "portNo": ps.PortNo, "operStatus": ps.OperStatus})
366
367 if agent := dMgr.getDeviceAgent(ctx, ps.DeviceId); agent != nil {
368 if err := agent.updatePortState(ctx, ps.PortType, ps.PortNo, ps.OperStatus); err != nil {
369 logger.Errorw(ctx, "updating-port-state-failed", log.Fields{"device-id": ps.DeviceId, "portNo": ps.PortNo, "error": err})
370 return nil, err
371 }
372 // Notify the logical device manager to change the port state
373 // Do this for NNI and UNIs only. PON ports are not known by logical device
374 if ps.PortType == voltha.Port_ETHERNET_NNI || ps.PortType == voltha.Port_ETHERNET_UNI {
375 go func() {
376 err := dMgr.logicalDeviceMgr.updatePortState(log.WithSpanFromContext(context.Background(), ctx), ps.DeviceId, ps.PortNo, ps.OperStatus)
377 if err != nil {
378 // While we want to handle (catch) and log when
379 // an update to a port was not able to be
380 // propagated to the logical port, we can report
381 // it as a warning and not an error because it
382 // doesn't stop or modify processing.
383 // TODO: VOL-2707
384 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
385 }
386 }()
387 }
388 return &empty.Empty{}, nil
389 }
390 return nil, status.Errorf(codes.NotFound, "%s", ps.DeviceId)
391}
392
393func (dMgr *Manager) DeleteAllPorts(ctx context.Context, deviceID *common.ID) (*empty.Empty, error) {
394 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeleteAllPorts")
395 logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": deviceID.Id})
396
397 if agent := dMgr.getDeviceAgent(ctx, deviceID.Id); agent != nil {
398 if err := agent.deleteAllPorts(ctx); err != nil {
399 return nil, err
400 }
401 // Notify the logical device manager to remove all logical ports, if needed.
402 // At this stage the device itself may gave been deleted already at a DeleteAllPorts
403 // typically is part of a device deletion phase.
404 if device, err := dMgr.getDeviceReadOnly(ctx, deviceID.Id); err == nil {
405 go func() {
406 subCtx := utils.WithSpanAndRPCMetadataFromContext(ctx)
407 if err := dMgr.logicalDeviceMgr.deleteAllLogicalPorts(subCtx, device); err != nil {
408 logger.Errorw(ctx, "unable-to-delete-logical-ports", log.Fields{"error": err})
409 }
410 }()
411 } else {
412 logger.Warnw(ctx, "failed-to-retrieve-device", log.Fields{"device-id": deviceID.Id})
413 return nil, err
414 }
415 return &empty.Empty{}, nil
416 }
417 return nil, status.Errorf(codes.NotFound, "%s", deviceID.Id)
418}
419
420// GetDevicePort returns the port details for a specific device port entry
khenaidoo9beaaf12021-10-19 17:32:01 -0400421func (dMgr *Manager) GetDevicePort(ctx context.Context, pf *ca.PortFilter) (*voltha.Port, error) {
khenaidood948f772021-08-11 17:49:24 -0400422 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "GetDevicePort")
423 logger.Debugw(ctx, "get-device-port", log.Fields{"device-id": pf.DeviceId})
424
425 agent := dMgr.getDeviceAgent(ctx, pf.DeviceId)
426 if agent == nil {
427 return nil, status.Errorf(codes.NotFound, "device-%s", pf.DeviceId)
428 }
429 return agent.getDevicePort(pf.Port)
430}
431
432// DevicePMConfigUpdate updates the pm configs as defined by the adapter.
433func (dMgr *Manager) DevicePMConfigUpdate(ctx context.Context, pc *voltha.PmConfigs) (*empty.Empty, error) {
434 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DevicePMConfigUpdate")
435 logger.Debugw(ctx, "device-pm-config-update", log.Fields{"device-id": pc.Id})
436
437 if pc.Id == "" {
438 return nil, status.Errorf(codes.FailedPrecondition, "invalid-device-Id")
439 }
440 if agent := dMgr.getDeviceAgent(ctx, pc.Id); agent != nil {
441 if err := agent.initPmConfigs(ctx, pc); err != nil {
442 return nil, err
443 }
444 return &empty.Empty{}, nil
445 }
446 return nil, status.Errorf(codes.NotFound, "%s", pc.Id)
447}
448
449// SendPacketIn receives packetIn request from adapter
khenaidoo9beaaf12021-10-19 17:32:01 -0400450func (dMgr *Manager) SendPacketIn(ctx context.Context, pi *ca.PacketIn) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400451 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "SendPacketIn")
452 logger.Debugw(ctx, "packet-in", log.Fields{"device-id": pi.DeviceId, "port": pi.Port})
453
454 // Get the logical device Id based on the deviceId
455 var device *voltha.Device
456 var err error
457 if device, err = dMgr.getDeviceReadOnly(ctx, pi.DeviceId); err != nil {
458 logger.Errorw(ctx, "device-not-found", log.Fields{"device-id": pi.DeviceId})
459 return nil, err
460 }
461 if !device.Root {
462 logger.Errorw(ctx, "device-not-root", log.Fields{"device-id": pi.DeviceId})
463 return nil, status.Errorf(codes.FailedPrecondition, "%s", pi.DeviceId)
464 }
465
466 if err := dMgr.logicalDeviceMgr.packetIn(ctx, device.ParentId, pi.Port, pi.Packet); err != nil {
467 return nil, err
468 }
469 return &empty.Empty{}, nil
470}
471
khenaidoo9beaaf12021-10-19 17:32:01 -0400472func (dMgr *Manager) DeviceReasonUpdate(ctx context.Context, dr *ca.DeviceReason) (*empty.Empty, error) {
khenaidood948f772021-08-11 17:49:24 -0400473 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "DeviceReasonUpdate")
474 logger.Debugw(ctx, "update-device-reason", log.Fields{"device-id": dr.DeviceId, "reason": dr.Reason})
475
476 if agent := dMgr.getDeviceAgent(ctx, dr.DeviceId); agent != nil {
477 if err := agent.updateDeviceReason(ctx, dr.Reason); err != nil {
478 return nil, err
479 }
480 return &empty.Empty{}, nil
481 }
482 return nil, status.Errorf(codes.NotFound, "%s", dr.DeviceId)
483}
484
485func (dMgr *Manager) ReconcileChildDevices(ctx context.Context, parentDeviceID *common.ID) (*empty.Empty, error) {
486 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "ReconcileChildDevices")
487 logger.Debugw(ctx, "reconcile-child-devices", log.Fields{"device-id": parentDeviceID.Id})
488
489 numberOfDevicesToReconcile := 0
490 dMgr.deviceAgents.Range(func(key, value interface{}) bool {
491 deviceAgent, ok := value.(*Agent)
492 if ok && deviceAgent.parentID == parentDeviceID.Id {
493 go deviceAgent.ReconcileDevice(utils.WithNewSpanAndRPCMetadataContext(ctx, "ReconcileChildDevices"))
494 numberOfDevicesToReconcile++
495 }
496 return true
497 })
498 logger.Debugw(ctx, "reconciling-child-devices-initiated", log.Fields{"parent-device-id": parentDeviceID.Id, "number-of-child-devices-to-reconcile": numberOfDevicesToReconcile})
499 return &empty.Empty{}, nil
500}
501
502func (dMgr *Manager) UpdateImageDownload(ctx context.Context, img *voltha.ImageDownload) (*empty.Empty, error) {
503 ctx = utils.WithNewSpanAndRPCMetadataContext(ctx, "UpdateImageDownload")
504 log.EnrichSpan(ctx, log.Fields{"device-id": img.Id})
505
506 logger.Debugw(ctx, "update-image-download", log.Fields{"device-id": img.Id, "image-name": img.Name})
507
508 if agent := dMgr.getDeviceAgent(ctx, img.Id); agent != nil {
509 if err := agent.updateImageDownload(ctx, img); err != nil {
510 logger.Debugw(ctx, "update-image-download-failed", log.Fields{"err": err, "image-name": img.Name})
511 return nil, err
512 }
513 } else {
514 return nil, status.Errorf(codes.NotFound, "%s", img.Id)
515 }
516 return &empty.Empty{}, nil
517}
khenaidooa46458b2021-12-15 16:50:44 -0500518
519func (dMgr *Manager) GetHealthStatus(stream core_service.CoreService_GetHealthStatusServer) error {
520 ctx := utils.WithRPCMetadataContext(context.Background(), "keep-alive-connection")
521 logger.Debugw(ctx, "receive-stream-connection", log.Fields{"stream": stream})
522
523 if stream == nil {
524 return fmt.Errorf("conn-is-nil %v", stream)
525 }
526 initialRequestTime := time.Now()
527 var remoteClient *common.Connection
528 var tempClient *common.Connection
529 var err error
530loop:
531 for {
532 tempClient, err = stream.Recv()
533 if err != nil {
534 logger.Warnw(ctx, "received-stream-error", log.Fields{"remote-client": remoteClient, "error": err})
Girish Gowdra11ddb232022-05-26 12:19:59 -0700535 dMgr.adapterMgr.SignalOnRxStreamCloseCh(ctx, remoteClient.Endpoint)
khenaidooa46458b2021-12-15 16:50:44 -0500536 break loop
537 }
538 // Send a response back
539 err = stream.Send(&health.HealthStatus{State: health.HealthStatus_HEALTHY})
540 if err != nil {
541 logger.Warnw(ctx, "sending-stream-error", log.Fields{"remote-client": remoteClient, "error": err})
Girish Gowdra11ddb232022-05-26 12:19:59 -0700542 dMgr.adapterMgr.SignalOnRxStreamCloseCh(ctx, remoteClient.Endpoint)
khenaidooa46458b2021-12-15 16:50:44 -0500543 break loop
544 }
545
546 remoteClient = tempClient
547 logger.Debugw(ctx, "received-keep-alive", log.Fields{"remote-client": remoteClient})
548
549 select {
550 case <-stream.Context().Done():
551 logger.Infow(ctx, "stream-keep-alive-context-done", log.Fields{"remote-client": remoteClient, "error": stream.Context().Err()})
552 break loop
553 case <-dMgr.doneCh:
554 logger.Warnw(ctx, "received-stop", log.Fields{"remote-client": remoteClient, "initial-conn-time": initialRequestTime})
555 break loop
556 default:
557 }
558 }
559 logger.Errorw(ctx, "connection-down", log.Fields{"remote-client": remoteClient, "error": err, "initial-conn-time": initialRequestTime})
560 return err
561}