blob: 58bd6cff481f921fc8d03a502b9e6a5585524950 [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 */
Girish Gowdra161d27a2021-05-05 12:01:44 -070017/*
Matteo Scandolof9d43412021-01-12 11:11:34 -080018 * 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"
Matteo Scandolof9d43412021-01-12 11:11:34 -080031 "reflect"
32 "sort"
33 "strings"
Girish Gowdra161d27a2021-05-05 12:01:44 -070034
35 mapset "github.com/deckarep/golang-set"
36 "github.com/google/gopacket"
Matteo Scandolof9d43412021-01-12 11:11:34 -080037)
38
39// Attribute types
40type AttributeType uint8
41
42const (
43 UnknownAttributeType AttributeType = iota // Not known
44 OctetsAttributeType // Series of zero or more octets
45 StringAttributeType // Readable String
46 UnsignedIntegerAttributeType // Integer (0..max)
47 TableAttributeType // Table (of Octets)
48 SignedIntegerAttributeType // Signed integer, often expressed as 2's complement
49 PointerAttributeType // Managed Entity ID or pointer to a Managed instance
50 BitFieldAttributeType // Bitfield
51 EnumerationAttributeType // Fixed number of values (Unsigned Integers)
52 CounterAttributeType // Incrementing counter
53)
54
55// AttributeDefinitionMap is a map of attribute definitions with the attribute index (0..15)
56// as the key
57type AttributeDefinitionMap map[uint]AttributeDefinition
58
59// AttributeDefinition defines a single specific Managed Entity's attributes
60type AttributeDefinition struct {
61 Name string
62 AttributeType AttributeType
63 Index uint
64 Mask uint16
65 DefValue interface{}
66 Size int // Size of attribute in bytes. 0 indicates variable/unknown
67 Access mapset.Set // AttributeAccess...
68 Constraint func(interface{}) *ParamError
69 Avc bool // If true, an AVC notification can occur for the attribute
70 Tca bool // If true, a threshold crossing alert alarm notification can occur for the attribute
71 Optional bool // If true, attribute is option, else mandatory
72 Deprecated bool // If true, attribute is deprecated
73}
74
75func (attr *AttributeDefinition) String() string {
76 return fmt.Sprintf("AttributeDefinition: %v (%v/%v): Size: %v, Default: %v, Access: %v",
77 attr.GetName(), attr.AttributeType, attr.GetIndex(), attr.GetSize(), attr.GetDefault(), attr.GetAccess())
78}
79
80// GetName returns the attribute's name
81func (attr AttributeDefinition) GetName() string { return attr.Name }
82
83// GetIndex returns the attribute index )0..15)
84func (attr AttributeDefinition) GetIndex() uint { return attr.Index }
85
86// GetDefault provides the default value for an attribute if not specified
87// during its creation
88func (attr AttributeDefinition) GetDefault() interface{} { return attr.DefValue }
89
90// GetSize returns the size of the attribute. For table attributes, the size is
91// the size of a single table.
92func (attr AttributeDefinition) GetSize() int { return attr.Size }
93
94// GetAccess provides the access information (Read, Write, ...)
95func (attr AttributeDefinition) GetAccess() mapset.Set { return attr.Access }
96
97// GetConstraints returns a function that can be called for the attribute
98// that will validate the value. An appropriate error is returned if the
99// constraint fails, otherwise nil is returned to indicate that the value
100// is valid.
101func (attr AttributeDefinition) GetConstraints() func(interface{}) *ParamError {
102 return attr.Constraint
103}
104
105// IsTableAttribute returns true if the attribute is a table
106func (attr AttributeDefinition) IsTableAttribute() bool {
107 return attr.AttributeType == TableAttributeType
108}
109
110// IsCounter returns true if the attribute is a counter (usually expressed as an
111// unsigned integer)
112func (attr AttributeDefinition) IsCounter() bool {
113 return attr.AttributeType == CounterAttributeType
114}
115
116// IsBitField returns true if the attribute is a bitfield
117func (attr AttributeDefinition) IsBitField() bool {
118 return attr.AttributeType == BitFieldAttributeType
119}
120
121// IsString returns true if the attribute is a string. Strings are typically encoded
122// into fixed length files and padded with 0's
123func (attr AttributeDefinition) IsString() bool {
124 return attr.AttributeType == StringAttributeType
125}
126
127// Decode takes a slice of bytes and converts them into a value appropriate for
128// the attribute, or returns an error on failure
129func (attr *AttributeDefinition) Decode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
130 if attr.IsTableAttribute() {
131 value, err := attr.tableAttributeDecode(data, df, msgType)
132 if err != nil {
133 return nil, err
134 }
135 if attr.GetConstraints() != nil {
136 if omciErr := attr.GetConstraints()(value); omciErr != nil {
137 return nil, omciErr.GetError()
138 }
139 }
140 return value, nil
141 }
142 size := attr.GetSize()
143
144 if len(data) < size {
145 df.SetTruncated()
146 return nil, NewMessageTruncatedError("packet too small for field")
147 }
148 switch attr.AttributeType {
149 case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
150 value := make([]byte, size)
151 copy(value, data[:size])
152 if attr.GetConstraints() != nil {
153 if omciErr := attr.GetConstraints()(value); omciErr != nil {
154 return nil, omciErr.GetError()
155 }
156 }
157 return value, nil
158
159 default:
160 switch attr.GetSize() {
161 default:
162 value := make([]byte, size)
163 copy(value, data[:size])
164 if attr.GetConstraints() != nil {
165 if omciErr := attr.GetConstraints()(value); omciErr != nil {
166 return nil, omciErr.GetError()
167 }
168 }
169 return value, nil
170 case 1:
171 value := data[0]
172 if attr.GetConstraints() != nil {
173 if omciErr := attr.GetConstraints()(value); omciErr != nil {
174 return nil, omciErr.GetError()
175 }
176 }
177 return value, nil
178 case 2:
179 value := binary.BigEndian.Uint16(data[0:2])
180 if attr.GetConstraints() != nil {
181 if omciErr := attr.GetConstraints()(value); omciErr != nil {
182 return nil, omciErr.GetError()
183 }
184 }
185 return value, nil
186 case 4:
187 value := binary.BigEndian.Uint32(data[0:4])
188 if attr.GetConstraints() != nil {
189 if omciErr := attr.GetConstraints()(value); omciErr != nil {
190 return nil, omciErr.GetError()
191 }
192 }
193 return value, nil
194 case 8:
195 value := binary.BigEndian.Uint64(data[0:8])
196 if attr.GetConstraints() != nil {
197 omciErr := attr.GetConstraints()(value)
198 if omciErr != nil {
199 return nil, omciErr.GetError()
200 }
201 }
202 return value, nil
203 }
204 }
205}
206
207// IOctetStream interface defines a way to convert a custom type to/from an octet
208// stream.
209type IOctetStream interface {
210 ToOctetString() ([]byte, error)
211 FromOctetString([]byte) (interface{}, error)
212}
213
214// InterfaceToOctets converts an attribute value to a string of octets
215func InterfaceToOctets(input interface{}) ([]byte, error) {
216 switch values := input.(type) {
217 case []byte:
218 return values, nil
219
220 case []uint16:
221 stream := make([]byte, 2*len(values))
222 for index, value := range values {
223 binary.BigEndian.PutUint16(stream[index*2:], value)
224 }
225 return stream, nil
226
227 case []uint32:
228 stream := make([]byte, 4*len(values))
229 for index, value := range values {
230 binary.BigEndian.PutUint32(stream[index*4:], value)
231 }
232 return stream, nil
233
234 case []uint64:
235 stream := make([]byte, 8*len(values))
236 for index, value := range values {
237 binary.BigEndian.PutUint64(stream[index*8:], value)
238 }
239 return stream, nil
240
241 case IOctetStream:
242 return values.ToOctetString()
243
244 default:
245 var typeName string
246 if t := reflect.TypeOf(input); t.Kind() == reflect.Ptr {
247 typeName = "*" + t.Elem().Name()
248 } else {
249 typeName = t.Name()
250 }
251 return nil, fmt.Errorf("unable to convert input to octet string: %v", typeName)
252 }
253}
254
255// SerializeTo takes an attribute value and converts it to a slice of bytes ready
256// for transmission
257func (attr *AttributeDefinition) SerializeTo(value interface{}, b gopacket.SerializeBuffer,
258 msgType byte, bytesAvailable int) (int, error) {
259 if attr.IsTableAttribute() {
260 return attr.tableAttributeSerializeTo(value, b, msgType, bytesAvailable)
261 }
262 if value == nil {
263 return 0, fmt.Errorf("attribute: %v is nil", attr.Name)
264 }
265 size := attr.GetSize()
266 if bytesAvailable < size {
267 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
268 }
269 bytes, err := b.AppendBytes(size)
270 if err != nil {
271 return 0, err
272 }
273 switch attr.AttributeType {
274 case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
275 byteStream, err := InterfaceToOctets(value)
276 if err != nil {
277 return 0, err
278 }
279 copy(bytes, byteStream)
280
281 default:
282 switch size {
283 default:
284 byteStream, err := InterfaceToOctets(value)
285 if err != nil {
286 return 0, err
287 }
288 copy(bytes, byteStream)
289 case 1:
290 switch value.(type) {
291 case int:
292 bytes[0] = byte(value.(int))
293 default:
294 bytes[0] = value.(byte)
295 }
296 case 2:
297 switch value.(type) {
298 case int:
299 binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
300 default:
301 binary.BigEndian.PutUint16(bytes, value.(uint16))
302 }
303 case 4:
304 switch value.(type) {
305 case int:
306 binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
307 default:
308 binary.BigEndian.PutUint32(bytes, value.(uint32))
309 }
310 case 8:
311 switch value.(type) {
312 case int:
313 binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
314 default:
315 binary.BigEndian.PutUint64(bytes, value.(uint64))
316 }
317 }
318 }
319 return size, nil
320}
321
322// BufferToTableAttributes takes the reconstructed octet buffer transmitted for
323// a table attribute (over many GetNextResponses) and converts it into the desired
324// format for each table row
325func (attr *AttributeDefinition) BufferToTableAttributes(data []byte) (interface{}, error) {
326 // Source is network byte order octets. Convert to proper array of slices
327 rowSize := attr.GetSize()
328 dataSize := len(data)
329 index := 0
330
331 switch rowSize {
332 default:
333 value := make([][]byte, dataSize/rowSize)
334 for offset := 0; offset < dataSize; offset += rowSize {
335 value[index] = make([]byte, rowSize)
336 copy(value[index], data[offset:])
337 index++
338 }
339 return value, nil
340 case 1:
341 value := make([]byte, dataSize)
342 copy(value, data)
343 return value, nil
344 case 2:
345 value := make([]uint16, dataSize/2)
346 for offset := 0; offset < dataSize; offset += rowSize {
347 value[offset] = binary.BigEndian.Uint16(data[offset:])
348 index++
349 }
350 return value, nil
351 case 4:
352 value := make([]uint32, dataSize/4)
353 for offset := 0; offset < dataSize; offset += rowSize {
354 value[offset] = binary.BigEndian.Uint32(data[offset:])
355 index++
356 }
357 return value, nil
358 case 8:
359 value := make([]uint64, dataSize/8)
360 for offset := 0; offset < dataSize; offset += rowSize {
361 value[offset] = binary.BigEndian.Uint64(data[offset:])
362 index++
363 }
364 return value, nil
365 }
366}
367
368func (attr *AttributeDefinition) tableAttributeDecode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
369 // Serialization of a table depends on the type of message. A
370 // Review of ITU-T G.988 shows that access on tables are
371 // either Read and/or Write, never Set-by-Create
372 switch msgType {
373 default:
374 return nil, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)
375
376 case byte(Get) | AK: // Get Response
377 // Size
378 value := binary.BigEndian.Uint32(data[0:4])
379 return value, nil
380
381 case byte(Set) | AR: // Set Request
382 fallthrough
383
384 case byte(GetNext) | AK: // Get Next Response
385 // Block of data (octets) that need to be reassembled before conversion
386 // to table/row-data. If table attribute is not explicitly given a value
387 // we have to assume the entire data buffer is the value. The receiver of
388 // this frame will need to trim off any addtional information at the end
389 // of the last frame sequence since they (and the ONU) are the only ones
390 // who know how long the data really is.
391 size := attr.GetSize()
392 if size != 0 && len(data) < attr.GetSize() {
393 df.SetTruncated()
394 return nil, NewMessageTruncatedError("packet too small for field")
395 } else if size == 0 {
396 return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
397 }
398 return data, nil
399
400 case byte(SetTable) | AR: // Set Table Request
401 // TODO: Only baseline supported at this time
402 return nil, errors.New("attribute encode for set-table-request not yet supported")
403 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800404}
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}