blob: 60874229884ca1c7abeaafe74f3ea9ef851fd6eb [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001/*
Joey Armstrong7a9af442024-01-03 19:26:36 -05002 * Copyright 2019-2024 Open Networking Foundation (ONF) and the ONF Contributors
khenaidooab1f7bd2019-11-14 14:00:27 -05003
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 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidooab1f7bd2019-11-14 14:00:27 -050017package mocks
18
19import (
20 "context"
21 "fmt"
khenaidood948f772021-08-11 17:49:24 -040022 "strconv"
Kent Hagerman2a07b862020-06-19 15:23:07 -040023 "strings"
khenaidooa46458b2021-12-15 16:50:44 -050024 "time"
Kent Hagerman2a07b862020-06-19 15:23:07 -040025
khenaidood948f772021-08-11 17:49:24 -040026 "github.com/golang/protobuf/ptypes/empty"
27 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
28 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
khenaidooa46458b2021-12-15 16:50:44 -050029 "github.com/opencord/voltha-protos/v5/go/adapter_service"
khenaidood948f772021-08-11 17:49:24 -040030 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoo9beaaf12021-10-19 17:32:01 -040031 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidood948f772021-08-11 17:49:24 -040032 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidooa46458b2021-12-15 16:50:44 -050033 "github.com/opencord/voltha-protos/v5/go/health"
khenaidood948f772021-08-11 17:49:24 -040034 "github.com/phayes/freeport"
35
khenaidooab1f7bd2019-11-14 14:00:27 -050036 "github.com/gogo/protobuf/proto"
khenaidood948f772021-08-11 17:49:24 -040037 com "github.com/opencord/voltha-lib-go/v7/pkg/adapters/common"
38 "github.com/opencord/voltha-lib-go/v7/pkg/log"
khenaidoo9beaaf12021-10-19 17:32:01 -040039 "github.com/opencord/voltha-protos/v5/go/omci"
khenaidood948f772021-08-11 17:49:24 -040040 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
41 "github.com/opencord/voltha-protos/v5/go/voltha"
khenaidooab1f7bd2019-11-14 14:00:27 -050042)
43
npujar1d86a522019-11-14 17:11:16 +053044// ONUAdapter represent ONU adapter attributes
khenaidooab1f7bd2019-11-14 14:00:27 -050045type ONUAdapter struct {
khenaidoo8b4abbf2020-04-24 17:04:30 -040046 *Adapter
khenaidood948f772021-08-11 17:49:24 -040047 grpcServer *vgrpc.GrpcServer
khenaidooab1f7bd2019-11-14 14:00:27 -050048}
49
npujar1d86a522019-11-14 17:11:16 +053050// NewONUAdapter creates ONU adapter
khenaidood948f772021-08-11 17:49:24 -040051func NewONUAdapter(ctx context.Context, coreEndpoint string, deviceType string, vendor string) *ONUAdapter {
52 // Get an available port
53 grpcPort, err := freeport.GetFreePort()
54 if err != nil {
55 logger.Fatalw(ctx, "no-free-port", log.Fields{"error": err})
khenaidoo67b22152020-03-02 16:01:25 -050056 }
khenaidood948f772021-08-11 17:49:24 -040057 listeningAddress := fmt.Sprintf("127.0.0.1:%s", strconv.Itoa(grpcPort))
58 onuAdapter := &ONUAdapter{Adapter: NewAdapter(listeningAddress, coreEndpoint, deviceType, vendor)}
59
60 onuAdapter.start(ctx)
61 return onuAdapter
62}
63
64func (onuA *ONUAdapter) onuRestarted(ctx context.Context, endPoint string) error {
65 logger.Errorw(ctx, "remote-restarted", log.Fields{"endpoint": endPoint})
66 return nil
67}
68
69func (onuA *ONUAdapter) start(ctx context.Context) {
70
71 // Set up the probe service
72 onuA.Probe = &probe.Probe{}
73 probePort, err := freeport.GetFreePort()
74 if err != nil {
75 logger.Fatal(ctx, "Cannot get a freeport for probePort")
76 }
77 probeAddress := "127.0.0.1:" + strconv.Itoa(probePort)
78 go onuA.Probe.ListenAndServe(ctx, probeAddress)
79
80 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, onuA.Probe)
81
82 onuA.Probe.RegisterService(ctx, "onu-grpc-service", onuA.coreEnpoint)
83
84 // start gRPC handler
85 onuA.grpcServer = vgrpc.NewGrpcServer(onuA.serviceEndpoint, nil, false, nil)
86
87 logger.Debugw(ctx, "ONUAdapter-address", log.Fields{"address": onuA.serviceEndpoint})
88
89 go onuA.startGRPCService(ctx, onuA.grpcServer, onuA, "onu-grpc-service")
90
91 // Establish grpc connection to Core
khenaidoo25057da2021-12-08 14:40:45 -050092 if onuA.coreClient, err = vgrpc.NewClient(
khenaidooa46458b2021-12-15 16:50:44 -050093 "mock-onu-endpoint",
khenaidoo25057da2021-12-08 14:40:45 -050094 onuA.coreEnpoint,
khenaidooa46458b2021-12-15 16:50:44 -050095 "core_service.CoreService",
khenaidoo25057da2021-12-08 14:40:45 -050096 onuA.onuRestarted); err != nil {
khenaidood948f772021-08-11 17:49:24 -040097 logger.Fatal(ctx, "grpc-client-not-created")
98 }
khenaidooa46458b2021-12-15 16:50:44 -050099 go onuA.coreClient.Start(probeCtx, setCoreServiceHandler)
khenaidood948f772021-08-11 17:49:24 -0400100
101 logger.Debugw(ctx, "ONUAdapter-started", log.Fields{"grpc-address": onuA.serviceEndpoint})
102}
103
104// Stop brings down core services
105func (onuA *ONUAdapter) StopGrpcClient() {
106 // Stop the grpc clients
107 onuA.coreClient.Stop(context.Background())
108}
109
110func (onuA *ONUAdapter) Stop() {
111 if onuA.grpcServer != nil {
112 onuA.grpcServer.Stop()
113 }
114 logger.Debugw(context.Background(), "ONUAdapter-stopped", log.Fields{"grpc-address": onuA.serviceEndpoint})
khenaidooab1f7bd2019-11-14 14:00:27 -0500115}
116
npujar1d86a522019-11-14 17:11:16 +0530117// Adopt_device creates new handler for added device
khenaidood948f772021-08-11 17:49:24 -0400118func (onuA *ONUAdapter) AdoptDevice(ctx context.Context, device *voltha.Device) (*empty.Empty, error) {
119 logger.Debugw(ctx, "AdoptDevice", log.Fields{"device": device.AdapterEndpoint, "device-type": onuA.DeviceType})
khenaidooab1f7bd2019-11-14 14:00:27 -0500120 go func() {
121 d := proto.Clone(device).(*voltha.Device)
122 d.Root = false
khenaidood948f772021-08-11 17:49:24 -0400123 d.Vendor = onuA.vendor
khenaidooab1f7bd2019-11-14 14:00:27 -0500124 d.Model = "go-mock"
125 d.SerialNumber = com.GetRandomSerialNumber()
126 d.MacAddress = strings.ToUpper(com.GetRandomMacAddress())
127 onuA.storeDevice(d)
khenaidood948f772021-08-11 17:49:24 -0400128
129 c, err := onuA.GetCoreClient()
130 if err != nil {
131 return
132 }
133 if _, err := c.DeviceUpdate(context.TODO(), d); err != nil {
134 logger.Fatalf(ctx, "deviceUpdate-failed-%s", err)
khenaidooab1f7bd2019-11-14 14:00:27 -0500135 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500136
khenaidood948f772021-08-11 17:49:24 -0400137 d.ConnectStatus = common.ConnectStatus_REACHABLE
138 d.OperStatus = common.OperStatus_DISCOVERED
khenaidoo93181522020-01-23 12:43:21 -0500139
khenaidoo9beaaf12021-10-19 17:32:01 -0400140 if _, err = c.DeviceStateUpdate(context.TODO(), &ca.DeviceStateFilter{DeviceId: d.Id, OperStatus: d.OperStatus, ConnStatus: d.ConnectStatus}); err != nil {
khenaidood948f772021-08-11 17:49:24 -0400141 logger.Fatalf(ctx, "PortCreated-failed-%s", err)
khenaidoo442e7c72020-03-10 16:13:48 -0400142 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500143
144 uniPortNo := uint32(2)
145 if device.ProxyAddress != nil {
146 if device.ProxyAddress.ChannelId != 0 {
147 uniPortNo = device.ProxyAddress.ChannelId
148 }
149 }
150
khenaidooc6c7bda2020-06-17 17:20:18 -0400151 capability := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
khenaidooab1f7bd2019-11-14 14:00:27 -0500152 uniPort := &voltha.Port{
khenaidood948f772021-08-11 17:49:24 -0400153 DeviceId: d.Id,
khenaidooab1f7bd2019-11-14 14:00:27 -0500154 PortNo: uniPortNo,
155 Label: fmt.Sprintf("uni-%d", uniPortNo),
156 Type: voltha.Port_ETHERNET_UNI,
khenaidood948f772021-08-11 17:49:24 -0400157 OperStatus: common.OperStatus_ACTIVE,
khenaidooc6c7bda2020-06-17 17:20:18 -0400158 OfpPort: &of.OfpPort{
159 HwAddr: macAddressToUint32Array("12:12:12:12:12:12"),
160 Config: 0,
161 State: uint32(of.OfpPortState_OFPPS_LIVE),
162 Curr: capability,
163 Advertised: capability,
164 Peer: capability,
165 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
166 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
167 },
khenaidooab1f7bd2019-11-14 14:00:27 -0500168 }
khenaidooc6c7bda2020-06-17 17:20:18 -0400169
khenaidood948f772021-08-11 17:49:24 -0400170 if _, err = c.PortCreated(context.TODO(), uniPort); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000171 logger.Fatalf(ctx, "PortCreated-failed-%s", err)
khenaidooab1f7bd2019-11-14 14:00:27 -0500172 }
173
174 ponPortNo := uint32(1)
175 if device.ParentPortNo != 0 {
176 ponPortNo = device.ParentPortNo
177 }
178
179 ponPort := &voltha.Port{
khenaidood948f772021-08-11 17:49:24 -0400180 DeviceId: d.Id,
khenaidooab1f7bd2019-11-14 14:00:27 -0500181 PortNo: ponPortNo,
182 Label: fmt.Sprintf("pon-%d", ponPortNo),
183 Type: voltha.Port_PON_ONU,
khenaidood948f772021-08-11 17:49:24 -0400184 OperStatus: common.OperStatus_ACTIVE,
khenaidooab1f7bd2019-11-14 14:00:27 -0500185 Peers: []*voltha.Port_PeerPort{{DeviceId: d.ParentId, // Peer device is OLT
khenaidoo6e55d9e2019-12-12 18:26:26 -0500186 PortNo: device.ParentPortNo}}, // Peer port is parent's port number
khenaidooab1f7bd2019-11-14 14:00:27 -0500187 }
khenaidood948f772021-08-11 17:49:24 -0400188
189 if _, err = c.PortCreated(context.TODO(), ponPort); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000190 logger.Fatalf(ctx, "PortCreated-failed-%s", err)
khenaidooab1f7bd2019-11-14 14:00:27 -0500191 }
192
khenaidood948f772021-08-11 17:49:24 -0400193 d.ConnectStatus = common.ConnectStatus_REACHABLE
194 d.OperStatus = common.OperStatus_ACTIVE
khenaidooab1f7bd2019-11-14 14:00:27 -0500195
khenaidoo9beaaf12021-10-19 17:32:01 -0400196 if _, err = c.DeviceStateUpdate(context.TODO(), &ca.DeviceStateFilter{DeviceId: d.Id, OperStatus: d.OperStatus, ConnStatus: d.ConnectStatus}); err != nil {
khenaidood948f772021-08-11 17:49:24 -0400197 logger.Fatalf(ctx, "PortCreated-failed-%s", err)
khenaidooab1f7bd2019-11-14 14:00:27 -0500198 }
khenaidood948f772021-08-11 17:49:24 -0400199
khenaidooab1f7bd2019-11-14 14:00:27 -0500200 //Get the latest device data from the Core
khenaidood948f772021-08-11 17:49:24 -0400201 if d, err = c.GetDevice(context.TODO(), &common.ID{Id: d.Id}); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000202 logger.Fatalf(ctx, "getting-device-failed-%s", err)
khenaidooab1f7bd2019-11-14 14:00:27 -0500203 }
204
khenaidoo8b4abbf2020-04-24 17:04:30 -0400205 onuA.updateDevice(d)
khenaidooab1f7bd2019-11-14 14:00:27 -0500206 }()
khenaidood948f772021-08-11 17:49:24 -0400207 return &empty.Empty{}, nil
khenaidooab1f7bd2019-11-14 14:00:27 -0500208}
209
Andrea Campanella025667e2021-01-14 11:50:07 +0100210// Single_get_value_request retrieves a single value.
211func (onuA *ONUAdapter) Single_get_value_request(ctx context.Context, // nolint
212 request extension.SingleGetValueRequest) (*extension.SingleGetValueResponse, error) {
213 logger.Fatalf(ctx, "Single_get_value_request unimplemented")
214 return nil, nil
215}
216
npujar1d86a522019-11-14 17:11:16 +0530217// Disable_device disables device
khenaidood948f772021-08-11 17:49:24 -0400218func (onuA *ONUAdapter) DisableDevice(ctx context.Context, device *voltha.Device) (*empty.Empty, error) { // nolint
khenaidooab1f7bd2019-11-14 14:00:27 -0500219 go func() {
220 if d := onuA.getDevice(device.Id); d == nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000221 logger.Fatalf(ctx, "device-not-found-%s", device.Id)
khenaidooab1f7bd2019-11-14 14:00:27 -0500222 }
khenaidood948f772021-08-11 17:49:24 -0400223
khenaidooab1f7bd2019-11-14 14:00:27 -0500224 cloned := proto.Clone(device).(*voltha.Device)
225 // Update the all ports state on that device to disable
khenaidood948f772021-08-11 17:49:24 -0400226 c, err := onuA.GetCoreClient()
227 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400228 return
khenaidooab1f7bd2019-11-14 14:00:27 -0500229 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500230
khenaidood948f772021-08-11 17:49:24 -0400231 if _, err := c.PortsStateUpdate(context.TODO(),
khenaidoo9beaaf12021-10-19 17:32:01 -0400232 &ca.PortStateFilter{
khenaidood948f772021-08-11 17:49:24 -0400233 DeviceId: cloned.Id,
234 PortTypeFilter: 0,
235 OperStatus: common.OperStatus_UNKNOWN,
236 }); err != nil {
237 logger.Warnw(ctx, "updating-ports-failed", log.Fields{"device-id": device.Id, "error": err})
238 }
239
240 //Update the device operational state
241 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
242 cloned.OperStatus = common.OperStatus_UNKNOWN
243
khenaidoo9beaaf12021-10-19 17:32:01 -0400244 if _, err := c.DeviceStateUpdate(context.TODO(), &ca.DeviceStateFilter{
khenaidood948f772021-08-11 17:49:24 -0400245 DeviceId: cloned.Id,
246 OperStatus: cloned.OperStatus,
247 ConnStatus: cloned.ConnectStatus,
248 }); err != nil {
249 // Device may already have been deleted in the core
divyadesaicb8b59d2020-08-18 09:55:47 +0000250 logger.Warnw(ctx, "device-state-update-failed", log.Fields{"device-id": device.Id, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400251 return
khenaidooab1f7bd2019-11-14 14:00:27 -0500252 }
khenaidood948f772021-08-11 17:49:24 -0400253
khenaidoo8b4abbf2020-04-24 17:04:30 -0400254 onuA.updateDevice(cloned)
khenaidood948f772021-08-11 17:49:24 -0400255
khenaidooab1f7bd2019-11-14 14:00:27 -0500256 }()
khenaidood948f772021-08-11 17:49:24 -0400257 return &empty.Empty{}, nil
khenaidooab1f7bd2019-11-14 14:00:27 -0500258}
259
khenaidood948f772021-08-11 17:49:24 -0400260func (onuA *ONUAdapter) ReEnableDevice(ctx context.Context, device *voltha.Device) (*empty.Empty, error) { // nolint
khenaidooab1f7bd2019-11-14 14:00:27 -0500261 go func() {
262 if d := onuA.getDevice(device.Id); d == nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000263 logger.Fatalf(ctx, "device-not-found-%s", device.Id)
khenaidooab1f7bd2019-11-14 14:00:27 -0500264 }
265
266 cloned := proto.Clone(device).(*voltha.Device)
khenaidood948f772021-08-11 17:49:24 -0400267
268 c, err := onuA.GetCoreClient()
269 if err != nil {
270 return
271 }
272
khenaidooab1f7bd2019-11-14 14:00:27 -0500273 // Update the all ports state on that device to enable
khenaidood948f772021-08-11 17:49:24 -0400274 if _, err := c.PortsStateUpdate(context.TODO(),
khenaidoo9beaaf12021-10-19 17:32:01 -0400275 &ca.PortStateFilter{
khenaidood948f772021-08-11 17:49:24 -0400276 DeviceId: cloned.Id,
277 PortTypeFilter: 0,
278 OperStatus: common.OperStatus_ACTIVE,
279 }); err != nil {
280 logger.Warnw(ctx, "updating-ports-failed", log.Fields{"device-id": device.Id, "error": err})
khenaidooab1f7bd2019-11-14 14:00:27 -0500281 }
282
283 //Update the device state
khenaidood948f772021-08-11 17:49:24 -0400284 cloned.ConnectStatus = common.ConnectStatus_REACHABLE
285 cloned.OperStatus = common.OperStatus_ACTIVE
khenaidooab1f7bd2019-11-14 14:00:27 -0500286
khenaidoo9beaaf12021-10-19 17:32:01 -0400287 if _, err := c.DeviceStateUpdate(context.TODO(), &ca.DeviceStateFilter{
khenaidood948f772021-08-11 17:49:24 -0400288 DeviceId: cloned.Id,
289 OperStatus: cloned.OperStatus,
290 ConnStatus: cloned.ConnectStatus,
291 }); err != nil {
292 // Device may already have been deleted in the core
divyadesaicb8b59d2020-08-18 09:55:47 +0000293 logger.Fatalf(ctx, "device-state-update-failed", log.Fields{"device-id": device.Id, "error": err})
khenaidood948f772021-08-11 17:49:24 -0400294 return
khenaidooab1f7bd2019-11-14 14:00:27 -0500295 }
khenaidoo8b4abbf2020-04-24 17:04:30 -0400296 onuA.updateDevice(cloned)
khenaidooab1f7bd2019-11-14 14:00:27 -0500297 }()
khenaidood948f772021-08-11 17:49:24 -0400298 return &empty.Empty{}, nil
khenaidooab1f7bd2019-11-14 14:00:27 -0500299}
khenaidoo67b22152020-03-02 16:01:25 -0500300
khenaidoo9beaaf12021-10-19 17:32:01 -0400301func (onuA *ONUAdapter) StartOmciTest(ctx context.Context, _ *ca.OMCITest) (*omci.TestResponse, error) { // nolint
302 return &omci.TestResponse{Result: omci.TestResponse_SUCCESS}, nil
yasin sapli5458a1c2021-06-14 22:24:38 +0000303}
khenaidooa46458b2021-12-15 16:50:44 -0500304
305func (onuA *ONUAdapter) GetHealthStatus(stream adapter_service.AdapterService_GetHealthStatusServer) error {
306 ctx := context.Background()
307 logger.Debugw(ctx, "receive-stream-connection", log.Fields{"stream": stream})
308
309 if stream == nil {
310 return fmt.Errorf("conn-is-nil %v", stream)
311 }
312 initialRequestTime := time.Now()
313 var remoteClient *common.Connection
314 var tempClient *common.Connection
315 var err error
316loop:
317 for {
318 tempClient, err = stream.Recv()
319 if err != nil {
320 logger.Warnw(ctx, "received-stream-error", log.Fields{"remote-client": remoteClient, "error": err})
321 break loop
322 }
323 err = stream.Send(&health.HealthStatus{State: health.HealthStatus_HEALTHY})
324 if err != nil {
325 logger.Warnw(ctx, "sending-stream-error", log.Fields{"remote-client": remoteClient, "error": err})
326 break loop
327 }
328 remoteClient = tempClient
329 logger.Debugw(ctx, "received-keep-alive", log.Fields{"remote-client": remoteClient})
330
331 select {
332 case <-stream.Context().Done():
333 logger.Infow(ctx, "stream-keep-alive-context-done", log.Fields{"remote-client": remoteClient, "error": stream.Context().Err()})
334 break loop
335 default:
336 }
337 }
338 logger.Errorw(ctx, "connection-down", log.Fields{"remote-client": remoteClient, "error": err, "initial-conn-time": initialRequestTime})
339 return err
340}