blob: c73d97061dfb2950a6ea29acbc352fafcfcf600a [file] [log] [blame]
Matteo Scandolof9d43412021-01-12 11:11:34 -08001/*
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 /*
18 * NOTE: This file was generated, manual edits will be overwritten!
19 *
20 * Generated by 'goCodeGenerator.py':
21 * https://github.com/cboling/OMCI-parser/README.md
22 */
23
24package generated
25
26import (
27 "encoding/base64"
28 "encoding/binary"
29 "errors"
30 "fmt"
31 "github.com/deckarep/golang-set"
32 "github.com/google/gopacket"
33 "reflect"
34 "sort"
35 "strings"
36)
37
38// Attribute types
39type AttributeType uint8
40
41const (
42 UnknownAttributeType AttributeType = iota // Not known
43 OctetsAttributeType // Series of zero or more octets
44 StringAttributeType // Readable String
45 UnsignedIntegerAttributeType // Integer (0..max)
46 TableAttributeType // Table (of Octets)
47 SignedIntegerAttributeType // Signed integer, often expressed as 2's complement
48 PointerAttributeType // Managed Entity ID or pointer to a Managed instance
49 BitFieldAttributeType // Bitfield
50 EnumerationAttributeType // Fixed number of values (Unsigned Integers)
51 CounterAttributeType // Incrementing counter
52)
53
54// AttributeDefinitionMap is a map of attribute definitions with the attribute index (0..15)
55// as the key
56type AttributeDefinitionMap map[uint]AttributeDefinition
57
58// AttributeDefinition defines a single specific Managed Entity's attributes
59type AttributeDefinition struct {
60 Name string
61 AttributeType AttributeType
62 Index uint
63 Mask uint16
64 DefValue interface{}
65 Size int // Size of attribute in bytes. 0 indicates variable/unknown
66 Access mapset.Set // AttributeAccess...
67 Constraint func(interface{}) *ParamError
68 Avc bool // If true, an AVC notification can occur for the attribute
69 Tca bool // If true, a threshold crossing alert alarm notification can occur for the attribute
70 Optional bool // If true, attribute is option, else mandatory
71 Deprecated bool // If true, attribute is deprecated
72}
73
74func (attr *AttributeDefinition) String() string {
75 return fmt.Sprintf("AttributeDefinition: %v (%v/%v): Size: %v, Default: %v, Access: %v",
76 attr.GetName(), attr.AttributeType, attr.GetIndex(), attr.GetSize(), attr.GetDefault(), attr.GetAccess())
77}
78
79// GetName returns the attribute's name
80func (attr AttributeDefinition) GetName() string { return attr.Name }
81
82// GetIndex returns the attribute index )0..15)
83func (attr AttributeDefinition) GetIndex() uint { return attr.Index }
84
85// GetDefault provides the default value for an attribute if not specified
86// during its creation
87func (attr AttributeDefinition) GetDefault() interface{} { return attr.DefValue }
88
89// GetSize returns the size of the attribute. For table attributes, the size is
90// the size of a single table.
91func (attr AttributeDefinition) GetSize() int { return attr.Size }
92
93// GetAccess provides the access information (Read, Write, ...)
94func (attr AttributeDefinition) GetAccess() mapset.Set { return attr.Access }
95
96// GetConstraints returns a function that can be called for the attribute
97// that will validate the value. An appropriate error is returned if the
98// constraint fails, otherwise nil is returned to indicate that the value
99// is valid.
100func (attr AttributeDefinition) GetConstraints() func(interface{}) *ParamError {
101 return attr.Constraint
102}
103
104// IsTableAttribute returns true if the attribute is a table
105func (attr AttributeDefinition) IsTableAttribute() bool {
106 return attr.AttributeType == TableAttributeType
107}
108
109// IsCounter returns true if the attribute is a counter (usually expressed as an
110// unsigned integer)
111func (attr AttributeDefinition) IsCounter() bool {
112 return attr.AttributeType == CounterAttributeType
113}
114
115// IsBitField returns true if the attribute is a bitfield
116func (attr AttributeDefinition) IsBitField() bool {
117 return attr.AttributeType == BitFieldAttributeType
118}
119
120// IsString returns true if the attribute is a string. Strings are typically encoded
121// into fixed length files and padded with 0's
122func (attr AttributeDefinition) IsString() bool {
123 return attr.AttributeType == StringAttributeType
124}
125
126// Decode takes a slice of bytes and converts them into a value appropriate for
127// the attribute, or returns an error on failure
128func (attr *AttributeDefinition) Decode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
129 if attr.IsTableAttribute() {
130 value, err := attr.tableAttributeDecode(data, df, msgType)
131 if err != nil {
132 return nil, err
133 }
134 if attr.GetConstraints() != nil {
135 if omciErr := attr.GetConstraints()(value); omciErr != nil {
136 return nil, omciErr.GetError()
137 }
138 }
139 return value, nil
140 }
141 size := attr.GetSize()
142
143 if len(data) < size {
144 df.SetTruncated()
145 return nil, NewMessageTruncatedError("packet too small for field")
146 }
147 switch attr.AttributeType {
148 case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
149 value := make([]byte, size)
150 copy(value, data[:size])
151 if attr.GetConstraints() != nil {
152 if omciErr := attr.GetConstraints()(value); omciErr != nil {
153 return nil, omciErr.GetError()
154 }
155 }
156 return value, nil
157
158 default:
159 switch attr.GetSize() {
160 default:
161 value := make([]byte, size)
162 copy(value, data[:size])
163 if attr.GetConstraints() != nil {
164 if omciErr := attr.GetConstraints()(value); omciErr != nil {
165 return nil, omciErr.GetError()
166 }
167 }
168 return value, nil
169 case 1:
170 value := data[0]
171 if attr.GetConstraints() != nil {
172 if omciErr := attr.GetConstraints()(value); omciErr != nil {
173 return nil, omciErr.GetError()
174 }
175 }
176 return value, nil
177 case 2:
178 value := binary.BigEndian.Uint16(data[0:2])
179 if attr.GetConstraints() != nil {
180 if omciErr := attr.GetConstraints()(value); omciErr != nil {
181 return nil, omciErr.GetError()
182 }
183 }
184 return value, nil
185 case 4:
186 value := binary.BigEndian.Uint32(data[0:4])
187 if attr.GetConstraints() != nil {
188 if omciErr := attr.GetConstraints()(value); omciErr != nil {
189 return nil, omciErr.GetError()
190 }
191 }
192 return value, nil
193 case 8:
194 value := binary.BigEndian.Uint64(data[0:8])
195 if attr.GetConstraints() != nil {
196 omciErr := attr.GetConstraints()(value)
197 if omciErr != nil {
198 return nil, omciErr.GetError()
199 }
200 }
201 return value, nil
202 }
203 }
204}
205
206// IOctetStream interface defines a way to convert a custom type to/from an octet
207// stream.
208type IOctetStream interface {
209 ToOctetString() ([]byte, error)
210 FromOctetString([]byte) (interface{}, error)
211}
212
213// InterfaceToOctets converts an attribute value to a string of octets
214func InterfaceToOctets(input interface{}) ([]byte, error) {
215 switch values := input.(type) {
216 case []byte:
217 return values, nil
218
219 case []uint16:
220 stream := make([]byte, 2*len(values))
221 for index, value := range values {
222 binary.BigEndian.PutUint16(stream[index*2:], value)
223 }
224 return stream, nil
225
226 case []uint32:
227 stream := make([]byte, 4*len(values))
228 for index, value := range values {
229 binary.BigEndian.PutUint32(stream[index*4:], value)
230 }
231 return stream, nil
232
233 case []uint64:
234 stream := make([]byte, 8*len(values))
235 for index, value := range values {
236 binary.BigEndian.PutUint64(stream[index*8:], value)
237 }
238 return stream, nil
239
240 case IOctetStream:
241 return values.ToOctetString()
242
243 default:
244 var typeName string
245 if t := reflect.TypeOf(input); t.Kind() == reflect.Ptr {
246 typeName = "*" + t.Elem().Name()
247 } else {
248 typeName = t.Name()
249 }
250 return nil, fmt.Errorf("unable to convert input to octet string: %v", typeName)
251 }
252}
253
254// SerializeTo takes an attribute value and converts it to a slice of bytes ready
255// for transmission
256func (attr *AttributeDefinition) SerializeTo(value interface{}, b gopacket.SerializeBuffer,
257 msgType byte, bytesAvailable int) (int, error) {
258 if attr.IsTableAttribute() {
259 return attr.tableAttributeSerializeTo(value, b, msgType, bytesAvailable)
260 }
261 if value == nil {
262 return 0, fmt.Errorf("attribute: %v is nil", attr.Name)
263 }
264 size := attr.GetSize()
265 if bytesAvailable < size {
266 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
267 }
268 bytes, err := b.AppendBytes(size)
269 if err != nil {
270 return 0, err
271 }
272 switch attr.AttributeType {
273 case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
274 byteStream, err := InterfaceToOctets(value)
275 if err != nil {
276 return 0, err
277 }
278 copy(bytes, byteStream)
279
280 default:
281 switch size {
282 default:
283 byteStream, err := InterfaceToOctets(value)
284 if err != nil {
285 return 0, err
286 }
287 copy(bytes, byteStream)
288 case 1:
289 switch value.(type) {
290 case int:
291 bytes[0] = byte(value.(int))
292 default:
293 bytes[0] = value.(byte)
294 }
295 case 2:
296 switch value.(type) {
297 case int:
298 binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
299 default:
300 binary.BigEndian.PutUint16(bytes, value.(uint16))
301 }
302 case 4:
303 switch value.(type) {
304 case int:
305 binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
306 default:
307 binary.BigEndian.PutUint32(bytes, value.(uint32))
308 }
309 case 8:
310 switch value.(type) {
311 case int:
312 binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
313 default:
314 binary.BigEndian.PutUint64(bytes, value.(uint64))
315 }
316 }
317 }
318 return size, nil
319}
320
321// BufferToTableAttributes takes the reconstructed octet buffer transmitted for
322// a table attribute (over many GetNextResponses) and converts it into the desired
323// format for each table row
324func (attr *AttributeDefinition) BufferToTableAttributes(data []byte) (interface{}, error) {
325 // Source is network byte order octets. Convert to proper array of slices
326 rowSize := attr.GetSize()
327 dataSize := len(data)
328 index := 0
329
330 switch rowSize {
331 default:
332 value := make([][]byte, dataSize/rowSize)
333 for offset := 0; offset < dataSize; offset += rowSize {
334 value[index] = make([]byte, rowSize)
335 copy(value[index], data[offset:])
336 index++
337 }
338 return value, nil
339 case 1:
340 value := make([]byte, dataSize)
341 copy(value, data)
342 return value, nil
343 case 2:
344 value := make([]uint16, dataSize/2)
345 for offset := 0; offset < dataSize; offset += rowSize {
346 value[offset] = binary.BigEndian.Uint16(data[offset:])
347 index++
348 }
349 return value, nil
350 case 4:
351 value := make([]uint32, dataSize/4)
352 for offset := 0; offset < dataSize; offset += rowSize {
353 value[offset] = binary.BigEndian.Uint32(data[offset:])
354 index++
355 }
356 return value, nil
357 case 8:
358 value := make([]uint64, dataSize/8)
359 for offset := 0; offset < dataSize; offset += rowSize {
360 value[offset] = binary.BigEndian.Uint64(data[offset:])
361 index++
362 }
363 return value, nil
364 }
365}
366
367func (attr *AttributeDefinition) tableAttributeDecode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
368 // Serialization of a table depends on the type of message. A
369 // Review of ITU-T G.988 shows that access on tables are
370 // either Read and/or Write, never Set-by-Create
371 switch msgType {
372 default:
373 return nil, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)
374
375 case byte(Get) | AK: // Get Response
376 // Size
377 value := binary.BigEndian.Uint32(data[0:4])
378 return value, nil
379
380 case byte(Set) | AR: // Set Request
381 fallthrough
382
383 case byte(GetNext) | AK: // Get Next Response
384 // Block of data (octets) that need to be reassembled before conversion
385 // to table/row-data. If table attribute is not explicitly given a value
386 // we have to assume the entire data buffer is the value. The receiver of
387 // this frame will need to trim off any addtional information at the end
388 // of the last frame sequence since they (and the ONU) are the only ones
389 // who know how long the data really is.
390 size := attr.GetSize()
391 if size != 0 && len(data) < attr.GetSize() {
392 df.SetTruncated()
393 return nil, NewMessageTruncatedError("packet too small for field")
394 } else if size == 0 {
395 return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
396 }
397 return data, nil
398
399 case byte(SetTable) | AR: // Set Table Request
400 // TODO: Only baseline supported at this time
401 return nil, errors.New("attribute encode for set-table-request not yet supported")
402 }
403 return nil, errors.New("TODO")
404}
405
406func (attr *AttributeDefinition) tableAttributeSerializeTo(value interface{}, b gopacket.SerializeBuffer, msgType byte,
407 bytesAvailable int) (int, error) {
408 // Serialization of a table depends on the type of message. A
409 // Review of ITU-T G.988 shows that access on tables are
410 // either Read and/or Write, never Set-by-Create
411 switch msgType {
412 default:
413 return 0, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)
414
415 case byte(Get) | AK: // Get Response
416 // Size
417 if bytesAvailable < 4 {
418 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
419 }
420 if dwordSize, ok := value.(uint32); ok {
421 bytes, err := b.AppendBytes(4)
422 if err != nil {
423 return 0, err
424 }
425 binary.BigEndian.PutUint32(bytes, dwordSize)
426 return 4, nil
427 }
428 return 0, errors.New("unexpected type for table serialization")
429
430 case byte(GetNext) | AK: // Get Next Response
431 // Values are already in network by order form
432 if data, ok := value.([]byte); ok {
433 if bytesAvailable < len(data) {
434 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
435 }
436 bytes, err := b.AppendBytes(len(data))
437 if err != nil {
438 return 0, err
439 }
440 copy(bytes, data)
441 return len(data), nil
442 }
443 return 0, errors.New("unexpected type for table serialization")
444
445 case byte(Set) | AR: // Set Request
446 // TODO: For complex table types (such as extended vlan tagging config) create an
447 // interface definition. Provide a switch type to look for that as well as for
448 // value being a byte slice... For now, just byte slice provided
449 break
450
451 case byte(SetTable) | AR: // Set Table Request
452 // TODO: Only baseline supported at this time
453 return 0, errors.New("attribute encode for set-table-request not yet supported")
454 }
455 size := attr.GetSize()
456 if bytesAvailable < size {
457 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
458 }
459 bytes, err := b.AppendBytes(size)
460 if err != nil {
461 return 0, err
462 }
463 switch attr.GetSize() {
464 default:
465 copy(bytes, value.([]byte))
466 case 1:
467 switch value.(type) {
468 case int:
469 bytes[0] = byte(value.(int))
470 default:
471 bytes[0] = value.(byte)
472 }
473 case 2:
474 switch value.(type) {
475 case int:
476 binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
477 default:
478 binary.BigEndian.PutUint16(bytes, value.(uint16))
479 }
480 case 4:
481 switch value.(type) {
482 case int:
483 binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
484 default:
485 binary.BigEndian.PutUint32(bytes, value.(uint32))
486 }
487 case 8:
488 switch value.(type) {
489 case int:
490 binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
491 default:
492 binary.BigEndian.PutUint64(bytes, value.(uint64))
493 }
494 }
495 return size, nil
496}
497
498// GetAttributeDefinitionByName searches the attribute definition map for the
499// attribute with the specified name (case insensitive)
500func GetAttributeDefinitionByName(attrMap AttributeDefinitionMap, name string) (*AttributeDefinition, error) {
501 nameLower := strings.ToLower(name)
502 for _, attrVal := range attrMap {
503 if nameLower == strings.ToLower(attrVal.GetName()) {
504 return &attrVal, nil
505 }
506 }
507 return nil, errors.New(fmt.Sprintf("attribute '%s' not found", name))
508}
509
510// GetAttributeDefinitionMapKeys is a convenience functions since we may need to
511// iterate a map in key index order. Maps in Go since v1.0 the iteration order
512// of maps have been randomized.
513func GetAttributeDefinitionMapKeys(attrMap AttributeDefinitionMap) []uint {
514 var keys []uint
515 for k := range attrMap {
516 keys = append(keys, k)
517 }
518 sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
519 return keys
520}
521
522// GetAttributeBitmap returns the attribute bitmask for a single attribute
523func GetAttributeBitmap(attrMap AttributeDefinitionMap, name string) (uint16, error) {
524 attrDef, err := GetAttributeDefinitionByName(attrMap, name)
525 if err != nil {
526 return 0, err
527 }
528 index := attrDef.GetIndex()
529 if index == 0 {
530 return 0, errors.New("managed entity ID should not be used in an attribute bitmask")
531 }
532 return uint16(1 << (16 - index)), nil
533}
534
535// GetAttributesBitmap is a convenience functions to scan a list of attributes
536// and return the bitmask that represents them
537func GetAttributesBitmap(attrMap AttributeDefinitionMap, attributes mapset.Set) (uint16, error) {
538 var mask uint16
539 for _, def := range attrMap {
540 if attributes.Contains(def.Name) {
541 mask |= def.Mask
542 attributes.Remove(def.Name)
543 }
544 }
545 if attributes.Cardinality() > 0 {
546 return 0, fmt.Errorf("unsupported attributes: %v", attributes)
547 }
548 return mask, nil
549}
550
551// GetAttributesValueMap returns the attribute value map with uninitialized values based
552// on the attribute bitmask
553func GetAttributesValueMap(attrDefs AttributeDefinitionMap, mask uint16, access mapset.Set) (AttributeValueMap, OmciErrors) {
554 attrMap := make(AttributeValueMap, 0)
555 for index, def := range attrDefs {
556 if index == 0 {
557 continue
558 }
559 checkMask := def.Mask
560 accessOk := access == nil || def.GetAccess().Intersect(access).Cardinality() > 0
561
562 if (mask&checkMask) != 0 && accessOk {
563 attrMap[def.GetName()] = nil
564 mask &= ^checkMask
565 }
566 }
567 if mask != 0 {
568 // Return map, but signaled failed attributes
569 return attrMap, NewParameterError(mask)
570 }
571 return attrMap, NewOmciSuccess()
572}
573
574///////////////////////////////////////////////////////////////////////
575// Packet definitions for attributes of various types/sizes
576func toOctets(str string) []byte {
577 data, err := base64.StdEncoding.DecodeString(str)
578 if err != nil {
579 panic(fmt.Sprintf("Invalid Base-64 string: '%v'", str))
580 }
581 return data
582}
583
584///////////////////////////////////////////////////////////////////////
585// Packet definitions for attributes of various types/sizes
586
587// ByteField returns an AttributeDefinition for an attribute that is encoded as a single
588// octet (8-bits).
589func ByteField(name string, attrType AttributeType, mask uint16, defVal uint8, access mapset.Set, avc bool,
590 optional bool, deprecated bool, index uint) AttributeDefinition {
591 return AttributeDefinition{
592 Name: name,
593 AttributeType: attrType,
594 Mask: mask,
595 Index: index,
596 DefValue: defVal,
597 Size: 1,
598 Access: access,
599 Avc: avc,
600 Optional: optional,
601 Deprecated: deprecated,
602 }
603}
604
605// Uint16Field returns an AttributeDefinition for an attribute that is encoded as two
606// octet (16-bits).
607func Uint16Field(name string, attrType AttributeType, mask uint16, defVal uint16, access mapset.Set, avc bool,
608 optional bool, deprecated bool, index uint) AttributeDefinition {
609 return AttributeDefinition{
610 Name: name,
611 AttributeType: attrType,
612 Mask: mask,
613 Index: index,
614 DefValue: defVal,
615 Size: 2,
616 Access: access,
617 Avc: avc,
618 Optional: optional,
619 Deprecated: deprecated,
620 }
621}
622
623// Uint32Field returns an AttributeDefinition for an attribute that is encoded as four
624// octet (32-bits).
625func Uint32Field(name string, attrType AttributeType, mask uint16, defVal uint32, access mapset.Set, avc bool,
626 optional bool, deprecated bool, index uint) AttributeDefinition {
627 return AttributeDefinition{
628 Name: name,
629 AttributeType: attrType,
630 Mask: mask,
631 Index: index,
632 DefValue: defVal,
633 Size: 4,
634 Access: access,
635 Avc: avc,
636 Optional: optional,
637 Deprecated: deprecated,
638 }
639}
640
641// Uint64Field returns an AttributeDefinition for an attribute that is encoded as eight
642// octet (64-bits).
643func Uint64Field(name string, attrType AttributeType, mask uint16, defVal uint64, access mapset.Set, avc bool,
644 optional bool, deprecated bool, index uint) AttributeDefinition {
645 return AttributeDefinition{
646 Name: name,
647 AttributeType: attrType,
648 Mask: mask,
649 Index: index,
650 DefValue: defVal,
651 Size: 8,
652 Access: access,
653 Avc: avc,
654 Optional: optional,
655 Deprecated: deprecated,
656 }
657}
658
659// MultiByteField returns an AttributeDefinition for an attribute that is encoded as multiple
660// octets that do not map into fields with a length that is 1, 2, 4, or 8 octets.
661func MultiByteField(name string, attrType AttributeType, mask uint16, size uint, defVal []byte, access mapset.Set, avc bool,
662 optional bool, deprecated bool, index uint) AttributeDefinition {
663 return AttributeDefinition{
664 Name: name,
665 AttributeType: attrType,
666 Mask: mask,
667 Index: index,
668 DefValue: defVal,
669 Size: int(size),
670 Access: access,
671 Avc: avc,
672 Optional: optional,
673 Deprecated: deprecated,
674 }
675}
676
677// Notes on various OMCI ME Table attribute fields. This comment will eventually be
678// removed once a good table solution is implemented. These are not all the MEs with
679// table attributes, but probably ones I care about to support initially.
680//
681// ME Notes
682// --------------------------------------------------------------------------------------------
683// Port-mapping package -> Combined Port table -> N * 25 sized rows (port (1) + ME(2) * 12)
684// ONU Remote Debug -> Reply table (N bytes)
685// ONU3-G -> Status snapshot recordtable M x N bytes
686// MCAST Gem interworkTP-> IPv4 multicast adress table (12*n) (two 2 byte fields, two 4 byte fields)
687// IPv6 multicast adress table (24*n) (various sub-fields)
688// L2 mcast gem TP -> MCAST MAC addr filtering table (11 * n) (various sub-fields)
689// MAC Bridge Port Filt -> MAC Filter table (8 * n) (3 fields, some are bits) *** BITS ***
690// MAC Bridge Port data -> Bridge Table (8*M) (vaius fields, some are bits) *** BITS ***
691// VLAN tagging filter -> Rx Vlan tag op table (16 * n) Lots of bit fields *** BITS ***
692// MCAST operations profile
693// MCAST Subscriber config info
694// MCAST subscriber monitor
695// OMCI -> Two tables (N bytes and 2*N bytes)
696// General pupose buffer -> N bytes
697// Enhanced security control (17 * N bytes), (16 * P Bytes) , (16 * Q bytes), and more...
698//
699// An early example of info to track
700
701// TableInfo is an early prototype of how to better model some tables that are
702// difficult to code.
703//
704// The Value member may be one of the following:
705// nil : Empty, no default, ...
706// value : A specific value that equates to one row, ie) 6 or toOctets("base64")
707// array : One or more rows of values. [2]uint16{2, 3}
708type TableInfo struct {
709 Value interface{} // See comment above
710 Size int // Table Row Size
711}
712
713func (t *TableInfo) String() string {
714 return fmt.Sprintf("TableInfo: Size: %d, Value(s): %v", t.Size, t.Value)
715}
716
717// TableField is used to define an attribute that is a table
718func TableField(name string, attrType AttributeType, mask uint16, tableInfo TableInfo, access mapset.Set,
719 avc bool, optional bool, deprecated bool, index uint) AttributeDefinition {
720 return AttributeDefinition{
721 Name: name,
722 AttributeType: attrType,
723 Mask: mask,
724 Index: index,
725 DefValue: tableInfo.Value,
726 Size: tableInfo.Size, //Number of elements
727 Access: access,
728 Avc: avc,
729 Optional: optional,
730 Deprecated: deprecated,
731 }
732}
733
734// UnknownField is currently not used and may be deprecated. Its original intent
735// was to be a placeholder during table attribute development
736func UnknownField(name string, mask uint16, size int, index uint) AttributeDefinition {
737 return AttributeDefinition{
738 Name: name,
739 AttributeType: UnknownAttributeType, // Stored as octet string
740 Mask: mask,
741 Index: index,
742 DefValue: nil,
743 Size: size,
744 Access: mapset.NewSet(Read, Write),
745 Avc: false,
746 Optional: false,
747 Deprecated: false,
748 }
749}
750
751// AttributeValueMap maps an attribute (by name) to its value
752type AttributeValueMap map[string]interface{}
753
754// MergeInDefaultValues will examine the Manage Entity defaults (for non-SetByCreate attributes). This
755// function is called on a MIB Create request but is provide for external use in case it is needed
756// before the MIB entry is created
757func MergeInDefaultValues(classID ClassID, attributes AttributeValueMap) OmciErrors {
758 // Get default values for non-SetByCreate attributes
759 attrDefs, err := GetAttributesDefinitions(classID)
760 if err.StatusCode() != Success {
761 return err
762 } else if attributes == nil {
763 return NewProcessingError("Invalid (nil) Attribute Value Map referenced")
764 }
765 nilAllowed := mapset.NewSet(StringAttributeType, OctetsAttributeType, TableAttributeType)
766 for index, attrDef := range attrDefs {
767 if !attrDef.Access.Contains(SetByCreate) && index != 0 &&
768 (attrDef.DefValue != nil || nilAllowed.Contains(attrDef.AttributeType)) {
769 name := attrDef.GetName()
770 if existing, found := attributes[name]; !found || existing == nil {
771 attributes[name] = attrDef.DefValue
772 }
773 }
774 }
775 return err
776}