blob: b3de89dc32a3f67aed9656f50e791a6fd12fbe8f [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"
22
23 "github.com/gogo/protobuf/proto"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070024 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070025 "github.com/opencord/voltha-protos/v3/go/voltha"
26 "google.golang.org/grpc/codes"
27 "google.golang.org/grpc/status"
28)
29
30// getPorts retrieves the ports information of the device based on the port type.
31func (agent *Agent) getPorts(ctx context.Context, portType voltha.Port_PortType) *voltha.Ports {
Rohan Agrawal31f21802020-06-12 05:38:46 +000032 logger.Debugw(ctx, "getPorts", log.Fields{"device-id": agent.deviceID, "port-type": portType})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070033 ports := &voltha.Ports{}
34 if device, _ := agent.deviceMgr.getDevice(ctx, agent.deviceID); device != nil {
35 for _, port := range device.Ports {
36 if port.Type == portType {
37 ports.Items = append(ports.Items, port)
38 }
39 }
40 }
41 return ports
42}
43
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070044func (agent *Agent) updatePortsOperState(ctx context.Context, operStatus voltha.OperStatus_Types) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +000045 logger.Debugw(ctx, "updatePortsOperState", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070046 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
47 return err
48 }
49 defer agent.requestQueue.RequestComplete()
50 cloned := agent.getDeviceWithoutLock()
51 for _, port := range cloned.Ports {
52 port.OperStatus = operStatus
53 }
54 // Store the device
55 return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
56}
57
58func (agent *Agent) updatePortState(ctx context.Context, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_Types) error {
59 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
60 return err
61 }
62 defer agent.requestQueue.RequestComplete()
63 // Work only on latest data
64 // TODO: Get list of ports from device directly instead of the entire device
65 cloned := agent.getDeviceWithoutLock()
66
67 // Ensure the enums passed in are valid - they will be invalid if they are not set when this function is invoked
68 if _, ok := voltha.Port_PortType_value[portType.String()]; !ok {
69 return status.Errorf(codes.InvalidArgument, "%s", portType)
70 }
71 for _, port := range cloned.Ports {
72 if port.Type == portType && port.PortNo == portNo {
73 port.OperStatus = operStatus
74 }
75 }
Rohan Agrawal31f21802020-06-12 05:38:46 +000076 logger.Debugw(ctx, "portStatusUpdate", log.Fields{"deviceId": cloned.Id})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070077 // Store the device
78 return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
79}
80
81func (agent *Agent) deleteAllPorts(ctx context.Context) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +000082 logger.Debugw(ctx, "deleteAllPorts", log.Fields{"deviceId": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070083 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
84 return err
85 }
86 defer agent.requestQueue.RequestComplete()
87
88 cloned := agent.getDeviceWithoutLock()
89
90 if cloned.AdminState != voltha.AdminState_DISABLED && cloned.AdminState != voltha.AdminState_DELETED {
91 err := status.Error(codes.FailedPrecondition, fmt.Sprintf("invalid-state-%v", cloned.AdminState))
Rohan Agrawal31f21802020-06-12 05:38:46 +000092 logger.Warnw(ctx, "invalid-state-removing-ports", log.Fields{"state": cloned.AdminState, "error": err})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070093 return err
94 }
95 if len(cloned.Ports) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +000096 logger.Debugw(ctx, "no-ports-present", log.Fields{"deviceId": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070097 return nil
98 }
99
100 cloned.Ports = []*voltha.Port{}
Rohan Agrawal31f21802020-06-12 05:38:46 +0000101 logger.Debugw(ctx, "portStatusUpdate", log.Fields{"deviceId": cloned.Id})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700102 // Store the device
103 return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
104}
105
106func (agent *Agent) addPort(ctx context.Context, port *voltha.Port) error {
107 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
108 return err
109 }
110 defer agent.requestQueue.RequestComplete()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000111 logger.Debugw(ctx, "addPort", log.Fields{"deviceId": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700112
113 cloned := agent.getDeviceWithoutLock()
114 updatePort := false
115 if cloned.Ports == nil {
116 // First port
Rohan Agrawal31f21802020-06-12 05:38:46 +0000117 logger.Debugw(ctx, "addPort-first-port-to-add", log.Fields{"deviceId": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700118 cloned.Ports = make([]*voltha.Port, 0)
119 } else {
120 for _, p := range cloned.Ports {
121 if p.Type == port.Type && p.PortNo == port.PortNo {
122 if p.Label == "" && p.Type == voltha.Port_PON_OLT {
123 //Creation of OLT PON port is being processed after a default PON port was created. Just update it.
Rohan Agrawal31f21802020-06-12 05:38:46 +0000124 logger.Infow(ctx, "update-pon-port-created-by-default", log.Fields{"default-port": p, "port-to-add": port})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700125 p.Label = port.Label
126 p.OperStatus = port.OperStatus
127 updatePort = true
128 break
129 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000130 logger.Debugw(ctx, "port already exists", log.Fields{"port": port})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700131 return nil
132 }
133 }
134 }
135 if !updatePort {
136 cp := proto.Clone(port).(*voltha.Port)
137 // Set the admin state of the port to ENABLE
138 cp.AdminState = voltha.AdminState_ENABLED
139 cloned.Ports = append(cloned.Ports, cp)
140 }
141 // Store the device
142 return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
143}
144
145func (agent *Agent) addPeerPort(ctx context.Context, peerPort *voltha.Port_PeerPort) error {
146 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
147 return err
148 }
149 defer agent.requestQueue.RequestComplete()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000150 logger.Debugw(ctx, "adding-peer-peerPort", log.Fields{"device-id": agent.deviceID, "peer-peerPort": peerPort})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700151
152 cloned := agent.getDeviceWithoutLock()
153
154 // Get the peer port on the device based on the peerPort no
155 found := false
156 for _, port := range cloned.Ports {
157 if port.PortNo == peerPort.PortNo { // found peerPort
158 cp := proto.Clone(peerPort).(*voltha.Port_PeerPort)
159 port.Peers = append(port.Peers, cp)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000160 logger.Debugw(ctx, "found-peer", log.Fields{"device-id": agent.deviceID, "portNo": peerPort.PortNo, "deviceId": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700161 found = true
162 break
163 }
164 }
165 if !found && agent.isRootdevice {
166 // An ONU PON port has been created before the corresponding creation of the OLT PON port. Create the OLT PON port
167 // with default values which will be updated once the OLT PON port creation is processed.
168 ponPort := &voltha.Port{
169 PortNo: peerPort.PortNo,
170 Type: voltha.Port_PON_OLT,
171 AdminState: voltha.AdminState_ENABLED,
172 DeviceId: agent.deviceID,
173 Peers: []*voltha.Port_PeerPort{proto.Clone(peerPort).(*voltha.Port_PeerPort)},
174 }
175 cloned.Ports = append(cloned.Ports, ponPort)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000176 logger.Infow(ctx, "adding-default-pon-port", log.Fields{"device-id": agent.deviceID, "peer": peerPort, "pon-port": ponPort})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700177 }
178
179 // Store the device
180 return agent.updateDeviceInStoreWithoutLock(ctx, cloned, false, "")
181}
182
183func (agent *Agent) disablePort(ctx context.Context, Port *voltha.Port) error {
184 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
185 return err
186 }
187 defer agent.requestQueue.RequestComplete()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000188 logger.Debugw(ctx, "disablePort", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700189 var cp *voltha.Port
190 // Get the most up to date the device info
191 device := agent.getDeviceWithoutLock()
192 for _, port := range device.Ports {
193 if port.PortNo == Port.PortNo {
194 port.AdminState = voltha.AdminState_DISABLED
195 cp = proto.Clone(port).(*voltha.Port)
196 break
197
198 }
199 }
200 if cp == nil {
201 return status.Errorf(codes.InvalidArgument, "%v", Port.PortNo)
202 }
203
204 if cp.Type != voltha.Port_PON_OLT {
205 return status.Errorf(codes.InvalidArgument, "Disabling of Port Type %v unimplemented", cp.Type)
206 }
207 // Store the device
208 if err := agent.updateDeviceInStoreWithoutLock(ctx, device, false, ""); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000209 logger.Debugw(ctx, "updateDeviceInStoreWithoutLock error ", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo, "error": err})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700210 return err
211 }
212
213 //send request to adapter
214 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
215 ch, err := agent.adapterProxy.DisablePort(ctx, device, cp)
216 if err != nil {
217 cancel()
218 return err
219 }
220 go agent.waitForAdapterResponse(subCtx, cancel, "disablePort", ch, agent.onSuccess, agent.onFailure)
221 return nil
222}
223
224func (agent *Agent) enablePort(ctx context.Context, Port *voltha.Port) error {
225 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
226 return err
227 }
228 defer agent.requestQueue.RequestComplete()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000229 logger.Debugw(ctx, "enablePort", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700230
231 var cp *voltha.Port
232 // Get the most up to date the device info
233 device := agent.getDeviceWithoutLock()
234 for _, port := range device.Ports {
235 if port.PortNo == Port.PortNo {
236 port.AdminState = voltha.AdminState_ENABLED
237 cp = proto.Clone(port).(*voltha.Port)
238 break
239 }
240 }
241
242 if cp == nil {
243 return status.Errorf(codes.InvalidArgument, "%v", Port.PortNo)
244 }
245
246 if cp.Type != voltha.Port_PON_OLT {
247 return status.Errorf(codes.InvalidArgument, "Enabling of Port Type %v unimplemented", cp.Type)
248 }
249 // Store the device
250 if err := agent.updateDeviceInStoreWithoutLock(ctx, device, false, ""); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000251 logger.Debugw(ctx, "updateDeviceInStoreWithoutLock error ", log.Fields{"device-id": agent.deviceID, "port-no": Port.PortNo, "error": err})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700252 return err
253 }
254 //send request to adapter
255 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
256 ch, err := agent.adapterProxy.EnablePort(ctx, device, cp)
257 if err != nil {
258 cancel()
259 return err
260 }
261 go agent.waitForAdapterResponse(subCtx, cancel, "enablePort", ch, agent.onSuccess, agent.onFailure)
262 return nil
263}