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