blob: c712b1d83c76a5caa61260f9d9936d860174fecd [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +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
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000017//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
Holger Hildebrandtfa074992020-03-27 15:42:06 +000019
20import (
21 "container/list"
22 "context"
23 "encoding/binary"
24 "encoding/hex"
25 "errors"
26 "sync"
27
28 //"time"
29
30 "github.com/google/gopacket"
31 // TODO!!! Some references could be resolved auto, but some need specific context ....
32 gp "github.com/google/gopacket"
33
34 "github.com/opencord/omci-lib-go"
35 me "github.com/opencord/omci-lib-go/generated"
36 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
37
38 //"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
39 "github.com/opencord/voltha-lib-go/v3/pkg/log"
40 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
41 //"github.com/opencord/voltha-protos/v3/go/openflow_13"
42 //"github.com/opencord/voltha-protos/v3/go/voltha"
43)
44
45const ConstDefaultOmciTimeout = 10 // ( 3 ?) Seconds
46
47//CallbackPair to be used for ReceiveCallback init
48type CallbackPair struct {
49 cbKey uint16
50 cbFunction func(*omci.OMCI, *gp.Packet) error
51}
52
53type omciTransferStructure struct {
54 txFrame []byte
55 timeout int
56 retry int
57 highPrio bool
58}
59
60//OmciCC structure holds information needed for OMCI communication (to/from OLT Adapter)
61type OmciCC struct {
62 enabled bool
63 pOnuDeviceEntry *OnuDeviceEntry
64 deviceID string
65 pBaseDeviceHandler *DeviceHandler
66 coreProxy adapterif.CoreProxy
67 adapterProxy adapterif.AdapterProxy
68 supportExtMsg bool
69 //txRequest
70 //rxResponse
71 //pendingRequest
72 txFrames, txOnuFrames uint32
73 rxFrames, rxOnuFrames, rxOnuDiscards uint32
74
75 // OMCI params
76 mutexTid sync.Mutex
77 tid uint16
78 mutexHpTid sync.Mutex
79 hpTid uint16
80 uploadSequNo uint16
81 uploadNoOfCmds uint16
82
83 mutexTxQueue sync.Mutex
84 txQueue *list.List
85 mutexRxSchedMap sync.Mutex
86 rxSchedulerMap map[uint16]func(*omci.OMCI, *gp.Packet) error
87}
88
89//NewOmciCC constructor returns a new instance of a OmciCC
90//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
91func NewOmciCC(ctx context.Context, onu_device_entry *OnuDeviceEntry,
92 device_id string, device_handler *DeviceHandler,
93 core_proxy adapterif.CoreProxy, adapter_proxy adapterif.AdapterProxy) *OmciCC {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000094 logger.Infow("init-omciCC", log.Fields{"deviceId": device_id})
Holger Hildebrandtfa074992020-03-27 15:42:06 +000095 var omciCC OmciCC
96 omciCC.enabled = false
97 omciCC.pOnuDeviceEntry = onu_device_entry
98 omciCC.deviceID = device_id
99 omciCC.pBaseDeviceHandler = device_handler
100 omciCC.coreProxy = core_proxy
101 omciCC.adapterProxy = adapter_proxy
102 omciCC.supportExtMsg = false
103 omciCC.txFrames = 0
104 omciCC.txOnuFrames = 0
105 omciCC.rxFrames = 0
106 omciCC.rxOnuFrames = 0
107 omciCC.rxOnuDiscards = 0
108 omciCC.tid = 0x1
109 omciCC.hpTid = 0x8000
110 omciCC.uploadSequNo = 0
111 omciCC.uploadNoOfCmds = 0
112
113 omciCC.txQueue = list.New()
114 omciCC.rxSchedulerMap = make(map[uint16]func(*omci.OMCI, *gp.Packet) error)
115
116 return &omciCC
117}
118
119// Rx handler for omci messages
120func (oo *OmciCC) ReceiveOnuMessage(ctx context.Context, omciMsg *omci.OMCI) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000121 logger.Debugw("rx-onu-autonomous-message", log.Fields{"omciMsgType": omciMsg.MessageType,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000122 "payload": hex.EncodeToString(omciMsg.Payload)})
123 /*
124 msgType = rxFrame.fields["message_type"] //assumed OmciOperationsValue
125 rxOnuFrames++
126
127 switch msgType {
128 case AlarmNotification:
129 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000130 logger.Info("Unhandled: received-onu-alarm-message")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000131 // python code was:
132 //if msg_type == EntityOperations.AlarmNotification.value:
133 // topic = OMCI_CC.event_bus_topic(self._device_id, RxEvent.Alarm_Notification)
134 // self.reactor.callLater(0, self.event_bus.publish, topic, msg)
135 //
136 return errors.New("RxAlarmNotification unimplemented")
137 }
138 case AttributeValueChange:
139 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000140 logger.Info("Unhandled: received-attribute-value-change")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000141 // python code was:
142 //elif msg_type == EntityOperations.AttributeValueChange.value:
143 // topic = OMCI_CC.event_bus_topic(self._device_id, RxEvent.AVC_Notification)
144 // self.reactor.callLater(0, self.event_bus.publish, topic, msg)
145 //
146 return errors.New("RxAttributeValueChange unimplemented")
147 }
148 case TestResult:
149 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000150 logger.Info("Unhandled: received-test-result")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000151 // python code was:
152 //elif msg_type == EntityOperations.TestResult.value:
153 // topic = OMCI_CC.event_bus_topic(self._device_id, RxEvent.Test_Result)
154 // self.reactor.callLater(0, self.event_bus.publish, topic, msg)
155 //
156 return errors.New("RxTestResult unimplemented")
157 }
158 default:
159 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000160 logger.Errorw("rx-onu-unsupported-autonomous-message", log.Fields{"msgType": msgType})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000161 rxOnuDiscards++
162 return errors.New("RxOnuMsgType unimplemented")
163 }
164 }
165 */
166 return errors.New("ReceiveOnuMessage unimplemented")
167}
168
169// Rx handler for onu messages
170// e.g. would call ReceiveOnuMessage() in case of TID=0 or Action=test ...
171func (oo *OmciCC) ReceiveMessage(ctx context.Context, rxMsg []byte) error {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000172 //logger.Debugw("cc-receive-omci-message", log.Fields{"RxOmciMessage-x2s": hex.EncodeToString(rxMsg)})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000173 if len(rxMsg) >= 44 { // then it should normally include the BaseFormat trailer Len
174 // NOTE: autocorrection only valid for OmciBaseFormat, which is not specifically verified here!!!
175 // (am extendedFormat message could be destroyed this way!)
176 trailerLenData := rxMsg[42:44]
177 trailerLen := binary.BigEndian.Uint16(trailerLenData)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000178 logger.Infow("omci-received-trailer-len", log.Fields{"Length": trailerLen})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000179 if trailerLen != 40 { // invalid base Format entry -> autocorrect
180 binary.BigEndian.PutUint16(rxMsg[42:44], 40)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000181 logger.Debug("cc-corrected-omci-message: trailer len inserted")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000182 }
183 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000184 logger.Errorw("received omci-message to small for OmciBaseFormat - abort", log.Fields{"Length": len(rxMsg)})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000185 return errors.New("RxOmciMessage to small for BaseFormat")
186 }
187
188 packet := gopacket.NewPacket(rxMsg, omci.LayerTypeOMCI, gopacket.NoCopy)
189 if packet == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000190 logger.Error("omci-message could not be decoded")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000191 return errors.New("could not decode rxMsg as OMCI")
192 }
193 omciLayer := packet.Layer(omci.LayerTypeOMCI)
194 if omciLayer == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000195 logger.Error("omci-message could not decode omci layer")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000196 return errors.New("could not decode omci layer")
197 }
198 omciMsg, ok := omciLayer.(*omci.OMCI)
199 if !ok {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000200 logger.Error("omci-message could not assign omci layer")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000201 return errors.New("could not assign omci layer")
202 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000203 logger.Debugw("omci-message-decoded:", log.Fields{"omciMsgType": omciMsg.MessageType,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000204 "transCorrId": omciMsg.TransactionID, "DeviceIdent": omciMsg.DeviceIdentifier})
205 if byte(omciMsg.MessageType) & ^me.AK == 0 {
206 // Not a response
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000207 logger.Debug("RxMsg is no Omci Response Message")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000208 if omciMsg.TransactionID == 0 {
209 return oo.ReceiveOnuMessage(ctx, omciMsg)
210 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000211 logger.Errorw("Unexpected TransCorrId != 0 not accepted for autonomous messages",
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000212 log.Fields{"msgType": omciMsg.MessageType, "payload": hex.EncodeToString(omciMsg.Payload)})
213 return errors.New("Autonomous Omci Message with TranSCorrId != 0 not acccepted")
214 }
215 } else {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000216 logger.Debug("RxMsg is a Omci Response Message: try to schedule it to the requester")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000217 oo.mutexRxSchedMap.Lock()
218 rxCallback, ok := oo.rxSchedulerMap[omciMsg.TransactionID]
219 if ok && rxCallback != nil {
220 //disadvantage of decoupling: error verification made difficult, but anyway the question is
221 // how to react on erroneous frame reception, maybe can simply be ignored
222 go rxCallback(omciMsg, &packet)
223 // having posted the response the request is regarded as 'done'
224 delete(oo.rxSchedulerMap, omciMsg.TransactionID)
225 oo.mutexRxSchedMap.Unlock()
226 } else {
227 oo.mutexRxSchedMap.Unlock()
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000228 logger.Error("omci-message-response for not registered transCorrId")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000229 return errors.New("could not find registered response handler tor transCorrId")
230 }
231 }
232
233 return nil
234 /* py code was:
235 Receive and OMCI message from the proxy channel to the OLT.
236
237 Call this from your ONU Adapter on a new OMCI Rx on the proxy channel
238 :param msg: (str) OMCI binary message (used as input to Scapy packet decoder)
239 """
240 if not self.enabled:
241 return
242
243 try:
244 now = arrow.utcnow()
245 d = None
246
247 # NOTE: Since we may need to do an independent ME map on a per-ONU basis
248 # save the current value of the entity_id_to_class_map, then
249 # replace it with our custom one before decode, and then finally
250 # restore it later. Tried other ways but really made the code messy.
251 saved_me_map = omci_entities.entity_id_to_class_map
252 omci_entities.entity_id_to_class_map = self._me_map
253
254 try:
255 rx_frame = msg if isinstance(msg, OmciFrame) else OmciFrame(msg)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000256 self.logger.debug('recv-omci-msg', omci_msg=hexlify(msg))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000257 except KeyError as e:
258 # Unknown, Unsupported, or vendor-specific ME. Key is the unknown classID
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000259 self.logger.debug('frame-decode-key-error', omci_msg=hexlify(msg), e=e)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000260 rx_frame = self._decode_unknown_me(msg)
261 self._rx_unknown_me += 1
262
263 except Exception as e:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000264 self.logger.exception('frame-decode', omci_msg=hexlify(msg), e=e)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000265 return
266
267 finally:
268 omci_entities.entity_id_to_class_map = saved_me_map # Always restore it.
269
270 rx_tid = rx_frame.fields['transaction_id']
271 msg_type = rx_frame.fields['message_type']
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000272 self.logger.debug('Received message for rx_tid', rx_tid = rx_tid, msg_type = msg_type)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000273 # Filter the Test Result frame and route through receive onu
274 # message method.
275 if rx_tid == 0 or msg_type == EntityOperations.TestResult.value:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000276 self.logger.debug('Receive ONU message', rx_tid=0)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000277 return self._receive_onu_message(rx_frame)
278
279 # Previously unreachable if this is the very first round-trip Rx or we
280 # have been running consecutive errors
281 if self._rx_frames == 0 or self._consecutive_errors != 0:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000282 self.logger.debug('Consecutive errors for rx', err = self._consecutive_errors)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000283 self.reactor.callLater(0, self._publish_connectivity_event, True)
284
285 self._rx_frames += 1
286 self._consecutive_errors = 0
287
288 try:
289 high_priority = self._tid_is_high_priority(rx_tid)
290 index = self._get_priority_index(high_priority)
291
292 # (timestamp, defer, frame, timeout, retry, delayedCall)
293 last_tx_tuple = self._tx_request[index]
294
295 if last_tx_tuple is None or \
296 last_tx_tuple[OMCI_CC.REQUEST_FRAME].fields.get('transaction_id') != rx_tid:
297 # Possible late Rx on a message that timed-out
298 if last_tx_tuple:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000299 self.logger.debug('Unknown message', rx_tid=rx_tid,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000300 tx_id=last_tx_tuple[OMCI_CC.REQUEST_FRAME].fields.get('transaction_id'))
301 self._rx_unknown_tid += 1
302 self._rx_late += 1
303 return
304
305 ts, d, tx_frame, timeout, retry, dc = last_tx_tuple
306 if dc is not None and not dc.cancelled and not dc.called:
307 dc.cancel()
308
309 _secs = self._update_rx_tx_stats(now, ts)
310
311 # Late arrival already serviced by a timeout?
312 if d.called:
313 self._rx_late += 1
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000314 self.logger.debug('Serviced by timeout. Late arrival', rx_late = self._rx_late)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000315 return
316
317 except Exception as e:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000318 self.logger.exception('frame-match', msg=hexlify(msg), e=e)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000319 if d is not None:
320 return d.errback(failure.Failure(e))
321 return
322
323 # Publish Rx event to listeners in a different task
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000324 self.logger.debug('Publish rx event', rx_tid = rx_tid,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000325 tx_tid = tx_frame.fields['transaction_id'])
326 reactor.callLater(0, self._publish_rx_frame, tx_frame, rx_frame)
327
328 # begin success callback chain (will cancel timeout and queue next Tx message)
329 self._rx_response[index] = rx_frame
330 d.callback(rx_frame)
331
332 except Exception as e:
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000333 self.logger.exception('rx-msg', e=e)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000334 */
335}
336
337func (oo *OmciCC) PublishRxResponseFrame(ctx context.Context, txFrame []byte, rxFrame []byte) error {
338 return errors.New("PublishRxResponseFrame unimplemented")
339 /*
340 def _publish_rx_frame(self, tx_frame, rx_frame):
341 */
342}
343
344//Queue the OMCI Frame for a transmit to the ONU via the proxy_channel
345func (oo *OmciCC) Send(ctx context.Context, txFrame []byte, timeout int, retry int, highPrio bool,
346 receiveCallbackPair CallbackPair) error {
347
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000348 logger.Debugw("register-response-callback:", log.Fields{"for TansCorrId": receiveCallbackPair.cbKey})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000349 // it could be checked, if the callback keay is already registered - but simply overwrite may be acceptable ...
350 oo.mutexRxSchedMap.Lock()
351 oo.rxSchedulerMap[receiveCallbackPair.cbKey] = receiveCallbackPair.cbFunction
352 oo.mutexRxSchedMap.Unlock()
353
354 //just use a simple list for starting - might need some more effort, especially for multi source write access
355 omciTxRequest := omciTransferStructure{
356 txFrame,
357 timeout,
358 retry,
359 highPrio,
360 }
361 oo.mutexTxQueue.Lock()
362 oo.txQueue.PushBack(omciTxRequest) // enqueue
363 oo.mutexTxQueue.Unlock()
364
365 // for first test just bypass and send directly:
366 go oo.sendNextRequest(ctx)
367 return nil
368}
369
370//Pull next tx request and send it
371func (oo *OmciCC) sendNextRequest(ctx context.Context) error {
372 // return errors.New("sendNextRequest unimplemented")
373
374 // just try to get something transferred !!
375 // avoid accessing the txQueue from parallel send requests
376 // block parallel omci send requests at least until SendIAP is 'committed'
377 // that should be feasible for an onu instance as on OMCI anyway window size 1 is assumed
378 oo.mutexTxQueue.Lock()
379 for oo.txQueue.Len() > 0 {
380 queueElement := oo.txQueue.Front() // First element
381 omciTxRequest := queueElement.Value.(omciTransferStructure)
382 /* compare olt device handler code:
383 func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000384 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000385 var deviceType string
386 var deviceID string
387 var proxyDeviceID string
388
389 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
390
391 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
392
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000393 logger.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000394 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
395 kwargs := make(map[string]interface{})
396 kwargs["onu_id"] = omciInd.OnuId
397 kwargs["parent_port_no"] = ponPort
398
399 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
400 if err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000401 logger.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000402 return
403 }
404 deviceType = onuDevice.Type
405 deviceID = onuDevice.Id
406 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
407 //if not exist in cache, then add to cache.
408 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
409 } else {
410 //found in cache
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000411 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000412 deviceType = onuInCache.(*OnuDevice).deviceType
413 deviceID = onuInCache.(*OnuDevice).deviceID
414 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
415 }
416 */
417 /* and compare onu_adapter py code:
418 omci_msg = InterAdapterOmciMessage(
419 message=bytes(frame),
420 proxy_address=self._proxy_address,
421 connect_status=self._device.connect_status)
422
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000423 self.logger.debug('sent-omci-msg', tid=tx_tid, omci_msg=hexlify(bytes(frame)))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000424
425 yield self._adapter_proxy.send_inter_adapter_message(
426 msg=omci_msg,
427 type=InterAdapterMessageType.OMCI_REQUEST,
428 from_adapter=self._device.type,
429 to_adapter=self._proxy_address.device_type,
430 to_device_id=self._device_id,
431 proxy_device_id=self._proxy_address.device_id
432 )
433 */
434 device, err := oo.coreProxy.GetDevice(ctx,
435 oo.pBaseDeviceHandler.deviceID, oo.deviceID) //parent, child
436 if err != nil || device == nil {
437 /*TODO: needs to handle error scenarios */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000438 logger.Errorw("Failed to fetch device", log.Fields{"err": err, "ParentId": oo.pBaseDeviceHandler.deviceID,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000439 "ChildId": oo.deviceID})
440 return errors.New("failed to fetch device")
441 }
442
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000443 logger.Debugw("omci-message-sending", log.Fields{"fromDeviceType": oo.pBaseDeviceHandler.DeviceType,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000444 "toDeviceType": oo.pBaseDeviceHandler.ProxyAddressType,
445 "onuDeviceID": oo.deviceID, "proxyDeviceID": oo.pBaseDeviceHandler.ProxyAddressID})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000446 logger.Debugw("omci-message-to-send:",
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000447 log.Fields{"TxOmciMessage": hex.EncodeToString(omciTxRequest.txFrame)})
448
449 omciMsg := &ic.InterAdapterOmciMessage{Message: omciTxRequest.txFrame}
450 if sendErr := oo.adapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
451 ic.InterAdapterMessageType_OMCI_REQUEST,
452 //fromType,toType,toDevId, ProxyDevId
453 oo.pBaseDeviceHandler.DeviceType, oo.pBaseDeviceHandler.ProxyAddressType,
454 oo.deviceID, oo.pBaseDeviceHandler.ProxyAddressID, ""); sendErr != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000455 logger.Errorw("send omci request error", log.Fields{"error": sendErr})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000456 return sendErr
457 }
458 oo.txQueue.Remove(queueElement) // Dequeue
459 }
460 oo.mutexTxQueue.Unlock()
461 return nil
462}
463
464func (oo *OmciCC) GetNextTid(highPriority bool) uint16 {
465 var next uint16
466 if highPriority {
467 oo.mutexTid.Lock()
468 next = oo.hpTid
469 oo.hpTid += 1
470 if oo.hpTid < 0x8000 {
471 oo.hpTid = 0x8000
472 }
473 oo.mutexTid.Unlock()
474 } else {
475 oo.mutexHpTid.Lock()
476 next = oo.tid
477 oo.tid += 1
478 if oo.tid >= 0x8000 {
479 oo.tid = 1
480 }
481 oo.mutexHpTid.Unlock()
482 }
483 return next
484}
485
486// ###################################################################################
487// # utility methods provided to work on OMCI messages
488func serialize(msgType omci.MessageType, request gopacket.SerializableLayer, tid uint16) ([]byte, error) {
489 omciLayer := &omci.OMCI{
490 TransactionID: tid,
491 MessageType: msgType,
492 }
493 var options gopacket.SerializeOptions
494 options.FixLengths = true
495
496 buffer := gopacket.NewSerializeBuffer()
497 err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
498 if err != nil {
499 return nil, err
500 }
501 return buffer.Bytes(), nil
502}
503
504func hexEncode(omciPkt []byte) ([]byte, error) {
505 dst := make([]byte, hex.EncodedLen(len(omciPkt)))
506 hex.Encode(dst, omciPkt)
507 return dst, nil
508}
509
510// ###################################################################################
511// # MIB Action shortcuts - still dummies - TODO!!!!!
512
513//supply a response handler for the MibSync omci response messages
514func (oo *OmciCC) receiveMibSyncResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
515
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000516 logger.Debugw("mib-sync-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000517 "transCorrId": omciMsg.TransactionID, "deviceId": oo.deviceID})
518
519 if oo.pOnuDeviceEntry == nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000520 logger.Error("Abort Receive MibSync OMCI, DeviceEntryPointer is nil")
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000521 return errors.New("DeviceEntryPointer is nil")
522 }
523
524 // no further test on SeqNo is done here, assignment from rxScheduler is trusted
525 // MibSync responses are simply transferred via deviceEntry to MibSync, no specific analysis here
526 mibSyncMsg := Message{
527 Type: OMCI,
528 Data: OmciMessage{
529 OmciMsg: omciMsg,
530 OmciPacket: packet,
531 },
532 }
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000533 //logger.Debugw("Message to be sent into channel:", log.Fields{"mibSyncMsg": mibSyncMsg})
Holger Hildebrandt9ac0d0f2020-05-13 11:22:02 +0000534 (*oo.pOnuDeviceEntry).pMibUploadFsm.commChan <- mibSyncMsg
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000535
536 return nil
537}
538
539func (oo *OmciCC) sendMibReset(ctx context.Context, timeout int, highPrio bool) error {
540
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000541 logger.Debugw("send MibReset-msg to:", log.Fields{"deviceId": oo.deviceID})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000542 request := &omci.MibResetRequest{
543 MeBasePacket: omci.MeBasePacket{
544 EntityClass: me.OnuDataClassID,
545 },
546 }
547 tid := oo.GetNextTid(highPrio)
548 pkt, err := serialize(omci.MibResetRequestType, request, tid)
549 if err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000550 logger.Errorw("Cannot serialize MibResetRequest", log.Fields{"Err": err})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000551 return err
552 }
553 omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
554 return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
555}
556
557func (oo *OmciCC) sendMibUpload(ctx context.Context, timeout int, highPrio bool) error {
558
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000559 logger.Debugw("send MibUpload-msg to:", log.Fields{"deviceId": oo.deviceID})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000560 request := &omci.MibUploadRequest{
561 MeBasePacket: omci.MeBasePacket{
562 EntityClass: me.OnuDataClassID,
563 },
564 }
565 tid := oo.GetNextTid(highPrio)
566 pkt, err := serialize(omci.MibUploadRequestType, request, tid)
567 if err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000568 logger.Errorw("Cannot serialize MibUploadRequest", log.Fields{"Err": err})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000569 return err
570 }
571 oo.uploadSequNo = 0
572 oo.uploadNoOfCmds = 0
573
574 omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
575 return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
576}
577
578func (oo *OmciCC) sendMibUploadNext(ctx context.Context, timeout int, highPrio bool) error {
579
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000580 logger.Debugw("send MibUploadNext-msg to:", log.Fields{"deviceId": oo.deviceID, "uploadSequNo": oo.uploadSequNo})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000581 request := &omci.MibUploadNextRequest{
582 MeBasePacket: omci.MeBasePacket{
583 EntityClass: me.OnuDataClassID,
584 },
585 CommandSequenceNumber: oo.uploadSequNo,
586 }
587 tid := oo.GetNextTid(highPrio)
588 pkt, err := serialize(omci.MibUploadNextRequestType, request, tid)
589 if err != nil {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000590 logger.Errorw("Cannot serialize MibUploadNextRequest", log.Fields{"Err": err})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000591 return err
592 }
593 oo.uploadSequNo++
594
595 omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
596 return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
597}
598
599/* py code example
600...
601def send_mib_upload(self, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
602 frame = OntDataFrame().mib_upload()
603 return self.send(frame, timeout=timeout, high_priority=high_priority)
604
605def send_mib_upload_next(self, seq_no, timeout=DEFAULT_OMCI_TIMEOUT, high_priority=False):
606 frame = OntDataFrame(sequence_number=seq_no).mib_upload_next()
607 return self.send(frame, timeout=timeout, high_priority=high_priority)
608...
609*/