| /* |
| * Copyright 2022-present Open Networking Foundation |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package vpagent |
| |
| import ( |
| "context" |
| "time" |
| |
| "voltha-go-controller/internal/pkg/intf" |
| |
| "github.com/golang/protobuf/ptypes/empty" |
| "github.com/opencord/voltha-lib-go/v7/pkg/log" |
| "github.com/opencord/voltha-protos/v5/go/voltha" |
| ) |
| |
| func (vpa *VPAgent) synchronizeDeviceList(ctx context.Context) { |
| // Send reconnection indication to the devices already known |
| for _, vpc := range vpa.clientMap { |
| vpc.ConnectInd(context.TODO(), intf.DeviceReDisc) |
| } |
| |
| // Refresh once to get everything started |
| vpa.refreshDeviceList() |
| |
| tick := time.NewTicker(vpa.DeviceListRefreshInterval) |
| loop: |
| for { |
| select { |
| case <-ctx.Done(): |
| logger.Errorw(ctx, "Context Done", log.Fields{"Context": ctx}) |
| break loop |
| case <-tick.C: |
| vpa.refreshDeviceList() |
| } |
| } |
| tick.Stop() |
| } |
| |
| func (vpa *VPAgent) refreshDeviceList() { |
| // If we exit, assume disconnected |
| if vpa.volthaClient == nil { |
| logger.Error(ctx, "no-voltha-connection") |
| vpa.events <- vpaEventVolthaDisconnected |
| return |
| } |
| deviceList, err := vpa.volthaClient.Get().ListLogicalDevices(context.Background(), &empty.Empty{}) |
| if err != nil { |
| logger.Errorw(ctx, "vpagent failed to query device list from voltha", |
| log.Fields{"error": err}) |
| vpa.events <- vpaEventVolthaDisconnected |
| return |
| } |
| |
| var toAdd []int |
| var toDel []string |
| var deviceIDMap = make(map[string]string) |
| for index, d := range deviceList.Items { |
| deviceID := d.Id |
| deviceIDMap[deviceID] = deviceID |
| if vpa.clientMap[deviceID] == nil { |
| toAdd = append(toAdd, index) |
| } |
| } |
| for key := range vpa.clientMap { |
| deviceID, ok := deviceIDMap[key] |
| if !ok || (ok && deviceID == "") { |
| toDel = append(toDel, key) |
| } |
| } |
| logger.Debugw(ctx, "Device Refresh", log.Fields{"ToAdd": toAdd, "ToDel": toDel}) |
| for i := 0; i < len(toAdd); i++ { |
| device := deviceList.Items[toAdd[i]] |
| serialNum := device.Desc.SerialNum |
| // If the blocked device list contain device serial number, do not add VPClient. |
| if vpa.VPClientAgent.IsBlockedDevice(serialNum) { |
| logger.Debugw(ctx, "Device Serial Number is present in the blocked device list", log.Fields{"device-serial-number": serialNum}) |
| } else { |
| vpa.addVPClient(device) // client is started in addVPClient |
| } |
| } |
| |
| for i := 0; i < len(toDel); i++ { |
| vpa.VPClientAgent.DelDevice(toDel[i]) |
| vpa.mapLock.Lock() |
| delete(vpa.clientMap, toDel[i]) |
| vpa.mapLock.Unlock() |
| } |
| } |
| |
| func (vpa *VPAgent) addVPClient(device *voltha.LogicalDevice) intf.IVPClient { |
| logger.Warnw(ctx, "GrpcClient addClient called ", log.Fields{"device-id": device.Id}) |
| vpa.mapLock.Lock() |
| defer vpa.mapLock.Unlock() |
| var serialNum = "Unknown" |
| if device.Desc != nil { |
| serialNum = device.Desc.SerialNum |
| } |
| vpc := vpa.clientMap[device.Id] |
| if vpc == nil { |
| vpa.VPClientAgent.AddNewDevice(&intf.VPClientCfg{ |
| DeviceID: device.Id, |
| SerialNum: serialNum, |
| SouthBoundID: device.RootDeviceId, |
| VolthaClient: vpa.volthaClient, |
| PacketOutChannel: vpa.packetOutChannel, |
| }) |
| |
| } |
| logger.Debugw(ctx, "Finished with addClient", log.Fields{"deviceID": device.Id}) |
| return vpc |
| } |
| |
| //AddClientToClientMap - called by controller once device obj is created |
| func (vpa *VPAgent) AddClientToClientMap(deviceID string, vpc intf.IVPClient) { |
| vpa.mapLock.Lock() |
| defer vpa.mapLock.Unlock() |
| |
| if vpc != nil { |
| vpa.clientMap[deviceID] = vpc |
| } |
| } |
| |
| func (vpa *VPAgent) getVPClient(deviceID string) intf.IVPClient { |
| if vpc, ok := vpa.clientMap[deviceID]; ok { |
| return vpc |
| } |
| return nil |
| } |