blob: ab171ef1ab77d65a8c2076dcda4bdc7858489b6d [file] [log] [blame]
Girish Gowdra64503432020-01-07 10:59:10 +05301/*
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 core
18
19import (
20 "context"
21 "encoding/hex"
22 "encoding/json"
23 "errors"
24 "fmt"
Girish Gowdra64503432020-01-07 10:59:10 +053025 "io"
26 "io/ioutil"
27 "os"
28 "strconv"
29 "sync"
30 "syscall"
31 "time"
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +030032
33 "github.com/cenkalti/backoff/v3"
34 "github.com/opencord/openolt-scale-tester/config"
Girish Gowdra5d7d6442020-09-08 17:03:11 -070035 "github.com/opencord/voltha-lib-go/v4/pkg/db/kvstore"
36 "github.com/opencord/voltha-lib-go/v4/pkg/log"
37 "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
38 oop "github.com/opencord/voltha-protos/v4/go/openolt"
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +030039 "google.golang.org/grpc"
40 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
Girish Gowdra64503432020-01-07 10:59:10 +053042)
43
44const (
45 ReasonOk = "OK"
46 TechProfileKVPath = "service/voltha/technology_profiles/%s/%d" // service/voltha/technology_profiles/xgspon/<tech_profile_tableID>
47)
48
49type OnuDeviceKey struct {
50 onuID uint32
51 ponInfID uint32
52}
53
54type OpenOltManager struct {
Girish Gowdra5d7d6442020-09-08 17:03:11 -070055 ipPort string
56 deviceInfo *oop.DeviceInfo
57 OnuDeviceMap map[OnuDeviceKey]*OnuDevice `json:"onuDeviceMap"`
58 TechProfile map[uint32]*techprofile.TechProfileIf
59 clientConn *grpc.ClientConn
60 openOltClient oop.OpenoltClient
61 testConfig *config.OpenOltScaleTesterConfig
62 rsrMgr *OpenOltResourceMgr
63 lockRsrAlloc sync.RWMutex
Girish Gowdraaeceb842020-08-21 12:10:39 -070064 lockOpenOltManager sync.RWMutex
Girish Gowdra64503432020-01-07 10:59:10 +053065}
66
Girish Gowdra64503432020-01-07 10:59:10 +053067func NewOpenOltManager(ipPort string) *OpenOltManager {
Girish Gowdra5d7d6442020-09-08 17:03:11 -070068 logger.Infow(nil, "initialized openolt manager with ipPort", log.Fields{"ipPort": ipPort})
Girish Gowdra64503432020-01-07 10:59:10 +053069 return &OpenOltManager{
Girish Gowdra5d7d6442020-09-08 17:03:11 -070070 ipPort: ipPort,
71 OnuDeviceMap: make(map[OnuDeviceKey]*OnuDevice),
72 lockRsrAlloc: sync.RWMutex{},
Girish Gowdraaeceb842020-08-21 12:10:39 -070073 lockOpenOltManager: sync.RWMutex{},
Girish Gowdra64503432020-01-07 10:59:10 +053074 }
75}
76
77func (om *OpenOltManager) readAndLoadTPsToEtcd() {
78 var byteValue []byte
79 var err error
80 // Verify that etcd is up before starting the application.
81 etcdIpPort := "http://" + om.testConfig.KVStoreHost + ":" + strconv.Itoa(om.testConfig.KVStorePort)
Girish Gowdra5d7d6442020-09-08 17:03:11 -070082 client, err := kvstore.NewEtcdClient(context.Background(), etcdIpPort, 5*time.Second, log.FatalLevel)
Girish Gowdra64503432020-01-07 10:59:10 +053083 if err != nil || client == nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -070084 logger.Fatal(nil, "error-initializing-etcd-client")
Girish Gowdra64503432020-01-07 10:59:10 +053085 return
86 }
87
88 // Load TPs to etcd for each of the specified tech-profiles
89 for _, tpID := range om.testConfig.TpIDList {
90 // Below should translate to something like "/app/ATT-64.json"
91 // The TP file should exist.
92 tpFilePath := "/app/" + om.testConfig.WorkflowName + "-" + strconv.Itoa(tpID) + ".json"
93 // Open our jsonFile
94 jsonFile, err := os.Open(tpFilePath)
95 // if we os.Open returns an error then handle it
96 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -070097 logger.Fatalw(nil, "could-not-find-tech-profile", log.Fields{"err": err, "tpFile": tpFilePath})
Girish Gowdra64503432020-01-07 10:59:10 +053098 }
Girish Gowdra5d7d6442020-09-08 17:03:11 -070099 logger.Debugw(nil, "tp-file-opened-successfully", log.Fields{"tpFile": tpFilePath})
Girish Gowdra64503432020-01-07 10:59:10 +0530100
101 // read our opened json file as a byte array.
102 if byteValue, err = ioutil.ReadAll(jsonFile); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700103 logger.Fatalw(nil, "could-not-read-tp-file", log.Fields{"err": err, "tpFile": tpFilePath})
Girish Gowdra64503432020-01-07 10:59:10 +0530104 }
105
106 var tp techprofile.TechProfile
107
108 if err = json.Unmarshal(byteValue, &tp); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700109 logger.Fatalw(nil, "could-not-unmarshal-tp", log.Fields{"err": err, "tpFile": tpFilePath})
Girish Gowdra64503432020-01-07 10:59:10 +0530110 } else {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700111 logger.Infow(nil, "tp-read-from-file", log.Fields{"tp": tp, "tpFile": tpFilePath})
Girish Gowdra64503432020-01-07 10:59:10 +0530112 }
113 kvPath := fmt.Sprintf(TechProfileKVPath, om.deviceInfo.Technology, tpID)
114 tpJson, err := json.Marshal(tp)
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300115 err = client.Put(context.Background(), kvPath, tpJson)
Girish Gowdra64503432020-01-07 10:59:10 +0530116 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700117 logger.Fatalw(nil, "tp-put-to-etcd-failed", log.Fields{"tpPath": kvPath, "err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530118 }
119 // verify the PUT succeeded.
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300120 kvResult, err := client.Get(context.Background(), kvPath)
Girish Gowdra64503432020-01-07 10:59:10 +0530121 if kvResult == nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700122 logger.Fatal(nil, "tp-not-found-on-kv-after-load", log.Fields{"key": kvPath, "err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530123 } else {
124 var KvTpIns techprofile.TechProfile
125 var resPtr = &KvTpIns
126 if value, err := kvstore.ToByte(kvResult.Value); err == nil {
127 if err = json.Unmarshal(value, resPtr); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700128 logger.Fatal(nil, "error-unmarshal-kv-result", log.Fields{"err": err, "key": kvPath, "value": value})
Girish Gowdra64503432020-01-07 10:59:10 +0530129 } else {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700130 logger.Infow(nil, "verified-ok-that-tp-load-was-good", log.Fields{"tpID": tpID, "kvPath": kvPath})
Girish Gowdra64503432020-01-07 10:59:10 +0530131 _ = jsonFile.Close()
132 continue
133 }
134 }
135 }
136 }
137}
138
139func (om *OpenOltManager) Start(testConfig *config.OpenOltScaleTesterConfig) error {
140 var err error
141 om.testConfig = testConfig
142
143 // Establish gRPC connection with the device
144 if om.clientConn, err = grpc.Dial(om.ipPort, grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700145 logger.Errorw(nil, "Failed to dial device", log.Fields{"ipPort": om.ipPort, "err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530146 return err
147 }
148 om.openOltClient = oop.NewOpenoltClient(om.clientConn)
149
150 // Populate Device Info
151 if deviceInfo, err := om.populateDeviceInfo(); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700152 logger.Error(nil, "error fetching device info", log.Fields{"err": err, "deviceInfo": deviceInfo})
Girish Gowdra64503432020-01-07 10:59:10 +0530153 return err
154 }
155
156 // Read and load TPs to etcd.
157 om.readAndLoadTPsToEtcd()
158
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700159 logger.Info(nil, "etcd-up-and-running--tp-loaded-successfully")
Girish Gowdra64503432020-01-07 10:59:10 +0530160
161 if om.rsrMgr = NewResourceMgr("ABCD", om.testConfig.KVStoreHost+":"+strconv.Itoa(om.testConfig.KVStorePort),
162 "etcd", "openolt", om.deviceInfo); om.rsrMgr == nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700163 logger.Error(nil, "Error while instantiating resource manager")
Girish Gowdra64503432020-01-07 10:59:10 +0530164 return errors.New("instantiating resource manager failed")
165 }
166
167 om.TechProfile = make(map[uint32]*techprofile.TechProfileIf)
168 if err = om.populateTechProfilePerPonPort(); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700169 logger.Error(nil, "Error while populating tech profile mgr\n")
Girish Gowdra64503432020-01-07 10:59:10 +0530170 return errors.New("error-loading-tech-profile-per-ponPort")
171 }
172
173 // Start reading indications
174 go om.readIndications()
175
176 // Provision OLT NNI Trap flows as needed by the Workflow
Thiyagarajan Subramanic4f8da82020-02-05 16:08:26 +0530177 if err = ProvisionNniTrapFlow(om.openOltClient, om.testConfig, om.rsrMgr); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700178 logger.Error(nil, "failed-to-add-nni-trap-flow", log.Fields{"err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530179 }
180
181 // Provision ONUs one by one
182 go om.provisionONUs()
183
184 return nil
185
186}
187
188func (om *OpenOltManager) populateDeviceInfo() (*oop.DeviceInfo, error) {
189 var err error
190
191 if om.deviceInfo, err = om.openOltClient.GetDeviceInfo(context.Background(), new(oop.Empty)); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700192 logger.Errorw(nil, "Failed to fetch device info", log.Fields{"err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530193 return nil, err
194 }
195
196 if om.deviceInfo == nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700197 logger.Errorw(nil, "Device info is nil", log.Fields{})
Girish Gowdra64503432020-01-07 10:59:10 +0530198 return nil, errors.New("failed to get device info from OLT")
199 }
200
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700201 logger.Debugw(nil, "Fetched device info", log.Fields{"deviceInfo": om.deviceInfo})
Girish Gowdra64503432020-01-07 10:59:10 +0530202
203 return om.deviceInfo, nil
204}
205
206func (om *OpenOltManager) provisionONUs() {
207 var numOfONUsPerPon uint
Girish Gowdraaeceb842020-08-21 12:10:39 -0700208 var i, j, k, onuID uint32
Girish Gowdra64503432020-01-07 10:59:10 +0530209 var err error
Girish Gowdraaeceb842020-08-21 12:10:39 -0700210 var onuWg sync.WaitGroup
211
212 defer func() {
213 // Stop the process once the job is done
214 _ = syscall.Kill(syscall.Getpid(), syscall.SIGINT)
215 }()
216
217 // If the number of ONUs to provision is not a power of 2, stop execution
218 // This is needed for ensure even distribution of ONUs across all PONs
219 if !isPowerOfTwo(om.testConfig.NumOfOnu) {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700220 logger.Errorw(nil, "num-of-onus-to-provision-is-not-a-power-of-2", log.Fields{"numOfOnus": om.testConfig.NumOfOnu})
Girish Gowdraaeceb842020-08-21 12:10:39 -0700221 return
Girish Gowdra64503432020-01-07 10:59:10 +0530222 }
Girish Gowdraaeceb842020-08-21 12:10:39 -0700223
224 // Number of ONUs to provision should not be less than the number of PON ports.
225 // We need at least one ONU per PON
226 if om.testConfig.NumOfOnu < uint(om.deviceInfo.PonPorts) {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700227 logger.Errorw(nil, "num-of-onu-is-less-than-num-of-pon-port", log.Fields{"numOfOnus": om.testConfig.NumOfOnu, "numOfPon": om.deviceInfo.PonPorts})
Girish Gowdraaeceb842020-08-21 12:10:39 -0700228 return
229 }
230
231 numOfONUsPerPon = om.testConfig.NumOfOnu / uint(om.deviceInfo.PonPorts)
Girish Gowdra64503432020-01-07 10:59:10 +0530232 totalOnusToProvision := numOfONUsPerPon * uint(om.deviceInfo.PonPorts)
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700233 logger.Infow(nil, "***** all-onu-provision-started ******",
Girish Gowdra64503432020-01-07 10:59:10 +0530234 log.Fields{"totalNumOnus": totalOnusToProvision,
235 "numOfOnusPerPon": numOfONUsPerPon,
236 "numOfPons": om.deviceInfo.PonPorts})
Girish Gowdra64503432020-01-07 10:59:10 +0530237
Girish Gowdraaeceb842020-08-21 12:10:39 -0700238 // These are the number of ONUs that will be provisioned per PON port per batch.
239 // Such number of ONUs will be chosen across all PON ports per batch
240 var onusPerIterationPerPonPort uint32 = 4
241
242 // If the total number of ONUs per PON is lesser than the default ONU to provision per pon port per batch
243 // then keep halving the ONU to provision per pon port per batch until we reach an acceptable number
244 // Note: the least possible value for onusPerIterationPerPonPort is 1
245 for uint32(numOfONUsPerPon) < onusPerIterationPerPonPort {
246 onusPerIterationPerPonPort /= 2
Girish Gowdra64503432020-01-07 10:59:10 +0530247 }
Girish Gowdra64503432020-01-07 10:59:10 +0530248
Girish Gowdraaeceb842020-08-21 12:10:39 -0700249 startTime := time.Now()
250 // Start provisioning the ONUs
251 for i = 0; i < uint32(numOfONUsPerPon)/onusPerIterationPerPonPort; i++ {
252 for j = 0; j < om.deviceInfo.PonPorts; j++ {
253 for k = 0; k < onusPerIterationPerPonPort; k++ {
254 om.lockRsrAlloc.Lock()
255 sn := GenerateNextONUSerialNumber()
256 om.lockRsrAlloc.Unlock()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700257 logger.Debugw(nil, "provisioning onu", log.Fields{"onuID": j, "ponPort": i, "serialNum": sn})
Girish Gowdraaeceb842020-08-21 12:10:39 -0700258 if onuID, err = om.rsrMgr.GetONUID(j); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700259 logger.Errorw(nil, "error getting onu id", log.Fields{"err": err})
Girish Gowdraaeceb842020-08-21 12:10:39 -0700260 continue
261 }
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700262 logger.Infow(nil, "onu-provision-started-from-olt-manager", log.Fields{"onuId": onuID, "ponIntf": i})
Girish Gowdraaeceb842020-08-21 12:10:39 -0700263
264 onuWg.Add(1)
265 go om.activateONU(j, onuID, sn, om.stringifySerialNumber(sn), &onuWg)
266 }
267 }
268 // Wait for the group of ONUs to complete processing before going to next batch of ONUs
269 onuWg.Wait()
270 }
271 endTime := time.Now()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700272 logger.Info(nil, "******** all-onu-provisioning-completed *******")
Girish Gowdraaeceb842020-08-21 12:10:39 -0700273 totalTime := endTime.Sub(startTime)
274 out := time.Time{}.Add(totalTime)
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700275 logger.Infof(nil, "****** Total Time to provision all the ONUs is => %s", out.Format("15:04:05"))
Girish Gowdraaeceb842020-08-21 12:10:39 -0700276
277 // TODO: We need to dump the results at the end. But below json marshall does not work. We will need custom Marshal function.
Girish Gowdra64503432020-01-07 10:59:10 +0530278 /*
279 e, err := json.Marshal(om)
280 if err != nil {
281 fmt.Println(err)
282 return
283 }
284 fmt.Println(string(e))
285 */
Girish Gowdra64503432020-01-07 10:59:10 +0530286}
287
Girish Gowdraaeceb842020-08-21 12:10:39 -0700288func (om *OpenOltManager) activateONU(intfID uint32, onuID uint32, serialNum *oop.SerialNumber, serialNumber string, onuWg *sync.WaitGroup) {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700289 logger.Debugw(nil, "activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
Girish Gowdra64503432020-01-07 10:59:10 +0530290 // TODO: need resource manager
291 var pir uint32 = 1000000
292 var onuDevice = OnuDevice{
293 SerialNum: serialNumber,
294 OnuID: onuID,
295 PonIntf: intfID,
296 openOltClient: om.openOltClient,
297 testConfig: om.testConfig,
298 rsrMgr: om.rsrMgr,
Girish Gowdraaeceb842020-08-21 12:10:39 -0700299 onuWg: onuWg,
Girish Gowdra64503432020-01-07 10:59:10 +0530300 }
301 var err error
302 onuDeviceKey := OnuDeviceKey{onuID: onuID, ponInfID: intfID}
303 Onu := oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: serialNum, Pir: pir}
304 now := time.Now()
305 nanos := now.UnixNano()
306 milliStart := nanos / 1000000
307 onuDevice.OnuProvisionStartTime = time.Unix(0, nanos)
308 if _, err = om.openOltClient.ActivateOnu(context.Background(), &Onu); err != nil {
309 st, _ := status.FromError(err)
310 if st.Code() == codes.AlreadyExists {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700311 logger.Debug(nil, "ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Girish Gowdra64503432020-01-07 10:59:10 +0530312 } else {
313 nanos = now.UnixNano()
314 milliEnd := nanos / 1000000
315 onuDevice.OnuProvisionEndTime = time.Unix(0, nanos)
316 onuDevice.OnuProvisionDurationInMs = milliEnd - milliStart
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700317 logger.Errorw(nil, "activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530318 onuDevice.Reason = err.Error()
Girish Gowdra64503432020-01-07 10:59:10 +0530319 }
320 } else {
321 nanos = now.UnixNano()
322 milliEnd := nanos / 1000000
323 onuDevice.OnuProvisionEndTime = time.Unix(0, nanos)
324 onuDevice.OnuProvisionDurationInMs = milliEnd - milliStart
325 onuDevice.Reason = ReasonOk
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700326 logger.Infow(nil, "activated-onu", log.Fields{"SerialNumber": serialNumber})
Girish Gowdra64503432020-01-07 10:59:10 +0530327 }
328
Girish Gowdraaeceb842020-08-21 12:10:39 -0700329 om.lockOpenOltManager.Lock()
Girish Gowdra64503432020-01-07 10:59:10 +0530330 om.OnuDeviceMap[onuDeviceKey] = &onuDevice
Girish Gowdraaeceb842020-08-21 12:10:39 -0700331 om.lockOpenOltManager.Unlock()
Girish Gowdra64503432020-01-07 10:59:10 +0530332
333 // If ONU activation was success provision the ONU
334 if err == nil {
Girish Gowdraaeceb842020-08-21 12:10:39 -0700335 om.lockOpenOltManager.RLock()
336 go om.OnuDeviceMap[onuDeviceKey].Start()
337 om.lockOpenOltManager.RUnlock()
338
Girish Gowdra64503432020-01-07 10:59:10 +0530339 }
340}
341
342func (om *OpenOltManager) stringifySerialNumber(serialNum *oop.SerialNumber) string {
343 if serialNum != nil {
344 return string(serialNum.VendorId) + om.stringifyVendorSpecific(serialNum.VendorSpecific)
345 }
346 return ""
347}
348
349func (om *OpenOltManager) stringifyVendorSpecific(vendorSpecific []byte) string {
350 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
351 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
352 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
353 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
354 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
355 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
356 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
357 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
358 return tmp
359}
360
361// readIndications to read the indications from the OLT device
362func (om *OpenOltManager) readIndications() {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700363 defer logger.Errorw(nil, "Indications ended", log.Fields{})
Girish Gowdra64503432020-01-07 10:59:10 +0530364 indications, err := om.openOltClient.EnableIndication(context.Background(), new(oop.Empty))
365 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700366 logger.Errorw(nil, "Failed to read indications", log.Fields{"err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530367 return
368 }
369 if indications == nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700370 logger.Errorw(nil, "Indications is nil", log.Fields{})
Girish Gowdra64503432020-01-07 10:59:10 +0530371 return
372 }
373
374 // Create an exponential backoff around re-enabling indications. The
375 // maximum elapsed time for the back off is set to 0 so that we will
376 // continue to retry. The max interval defaults to 1m, but is set
377 // here for code clarity
378 indicationBackoff := backoff.NewExponentialBackOff()
379 indicationBackoff.MaxElapsedTime = 0
380 indicationBackoff.MaxInterval = 1 * time.Minute
381 for {
382 indication, err := indications.Recv()
383 if err == io.EOF {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700384 logger.Infow(nil, "EOF for indications", log.Fields{"err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530385 // Use an exponential back off to prevent getting into a tight loop
386 duration := indicationBackoff.NextBackOff()
387 if duration == backoff.Stop {
388 // If we reach a maximum then warn and reset the backoff
389 // timer and keep attempting.
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700390 logger.Warnw(nil, "Maximum indication backoff reached, resetting backoff timer",
Girish Gowdra64503432020-01-07 10:59:10 +0530391 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
392 indicationBackoff.Reset()
393 }
394 time.Sleep(indicationBackoff.NextBackOff())
395 indications, err = om.openOltClient.EnableIndication(context.Background(), new(oop.Empty))
396 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700397 logger.Errorw(nil, "Failed to read indications", log.Fields{"err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530398 return
399 }
400 continue
401 }
402 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700403 logger.Infow(nil, "Failed to read from indications", log.Fields{"err": err})
Girish Gowdra64503432020-01-07 10:59:10 +0530404 break
405 }
406 // Reset backoff if we have a successful receive
407 indicationBackoff.Reset()
408 om.handleIndication(indication)
409
410 }
411}
412
413func (om *OpenOltManager) handleIndication(indication *oop.Indication) {
414 switch indication.Data.(type) {
415 case *oop.Indication_OltInd:
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700416 logger.Info(nil, "received olt indication")
Girish Gowdra64503432020-01-07 10:59:10 +0530417 case *oop.Indication_IntfInd:
418 intfInd := indication.GetIntfInd()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700419 logger.Infow(nil, "Received interface indication ", log.Fields{"InterfaceInd": intfInd})
Girish Gowdra64503432020-01-07 10:59:10 +0530420 case *oop.Indication_IntfOperInd:
421 intfOperInd := indication.GetIntfOperInd()
422 if intfOperInd.GetType() == "nni" {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700423 logger.Info(nil, "received interface oper indication for nni port")
Girish Gowdra64503432020-01-07 10:59:10 +0530424 } else if intfOperInd.GetType() == "pon" {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700425 logger.Info(nil, "received interface oper indication for pon port")
Girish Gowdra64503432020-01-07 10:59:10 +0530426 }
427 /*
428 case *oop.Indication_OnuDiscInd:
429 onuDiscInd := indication.GetOnuDiscInd()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700430 logger.Infow(nil, "Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdra64503432020-01-07 10:59:10 +0530431 */
432 case *oop.Indication_OnuInd:
433 onuInd := indication.GetOnuInd()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700434 logger.Infow(nil, "Received Onu indication ", log.Fields{"OnuInd": onuInd})
Girish Gowdra64503432020-01-07 10:59:10 +0530435 case *oop.Indication_OmciInd:
436 omciInd := indication.GetOmciInd()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700437 logger.Debugw(nil, "Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
Girish Gowdra64503432020-01-07 10:59:10 +0530438 case *oop.Indication_PktInd:
439 pktInd := indication.GetPktInd()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700440 logger.Infow(nil, "Received packet indication ", log.Fields{"PktInd": pktInd})
Girish Gowdra64503432020-01-07 10:59:10 +0530441 /*
442 case *oop.Indication_PortStats:
443 portStats := indication.GetPortStats()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700444 logger.Infow(nil, "Received port stats", log.Fields{"portStats": portStats})
Girish Gowdra64503432020-01-07 10:59:10 +0530445 case *oop.Indication_FlowStats:
446 flowStats := indication.GetFlowStats()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700447 logger.Infow(nil, "Received flow stats", log.Fields{"FlowStats": flowStats})
Girish Gowdra64503432020-01-07 10:59:10 +0530448 */
449 case *oop.Indication_AlarmInd:
450 alarmInd := indication.GetAlarmInd()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700451 logger.Infow(nil, "Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Girish Gowdra64503432020-01-07 10:59:10 +0530452 }
453}
454
455func (om *OpenOltManager) populateTechProfilePerPonPort() error {
456 var tpCount int
457 for _, techRange := range om.deviceInfo.Ranges {
458 for _, intfID := range techRange.IntfIds {
459 om.TechProfile[intfID] = &(om.rsrMgr.ResourceMgrs[intfID].TechProfileMgr)
460 tpCount++
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700461 logger.Debugw(nil, "Init tech profile done", log.Fields{"intfID": intfID})
Girish Gowdra64503432020-01-07 10:59:10 +0530462 }
463 }
464 //Make sure we have as many tech_profiles as there are pon ports on the device
465 if tpCount != int(om.deviceInfo.GetPonPorts()) {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700466 logger.Errorw(nil, "Error while populating techprofile",
Girish Gowdra64503432020-01-07 10:59:10 +0530467 log.Fields{"numofTech": tpCount, "numPonPorts": om.deviceInfo.GetPonPorts()})
468 return errors.New("error while populating techprofile mgrs")
469 }
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700470 logger.Infow(nil, "Populated techprofile for ponports successfully",
Girish Gowdra64503432020-01-07 10:59:10 +0530471 log.Fields{"numofTech": tpCount, "numPonPorts": om.deviceInfo.GetPonPorts()})
472 return nil
473}
Girish Gowdraaeceb842020-08-21 12:10:39 -0700474
475func isPowerOfTwo(numOfOnus uint) bool {
476 return (numOfOnus & (numOfOnus - 1)) == 0
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700477}