blob: f9bf7de539995adbcf498368ee502487cd5c10c7 [file] [log] [blame]
Mahir Gunyelfa6ea272020-06-10 17:03:51 -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 device
18
19import (
20 "context"
21 "fmt"
Maninder9a1bc0d2020-10-26 11:34:02 +053022 "github.com/opencord/voltha-protos/v4/go/common"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070023
24 "github.com/gogo/protobuf/proto"
Kent Hagerman2a07b862020-06-19 15:23:07 -040025 "github.com/opencord/voltha-go/rw_core/core/device/port"
Himani Chawlab4c25912020-11-12 17:16:38 +053026 coreutils "github.com/opencord/voltha-go/rw_core/utils"
yasin sapli5458a1c2021-06-14 22:24:38 +000027 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Maninderdfadc982020-10-28 14:04:33 +053028 "github.com/opencord/voltha-protos/v4/go/voltha"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070029 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
31)
32
Kent Hagerman2a07b862020-06-19 15:23:07 -040033// listDevicePorts returns device ports
34func (agent *Agent) listDevicePorts() map[uint32]*voltha.Port {
35 portIDs := agent.portLoader.ListIDs()
36 ports := make(map[uint32]*voltha.Port, len(portIDs))
37 for portID := range portIDs {
38 if portHandle, have := agent.portLoader.Lock(portID); have {
39 ports[portID] = portHandle.GetReadOnly()
40 portHandle.Unlock()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070041 }
42 }
43 return ports
44}
45
Kent Hagerman2a07b862020-06-19 15:23:07 -040046// getPorts retrieves the ports information of the device based on the port type.
47func (agent *Agent) getPorts(ctx context.Context, portType voltha.Port_PortType) *voltha.Ports {
Himani Chawlab4c25912020-11-12 17:16:38 +053048 logger.Debugw(ctx, "get-ports", log.Fields{"device-id": agent.deviceID, "port-type": portType})
Kent Hagerman2a07b862020-06-19 15:23:07 -040049 ports := &voltha.Ports{}
50 for _, port := range agent.listDevicePorts() {
51 if port.Type == portType {
52 ports.Items = append(ports.Items, port)
53 }
54 }
55 return ports
56}
57
58func (agent *Agent) getDevicePort(portID uint32) (*voltha.Port, error) {
59 portHandle, have := agent.portLoader.Lock(portID)
60 if !have {
61 return nil, status.Errorf(codes.NotFound, "port-%d", portID)
62 }
63 defer portHandle.Unlock()
64 return portHandle.GetReadOnly(), nil
65}
66
67func (agent *Agent) updatePortsOperState(ctx context.Context, portTypeFilter uint32, operStatus voltha.OperStatus_Types) error {
Himani Chawlab4c25912020-11-12 17:16:38 +053068 logger.Debugw(ctx, "update-ports-oper-state", log.Fields{"device-id": agent.deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -040069
70 for portID := range agent.portLoader.ListIDs() {
71 if portHandle, have := agent.portLoader.Lock(portID); have {
72 if oldPort := portHandle.GetReadOnly(); (1<<oldPort.Type)&portTypeFilter == 0 { // only update port types not included in the mask
73 // clone top-level port struct
74 newPort := *oldPort
75 newPort.OperStatus = operStatus
76 if err := portHandle.Update(ctx, &newPort); err != nil {
77 portHandle.Unlock()
78 return err
79 }
80
81 // Notify the logical device manager to change the port state
82 // Do this for NNI and UNIs only. PON ports are not known by logical device
83 if newPort.Type == voltha.Port_ETHERNET_NNI || newPort.Type == voltha.Port_ETHERNET_UNI {
Himani Chawlab4c25912020-11-12 17:16:38 +053084 subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
85
Kent Hagerman2a07b862020-06-19 15:23:07 -040086 go func(portID uint32, ctx context.Context) {
87 if err := agent.deviceMgr.logicalDeviceMgr.updatePortState(ctx, agent.deviceID, portID, operStatus); err != nil {
88 // TODO: VOL-2707
89 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
90 }
Himani Chawlab4c25912020-11-12 17:16:38 +053091 }(portID, subCtx)
Kent Hagerman2a07b862020-06-19 15:23:07 -040092 }
93 }
94 portHandle.Unlock()
95 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070096 }
Kent Hagerman2a07b862020-06-19 15:23:07 -040097 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070098}
99
100func (agent *Agent) updatePortState(ctx context.Context, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700101 // Ensure the enums passed in are valid - they will be invalid if they are not set when this function is invoked
102 if _, ok := voltha.Port_PortType_value[portType.String()]; !ok {
103 return status.Errorf(codes.InvalidArgument, "%s", portType)
104 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400105
106 portHandle, have := agent.portLoader.Lock(portNo)
107 if !have {
108 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700109 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400110 defer portHandle.Unlock()
111
112 port := portHandle.GetReadOnly()
113 if port.Type != portType {
114 return nil
115 }
116
117 newPort := *port // clone top-level port struct
118 newPort.OperStatus = operStatus
119 return portHandle.Update(ctx, &newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700120}
121
122func (agent *Agent) deleteAllPorts(ctx context.Context) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530123 logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": agent.deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400124
Kent Hagermancba2f302020-07-28 13:37:36 -0400125 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400126 if err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700127 return err
128 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700129
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530130 if device.AdminState != voltha.AdminState_DISABLED && !agent.isDeletionInProgress() {
131 err := status.Error(codes.FailedPrecondition, fmt.Sprintf("invalid-admin-state-%v",
132 device.AdminState))
Kent Hagerman2a07b862020-06-19 15:23:07 -0400133 logger.Warnw(ctx, "invalid-state-removing-ports", log.Fields{"state": device.AdminState, "error": err})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700134 return err
135 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700136
Kent Hagerman2a07b862020-06-19 15:23:07 -0400137 for portID := range agent.portLoader.ListIDs() {
138 if portHandle, have := agent.portLoader.Lock(portID); have {
139 if err := portHandle.Delete(ctx); err != nil {
140 portHandle.Unlock()
141 return err
142 }
143 portHandle.Unlock()
144 }
145 }
146 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700147}
148
149func (agent *Agent) addPort(ctx context.Context, port *voltha.Port) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000150 logger.Debugw(ctx, "addPort", log.Fields{"device-id": agent.deviceID})
Maninder9a1bc0d2020-10-26 11:34:02 +0530151 var desc string
152 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
153
154 defer agent.logDeviceUpdate(ctx, "addPort", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700155
Kent Hagerman2a07b862020-06-19 15:23:07 -0400156 port.AdminState = voltha.AdminState_ENABLED
157
158 portHandle, created, err := agent.portLoader.LockOrCreate(ctx, port)
159 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530160 desc = err.Error()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400161 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700162 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400163 defer portHandle.Unlock()
164
165 if created {
Maninder9a1bc0d2020-10-26 11:34:02 +0530166 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
Kent Hagerman2a07b862020-06-19 15:23:07 -0400167 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700168 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400169
170 oldPort := portHandle.GetReadOnly()
171 if oldPort.Label != "" || oldPort.Type != voltha.Port_PON_OLT {
Himani Chawlab4c25912020-11-12 17:16:38 +0530172 logger.Debugw(ctx, "port-already-exists", log.Fields{"port": port})
Maninder9a1bc0d2020-10-26 11:34:02 +0530173 desc = fmt.Sprintf("port already exists, port : %s", port)
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
Maninder9a1bc0d2020-10-26 11:34:02 +0530240 var desc string
241 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
242
243 defer agent.logDeviceUpdate(ctx, "disablePort", nil, nil, operStatus, &desc)
244
Kent Hagerman2a07b862020-06-19 15:23:07 -0400245 portHandle, have := agent.portLoader.Lock(portID)
246 if !have {
Maninder9a1bc0d2020-10-26 11:34:02 +0530247 desc = fmt.Sprintf("Invalid argument portID: %v", portID)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400248 return status.Errorf(codes.InvalidArgument, "%v", portID)
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 {
Maninder9a1bc0d2020-10-26 11:34:02 +0530255 desc = fmt.Sprintf("Disabling of Port Type %v unimplemented", oldPort.Type)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400256 return status.Errorf(codes.InvalidArgument, "Disabling of Port Type %v unimplemented", oldPort.Type)
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 {
Maninder9a1bc0d2020-10-26 11:34:02 +0530262 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700263 return err
264 }
265
266 //send request to adapter
Kent Hagermancba2f302020-07-28 13:37:36 -0400267 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400268 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530269 desc = err.Error()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400270 return err
271 }
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000272 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530273 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
274
Kent Hagerman2a07b862020-06-19 15:23:07 -0400275 ch, err := agent.adapterProxy.DisablePort(ctx, device, &newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700276 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530277 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700278 cancel()
279 return err
280 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530281 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
282 go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "disablePort", ch, agent.onSuccess, agent.onFailure, nil)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700283 return nil
284}
285
Kent Hagerman2a07b862020-06-19 15:23:07 -0400286func (agent *Agent) enablePort(ctx context.Context, portID uint32) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530287 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400288
Maninder9a1bc0d2020-10-26 11:34:02 +0530289 var desc string
290 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
291
292 defer agent.logDeviceUpdate(ctx, "enablePort", nil, nil, operStatus, &desc)
293
Kent Hagerman2a07b862020-06-19 15:23:07 -0400294 portHandle, have := agent.portLoader.Lock(portID)
295 if !have {
Maninder9a1bc0d2020-10-26 11:34:02 +0530296 desc = fmt.Sprintf("Invalid Argument portID: %v", portID)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400297 return status.Errorf(codes.InvalidArgument, "%v", portID)
298 }
299 defer portHandle.Unlock()
300
301 oldPort := portHandle.GetReadOnly()
302
303 if oldPort.Type != voltha.Port_PON_OLT {
Maninder9a1bc0d2020-10-26 11:34:02 +0530304 desc = fmt.Sprintf("Enabling of Port Type %v unimplemented", oldPort.Type)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400305 return status.Errorf(codes.InvalidArgument, "Enabling of Port Type %v unimplemented", oldPort.Type)
306 }
307
308 newPort := *oldPort
309 newPort.AdminState = voltha.AdminState_ENABLED
310 if err := portHandle.Update(ctx, &newPort); err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530311 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700312 return err
313 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700314
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700315 //send request to adapter
Kent Hagermancba2f302020-07-28 13:37:36 -0400316 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400317 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530318 desc = err.Error()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400319 return err
320 }
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000321 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530322 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
323
Kent Hagerman2a07b862020-06-19 15:23:07 -0400324 ch, err := agent.adapterProxy.EnablePort(ctx, device, &newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700325 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530326 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700327 cancel()
328 return err
329 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530330 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
331 go agent.waitForAdapterResponseAndLogDeviceUpdate(subCtx, cancel, "enablePort", ch, agent.onSuccess, agent.onFailure, nil)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700332 return nil
333}