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