blob: 1246c56d130e12aa4c83724211072501e92e1f5a [file] [log] [blame]
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001/*
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 */
20package generated
21
22import (
23 "encoding/binary"
24 "errors"
25 "fmt"
26 "github.com/deckarep/golang-set"
27 "github.com/google/gopacket"
28 "sort"
29 "strings"
30)
31
32type AttributeDefinitionMap map[uint]*AttributeDefinition
33
34// AttributeDefinition defines a single specific Managed Entity's attributes
35type AttributeDefinition struct {
36 Name string
37 Index uint
38 DefValue interface{} // Note: Not supported yet
39 Size int
40 Access mapset.Set // AttributeAccess...
41 Constraint func(interface{}) *ParamError
42 Avc bool // If true, an AVC notification can occur for the attribute
43 Tca bool // If true, a threshold crossing alert alarm notification can occur for the attribute
44 Counter bool // If true, this attribute is a PM counter
45 Optional bool // If true, attribute is option, else mandatory
46 TableSupport bool // If true, attribute is a table
47 Deprecated bool // If true, this attribute is deprecated and only 'read' operations (if-any) performed
48}
49
50func (attr *AttributeDefinition) String() string {
51 return fmt.Sprintf("AttributeDefinition: %v (%v): Size: %v, Default: %v, Access: %v",
52 attr.GetName(), attr.GetIndex(), attr.GetSize(), attr.GetDefault(), attr.GetAccess())
53}
54func (attr *AttributeDefinition) GetName() string { return attr.Name }
55func (attr *AttributeDefinition) GetIndex() uint { return attr.Index }
56func (attr *AttributeDefinition) GetDefault() interface{} { return attr.DefValue }
57func (attr *AttributeDefinition) GetSize() int { return attr.Size }
58func (attr *AttributeDefinition) GetAccess() mapset.Set { return attr.Access }
59func (attr *AttributeDefinition) GetConstraints() func(interface{}) *ParamError {
60 return attr.Constraint
61}
62func (attr *AttributeDefinition) IsTableAttribute() bool {
63 return attr.TableSupport
64}
65
66func (attr *AttributeDefinition) Decode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
67 if attr.IsTableAttribute() {
68 value, err := attr.tableAttributeDecode(data, df, msgType)
69 if err != nil {
70 return nil, err
71 }
72 if attr.GetConstraints() != nil {
73 if omciErr := attr.GetConstraints()(value); omciErr != nil {
74 return nil, omciErr.GetError()
75 }
76 }
77 return value, nil
78 }
79 size := attr.GetSize()
80
81 if len(data) < size {
82 df.SetTruncated()
83 return nil, NewMessageTruncatedError("packet too small for field")
84 }
85 switch attr.GetSize() {
86 default:
87 value := make([]byte, size)
88 copy(value, data[:size])
89 if attr.GetConstraints() != nil {
90 if omciErr := attr.GetConstraints()(value); omciErr != nil {
91 return nil, omciErr.GetError()
92 }
93 }
94 return value, nil
95 case 1:
96 value := data[0]
97 if attr.GetConstraints() != nil {
98 if omciErr := attr.GetConstraints()(value); omciErr != nil {
99 return nil, omciErr.GetError()
100 }
101 }
102 return value, nil
103 case 2:
104 value := binary.BigEndian.Uint16(data[0:2])
105 if attr.GetConstraints() != nil {
106 if omciErr := attr.GetConstraints()(value); omciErr != nil {
107 return nil, omciErr.GetError()
108 }
109 }
110 return value, nil
111 case 4:
112 value := binary.BigEndian.Uint32(data[0:4])
113 if attr.GetConstraints() != nil {
114 if omciErr := attr.GetConstraints()(value); omciErr != nil {
115 return nil, omciErr.GetError()
116 }
117 }
118 return value, nil
119 case 8:
120 value := binary.BigEndian.Uint64(data[0:8])
121 if attr.GetConstraints() != nil {
122 omciErr := attr.GetConstraints()(value)
123 if omciErr != nil {
124 return nil, omciErr.GetError()
125 }
126 }
127 return value, nil
128 }
129}
130
131func (attr *AttributeDefinition) SerializeTo(value interface{}, b gopacket.SerializeBuffer,
132 msgType byte, bytesAvailable int) (int, error) {
133 if attr.IsTableAttribute() {
134 return attr.tableAttributeSerializeTo(value, b, msgType, bytesAvailable)
135 }
136 size := attr.GetSize()
137 if bytesAvailable < size {
138 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
139 }
140 bytes, err := b.AppendBytes(size)
141 if err != nil {
142 return 0, err
143 }
144 switch size {
145 default:
146 copy(bytes, value.([]byte))
147 case 1:
148 switch value.(type) {
149 case int:
150 bytes[0] = byte(value.(int))
151 default:
152 bytes[0] = value.(byte)
153 }
154 case 2:
155 switch value.(type) {
156 case int:
157 binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
158 default:
159 binary.BigEndian.PutUint16(bytes, value.(uint16))
160 }
161 case 4:
162 switch value.(type) {
163 case int:
164 binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
165 default:
166 binary.BigEndian.PutUint32(bytes, value.(uint32))
167 }
168 case 8:
169 switch value.(type) {
170 case int:
171 binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
172 default:
173 binary.BigEndian.PutUint64(bytes, value.(uint64))
174 }
175 }
176 return size, nil
177}
178
179// BufferToTableAttributes takes the reconstructed octet buffer transmitted for
180// a table attribute (over many GetNextResponses) and converts it into the desired
181// format for each table row
182func (attr *AttributeDefinition) BufferToTableAttributes(data []byte) (interface{}, error) {
183 // Source is network byte order octets. Convert to proper array of slices
184 rowSize := attr.GetSize()
185 dataSize := len(data)
186 index := 0
187
188 switch rowSize {
189 default:
190 value := make([][]byte, dataSize/rowSize)
191 for offset := 0; offset < dataSize; offset += rowSize {
192 value[index] = make([]byte, rowSize)
193 copy(value[index], data[offset:])
194 index++
195 }
196 return value, nil
197 case 1:
198 value := make([]byte, dataSize)
199 copy(value, data)
200 return value, nil
201 case 2:
202 value := make([]uint16, dataSize/2)
203 for offset := 0; offset < dataSize; offset += rowSize {
204 value[offset] = binary.BigEndian.Uint16(data[offset:])
205 index++
206 }
207 return value, nil
208 case 4:
209 value := make([]uint32, dataSize/4)
210 for offset := 0; offset < dataSize; offset += rowSize {
211 value[offset] = binary.BigEndian.Uint32(data[offset:])
212 index++
213 }
214 return value, nil
215 case 8:
216 value := make([]uint64, dataSize/8)
217 for offset := 0; offset < dataSize; offset += rowSize {
218 value[offset] = binary.BigEndian.Uint64(data[offset:])
219 index++
220 }
221 return value, nil
222 }
223}
224
225func (attr *AttributeDefinition) tableAttributeDecode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
226 // Serialization of a table depends on the type of message. A
227 // Review of ITU-T G.988 shows that access on tables are
228 // either Read and/or Write, never Set-by-Create
229 switch msgType {
230 default:
231 return nil, errors.New(fmt.Sprintf("unsupported Message Type '%v' for table serialization", msgType))
232
233 case byte(Get) | AK: // Get Response
234 // Size
235 value := binary.BigEndian.Uint32(data[0:4])
236 return value, nil
237
238 case byte(GetNext) | AK: // Get Next Response
239 // Block of data (octets) that need to be reassembled before conversion
240 // to table/row-data. If table attribute is not explicitly given a value
241 // we have to assume the entire data buffer is the value. The receiver of
242 // this frame will need to trim off any addtional information at the end
243 // of the last frame sequence since they (and the ONU) are the only ones
244 // who know how long the data really is.
245 size := attr.GetSize()
246 if size != 0 && len(data) < attr.GetSize() {
247 df.SetTruncated()
248 return nil, NewMessageTruncatedError("packet too small for field")
249 } else if size == 0 {
250 return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
251 }
252 return data, nil
253
254 case byte(Set) | AR: // Set Request
255 fmt.Println("TODO")
256 return nil, errors.New("TODO")
257
258 case byte(SetTable) | AR: // Set Table Request
259 // TODO: Only baseline supported at this time
260 return nil, errors.New("attribute encode for set-table-request not yet supported")
261 }
262 return nil, errors.New("TODO")
263}
264
265func (attr *AttributeDefinition) tableAttributeSerializeTo(value interface{}, b gopacket.SerializeBuffer, msgType byte,
266 bytesAvailable int) (int, error) {
267 // Serialization of a table depends on the type of message. A
268 // Review of ITU-T G.988 shows that access on tables are
269 // either Read and/or Write, never Set-by-Create
270 switch msgType {
271 default:
272 return 0, errors.New(fmt.Sprintf("unsupported Message Type '%v' for table serialization", msgType))
273
274 case byte(Get) | AK: // Get Response
275 // Size
276 if bytesAvailable < 4 {
277 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
278 }
279 if dwordSize, ok := value.(uint32); ok {
280 bytes, err := b.AppendBytes(4)
281 if err != nil {
282 return 0, err
283 }
284 binary.BigEndian.PutUint32(bytes, dwordSize)
285 return 4, nil
286 }
287 return 0, errors.New("unexpected type for table serialization")
288
289 case byte(GetNext) | AK: // Get Next Response
290 // Values are already in network by order form
291 if data, ok := value.([]byte); ok {
292 if bytesAvailable < len(data) {
293 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
294 }
295 bytes, err := b.AppendBytes(len(data))
296 if err != nil {
297 return 0, err
298 }
299 copy(bytes, data)
300 return len(data), nil
301 }
302 return 0, errors.New("unexpected type for table serialization")
303
304 case byte(Set) | AR: // Set Request
305 fmt.Println("TODO")
306
307 case byte(SetTable) | AR: // Set Table Request
308 // TODO: Only baseline supported at this time
309 return 0, errors.New("attribute encode for set-table-request not yet supported")
310 }
311 size := attr.GetSize()
312 if bytesAvailable < size {
313 return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
314 }
315 bytes, err := b.AppendBytes(size)
316 if err != nil {
317 return 0, err
318 }
319 switch attr.GetSize() {
320 default:
321 copy(bytes, value.([]byte))
322 case 1:
323 switch value.(type) {
324 case int:
325 bytes[0] = byte(value.(int))
326 default:
327 bytes[0] = value.(byte)
328 }
329 case 2:
330 switch value.(type) {
331 case int:
332 binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
333 default:
334 binary.BigEndian.PutUint16(bytes, value.(uint16))
335 }
336 case 4:
337 switch value.(type) {
338 case int:
339 binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
340 default:
341 binary.BigEndian.PutUint32(bytes, value.(uint32))
342 }
343 case 8:
344 switch value.(type) {
345 case int:
346 binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
347 default:
348 binary.BigEndian.PutUint64(bytes, value.(uint64))
349 }
350 }
351 return size, nil
352}
353
354// GetAttributeDefinitionByName searches the attribute definition map for the
355// attribute with the specified name (case insensitive)
356func GetAttributeDefinitionByName(attrMap *AttributeDefinitionMap, name string) (*AttributeDefinition, OmciErrors) {
357 nameLower := strings.ToLower(name)
358 for _, attrVal := range *attrMap {
359 if nameLower == strings.ToLower(attrVal.GetName()) {
360 return attrVal, nil
361 }
362 }
363 return nil, NewAttributeFailureError(fmt.Sprintf("attribute '%s' not found", name))
364}
365
366// GetAttributeDefinitionMapKeys is a convenience functions since we may need to
367// iterate a map in key index order. Maps in Go since v1.0 the iteration order
368// of maps have been randomized.
369func GetAttributeDefinitionMapKeys(attrMap AttributeDefinitionMap) []uint {
370 var keys []uint
371 for k := range attrMap {
372 keys = append(keys, k)
373 }
374 sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
375 return keys
376}
377
378// GetAttributeBitmap is a convenience functions to scan a list of attributes
379// and return the bitmask that represents them
380func GetAttributeBitmap(attrMap AttributeDefinitionMap, attributes mapset.Set) (uint16, error) {
381 var mask uint16
382 for k, def := range attrMap {
383 if attributes.Contains(def.Name) {
384 mask |= 1 << uint16(16-k)
385 attributes.Remove(def.Name)
386 }
387 }
388 if attributes.Cardinality() > 0 {
389 return 0, errors.New(fmt.Sprintf("unsupported attributes: %v", attributes))
390 }
391 return mask, nil
392}
393
394///////////////////////////////////////////////////////////////////////
395// Packet definitions for attributes of various types/sizes
396
397func ByteField(name string, defVal uint8, access mapset.Set, avc bool,
398 counter bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
399 return &AttributeDefinition{
400 Name: name,
401 Index: index,
402 DefValue: defVal,
403 Size: 1,
404 Access: access,
405 Avc: avc,
406 Counter: counter,
407 TableSupport: false,
408 Optional: optional,
409 Deprecated: deprecated,
410 }
411}
412
413func Uint16Field(name string, defVal uint16, access mapset.Set, avc bool,
414 counter bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
415 return &AttributeDefinition{
416 Name: name,
417 Index: index,
418 DefValue: defVal,
419 Size: 2,
420 Access: access,
421 Avc: avc,
422 Counter: counter,
423 TableSupport: false,
424 Optional: optional,
425 Deprecated: deprecated,
426 }
427}
428
429func Uint32Field(name string, defVal uint32, access mapset.Set, avc bool,
430 counter bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
431 return &AttributeDefinition{
432 Name: name,
433 Index: index,
434 DefValue: defVal,
435 Size: 4,
436 Access: access,
437 Avc: avc,
438 Counter: counter,
439 TableSupport: false,
440 Optional: optional,
441 Deprecated: deprecated,
442 }
443}
444
445func Uint64Field(name string, defVal uint64, access mapset.Set, avc bool,
446 counter bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
447 return &AttributeDefinition{
448 Name: name,
449 Index: index,
450 DefValue: defVal,
451 Size: 8,
452 Access: access,
453 Avc: avc,
454 Counter: counter,
455 TableSupport: false,
456 Optional: optional,
457 Deprecated: deprecated,
458 }
459}
460
461func MultiByteField(name string, size uint, defVal []byte, access mapset.Set, avc bool,
462 counter bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
463 return &AttributeDefinition{
464 Name: name,
465 Index: index,
466 DefValue: defVal,
467 Size: int(size),
468 Access: access,
469 Avc: avc,
470 Counter: counter,
471 TableSupport: false,
472 Optional: optional,
473 Deprecated: deprecated,
474 }
475}
476
477// Notes on various OMCI ME Table attribute fields. This comment will eventually be
478// removed once a good table solution is implemented. These are not all the MEs with
479// table attributes, but probably ones I care about to support initially.
480//
481// ME Notes
482// --------------------------------------------------------------------------------------------
483// Port-mapping package -> Combined Port table -> N * 25 sized rows (port (1) + ME(2) * 12)
484// ONU Remote Debug -> Reply table (N bytes)
485// ONU3-G -> Status snapshot recordtable M x N bytes
486// MCAST Gem interworkTP-> IPv4 multicast adress table (12*n) (two 2 byte fields, two 4 byte fields)
487// IPv6 multicast adress table (24*n) (various sub-fields)
488// L2 mcast gem TP -> MCAST MAC addr filtering table (11 * n) (various sub-fields)
489// MAC Bridge Port Filt -> MAC Filter table (8 * n) (3 fields, some are bits) *** BITS ***
490// MAC Bridge Port data -> Bridge Table (8*M) (vaius fields, some are bits) *** BITS ***
491// VLAN tagging filter -> Rx Vlan tag op table (16 * n) Lots of bit fields *** BITS ***
492// MCAST operations profile
493// MCAST Subscriber config info
494// MCAST subscriber monitor
495// OMCI -> Two tables (N bytes and 2*N bytes)
496// General pupose buffer -> N bytes
497// Enhanced security control (17 * N bytes), (16 * P Bytes) , (16 * Q bytes), and more...
498//
499// An early example of info to track
500//
501type TableInfo struct {
502 Value interface{}
503 Size int
504}
505
506func (t *TableInfo) String() string {
507 return fmt.Sprintf("TableInfo: Size: %d, Value(s): %v", t.Size, t.Value)
508}
509
510// Now the field
511func TableField(name string, tableInfo TableInfo, access mapset.Set,
512 avc bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
513 return &AttributeDefinition{
514 Name: name,
515 Index: index,
516 DefValue: tableInfo.Value,
517 Size: tableInfo.Size, //Number of elements
518 Access: access,
519 Avc: avc,
520 Counter: false,
521 TableSupport: true,
522 Optional: optional,
523 Deprecated: deprecated,
524 }
525}
526
527func UnknownField(name string, defVal uint64, access mapset.Set, avc bool,
528 counter bool, optional bool, deprecated bool, index uint) *AttributeDefinition {
529 return &AttributeDefinition{
530 Name: name,
531 Index: index,
532 DefValue: defVal,
533 Size: 99999999,
534 Access: access,
535 Avc: avc,
536 Counter: counter,
537 TableSupport: false,
538 Optional: optional,
539 Deprecated: deprecated,
540 }
541}
542
543///////////////////////////////////////////////////////////////////////
544// Attribute Name to Value (Interfaced defined in generated subdirectory)
545
546type AttributeValueMap map[string]interface{}