blob: 5a5e64d516beaf9d9f6fb51b7f6d98bf88f48400 [file] [log] [blame]
Chip Boling610117d2021-09-09 11:24:34 -05001/*
2 * Copyright (c) 2018 - present. Boling Consulting Solutions (bcsw.net)
3 * Copyright 2020-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package omci
19
20import (
21 "encoding/binary"
22 "errors"
23 "fmt"
24 "github.com/google/gopacket"
25 me "github.com/opencord/omci-lib-go/generated"
26)
27
28type GetAllAlarmsRequest struct {
29 MeBasePacket
30 AlarmRetrievalMode byte
31}
32
33func (omci *GetAllAlarmsRequest) String() string {
34 return fmt.Sprintf("%v, Retrieval Mode: %v",
35 omci.MeBasePacket.String(), omci.AlarmRetrievalMode)
36}
37
38// LayerType returns LayerTypeGetAllAlarmsRequest
39func (omci *GetAllAlarmsRequest) LayerType() gopacket.LayerType {
40 return LayerTypeGetAllAlarmsRequest
41}
42
43// CanDecode returns the set of layer types that this DecodingLayer can decode
44func (omci *GetAllAlarmsRequest) CanDecode() gopacket.LayerClass {
45 return LayerTypeGetAllAlarmsRequest
46}
47
48// NextLayerType returns the layer type contained by this DecodingLayer.
49func (omci *GetAllAlarmsRequest) NextLayerType() gopacket.LayerType {
50 return gopacket.LayerTypePayload
51}
52
53// DecodeFromBytes decodes the given bytes of a Get All Alarms Request into this layer
54func (omci *GetAllAlarmsRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
55 // Common ClassID/EntityID decode in msgBase
56 var hdrSize int
57 if omci.Extended {
58 //start here
59 hdrSize = 6 + 1
60 } else {
61 hdrSize = 4 + 1
62 }
63 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
64 if err != nil {
65 return err
66 }
67 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
68 me.ParamData{EntityID: omci.EntityInstance})
69 if omciErr.StatusCode() != me.Success {
70 return omciErr.GetError()
71 }
72 // ME needs to support Get All Alarms
73 if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
74 return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
75 }
76 // Entity Class are always ONU DATA (2) and Entity Instance of 0
77 if omci.EntityClass != me.OnuDataClassID {
78 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms request: %v",
79 omci.EntityClass)
80 return me.NewProcessingError(msg)
81 }
82 if omci.EntityInstance != 0 {
83 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms request: %v",
84 omci.EntityInstance)
85 return me.NewUnknownInstanceError(msg)
86 }
87 var offset int
88 if omci.Extended {
89 offset = 2
90 }
91 omci.AlarmRetrievalMode = data[4+offset]
92 if omci.AlarmRetrievalMode > 1 {
93 msg := fmt.Sprintf("invalid Alarm Retrieval Mode for Get All Alarms request: %v, must be 0..1",
94 omci.AlarmRetrievalMode)
95 return errors.New(msg)
96 }
97 return nil
98}
99
100func decodeGetAllAlarmsRequest(data []byte, p gopacket.PacketBuilder) error {
101 omci := &GetAllAlarmsRequest{}
102 omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
103 return decodingLayerDecoder(omci, data, p)
104}
105
106func decodeGetAllAlarmsRequestExtended(data []byte, p gopacket.PacketBuilder) error {
107 omci := &GetAllAlarmsRequest{}
108 omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
109 omci.Extended = true
110 return decodingLayerDecoder(omci, data, p)
111}
112
113// SerializeTo provides serialization of an Get All Alarms Request message
114func (omci *GetAllAlarmsRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
115 // Basic (common) OMCI Header is 8 octets, 10
116 err := omci.MeBasePacket.SerializeTo(b)
117 if err != nil {
118 return err
119 }
120 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
121 me.ParamData{EntityID: omci.EntityInstance})
122 if omciErr.StatusCode() != me.Success {
123 return omciErr.GetError()
124 }
125 // ME needs to support Get All Alarms
126 if !me.SupportsMsgType(entity, me.GetAllAlarms) {
127 return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
128 }
129 var offset int
130 if omci.Extended {
131 offset = 2
132 }
133 bytes, err := b.AppendBytes(offset + 1)
134 if err != nil {
135 return err
136 }
137 if omci.Extended {
138 binary.BigEndian.PutUint16(bytes, uint16(1))
139 }
140 bytes[offset] = omci.AlarmRetrievalMode
141 return nil
142}
143
144type GetAllAlarmsResponse struct {
145 MeBasePacket
146 NumberOfCommands uint16
147}
148
149func (omci *GetAllAlarmsResponse) String() string {
150 return fmt.Sprintf("%v, NumberOfCommands: %d",
151 omci.MeBasePacket.String(), omci.NumberOfCommands)
152}
153
154// LayerType returns LayerTypeGetAllAlarmsResponse
155func (omci *GetAllAlarmsResponse) LayerType() gopacket.LayerType {
156 return LayerTypeGetAllAlarmsResponse
157}
158
159// CanDecode returns the set of layer types that this DecodingLayer can decode
160func (omci *GetAllAlarmsResponse) CanDecode() gopacket.LayerClass {
161 return LayerTypeGetAllAlarmsResponse
162}
163
164// NextLayerType returns the layer type contained by this DecodingLayer.
165func (omci *GetAllAlarmsResponse) NextLayerType() gopacket.LayerType {
166 return gopacket.LayerTypePayload
167}
168
169// DecodeFromBytes decodes the given bytes of a Get All Alarms Response into this layer
170func (omci *GetAllAlarmsResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
171 // Common ClassID/EntityID decode in msgBase
172 var hdrSize int
173 if omci.Extended {
174 //start here
175 hdrSize = 6 + 2
176 } else {
177 hdrSize = 4 + 2
178 }
179 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
180 if err != nil {
181 return err
182 }
183 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
184 me.ParamData{EntityID: omci.EntityInstance})
185 if omciErr.StatusCode() != me.Success {
186 return omciErr.GetError()
187 }
188 // ME needs to support Get All Alarms
189 if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
190 return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
191 }
192 // Entity Class are always ONU DATA (2) and Entity Instance of 0
193 if omci.EntityClass != me.OnuDataClassID {
194 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms response: %v",
195 omci.EntityClass)
196 return me.NewProcessingError(msg)
197 }
198 if omci.EntityInstance != 0 {
199 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms response: %v",
200 omci.EntityInstance)
201 return me.NewUnknownInstanceError(msg)
202 }
203 var offset int
204 if omci.Extended {
205 offset = 2
206 }
207 omci.NumberOfCommands = binary.BigEndian.Uint16(data[4+offset:])
208 return nil
209}
210
211func decodeGetAllAlarmsResponse(data []byte, p gopacket.PacketBuilder) error {
212 omci := &GetAllAlarmsResponse{}
213 omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
214 return decodingLayerDecoder(omci, data, p)
215}
216
217func decodeGetAllAlarmsResponseExtended(data []byte, p gopacket.PacketBuilder) error {
218 omci := &GetAllAlarmsResponse{}
219 omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
220 omci.Extended = true
221 return decodingLayerDecoder(omci, data, p)
222}
223
224// SerializeTo provides serialization of an Get All Alarms Response message
225func (omci *GetAllAlarmsResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
226 // Basic (common) OMCI Header is 8 octets, 10
227 err := omci.MeBasePacket.SerializeTo(b)
228 if err != nil {
229 return err
230 }
231 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
232 me.ParamData{EntityID: omci.EntityInstance})
233 if omciErr.StatusCode() != me.Success {
234 return omciErr.GetError()
235 }
236 // ME needs to support Get All Alarms
237 if !me.SupportsMsgType(entity, me.GetAllAlarms) {
238 return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
239 }
240 var offset int
241 if omci.Extended {
242 offset = 2
243 }
244 bytes, err := b.AppendBytes(offset + 2)
245 if err != nil {
246 return err
247 }
248 if omci.Extended {
249 binary.BigEndian.PutUint16(bytes, uint16(2))
250 }
251 binary.BigEndian.PutUint16(bytes[offset:], omci.NumberOfCommands)
252 return nil
253}
254
255type GetAllAlarmsNextRequest struct {
256 MeBasePacket
257 CommandSequenceNumber uint16
258}
259
260func (omci *GetAllAlarmsNextRequest) String() string {
261 return fmt.Sprintf("%v, Sequence Number: %d",
262 omci.MeBasePacket.String(), omci.CommandSequenceNumber)
263}
264
265// LayerType returns LayerTypeGetAllAlarmsNextRequest
266func (omci *GetAllAlarmsNextRequest) LayerType() gopacket.LayerType {
267 return LayerTypeGetAllAlarmsNextRequest
268}
269
270// CanDecode returns the set of layer types that this DecodingLayer can decode
271func (omci *GetAllAlarmsNextRequest) CanDecode() gopacket.LayerClass {
272 return LayerTypeGetAllAlarmsNextRequest
273}
274
275// NextLayerType returns the layer type contained by this DecodingLayer.
276func (omci *GetAllAlarmsNextRequest) NextLayerType() gopacket.LayerType {
277 return gopacket.LayerTypePayload
278}
279
280// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Request into this layer
281func (omci *GetAllAlarmsNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
282 // Common ClassID/EntityID decode in msgBase
283 var hdrSize int
284 if omci.Extended {
285 //start here
286 hdrSize = 6 + 2
287 } else {
288 hdrSize = 4 + 2
289 }
290 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
291 if err != nil {
292 return err
293 }
294 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
295 me.ParamData{EntityID: omci.EntityInstance})
296 if omciErr.StatusCode() != me.Success {
297 return omciErr.GetError()
298 }
299 // ME needs to support Get All Alarms
300 if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
301 return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
302 }
303 // Entity Class are always ONU DATA (2) and Entity Instance of 0
304 if omci.EntityClass != me.OnuDataClassID {
305 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next request: %v",
306 omci.EntityClass)
307 return me.NewProcessingError(msg)
308 }
309 if omci.EntityInstance != 0 {
310 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next request: %v",
311 omci.EntityInstance)
312 return me.NewUnknownInstanceError(msg)
313 }
314 var offset int
315 if omci.Extended {
316 offset = 2
317 }
318 omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4+offset:])
319 return nil
320}
321
322func decodeGetAllAlarmsNextRequest(data []byte, p gopacket.PacketBuilder) error {
323 omci := &GetAllAlarmsNextRequest{}
324 omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
325 return decodingLayerDecoder(omci, data, p)
326}
327
328func decodeGetAllAlarmsNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
329 omci := &GetAllAlarmsNextRequest{}
330 omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
331 omci.Extended = true
332 return decodingLayerDecoder(omci, data, p)
333}
334
335// SerializeTo provides serialization of an Get All Alarms Next Request message
336func (omci *GetAllAlarmsNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
337 // Basic (common) OMCI Header is 8 octets, 10
338 err := omci.MeBasePacket.SerializeTo(b)
339 if err != nil {
340 return err
341 }
342 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
343 me.ParamData{EntityID: omci.EntityInstance})
344 if omciErr.StatusCode() != me.Success {
345 return omciErr.GetError()
346 }
347 // ME needs to support Get All Alarms Next
348 if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
349 return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
350 }
351 var offset int
352 if omci.Extended {
353 offset = 2
354 }
355 bytes, err := b.AppendBytes(offset + 2)
356 if err != nil {
357 return err
358 }
359 if omci.Extended {
360 binary.BigEndian.PutUint16(bytes, uint16(2))
361 }
362 binary.BigEndian.PutUint16(bytes[offset:], omci.CommandSequenceNumber)
363 return nil
364}
365
366type AdditionalAlarmsData struct {
367 AlarmEntityClass me.ClassID
368 AlarmEntityInstance uint16
369 AlarmBitMap [28]byte // 224 bits
370}
371
372type GetAllAlarmsNextResponse struct {
373 MeBasePacket
374 AlarmEntityClass me.ClassID
375 AlarmEntityInstance uint16
376 AlarmBitMap [28]byte // 224 bits
377 AdditionalAlarms []AdditionalAlarmsData // Valid only for extended message set version
378}
379
380func (omci *GetAllAlarmsNextResponse) String() string {
381 return fmt.Sprintf("%v, CID: %v, EID: (%d/%#x), Bitmap: %v",
382 omci.MeBasePacket.String(), omci.AlarmEntityClass, omci.AlarmEntityInstance,
383 omci.AlarmEntityInstance, omci.AlarmBitMap)
384}
385
386// LayerType returns LayerTypeGetAllAlarmsNextResponse
387func (omci *GetAllAlarmsNextResponse) LayerType() gopacket.LayerType {
388 return LayerTypeGetAllAlarmsNextResponse
389}
390
391// CanDecode returns the set of layer types that this DecodingLayer can decode
392func (omci *GetAllAlarmsNextResponse) CanDecode() gopacket.LayerClass {
393 return LayerTypeGetAllAlarmsNextResponse
394}
395
396// NextLayerType returns the layer type contained by this DecodingLayer.
397func (omci *GetAllAlarmsNextResponse) NextLayerType() gopacket.LayerType {
398 return gopacket.LayerTypePayload
399}
400
401// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Response into this layer
402func (omci *GetAllAlarmsNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
403 // Common ClassID/EntityID decode in msgBase
404 var hdrSize int
405 if omci.Extended {
406 hdrSize = 6
407 } else {
408 hdrSize = 4
409 }
410 err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
411 if err != nil {
412 return err
413 }
414 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
415 me.ParamData{EntityID: omci.EntityInstance})
416 if omciErr.StatusCode() != me.Success {
417 return omciErr.GetError()
418 }
419 // ME needs to support Get All Alarms Next
420 if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
421 return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
422 }
423 // Entity Class are always ONU DATA (2) and Entity Instance of 0
424 if omci.EntityClass != me.OnuDataClassID {
425 msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next response: %v",
426 omci.EntityClass)
427 return me.NewProcessingError(msg)
428 }
429 if omci.EntityInstance != 0 {
430 msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next response: %v",
431 omci.EntityInstance)
432 return me.NewUnknownInstanceError(msg)
433 }
434 //err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+4+28) // Decode reported ME. If an out-of-range sequence number was sent, this will
435 // // contain an ME with class ID and entity ID of zero and you should get an
436 // // error of "managed entity definition not found" returned.
437 var offset int
438 msgContentsLen := 28
439 if omci.Extended {
440 offset = 2 // Message Contents length (2)
441 msgContentsLen = int(binary.BigEndian.Uint16(data[6:]))
442 }
443 if len(data[4+offset:]) < 4+msgContentsLen {
444 p.SetTruncated()
445 return errors.New("frame too small: Get All Alarms Next Response Managed Entity attribute truncated")
446 }
447 omci.AlarmEntityClass = me.ClassID(binary.BigEndian.Uint16(data[4+offset:]))
448 omci.AlarmEntityInstance = binary.BigEndian.Uint16(data[6+offset:])
449
450 copy(omci.AlarmBitMap[:], data[8+offset:36])
451 remaining := len(data) - (6 + 4 + 28)
452
453 if !omci.Extended || remaining <= 0 {
454 return nil
455 }
456 offset = 6 + 4 + 28
457 omci.AdditionalAlarms = make([]AdditionalAlarmsData, 0)
458 for remaining > 0 {
459 if remaining < 4+28 {
460 p.SetTruncated()
461 return errors.New("frame too small: Get All Alarms Next Response Managed Entity attribute truncated")
462 }
463 alarm := AdditionalAlarmsData{
464 AlarmEntityClass: me.ClassID(binary.BigEndian.Uint16(data[offset:])),
465 AlarmEntityInstance: binary.BigEndian.Uint16(data[offset+2:]),
466 }
467 copy(alarm.AlarmBitMap[:], data[offset+4:])
468 omci.AdditionalAlarms = append(omci.AdditionalAlarms, alarm)
469
470 offset += 4 + 28
471 remaining -= 4 + 28
472 }
473 return nil
474}
475
476func decodeGetAllAlarmsNextResponse(data []byte, p gopacket.PacketBuilder) error {
477 omci := &GetAllAlarmsNextResponse{}
478 omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
479 return decodingLayerDecoder(omci, data, p)
480}
481
482func decodeGetAllAlarmsNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
483 omci := &GetAllAlarmsNextResponse{}
484 omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
485 omci.Extended = true
486 return decodingLayerDecoder(omci, data, p)
487}
488
489// SerializeTo provides serialization of an Get All Alarms Next Response message
490func (omci *GetAllAlarmsNextResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
491 // Basic (common) OMCI Header is 8 octets, 10
492 err := omci.MeBasePacket.SerializeTo(b)
493 if err != nil {
494 return err
495 }
496 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
497 me.ParamData{EntityID: omci.EntityInstance})
498 if omciErr.StatusCode() != me.Success {
499 return omciErr.GetError()
500 }
501 // ME needs to support Get All Alarms Next
502 if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
503 return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
504 }
505 contentLength := 2 + 2 + 28
506 maxLength := MaxBaselineLength - 8 - 8
507 var extraMEs int
508 var offset int
509
510 if omci.Extended {
511 maxLength = MaxExtendedLength - 10 - 4
512 offset = 2
513 contentLength += 2 // Length field
514 if omci.AdditionalAlarms != nil {
515 extraMEs = len(omci.AdditionalAlarms)
516 contentLength += extraMEs*4 + 28
517 }
518 }
519 if contentLength > maxLength {
520 msg := fmt.Sprintf("not enough space to fit all requested Managed Entities, have %v, requested: %v",
521 maxLength, contentLength)
522 return me.NewMessageTruncatedError(msg)
523 }
524 // Allocate space for all
525 bytes, err := b.AppendBytes(contentLength)
526 if err != nil {
527 return err
528 }
529 // Always encode the first ME alarm data
530 binary.BigEndian.PutUint16(bytes[offset:], uint16(omci.AlarmEntityClass))
531 binary.BigEndian.PutUint16(bytes[offset+2:], omci.AlarmEntityInstance)
532 copy(bytes[offset+4:], omci.AlarmBitMap[:])
533
534 if omci.Extended {
535 binary.BigEndian.PutUint16(bytes, uint16(contentLength-2))
536
537 if omci.AdditionalAlarms != nil {
538 for index, value := range omci.AdditionalAlarms {
539 offset = (32 * (index + 1)) + 2
540 binary.BigEndian.PutUint16(bytes[offset:], uint16(value.AlarmEntityClass))
541 binary.BigEndian.PutUint16(bytes[offset+2:], value.AlarmEntityInstance)
542 copy(bytes[offset+4:], value.AlarmBitMap[:])
543 }
544 }
545 }
546 return nil
547}
548
549const AlarmBitmapSize = 224
550
551type AlarmNotificationMsg struct {
552 MeBasePacket
553 AlarmBitmap [AlarmBitmapSize / 8]byte
554 zeroPadding [3]byte // Note: This zero padding is not present in the Extended Message Set
555 AlarmSequenceNumber byte
556}
557
558func (omci *AlarmNotificationMsg) String() string {
559 return fmt.Sprintf("%v, Sequence Number: %d, Alarm Bitmap: %v",
560 omci.MeBasePacket.String(), omci.AlarmSequenceNumber, omci.AlarmBitmap)
561}
562
563// LayerType returns LayerTypeAlarmNotification
564func (omci *AlarmNotificationMsg) LayerType() gopacket.LayerType {
565 return LayerTypeAlarmNotification
566}
567
568// CanDecode returns the set of layer types that this DecodingLayer can decode
569func (omci *AlarmNotificationMsg) CanDecode() gopacket.LayerClass {
570 return LayerTypeAlarmNotification
571}
572
573// NextLayerType returns the layer type contained by this DecodingLayer.
574func (omci *AlarmNotificationMsg) NextLayerType() gopacket.LayerType {
575 return gopacket.LayerTypePayload
576}
577
578func (omci *AlarmNotificationMsg) IsAlarmActive(alarmNumber uint8) (bool, error) {
579 if alarmNumber >= AlarmBitmapSize {
580 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
581 return false, errors.New(msg)
582 }
583 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
584 me.ParamData{EntityID: omci.EntityInstance})
585 if omciErr.StatusCode() != me.Success {
586 return false, omciErr.GetError()
587 }
588 alarmMap := entity.GetAlarmMap()
589 if alarmMap == nil {
590 msg := "managed entity does not support Alarm notifications"
591 return false, errors.New(msg)
592 }
593 if _, ok := alarmMap[alarmNumber]; !ok {
594 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
595 return false, errors.New(msg)
596 }
597 octet := alarmNumber / 8
598 bit := 7 - (alarmNumber % 8)
599 return omci.AlarmBitmap[octet]>>bit == 1, nil
600}
601
602func (omci *AlarmNotificationMsg) IsAlarmClear(alarmNumber uint8) (bool, error) {
603 if alarmNumber >= AlarmBitmapSize {
604 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
605 return false, errors.New(msg)
606 }
607 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
608 me.ParamData{EntityID: omci.EntityInstance})
609 if omciErr.StatusCode() != me.Success {
610 return false, omciErr.GetError()
611 }
612 alarmMap := entity.GetAlarmMap()
613 if alarmMap == nil {
614 return false, errors.New("managed entity does not support Alarm notifications")
615 }
616 if _, ok := alarmMap[alarmNumber]; !ok {
617 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
618 return false, errors.New(msg)
619 }
620 octet := alarmNumber / 8
621 bit := 7 - (alarmNumber % 8)
622 return omci.AlarmBitmap[octet]>>bit == 0, nil
623}
624
625func (omci *AlarmNotificationMsg) ActivateAlarm(alarmNumber uint8) error {
626 if alarmNumber >= AlarmBitmapSize {
627 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
628 return errors.New(msg)
629 }
630 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
631 me.ParamData{EntityID: omci.EntityInstance})
632 if omciErr.StatusCode() != me.Success {
633 return omciErr.GetError()
634 }
635 alarmMap := entity.GetAlarmMap()
636 if alarmMap == nil {
637 return errors.New("managed entity does not support Alarm notifications")
638 }
639 if _, ok := alarmMap[alarmNumber]; !ok {
640 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
641 return errors.New(msg)
642 }
643 octet := alarmNumber / 8
644 bit := 7 - (alarmNumber % 8)
645 omci.AlarmBitmap[octet] |= 1 << bit
646 return nil
647}
648
649func (omci *AlarmNotificationMsg) ClearAlarm(alarmNumber uint8) error {
650 if alarmNumber >= AlarmBitmapSize {
651 msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
652 return errors.New(msg)
653 }
654 entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
655 me.ParamData{EntityID: omci.EntityInstance})
656 if omciErr.StatusCode() != me.Success {
657 return omciErr.GetError()
658 }
659 alarmMap := entity.GetAlarmMap()
660 if alarmMap == nil {
661 return errors.New("managed entity does not support Alarm notifications")
662 }
663 if _, ok := alarmMap[alarmNumber]; !ok {
664 msg := fmt.Sprintf("unsupported invalid alarm number: %v", alarmNumber)
665 return errors.New(msg)
666 }
667 octet := alarmNumber / 8
668 bit := 7 - (alarmNumber % 8)
669 omci.AlarmBitmap[octet] &= ^(1 << bit)
670 return nil
671}
672
673// DecodeFromBytes decodes the given bytes of an Alarm Notification into this layer
674func (omci *AlarmNotificationMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
675 // Common ClassID/EntityID decode in msgBase
676 err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+28)
677 if err != nil {
678 return err
679 }
680 meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
681 me.ParamData{EntityID: omci.EntityInstance})
682 if omciErr.StatusCode() != me.Success {
683 return omciErr.GetError()
684 }
685 // Is this an unsupported or vendor specific ME. If so, it is not an error to decode
686 // the alarms. We just cannot provide any alarm names. Handle decode here.
687 classSupport := meDefinition.GetClassSupport()
688 isUnsupported := classSupport == me.UnsupportedManagedEntity ||
689 classSupport == me.UnsupportedVendorSpecificManagedEntity
690
691 mapOffset := 4
692 if omci.Extended {
693 mapOffset = 6
694 if len(data) < 6+28+1 {
695 p.SetTruncated()
696 return errors.New("frame too small")
697 }
698 }
699 // Look for a non-nil/not empty Alarm Map to determine if this ME supports alarms
700 if alarmMap := meDefinition.GetAlarmMap(); isUnsupported || (alarmMap != nil && len(alarmMap) > 0) {
701 for index, octet := range data[mapOffset : (AlarmBitmapSize/8)-mapOffset] {
702 omci.AlarmBitmap[index] = octet
703 }
704 if omci.Extended {
705 omci.AlarmSequenceNumber = data[mapOffset+(AlarmBitmapSize/8)]
706 } else {
707 padOffset := mapOffset + (AlarmBitmapSize / 8)
708 omci.zeroPadding[0] = data[padOffset]
709 omci.zeroPadding[1] = data[padOffset+1]
710 omci.zeroPadding[2] = data[padOffset+2]
711 omci.AlarmSequenceNumber = data[padOffset+3]
712 }
713 return nil
714 }
715 return me.NewProcessingError("managed entity does not support alarm notifications")
716}
717
718func decodeAlarmNotification(data []byte, p gopacket.PacketBuilder) error {
719 omci := &AlarmNotificationMsg{}
720 omci.MsgLayerType = LayerTypeAlarmNotification
721 return decodingLayerDecoder(omci, data, p)
722}
723
724func decodeAlarmNotificationExtended(data []byte, p gopacket.PacketBuilder) error {
725 omci := &AlarmNotificationMsg{}
726 omci.MsgLayerType = LayerTypeAlarmNotification
727 omci.Extended = true
728 return decodingLayerDecoder(omci, data, p)
729}
730
731// SerializeTo provides serialization of an Alarm Notification message
732func (omci *AlarmNotificationMsg) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
733 // Basic (common) OMCI Header is 8 octets, 10
734 err := omci.MeBasePacket.SerializeTo(b)
735 if err != nil {
736 return err
737 }
738 // TODO: Support of encoding AlarmNotification into supported types not yet supported
739 //meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
740 // me.ParamData{EntityID: omci.EntityInstance})
741 //if omciErr.StatusCode() != me.Success {
742 // return omciErr.GetError()
743 //}
744 //if !me.SupportsMsgType(meDefinition, me.AlarmNotification) {
745 // return me.NewProcessingError("managed entity does not support Alarm Notification Message-Type")
746 //}
747 if omci.Extended {
748 bytes, err := b.AppendBytes(2 + (AlarmBitmapSize / 8) + 1)
749 if err != nil {
750 return err
751 }
752 binary.BigEndian.PutUint16(bytes, uint16((AlarmBitmapSize/8)+1))
753
754 for index, octet := range omci.AlarmBitmap {
755 bytes[2+index] = octet
756 }
757 bytes[2+(AlarmBitmapSize/8)] = omci.AlarmSequenceNumber
758 } else {
759 bytes, err := b.AppendBytes((AlarmBitmapSize / 8) + 3 + 1)
760 if err != nil {
761 return err
762 }
763 for index, octet := range omci.AlarmBitmap {
764 bytes[index] = octet
765 }
766 padOffset := AlarmBitmapSize / 8
767 bytes[padOffset] = 0
768 bytes[padOffset+1] = 0
769 bytes[padOffset+2] = 0
770 bytes[padOffset+3] = omci.AlarmSequenceNumber
771 }
772 return nil
773}