blob: fe122bd08571d7ffe8adeb0bf05a577daf8c5130 [file] [log] [blame]
Mahir Gunyelfa6ea272020-06-10 17:03:51 -07001/*
Joey Armstrong7a9af442024-01-03 19:26:36 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Mahir Gunyelfa6ea272020-06-10 17:03:51 -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 device
18
19import (
20 "context"
21 "fmt"
khenaidood948f772021-08-11 17:49:24 -040022
23 "github.com/opencord/voltha-protos/v5/go/common"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070024
25 "github.com/gogo/protobuf/proto"
Kent Hagerman2a07b862020-06-19 15:23:07 -040026 "github.com/opencord/voltha-go/rw_core/core/device/port"
Himani Chawlab4c25912020-11-12 17:16:38 +053027 coreutils "github.com/opencord/voltha-go/rw_core/utils"
khenaidood948f772021-08-11 17:49:24 -040028 "github.com/opencord/voltha-lib-go/v7/pkg/log"
29 "github.com/opencord/voltha-protos/v5/go/voltha"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070030 "google.golang.org/grpc/codes"
31 "google.golang.org/grpc/status"
32)
33
Kent Hagerman2a07b862020-06-19 15:23:07 -040034// listDevicePorts returns device ports
35func (agent *Agent) listDevicePorts() map[uint32]*voltha.Port {
36 portIDs := agent.portLoader.ListIDs()
37 ports := make(map[uint32]*voltha.Port, len(portIDs))
38 for portID := range portIDs {
39 if portHandle, have := agent.portLoader.Lock(portID); have {
40 ports[portID] = portHandle.GetReadOnly()
41 portHandle.Unlock()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070042 }
43 }
44 return ports
45}
46
Kent Hagerman2a07b862020-06-19 15:23:07 -040047// getPorts retrieves the ports information of the device based on the port type.
48func (agent *Agent) getPorts(ctx context.Context, portType voltha.Port_PortType) *voltha.Ports {
Himani Chawlab4c25912020-11-12 17:16:38 +053049 logger.Debugw(ctx, "get-ports", log.Fields{"device-id": agent.deviceID, "port-type": portType})
Kent Hagerman2a07b862020-06-19 15:23:07 -040050 ports := &voltha.Ports{}
51 for _, port := range agent.listDevicePorts() {
52 if port.Type == portType {
53 ports.Items = append(ports.Items, port)
54 }
55 }
56 return ports
57}
58
59func (agent *Agent) getDevicePort(portID uint32) (*voltha.Port, error) {
60 portHandle, have := agent.portLoader.Lock(portID)
61 if !have {
62 return nil, status.Errorf(codes.NotFound, "port-%d", portID)
63 }
64 defer portHandle.Unlock()
65 return portHandle.GetReadOnly(), nil
66}
67
68func (agent *Agent) updatePortsOperState(ctx context.Context, portTypeFilter uint32, operStatus voltha.OperStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +053069 logger.Debugw(ctx, "update-ports-oper-state", log.Fields{"device-id": agent.deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -040070
71 for portID := range agent.portLoader.ListIDs() {
72 if portHandle, have := agent.portLoader.Lock(portID); have {
73 if oldPort := portHandle.GetReadOnly(); (1<<oldPort.Type)&portTypeFilter == 0 { // only update port types not included in the mask
74 // clone top-level port struct
75 newPort := *oldPort
76 newPort.OperStatus = operStatus
77 if err := portHandle.Update(ctx, &newPort); err != nil {
78 portHandle.Unlock()
79 return err
80 }
81
82 // Notify the logical device manager to change the port state
83 // Do this for NNI and UNIs only. PON ports are not known by logical device
84 if newPort.Type == voltha.Port_ETHERNET_NNI || newPort.Type == voltha.Port_ETHERNET_UNI {
nikesh.krishnan95142d52023-02-24 15:32:11 +053085 if err := agent.deviceMgr.logicalDeviceMgr.updatePortState(ctx, agent.deviceID, portID, operStatus); err != nil {
86 // TODO: VOL-2707
87 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
88 }
Himani Chawlab4c25912020-11-12 17:16:38 +053089
Kent Hagerman2a07b862020-06-19 15:23:07 -040090 }
91 }
92 portHandle.Unlock()
93 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070094 }
Kent Hagerman2a07b862020-06-19 15:23:07 -040095 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070096}
97
98func (agent *Agent) updatePortState(ctx context.Context, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070099 // Ensure the enums passed in are valid - they will be invalid if they are not set when this function is invoked
100 if _, ok := voltha.Port_PortType_value[portType.String()]; !ok {
101 return status.Errorf(codes.InvalidArgument, "%s", portType)
102 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400103
104 portHandle, have := agent.portLoader.Lock(portNo)
105 if !have {
106 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700107 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400108 defer portHandle.Unlock()
109
110 port := portHandle.GetReadOnly()
111 if port.Type != portType {
112 return nil
113 }
114
115 newPort := *port // clone top-level port struct
116 newPort.OperStatus = operStatus
117 return portHandle.Update(ctx, &newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700118}
119
120func (agent *Agent) deleteAllPorts(ctx context.Context) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530121 logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": agent.deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400122
Kent Hagermancba2f302020-07-28 13:37:36 -0400123 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400124 if err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700125 return err
126 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700127
serkant.uluderyaad1e6832020-12-17 21:08:38 +0300128 if !agent.isDeletionInProgress() {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530129 err := status.Error(codes.FailedPrecondition, fmt.Sprintf("invalid-admin-state-%v",
130 device.AdminState))
Kent Hagerman2a07b862020-06-19 15:23:07 -0400131 logger.Warnw(ctx, "invalid-state-removing-ports", log.Fields{"state": device.AdminState, "error": err})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700132 return err
133 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700134
Kent Hagerman2a07b862020-06-19 15:23:07 -0400135 for portID := range agent.portLoader.ListIDs() {
136 if portHandle, have := agent.portLoader.Lock(portID); have {
137 if err := portHandle.Delete(ctx); err != nil {
138 portHandle.Unlock()
139 return err
140 }
141 portHandle.Unlock()
142 }
143 }
144 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700145}
146
147func (agent *Agent) addPort(ctx context.Context, port *voltha.Port) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000148 logger.Debugw(ctx, "addPort", log.Fields{"device-id": agent.deviceID})
Maninder9a1bc0d2020-10-26 11:34:02 +0530149 var desc string
khenaidood948f772021-08-11 17:49:24 -0400150 var err error
Maninder9a1bc0d2020-10-26 11:34:02 +0530151 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
152
khenaidood948f772021-08-11 17:49:24 -0400153 defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700154
Kent Hagerman2a07b862020-06-19 15:23:07 -0400155 port.AdminState = voltha.AdminState_ENABLED
156
157 portHandle, created, err := agent.portLoader.LockOrCreate(ctx, port)
158 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530159 desc = err.Error()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400160 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700161 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400162 defer portHandle.Unlock()
163
164 if created {
Maninder9a1bc0d2020-10-26 11:34:02 +0530165 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
Kent Hagerman2a07b862020-06-19 15:23:07 -0400166 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700167 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400168
169 oldPort := portHandle.GetReadOnly()
170 if oldPort.Label != "" || oldPort.Type != voltha.Port_PON_OLT {
Himani Chawlab4c25912020-11-12 17:16:38 +0530171 logger.Debugw(ctx, "port-already-exists", log.Fields{"port": port})
Maninder9a1bc0d2020-10-26 11:34:02 +0530172 desc = fmt.Sprintf("port already exists, port : %s", port)
khenaidood948f772021-08-11 17:49:24 -0400173 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
Kent Hagerman2a07b862020-06-19 15:23:07 -0400174 return nil
175 }
176
177 // Creation of OLT PON port is being processed after a default PON port was created. Just update it.
178 logger.Infow(ctx, "update-pon-port-created-by-default", log.Fields{"default-port": oldPort, "port-to-add": port})
179 newPort := *oldPort // clone top-level port struct
180 newPort.Label = port.Label
181 newPort.OperStatus = port.OperStatus
182
Maninder9a1bc0d2020-10-26 11:34:02 +0530183 err = portHandle.Update(ctx, &newPort)
184 if err != nil {
185 desc = err.Error()
186 return err
187 }
188 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
189 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700190}
191
192func (agent *Agent) addPeerPort(ctx context.Context, peerPort *voltha.Port_PeerPort) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000193 logger.Debugw(ctx, "adding-peer-peerPort", log.Fields{"device-id": agent.deviceID, "peer-peerPort": peerPort})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700194
Kent Hagerman2a07b862020-06-19 15:23:07 -0400195 var portHandle *port.Handle
196 if agent.isRootDevice {
197 // If an ONU PON port needs to be referenced before the corresponding creation of the OLT PON port, then create the OLT PON port
198 // with default values, and update it later when the OLT PON port creation is processed.
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700199 ponPort := &voltha.Port{
200 PortNo: peerPort.PortNo,
201 Type: voltha.Port_PON_OLT,
202 AdminState: voltha.AdminState_ENABLED,
203 DeviceId: agent.deviceID,
Kent Hagerman2a07b862020-06-19 15:23:07 -0400204 Peers: []*voltha.Port_PeerPort{peerPort},
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700205 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400206
207 h, created, err := agent.portLoader.LockOrCreate(ctx, ponPort)
208 if err != nil {
209 return err
210 }
211 defer h.Unlock()
212
213 if created {
214 logger.Infow(ctx, "added-default-pon-port", log.Fields{"device-id": agent.deviceID, "peer": peerPort, "pon-port": ponPort})
215 return nil
216 }
217
218 portHandle = h
219 } else {
220 h, have := agent.portLoader.Lock(peerPort.PortNo)
221 if !have {
222 return nil
223 }
224 defer h.Unlock()
225
226 portHandle = h
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700227 }
228
Kent Hagerman2a07b862020-06-19 15:23:07 -0400229 logger.Debugw(ctx, "found-peer", log.Fields{"device-id": agent.deviceID, "portNo": peerPort.PortNo, "deviceId": agent.deviceID})
230
231 newPort := proto.Clone(portHandle.GetReadOnly()).(*voltha.Port)
232 newPort.Peers = append(newPort.Peers, peerPort)
233
234 return portHandle.Update(ctx, newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700235}
236
Kent Hagerman2a07b862020-06-19 15:23:07 -0400237func (agent *Agent) disablePort(ctx context.Context, portID uint32) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530238 logger.Debugw(ctx, "disable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700239
khenaidood948f772021-08-11 17:49:24 -0400240 var err error
Maninder9a1bc0d2020-10-26 11:34:02 +0530241 var desc string
242 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
khenaidood948f772021-08-11 17:49:24 -0400243 defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
Maninder9a1bc0d2020-10-26 11:34:02 +0530244
Kent Hagerman2a07b862020-06-19 15:23:07 -0400245 portHandle, have := agent.portLoader.Lock(portID)
246 if !have {
khenaidood948f772021-08-11 17:49:24 -0400247 err = status.Errorf(codes.InvalidArgument, "%v", portID)
248 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700249 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400250 defer portHandle.Unlock()
251
252 oldPort := portHandle.GetReadOnly()
253
254 if oldPort.Type != voltha.Port_PON_OLT {
khenaidood948f772021-08-11 17:49:24 -0400255 err = status.Errorf(codes.Unimplemented, "disabling of Port Type %v unimplemented", oldPort.Type)
256 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700257 }
258
Kent Hagerman2a07b862020-06-19 15:23:07 -0400259 newPort := *oldPort
260 newPort.AdminState = voltha.AdminState_DISABLED
261 if err := portHandle.Update(ctx, &newPort); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700262 return err
263 }
264
265 //send request to adapter
Kent Hagermancba2f302020-07-28 13:37:36 -0400266 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400267 if err != nil {
268 return err
269 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530270
khenaidood948f772021-08-11 17:49:24 -0400271 // Send the request to the adapter
272 client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700273 if err != nil {
khenaidood948f772021-08-11 17:49:24 -0400274 logger.Errorw(ctx, "grpc-client-nil",
275 log.Fields{
276 "error": err,
277 "device-id": agent.deviceID,
278 "device-type": agent.deviceType,
279 "adapter-endpoint": device.AdapterEndpoint,
280 })
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700281 return err
282 }
khenaidood948f772021-08-11 17:49:24 -0400283 subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
Maninder9a1bc0d2020-10-26 11:34:02 +0530284 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
khenaidood948f772021-08-11 17:49:24 -0400285 go func() {
286 defer cancel()
287 _, err := client.DisablePort(subCtx, &newPort)
288 if err == nil {
289 agent.onSuccess(subCtx, nil, nil, true)
290 } else {
291 agent.onFailure(subCtx, err, nil, nil, true)
292 }
293 }()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700294 return nil
295}
296
Kent Hagerman2a07b862020-06-19 15:23:07 -0400297func (agent *Agent) enablePort(ctx context.Context, portID uint32) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530298 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400299
khenaidood948f772021-08-11 17:49:24 -0400300 var err error
Maninder9a1bc0d2020-10-26 11:34:02 +0530301 var desc string
302 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
khenaidood948f772021-08-11 17:49:24 -0400303 defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
Maninder9a1bc0d2020-10-26 11:34:02 +0530304
Kent Hagerman2a07b862020-06-19 15:23:07 -0400305 portHandle, have := agent.portLoader.Lock(portID)
306 if !have {
khenaidood948f772021-08-11 17:49:24 -0400307 err = status.Errorf(codes.InvalidArgument, "%v", portID)
308 return err
Kent Hagerman2a07b862020-06-19 15:23:07 -0400309 }
310 defer portHandle.Unlock()
311
312 oldPort := portHandle.GetReadOnly()
313
314 if oldPort.Type != voltha.Port_PON_OLT {
khenaidood948f772021-08-11 17:49:24 -0400315 err = status.Errorf(codes.Unimplemented, "enabling of Port Type %v unimplemented", oldPort.Type)
316 return err
Kent Hagerman2a07b862020-06-19 15:23:07 -0400317 }
318
319 newPort := *oldPort
320 newPort.AdminState = voltha.AdminState_ENABLED
khenaidood948f772021-08-11 17:49:24 -0400321 if err = portHandle.Update(ctx, &newPort); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700322 return err
323 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700324
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700325 //send request to adapter
Kent Hagermancba2f302020-07-28 13:37:36 -0400326 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400327 if err != nil {
328 return err
329 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530330
khenaidood948f772021-08-11 17:49:24 -0400331 client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700332 if err != nil {
khenaidood948f772021-08-11 17:49:24 -0400333 logger.Errorw(ctx, "grpc-client-nil",
334 log.Fields{
335 "error": err,
336 "device-id": agent.deviceID,
337 "device-type": agent.deviceType,
338 "adapter-endpoint": device.AdapterEndpoint,
339 })
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700340 return err
341 }
khenaidood948f772021-08-11 17:49:24 -0400342 subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
Maninder9a1bc0d2020-10-26 11:34:02 +0530343 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
khenaidood948f772021-08-11 17:49:24 -0400344 go func() {
345 defer cancel()
346 _, err := client.EnablePort(subCtx, &newPort)
347 if err == nil {
348 agent.onSuccess(subCtx, nil, nil, true)
349 } else {
350 agent.onFailure(subCtx, err, nil, nil, true)
351 }
352 }()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700353 return nil
354}