blob: 807412de3c081d45a40dbbc07d61b8fb98cce34d [file] [log] [blame]
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001/*
2 * Copyright 2020-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
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000022 "encoding/json"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000023 "errors"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000024 "fmt"
25 "strconv"
mpagenko3af1f032020-06-10 08:53:41 +000026 "strings"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000027
28 "github.com/looplab/fsm"
29
30 //"sync"
31 //"time"
32
33 //"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
34 "github.com/opencord/omci-lib-go"
35 me "github.com/opencord/omci-lib-go/generated"
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000036 "github.com/opencord/voltha-lib-go/v3/pkg/db"
37 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000038 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 //ic "github.com/opencord/voltha-protos/v3/go/inter_container"
40 //"github.com/opencord/voltha-protos/v3/go/openflow_13"
41 //"github.com/opencord/voltha-protos/v3/go/voltha"
42)
43
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000044var supportedClassIds = []me.ClassID{
45 me.CardholderClassID, // 5
46 me.CircuitPackClassID, // 6
47 me.SoftwareImageClassID, // 7
48 me.PhysicalPathTerminationPointEthernetUniClassID, // 11
49 me.OltGClassID, // 131
50 me.OnuPowerSheddingClassID, // 133
51 me.IpHostConfigDataClassID, // 134
52 me.OnuGClassID, // 256
53 me.Onu2GClassID, // 257
54 me.TContClassID, // 262
55 me.AniGClassID, // 263
56 me.UniGClassID, // 264
57 me.PriorityQueueClassID, // 277
58 me.TrafficSchedulerClassID, // 278
59 me.VirtualEthernetInterfacePointClassID, // 329
60 me.EnhancedSecurityControlClassID, // 332
61 me.OnuDynamicPowerManagementControlClassID, // 336
62 // 347 // definitions for ME "IPv6 host config data" are currently missing in omci-lib-go!
63}
64
65var fsmMsg TestMessageType
66
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000067func (onuDeviceEntry *OnuDeviceEntry) enterStartingState(e *fsm.Event) {
68 logger.Debugw("MibSync FSM", log.Fields{"Start processing MibSync-msgs in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
69
Holger Hildebrandt24d51952020-05-04 14:03:42 +000070 onuDeviceEntry.pOnuDB = NewOnuDeviceDB(context.TODO(), onuDeviceEntry)
71
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000072 go onuDeviceEntry.ProcessMibSyncMessages()
73}
74
75func (onuDeviceEntry *OnuDeviceEntry) enterLoadingMibTemplateState(e *fsm.Event) {
76 logger.Debugw("MibSync FSM", log.Fields{"Start MibTemplate processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +000077
78 meStoredFromTemplate := false
79
80 //TODO: perform MIB-reset
81 //TODO: needs to handle timeouts
82
83 //TODO: etrieve these values via OMCI GetRequests
84 //OltGClassID
85 onuDeviceEntry.vendorID = "BBSM"
86 onuDeviceEntry.serialNumber = "BBSM00000001"
87 //Onu2GClassID
88 onuDeviceEntry.equipmentID = "12345123451234512345"
89 //SoftwareImageClassID
90 onuDeviceEntry.activeSwVersion = "00000000000001"
91 //IpHostConfigDataClassID
92 onuDeviceEntry.macAddress = "00:00:00:00:00:00"
93
94 Path := fmt.Sprintf(SuffixMibTemplateKvStore, onuDeviceEntry.vendorID, onuDeviceEntry.equipmentID, onuDeviceEntry.activeSwVersion)
95 Value, err := onuDeviceEntry.mibTemplateKVStore.Get(context.TODO(), Path)
96 if err == nil {
97 if Value != nil {
98 logger.Debugf("MibSync FSM - MibTemplate read: Key: %s, Value: %s %s", Value.Key, Value.Value)
mpagenko3af1f032020-06-10 08:53:41 +000099
100 // swap out tokens with specific data
101 mibTmpString, _ := kvstore.ToString(Value.Value)
102 mibTmpString2 := strings.Replace(mibTmpString, "%SERIAL_NUMBER%", onuDeviceEntry.serialNumber, -1)
103 mibTmpString = strings.Replace(mibTmpString2, "%MAC_ADDRESS%", onuDeviceEntry.macAddress, -1)
104 mibTmpBytes := []byte(mibTmpString)
105 logger.Debugf("MibSync FSM - MibTemplate tokens swapped out: %s", mibTmpBytes)
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000106
107 var fistLevelMap map[string]interface{}
108 if err = json.Unmarshal(mibTmpBytes, &fistLevelMap); err != nil {
109 logger.Error("MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": onuDeviceEntry.deviceID})
110 } else {
111 for fistLevelKey, firstLevelValue := range fistLevelMap {
112 logger.Debugw("MibSync FSM - fistLevelKey", log.Fields{"fistLevelKey": fistLevelKey})
113 if uint16ValidNumber, err := strconv.ParseUint(fistLevelKey, 10, 16); err == nil {
114 meClassId := me.ClassID(uint16ValidNumber)
115 logger.Debugw("MibSync FSM - fistLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
116 if IsSupportedClassId(meClassId) {
117 logger.Debugw("MibSync FSM - fistLevelKey is a supported classId", log.Fields{"meClassId": meClassId})
118 secondLevelMap := firstLevelValue.(map[string]interface{})
119 for secondLevelKey, secondLevelValue := range secondLevelMap {
120 logger.Debugw("MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
121 if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
122 meEntityId := uint16(uint16ValidNumber)
123 logger.Debugw("MibSync FSM - secondLevelKey is a numberand a valid EntityId", log.Fields{"meEntityId": meEntityId})
124 thirdLevelMap := secondLevelValue.(map[string]interface{})
125 for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
126 if thirdLevelKey == "attributes" {
127 logger.Debugw("MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
128 attributesMap := thirdLevelValue.(map[string]interface{})
129 logger.Debugw("MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
130 onuDeviceEntry.pOnuDB.StoreMe(meClassId, meEntityId, attributesMap)
131 meStoredFromTemplate = true
132 }
133 }
134 }
135 }
136 }
137 }
138 }
139 }
140 } else {
141 logger.Debugw("No MIB template found", log.Fields{"device-id": onuDeviceEntry.deviceID})
142 }
143 } else {
144 logger.Errorf("Get from kvstore operation failed for path %s", Path)
145 }
146 if meStoredFromTemplate {
147 logger.Debug("MibSync FSM - valid MEs stored from template")
148 onuDeviceEntry.pOnuDB.LogMeDb()
149 fsmMsg = LoadMibTemplateOk
150 } else {
151 logger.Debug("MibSync FSM - no valid MEs stored from template - perform MIB-upload!")
152 fsmMsg = LoadMibTemplateFailed
153 }
154
155 mibSyncMsg := Message{
156 Type: TestMsg,
157 Data: TestMessage{
158 TestMessageVal: fsmMsg,
159 },
160 }
161 onuDeviceEntry.pMibUploadFsm.commChan <- mibSyncMsg
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000162}
163
164func (onuDeviceEntry *OnuDeviceEntry) enterUploadingState(e *fsm.Event) {
165 logger.Debugw("MibSync FSM", log.Fields{"send mibReset in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
166 onuDeviceEntry.PDevOmciCC.sendMibReset(context.TODO(), ConstDefaultOmciTimeout, true)
167}
168
169func (onuDeviceEntry *OnuDeviceEntry) enterInSyncState(e *fsm.Event) {
170 logger.Debugw("MibSync FSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
171 onuDeviceEntry.transferSystemEvent(MibDatabaseSync)
172}
173
174func (onuDeviceEntry *OnuDeviceEntry) enterExaminingMdsState(e *fsm.Event) {
175 logger.Debugw("MibSync FSM", log.Fields{"Start GetMds processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
176 logger.Debug("function not implemented yet")
177}
178
179func (onuDeviceEntry *OnuDeviceEntry) enterResynchronizingState(e *fsm.Event) {
180 logger.Debugw("MibSync FSM", log.Fields{"Start MibResync processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
181 logger.Debug("function not implemented yet")
182}
183
184func (onuDeviceEntry *OnuDeviceEntry) enterAuditingState(e *fsm.Event) {
185 logger.Debugw("MibSync FSM", log.Fields{"Start MibResync processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
186 logger.Debug("function not implemented yet")
187}
188
189func (onuDeviceEntry *OnuDeviceEntry) enterOutOfSyncState(e *fsm.Event) {
190 logger.Debugw("MibSync FSM", log.Fields{"Start MibReconcile processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
191 logger.Debug("function not implemented yet")
192}
193
194func (onuDeviceEntry *OnuDeviceEntry) ProcessMibSyncMessages( /*ctx context.Context*/ ) {
195 logger.Debugw("MibSync Msg", log.Fields{"Start routine to process OMCI-messages for device-id": onuDeviceEntry.deviceID})
196loop:
197 for {
198 select {
199 // case <-ctx.Done():
200 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": onuDeviceEntry.deviceID})
201 // break loop
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000202 case message, ok := <-onuDeviceEntry.pMibUploadFsm.commChan:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000203 if !ok {
204 logger.Info("MibSync Msg", log.Fields{"Message couldn't be read from channel for device-id": onuDeviceEntry.deviceID})
205 break loop
206 }
207 logger.Debugw("MibSync Msg", log.Fields{"Received message on ONU MibSyncChan for device-id": onuDeviceEntry.deviceID})
208
209 switch message.Type {
210 case TestMsg:
211 msg, _ := message.Data.(TestMessage)
212 onuDeviceEntry.handleTestMsg(msg)
213 case OMCI:
214 msg, _ := message.Data.(OmciMessage)
215 onuDeviceEntry.handleOmciMessage(msg)
216 default:
217 logger.Warn("MibSync Msg", log.Fields{"Unknown message type received for device-id": onuDeviceEntry.deviceID, "message.Type": message.Type})
218 }
219 }
220 }
221 logger.Info("MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": onuDeviceEntry.deviceID})
222 // TODO: only this action?
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000223 onuDeviceEntry.pMibUploadFsm.pFsm.Event("stop")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000224}
225
226func (onuDeviceEntry *OnuDeviceEntry) handleTestMsg(msg TestMessage) {
227
228 logger.Debugw("MibSync Msg", log.Fields{"TestMessage received for device-id": onuDeviceEntry.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
229
230 switch msg.TestMessageVal {
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000231 case LoadMibTemplateFailed:
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000232 onuDeviceEntry.pMibUploadFsm.pFsm.Event("upload_mib")
233 logger.Debugw("MibSync Msg", log.Fields{"state": string(onuDeviceEntry.pMibUploadFsm.pFsm.Current())})
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000234 case LoadMibTemplateOk:
235 onuDeviceEntry.pMibUploadFsm.pFsm.Event("success")
236 logger.Debugw("MibSync Msg", log.Fields{"state": string(onuDeviceEntry.pMibUploadFsm.pFsm.Current())})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000237 default:
238 logger.Warn("MibSync Msg", log.Fields{"Unknown message type received for device-id": onuDeviceEntry.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
239 }
240}
241
242func (onuDeviceEntry *OnuDeviceEntry) handleOmciMessage(msg OmciMessage) {
243
244 logger.Debugw("MibSync Msg", log.Fields{"OmciMessage received for device-id": onuDeviceEntry.deviceID,
245 "msgType": msg.OmciMsg.MessageType})
246
247 //further analysis could be done here based on msg.OmciMsg.Payload, e.g. verification of error code ...
248 switch msg.OmciMsg.MessageType {
249 case omci.MibResetResponseType:
250 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibResetResponse)
251 if msgLayer == nil {
252 logger.Error("Omci Msg layer could not be detected")
253 return
254 }
255 msgObj, msgOk := msgLayer.(*omci.MibResetResponse)
256 if !msgOk {
257 logger.Error("Omci Msg layer could not be assigned")
258 return
259 }
260 logger.Debugw("MibResetResponse Data", log.Fields{"data-fields": msgObj})
261 if msgObj.Result != me.Success {
262 logger.Errorw("Omci MibResetResponse Error - strange - what to do?", log.Fields{"Error": msgObj.Result})
263 return
264 }
265 onuDeviceEntry.PDevOmciCC.sendMibUpload(context.TODO(), ConstDefaultOmciTimeout, true)
266 case omci.MibUploadResponseType:
267 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadResponse)
268 if msgLayer == nil {
269 logger.Error("Omci Msg layer could not be detected")
270 return
271 }
272 msgObj, msgOk := msgLayer.(*omci.MibUploadResponse)
273 if !msgOk {
274 logger.Error("Omci Msg layer could not be assigned")
275 return
276 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000277 logger.Debugw("MibUploadResponse Data for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000278 /* to be verified / reworked !!! */
279 onuDeviceEntry.PDevOmciCC.uploadNoOfCmds = msgObj.NumberOfCommands
280 if onuDeviceEntry.PDevOmciCC.uploadSequNo < onuDeviceEntry.PDevOmciCC.uploadNoOfCmds {
281 onuDeviceEntry.PDevOmciCC.sendMibUploadNext(context.TODO(), ConstDefaultOmciTimeout, true)
282 } else {
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000283 logger.Error("Invalid number of commands received for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "uploadNoOfCmds": onuDeviceEntry.PDevOmciCC.uploadNoOfCmds})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000284 //TODO right action?
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000285 onuDeviceEntry.pMibUploadFsm.pFsm.Event("timeout")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000286 }
287 case omci.MibUploadNextResponseType:
288 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadNextResponse)
289 if msgLayer == nil {
290 logger.Error("Omci Msg layer could not be detected")
291 return
292 }
293 msgObj, msgOk := msgLayer.(*omci.MibUploadNextResponse)
294 if !msgOk {
295 logger.Error("Omci Msg layer could not be assigned")
296 return
297 }
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000298 logger.Debugw("MibUploadNextResponse Data for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
299
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000300 meClassId := msgObj.ReportedME.GetClassID()
301 meEntityId := msgObj.ReportedME.GetEntityID()
302 meAttributes := msgObj.ReportedME.GetAttributeValueMap()
303
304 onuDeviceEntry.pOnuDB.StoreMe(meClassId, meEntityId, meAttributes)
Holger Hildebrandt24d51952020-05-04 14:03:42 +0000305
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000306 if onuDeviceEntry.PDevOmciCC.uploadSequNo < onuDeviceEntry.PDevOmciCC.uploadNoOfCmds {
307 onuDeviceEntry.PDevOmciCC.sendMibUploadNext(context.TODO(), ConstDefaultOmciTimeout, true)
308 } else {
309 //TODO
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000310 onuDeviceEntry.pOnuDB.LogMeDb()
311 onuDeviceEntry.pMibUploadFsm.pFsm.Event("success")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000312 }
313 }
314}
315
Holger Hildebrandtccd390c2020-05-29 13:49:04 +0000316func (onuDeviceEntry *OnuDeviceEntry) newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
317 logger.Infow("kv-store-type", log.Fields{"store": storeType})
318 switch storeType {
319 case "consul":
320 return kvstore.NewConsulClient(address, timeout)
321 case "etcd":
322 return kvstore.NewEtcdClient(address, timeout, log.FatalLevel)
323 }
324 return nil, errors.New("unsupported-kv-store")
325}
326
327func (onuDeviceEntry *OnuDeviceEntry) SetKVClient(backend string, Host string, Port int, BasePathKvStore string) *db.Backend {
328 logger.Debugw("SetKVClient with params:", log.Fields{"backend": backend, "Host": Host, "Port": Port,
329 "BasePathKvStore": BasePathKvStore, "deviceId": onuDeviceEntry.deviceID})
330
331 addr := Host + ":" + strconv.Itoa(Port)
332 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
333 // issue between kv store and backend , core is not calling NewBackend directly
334 kvClient, err := onuDeviceEntry.newKVClient(backend, addr, KvstoreTimeout)
335 if err != nil {
336 logger.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
337 return nil
338 }
339
340 kvbackend := &db.Backend{
341 Client: kvClient,
342 StoreType: backend,
343 Host: Host,
344 Port: Port,
345 Timeout: KvstoreTimeout,
346 PathPrefix: BasePathKvStore}
347
348 return kvbackend
349}
350
351func IsSupportedClassId(meClassId me.ClassID) bool {
352 for _, v := range supportedClassIds {
353 if v == meClassId {
354 return true
355 }
356 }
357 return false
358}
359
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000360func (onuDeviceEntry *OnuDeviceEntry) MibDbVolatileDict() error {
361 logger.Debug("MibVolatileDict- running from default Entry code")
362 return errors.New("not_implemented")
363}
364
365// func (onuDeviceEntry *OnuDeviceEntry) MibTemplateTask() error {
366// return errors.New("not_implemented")
367// }
368// func (onuDeviceEntry *OnuDeviceEntry) MibUploadTask() error {
369// return errors.New("not_implemented")
370// }
371// func (onuDeviceEntry *OnuDeviceEntry) GetMdsTask() error {
372// return errors.New("not_implemented")
373// }
374// func (onuDeviceEntry *OnuDeviceEntry) MibResyncTask() error {
375// return errors.New("not_implemented")
376// }
377// func (onuDeviceEntry *OnuDeviceEntry) MibReconcileTask() error {
378// return errors.New("not_implemented")
379// }