blob: bdb678eff7689d32bb81a4793b0d11328768c81b [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"
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 {
Himani Chawlab4c25912020-11-12 17:16:38 +053085 subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx)
86
Kent Hagerman2a07b862020-06-19 15:23:07 -040087 go func(portID uint32, ctx context.Context) {
88 if err := agent.deviceMgr.logicalDeviceMgr.updatePortState(ctx, agent.deviceID, portID, operStatus); err != nil {
89 // TODO: VOL-2707
90 logger.Warnw(ctx, "unable-to-update-logical-port-state", log.Fields{"error": err})
91 }
Himani Chawlab4c25912020-11-12 17:16:38 +053092 }(portID, subCtx)
Kent Hagerman2a07b862020-06-19 15:23:07 -040093 }
94 }
95 portHandle.Unlock()
96 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070097 }
Kent Hagerman2a07b862020-06-19 15:23:07 -040098 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070099}
100
101func (agent *Agent) updatePortState(ctx context.Context, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700102 // Ensure the enums passed in are valid - they will be invalid if they are not set when this function is invoked
103 if _, ok := voltha.Port_PortType_value[portType.String()]; !ok {
104 return status.Errorf(codes.InvalidArgument, "%s", portType)
105 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400106
107 portHandle, have := agent.portLoader.Lock(portNo)
108 if !have {
109 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700110 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400111 defer portHandle.Unlock()
112
113 port := portHandle.GetReadOnly()
114 if port.Type != portType {
115 return nil
116 }
117
118 newPort := *port // clone top-level port struct
119 newPort.OperStatus = operStatus
120 return portHandle.Update(ctx, &newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700121}
122
123func (agent *Agent) deleteAllPorts(ctx context.Context) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530124 logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": agent.deviceID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400125
Kent Hagermancba2f302020-07-28 13:37:36 -0400126 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400127 if err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700128 return err
129 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700130
serkant.uluderyaad1e6832020-12-17 21:08:38 +0300131 if !agent.isDeletionInProgress() {
Himani Chawla2ba1c9c2020-10-07 13:19:03 +0530132 err := status.Error(codes.FailedPrecondition, fmt.Sprintf("invalid-admin-state-%v",
133 device.AdminState))
Kent Hagerman2a07b862020-06-19 15:23:07 -0400134 logger.Warnw(ctx, "invalid-state-removing-ports", log.Fields{"state": device.AdminState, "error": err})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700135 return err
136 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700137
Kent Hagerman2a07b862020-06-19 15:23:07 -0400138 for portID := range agent.portLoader.ListIDs() {
139 if portHandle, have := agent.portLoader.Lock(portID); have {
140 if err := portHandle.Delete(ctx); err != nil {
141 portHandle.Unlock()
142 return err
143 }
144 portHandle.Unlock()
145 }
146 }
147 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700148}
149
150func (agent *Agent) addPort(ctx context.Context, port *voltha.Port) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000151 logger.Debugw(ctx, "addPort", log.Fields{"device-id": agent.deviceID})
Maninder9a1bc0d2020-10-26 11:34:02 +0530152 var desc string
khenaidood948f772021-08-11 17:49:24 -0400153 var err error
Maninder9a1bc0d2020-10-26 11:34:02 +0530154 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
155
khenaidood948f772021-08-11 17:49:24 -0400156 defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700157
Kent Hagerman2a07b862020-06-19 15:23:07 -0400158 port.AdminState = voltha.AdminState_ENABLED
159
160 portHandle, created, err := agent.portLoader.LockOrCreate(ctx, port)
161 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530162 desc = err.Error()
Kent Hagerman2a07b862020-06-19 15:23:07 -0400163 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700164 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400165 defer portHandle.Unlock()
166
167 if created {
Maninder9a1bc0d2020-10-26 11:34:02 +0530168 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
Kent Hagerman2a07b862020-06-19 15:23:07 -0400169 return nil
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700170 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400171
172 oldPort := portHandle.GetReadOnly()
173 if oldPort.Label != "" || oldPort.Type != voltha.Port_PON_OLT {
Himani Chawlab4c25912020-11-12 17:16:38 +0530174 logger.Debugw(ctx, "port-already-exists", log.Fields{"port": port})
Maninder9a1bc0d2020-10-26 11:34:02 +0530175 desc = fmt.Sprintf("port already exists, port : %s", port)
khenaidood948f772021-08-11 17:49:24 -0400176 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
Kent Hagerman2a07b862020-06-19 15:23:07 -0400177 return nil
178 }
179
180 // Creation of OLT PON port is being processed after a default PON port was created. Just update it.
181 logger.Infow(ctx, "update-pon-port-created-by-default", log.Fields{"default-port": oldPort, "port-to-add": port})
182 newPort := *oldPort // clone top-level port struct
183 newPort.Label = port.Label
184 newPort.OperStatus = port.OperStatus
185
Maninder9a1bc0d2020-10-26 11:34:02 +0530186 err = portHandle.Update(ctx, &newPort)
187 if err != nil {
188 desc = err.Error()
189 return err
190 }
191 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
192 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700193}
194
195func (agent *Agent) addPeerPort(ctx context.Context, peerPort *voltha.Port_PeerPort) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000196 logger.Debugw(ctx, "adding-peer-peerPort", log.Fields{"device-id": agent.deviceID, "peer-peerPort": peerPort})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700197
Kent Hagerman2a07b862020-06-19 15:23:07 -0400198 var portHandle *port.Handle
199 if agent.isRootDevice {
200 // If an ONU PON port needs to be referenced before the corresponding creation of the OLT PON port, then create the OLT PON port
201 // with default values, and update it later when the OLT PON port creation is processed.
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700202 ponPort := &voltha.Port{
203 PortNo: peerPort.PortNo,
204 Type: voltha.Port_PON_OLT,
205 AdminState: voltha.AdminState_ENABLED,
206 DeviceId: agent.deviceID,
Kent Hagerman2a07b862020-06-19 15:23:07 -0400207 Peers: []*voltha.Port_PeerPort{peerPort},
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700208 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400209
210 h, created, err := agent.portLoader.LockOrCreate(ctx, ponPort)
211 if err != nil {
212 return err
213 }
214 defer h.Unlock()
215
216 if created {
217 logger.Infow(ctx, "added-default-pon-port", log.Fields{"device-id": agent.deviceID, "peer": peerPort, "pon-port": ponPort})
218 return nil
219 }
220
221 portHandle = h
222 } else {
223 h, have := agent.portLoader.Lock(peerPort.PortNo)
224 if !have {
225 return nil
226 }
227 defer h.Unlock()
228
229 portHandle = h
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700230 }
231
Kent Hagerman2a07b862020-06-19 15:23:07 -0400232 logger.Debugw(ctx, "found-peer", log.Fields{"device-id": agent.deviceID, "portNo": peerPort.PortNo, "deviceId": agent.deviceID})
233
234 newPort := proto.Clone(portHandle.GetReadOnly()).(*voltha.Port)
235 newPort.Peers = append(newPort.Peers, peerPort)
236
237 return portHandle.Update(ctx, newPort)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700238}
239
Kent Hagerman2a07b862020-06-19 15:23:07 -0400240func (agent *Agent) disablePort(ctx context.Context, portID uint32) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530241 logger.Debugw(ctx, "disable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700242
khenaidood948f772021-08-11 17:49:24 -0400243 var err error
Maninder9a1bc0d2020-10-26 11:34:02 +0530244 var desc string
245 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
khenaidood948f772021-08-11 17:49:24 -0400246 defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
Maninder9a1bc0d2020-10-26 11:34:02 +0530247
Kent Hagerman2a07b862020-06-19 15:23:07 -0400248 portHandle, have := agent.portLoader.Lock(portID)
249 if !have {
khenaidood948f772021-08-11 17:49:24 -0400250 err = status.Errorf(codes.InvalidArgument, "%v", portID)
251 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700252 }
Kent Hagerman2a07b862020-06-19 15:23:07 -0400253 defer portHandle.Unlock()
254
255 oldPort := portHandle.GetReadOnly()
256
257 if oldPort.Type != voltha.Port_PON_OLT {
khenaidood948f772021-08-11 17:49:24 -0400258 err = status.Errorf(codes.Unimplemented, "disabling of Port Type %v unimplemented", oldPort.Type)
259 return err
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700260 }
261
Kent Hagerman2a07b862020-06-19 15:23:07 -0400262 newPort := *oldPort
263 newPort.AdminState = voltha.AdminState_DISABLED
264 if err := portHandle.Update(ctx, &newPort); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700265 return err
266 }
267
268 //send request to adapter
Kent Hagermancba2f302020-07-28 13:37:36 -0400269 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400270 if err != nil {
271 return err
272 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530273
khenaidood948f772021-08-11 17:49:24 -0400274 // Send the request to the adapter
275 client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700276 if err != nil {
khenaidood948f772021-08-11 17:49:24 -0400277 logger.Errorw(ctx, "grpc-client-nil",
278 log.Fields{
279 "error": err,
280 "device-id": agent.deviceID,
281 "device-type": agent.deviceType,
282 "adapter-endpoint": device.AdapterEndpoint,
283 })
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700284 return err
285 }
khenaidood948f772021-08-11 17:49:24 -0400286 subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
Maninder9a1bc0d2020-10-26 11:34:02 +0530287 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
khenaidood948f772021-08-11 17:49:24 -0400288 go func() {
289 defer cancel()
290 _, err := client.DisablePort(subCtx, &newPort)
291 if err == nil {
292 agent.onSuccess(subCtx, nil, nil, true)
293 } else {
294 agent.onFailure(subCtx, err, nil, nil, true)
295 }
296 }()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700297 return nil
298}
299
Kent Hagerman2a07b862020-06-19 15:23:07 -0400300func (agent *Agent) enablePort(ctx context.Context, portID uint32) error {
Himani Chawlab4c25912020-11-12 17:16:38 +0530301 logger.Debugw(ctx, "enable-port", log.Fields{"device-id": agent.deviceID, "port-no": portID})
Kent Hagerman2a07b862020-06-19 15:23:07 -0400302
khenaidood948f772021-08-11 17:49:24 -0400303 var err error
Maninder9a1bc0d2020-10-26 11:34:02 +0530304 var desc string
305 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
khenaidood948f772021-08-11 17:49:24 -0400306 defer func() { agent.logDeviceUpdate(ctx, nil, nil, operStatus, err, desc) }()
Maninder9a1bc0d2020-10-26 11:34:02 +0530307
Kent Hagerman2a07b862020-06-19 15:23:07 -0400308 portHandle, have := agent.portLoader.Lock(portID)
309 if !have {
khenaidood948f772021-08-11 17:49:24 -0400310 err = status.Errorf(codes.InvalidArgument, "%v", portID)
311 return err
Kent Hagerman2a07b862020-06-19 15:23:07 -0400312 }
313 defer portHandle.Unlock()
314
315 oldPort := portHandle.GetReadOnly()
316
317 if oldPort.Type != voltha.Port_PON_OLT {
khenaidood948f772021-08-11 17:49:24 -0400318 err = status.Errorf(codes.Unimplemented, "enabling of Port Type %v unimplemented", oldPort.Type)
319 return err
Kent Hagerman2a07b862020-06-19 15:23:07 -0400320 }
321
322 newPort := *oldPort
323 newPort.AdminState = voltha.AdminState_ENABLED
khenaidood948f772021-08-11 17:49:24 -0400324 if err = portHandle.Update(ctx, &newPort); err != nil {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700325 return err
326 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700327
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700328 //send request to adapter
Kent Hagermancba2f302020-07-28 13:37:36 -0400329 device, err := agent.getDeviceReadOnly(ctx)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400330 if err != nil {
331 return err
332 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530333
khenaidood948f772021-08-11 17:49:24 -0400334 client, err := agent.adapterMgr.GetAdapterClient(ctx, agent.adapterEndpoint)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700335 if err != nil {
khenaidood948f772021-08-11 17:49:24 -0400336 logger.Errorw(ctx, "grpc-client-nil",
337 log.Fields{
338 "error": err,
339 "device-id": agent.deviceID,
340 "device-type": agent.deviceType,
341 "adapter-endpoint": device.AdapterEndpoint,
342 })
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700343 return err
344 }
khenaidood948f772021-08-11 17:49:24 -0400345 subCtx, cancel := context.WithTimeout(coreutils.WithAllMetadataFromContext(ctx), agent.rpcTimeout)
Maninder9a1bc0d2020-10-26 11:34:02 +0530346 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
khenaidood948f772021-08-11 17:49:24 -0400347 go func() {
348 defer cancel()
349 _, err := client.EnablePort(subCtx, &newPort)
350 if err == nil {
351 agent.onSuccess(subCtx, nil, nil, true)
352 } else {
353 agent.onFailure(subCtx, err, nil, nil, true)
354 }
355 }()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700356 return nil
357}