Chip Boling | 610117d | 2021-09-09 11:24:34 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 - present. Boling Consulting Solutions (bcsw.net) |
| 3 | * Copyright 2020-present Open Networking Foundation |
| 4 | |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
| 17 | |
| 18 | package omci_test |
| 19 | |
| 20 | import ( |
| 21 | "encoding/base64" |
| 22 | "encoding/binary" |
| 23 | "fmt" |
| 24 | "github.com/google/gopacket" |
Andrea Campanella | e0cd823 | 2021-10-15 15:10:23 +0200 | [diff] [blame] | 25 | . "github.com/opencord/omci-lib-go/v2" |
| 26 | me "github.com/opencord/omci-lib-go/v2/generated" |
Chip Boling | 610117d | 2021-09-09 11:24:34 -0500 | [diff] [blame] | 27 | "github.com/stretchr/testify/assert" |
| 28 | "strings" |
| 29 | "testing" |
| 30 | ) |
| 31 | |
| 32 | func TestGetRequestDecode(t *testing.T) { |
| 33 | goodMessage := "035e490a01070000004400000000000000000000000000000000000000000000000000000000000000000028" |
| 34 | data, err := stringToPacket(goodMessage) |
| 35 | assert.NoError(t, err) |
| 36 | |
| 37 | packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy) |
| 38 | assert.NotNil(t, packet) |
| 39 | |
| 40 | omciLayer := packet.Layer(LayerTypeOMCI) |
| 41 | assert.NotNil(t, omciLayer) |
| 42 | |
| 43 | omciMsg, ok := omciLayer.(*OMCI) |
| 44 | assert.True(t, ok) |
| 45 | assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType()) |
| 46 | assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode()) |
| 47 | assert.Equal(t, LayerTypeGetRequest, omciMsg.NextLayerType()) |
| 48 | assert.Equal(t, uint16(0x035e), omciMsg.TransactionID) |
| 49 | assert.Equal(t, GetRequestType, omciMsg.MessageType) |
| 50 | assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier) |
| 51 | assert.Equal(t, uint16(40), omciMsg.Length) |
| 52 | |
| 53 | msgLayer := packet.Layer(LayerTypeGetRequest) |
| 54 | assert.NotNil(t, msgLayer) |
| 55 | |
| 56 | request, ok2 := msgLayer.(*GetRequest) |
| 57 | assert.True(t, ok2) |
| 58 | assert.NotNil(t, request) |
| 59 | assert.Equal(t, LayerTypeGetRequest, request.LayerType()) |
| 60 | assert.Equal(t, LayerTypeGetRequest, request.CanDecode()) |
| 61 | assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType()) |
| 62 | |
| 63 | // Verify string output for message |
| 64 | packetString := packet.String() |
| 65 | assert.NotZero(t, len(packetString)) |
| 66 | } |
| 67 | |
| 68 | func TestGetRequestSerialize(t *testing.T) { |
| 69 | goodMessage := "035e490a01070000004400000000000000000000000000000000000000000000000000000000000000000028" |
| 70 | |
| 71 | omciLayer := &OMCI{ |
| 72 | TransactionID: 0x035e, |
| 73 | MessageType: GetRequestType, |
| 74 | // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline |
| 75 | // Length: 0x28, // Optional, defaults to 40 octets |
| 76 | } |
| 77 | request := &GetRequest{ |
| 78 | MeBasePacket: MeBasePacket{ |
| 79 | EntityClass: me.AniGClassID, |
| 80 | EntityInstance: uint16(0), |
| 81 | }, |
| 82 | AttributeMask: uint16(0x0044), |
| 83 | } |
| 84 | // Test serialization back to former string |
| 85 | var options gopacket.SerializeOptions |
| 86 | options.FixLengths = true |
| 87 | |
| 88 | buffer := gopacket.NewSerializeBuffer() |
| 89 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 90 | assert.NoError(t, err) |
| 91 | |
| 92 | outgoingPacket := buffer.Bytes() |
| 93 | reconstituted := packetToString(outgoingPacket) |
| 94 | assert.Equal(t, strings.ToLower(goodMessage), reconstituted) |
| 95 | } |
| 96 | |
| 97 | func TestGetRequestZeroTICSerialize(t *testing.T) { |
| 98 | omciLayer := &OMCI{ |
| 99 | TransactionID: 0x0000, |
| 100 | MessageType: GetRequestType, |
| 101 | // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline |
| 102 | // Length: 0x28, // Optional, defaults to 40 octets |
| 103 | } |
| 104 | request := &GetRequest{ |
| 105 | MeBasePacket: MeBasePacket{ |
| 106 | EntityClass: me.AniGClassID, |
| 107 | EntityInstance: uint16(0), |
| 108 | }, |
| 109 | AttributeMask: uint16(0x0044), |
| 110 | } |
| 111 | // Test serialization back to former string |
| 112 | var options gopacket.SerializeOptions |
| 113 | options.FixLengths = true |
| 114 | |
| 115 | buffer := gopacket.NewSerializeBuffer() |
| 116 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 117 | assert.Error(t, err) |
| 118 | } |
| 119 | |
| 120 | func TestGetResponseDecode(t *testing.T) { |
| 121 | goodMessage := "035e290a01070000000044dbcb05f10000000000000000000000000000000000000000000000000000000028" |
| 122 | data, err := stringToPacket(goodMessage) |
| 123 | assert.NoError(t, err) |
| 124 | |
| 125 | packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy) |
| 126 | assert.NotNil(t, packet) |
| 127 | |
| 128 | omciLayer := packet.Layer(LayerTypeOMCI) |
| 129 | assert.NotNil(t, omciLayer) |
| 130 | |
| 131 | omciMsg, ok := omciLayer.(*OMCI) |
| 132 | assert.True(t, ok) |
| 133 | assert.Equal(t, uint16(0x035e), omciMsg.TransactionID) |
| 134 | assert.Equal(t, GetResponseType, omciMsg.MessageType) |
| 135 | assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier) |
| 136 | assert.Equal(t, uint16(40), omciMsg.Length) |
| 137 | |
| 138 | msgLayer := packet.Layer(LayerTypeGetResponse) |
| 139 | assert.NotNil(t, msgLayer) |
| 140 | |
| 141 | response, ok2 := msgLayer.(*GetResponse) |
| 142 | assert.True(t, ok2) |
| 143 | assert.NotNil(t, response) |
| 144 | assert.Equal(t, LayerTypeGetResponse, response.LayerType()) |
| 145 | assert.Equal(t, LayerTypeGetResponse, response.CanDecode()) |
| 146 | assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType()) |
| 147 | assert.Equal(t, response.Result, me.Success) |
| 148 | assert.Equal(t, response.AttributeMask, uint16(0x0044)) |
| 149 | assert.Equal(t, response.Attributes["TransmitOpticalLevel"], uint16(0x05f1)) |
| 150 | assert.Equal(t, response.Attributes["OpticalSignalLevel"], uint16(0xdbcb)) |
| 151 | |
| 152 | // Verify string output for message |
| 153 | packetString := packet.String() |
| 154 | assert.NotZero(t, len(packetString)) |
| 155 | } |
| 156 | |
| 157 | func TestGetResponseSerialize(t *testing.T) { |
| 158 | goodMessage := "035e290a01070000000044dbcb05f10000000000000000000000000000000000000000000000000000000028" |
| 159 | |
| 160 | omciLayer := &OMCI{ |
| 161 | TransactionID: 0x035e, |
| 162 | MessageType: GetResponseType, |
| 163 | // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline |
| 164 | // Length: 0x28, // Optional, defaults to 40 octets |
| 165 | } |
| 166 | request := &GetResponse{ |
| 167 | MeBasePacket: MeBasePacket{ |
| 168 | EntityClass: me.AniGClassID, |
| 169 | EntityInstance: uint16(0), |
| 170 | }, |
| 171 | Result: 0, |
| 172 | AttributeMask: uint16(0x0044), |
| 173 | Attributes: me.AttributeValueMap{ |
| 174 | "TransmitOpticalLevel": uint16(0x05f1), |
| 175 | "OpticalSignalLevel": uint16(0xdbcb)}, |
| 176 | } |
| 177 | // Test serialization back to former string |
| 178 | var options gopacket.SerializeOptions |
| 179 | options.FixLengths = true |
| 180 | |
| 181 | buffer := gopacket.NewSerializeBuffer() |
| 182 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 183 | assert.NoError(t, err) |
| 184 | |
| 185 | outgoingPacket := buffer.Bytes() |
| 186 | reconstituted := packetToString(outgoingPacket) |
| 187 | assert.Equal(t, strings.ToLower(goodMessage), reconstituted) |
| 188 | } |
| 189 | |
| 190 | func TestGetResponseZeroTICSerialize(t *testing.T) { |
| 191 | omciLayer := &OMCI{ |
| 192 | TransactionID: 0x0, |
| 193 | MessageType: GetResponseType, |
| 194 | // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline |
| 195 | // Length: 0x28, // Optional, defaults to 40 octets |
| 196 | } |
| 197 | request := &GetResponse{ |
| 198 | MeBasePacket: MeBasePacket{ |
| 199 | EntityClass: me.AniGClassID, |
| 200 | EntityInstance: uint16(0), |
| 201 | }, |
| 202 | Result: 0, |
| 203 | AttributeMask: uint16(0x0044), |
| 204 | Attributes: me.AttributeValueMap{ |
| 205 | "TransmitOpticalLevel": uint16(0x05f1), |
| 206 | "OpticalSignalLevel": uint16(0xdbcb)}, |
| 207 | } |
| 208 | // Test serialization back to former string |
| 209 | var options gopacket.SerializeOptions |
| 210 | options.FixLengths = true |
| 211 | |
| 212 | buffer := gopacket.NewSerializeBuffer() |
| 213 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 214 | assert.Error(t, err) |
| 215 | } |
| 216 | |
| 217 | /////////////////////////////////////////////////////////////////////// |
| 218 | // Packet definitions for attributes of various types/sizes |
| 219 | func toOctets(str string) []byte { |
| 220 | data, err := base64.StdEncoding.DecodeString(str) |
| 221 | if err != nil { |
| 222 | panic(fmt.Sprintf("Invalid Base-64 string: '%v'", str)) |
| 223 | } |
| 224 | return data |
| 225 | } |
| 226 | |
| 227 | func TestGetResponseSerializeTruncationFailure(t *testing.T) { |
| 228 | // Too much data and 'fix-length' is not specified. This response has 26 |
| 229 | // octets in the requested data, but only 25 octets available |
| 230 | |
| 231 | omciLayer := &OMCI{ |
| 232 | TransactionID: 0x035e, |
| 233 | MessageType: GetResponseType, |
| 234 | // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline |
| 235 | // Length: 0x28, // Optional, defaults to 40 octets |
| 236 | } |
| 237 | request := &GetResponse{ |
| 238 | MeBasePacket: MeBasePacket{ |
| 239 | EntityClass: me.OnuGClassID, |
| 240 | EntityInstance: uint16(0), |
| 241 | }, |
| 242 | Result: 0, |
| 243 | AttributeMask: uint16(0xE000), |
| 244 | Attributes: me.AttributeValueMap{ |
| 245 | "VendorId": toOctets("ICAgIA=="), |
| 246 | "Version": toOctets("MAAAAAAAAAAAAAAAAAA="), |
| 247 | "SerialNumber": toOctets("AAAAAAAAAAA="), |
| 248 | }, |
| 249 | } |
| 250 | // Test serialization and verify truncation failure |
| 251 | var options gopacket.SerializeOptions |
| 252 | options.FixLengths = false |
| 253 | |
| 254 | buffer := gopacket.NewSerializeBuffer() |
| 255 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 256 | assert.Error(t, err) |
| 257 | assert.IsType(t, &me.MessageTruncatedError{}, err) |
| 258 | } |
| 259 | |
| 260 | func TestGetResponseSerializeTruncationButOkay(t *testing.T) { |
| 261 | // Too much data and 'fix-length' is specified so it packs as much as |
| 262 | // possible and adjusts the failure masks |
| 263 | |
| 264 | omciLayer := &OMCI{ |
| 265 | TransactionID: 0x035e, |
| 266 | MessageType: GetResponseType, |
| 267 | // DeviceIdentifier: omci.BaselineIdent, // Optional, defaults to Baseline |
| 268 | // Length: 0x28, // Optional, defaults to 40 octets |
| 269 | } |
| 270 | response := &GetResponse{ |
| 271 | MeBasePacket: MeBasePacket{ |
| 272 | EntityClass: me.OnuGClassID, |
| 273 | EntityInstance: uint16(0), |
| 274 | }, |
| 275 | Result: 0, |
| 276 | AttributeMask: uint16(0xE000), |
| 277 | Attributes: me.AttributeValueMap{ |
| 278 | "VendorId": toOctets("ICAgIA=="), |
| 279 | "Version": toOctets("MAAAAAAAAAAAAAAAAAA="), |
| 280 | "SerialNumber": toOctets("AAAAAAAAAAA="), |
| 281 | }, |
| 282 | } |
| 283 | // Test serialization and verify truncation failure |
| 284 | var options gopacket.SerializeOptions |
| 285 | options.FixLengths = true |
| 286 | |
| 287 | buffer := gopacket.NewSerializeBuffer() |
| 288 | err := gopacket.SerializeLayers(buffer, options, omciLayer, response) |
| 289 | assert.NoError(t, err) |
| 290 | |
| 291 | // Now deserialize it and see if we have the proper result (Attribute Failure) |
| 292 | // and a non-zero failed mask |
| 293 | responsePacket := buffer.Bytes() |
| 294 | packet := gopacket.NewPacket(responsePacket, LayerTypeOMCI, gopacket.NoCopy) |
| 295 | assert.NotNil(t, packet) |
| 296 | |
| 297 | omciLayer2 := packet.Layer(LayerTypeOMCI) |
| 298 | assert.NotNil(t, omciLayer2) |
| 299 | |
| 300 | omciMsg2, ok := omciLayer2.(*OMCI) |
| 301 | assert.True(t, ok) |
| 302 | assert.Equal(t, LayerTypeOMCI, omciMsg2.LayerType()) |
| 303 | assert.Equal(t, LayerTypeOMCI, omciMsg2.CanDecode()) |
| 304 | assert.Equal(t, LayerTypeGetResponse, omciMsg2.NextLayerType()) |
| 305 | assert.Equal(t, omciMsg2.TransactionID, omciLayer.TransactionID) |
| 306 | assert.Equal(t, GetResponseType, omciLayer.MessageType) |
| 307 | assert.Equal(t, BaselineIdent, omciLayer.DeviceIdentifier) |
| 308 | assert.Equal(t, uint16(40), omciLayer.Length) |
| 309 | |
| 310 | msgLayer2 := packet.Layer(LayerTypeGetResponse) |
| 311 | assert.NotNil(t, msgLayer2) |
| 312 | |
| 313 | response2, ok2 := msgLayer2.(*GetResponse) |
| 314 | assert.True(t, ok2) |
| 315 | assert.NotNil(t, response2) |
| 316 | assert.Equal(t, LayerTypeGetResponse, response2.LayerType()) |
| 317 | assert.Equal(t, LayerTypeGetResponse, response2.CanDecode()) |
| 318 | assert.Equal(t, gopacket.LayerTypePayload, response2.NextLayerType()) |
| 319 | assert.Equal(t, me.AttributeFailure, response2.Result) |
| 320 | assert.NotZero(t, response2.AttributeMask) |
| 321 | assert.NotZero(t, response2.FailedAttributeMask) |
| 322 | assert.Zero(t, response2.UnsupportedAttributeMask) |
| 323 | } |
| 324 | |
| 325 | func TestGetResponseTableFailedAttributesDecode(t *testing.T) { |
| 326 | // This is a GET Response with failed and unsupported attributes |
| 327 | // TODO:Implement |
| 328 | } |
| 329 | |
| 330 | func TestGetResponseTableFailedAttributesSerialize(t *testing.T) { |
| 331 | // This is a GET Response with failed and unsupported attributes |
| 332 | // TODO:Implement |
| 333 | } |
| 334 | |
| 335 | func TestGetResponseTableAttributeDecode(t *testing.T) { |
| 336 | // This is a GET Response for a table attribute. It should return the attribute |
| 337 | // size as a uint16. |
| 338 | // TODO:Implement |
| 339 | } |
| 340 | |
| 341 | func TestGetResponseTableAttributeSerialize(t *testing.T) { |
| 342 | // This is a GET Response for a table attribute. It should return the attribute |
| 343 | // size as a uint16. |
| 344 | // TODO:Implement |
| 345 | } |
| 346 | |
| 347 | func TestExtendedGetRequestDecode(t *testing.T) { |
| 348 | //ONU-2G: 257 |
| 349 | goodMessage := "035e490b010100000002fffc" |
| 350 | data, err := stringToPacket(goodMessage) |
| 351 | assert.NoError(t, err) |
| 352 | |
| 353 | packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy) |
| 354 | assert.NotNil(t, packet) |
| 355 | |
| 356 | omciLayer := packet.Layer(LayerTypeOMCI) |
| 357 | assert.NotNil(t, omciLayer) |
| 358 | |
| 359 | omciMsg, ok := omciLayer.(*OMCI) |
| 360 | assert.True(t, ok) |
| 361 | assert.NotNil(t, omciMsg) |
| 362 | assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType()) |
| 363 | assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode()) |
| 364 | assert.Equal(t, LayerTypeGetRequest, omciMsg.NextLayerType()) |
| 365 | assert.Equal(t, uint16(0x035e), omciMsg.TransactionID) |
| 366 | assert.Equal(t, GetRequestType, omciMsg.MessageType) |
| 367 | assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier) |
| 368 | assert.Equal(t, uint16(2), omciMsg.Length) |
| 369 | |
| 370 | msgLayer := packet.Layer(LayerTypeGetRequest) |
| 371 | assert.NotNil(t, msgLayer) |
| 372 | |
| 373 | request, ok2 := msgLayer.(*GetRequest) |
| 374 | assert.True(t, ok2) |
| 375 | assert.NotNil(t, request) |
| 376 | assert.Equal(t, LayerTypeGetRequest, request.LayerType()) |
| 377 | assert.Equal(t, LayerTypeGetRequest, request.CanDecode()) |
| 378 | assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType()) |
| 379 | |
| 380 | //ONU-2G: 257 |
| 381 | assert.Equal(t, me.Onu2GClassID, request.EntityClass) |
| 382 | assert.Equal(t, uint16(0), request.EntityInstance) |
| 383 | assert.Equal(t, uint16(0xfffc), request.AttributeMask) |
| 384 | |
| 385 | // Verify string output for message |
| 386 | packetString := packet.String() |
| 387 | assert.NotZero(t, len(packetString)) |
| 388 | } |
| 389 | |
| 390 | func TestExtendedGetRequestDecodeTruncated(t *testing.T) { |
| 391 | goodMessage := "035e490b010100000002ff" |
| 392 | data, err := stringToPacket(goodMessage) |
| 393 | assert.NoError(t, err) |
| 394 | |
| 395 | packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy) |
| 396 | assert.NotNil(t, packet) |
| 397 | |
| 398 | failure := packet.ErrorLayer() |
| 399 | assert.NotNil(t, failure) |
| 400 | |
| 401 | decodeFailure, ok := failure.(*gopacket.DecodeFailure) |
| 402 | assert.NotNil(t, decodeFailure) |
| 403 | assert.True(t, ok) |
| 404 | assert.NotNil(t, decodeFailure.String()) |
| 405 | assert.True(t, len(decodeFailure.String()) > 0) |
| 406 | |
| 407 | metadata := packet.Metadata() |
| 408 | assert.NotNil(t, metadata) |
| 409 | assert.True(t, metadata.Truncated) |
| 410 | |
| 411 | // Verify string output for message |
| 412 | packetString := packet.String() |
| 413 | assert.NotZero(t, len(packetString)) |
| 414 | } |
| 415 | |
| 416 | func TestExtendedGetRequestSerialize(t *testing.T) { |
| 417 | goodMessage := "035e490b010100000002fffc" |
| 418 | |
| 419 | omciLayer := &OMCI{ |
| 420 | TransactionID: 0x035e, |
| 421 | MessageType: GetRequestType, |
| 422 | DeviceIdentifier: ExtendedIdent, |
| 423 | // Length parameter is optional for Extended message format serialization |
| 424 | // and if present it will be overwritten during the serialization with the |
| 425 | // actual value. |
| 426 | } |
| 427 | request := &GetRequest{ |
| 428 | MeBasePacket: MeBasePacket{ |
| 429 | EntityClass: me.Onu2GClassID, |
| 430 | EntityInstance: uint16(0), |
| 431 | Extended: true, |
| 432 | }, |
| 433 | AttributeMask: uint16(0xfffc), |
| 434 | } |
| 435 | // Test serialization back to former string |
| 436 | var options gopacket.SerializeOptions |
| 437 | options.FixLengths = true |
| 438 | |
| 439 | buffer := gopacket.NewSerializeBuffer() |
| 440 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 441 | assert.NoError(t, err) |
| 442 | |
| 443 | outgoingPacket := buffer.Bytes() |
| 444 | reconstituted := packetToString(outgoingPacket) |
| 445 | assert.Equal(t, strings.ToLower(goodMessage), reconstituted) |
| 446 | } |
| 447 | |
| 448 | func TestExtendedGetResponseDecode(t *testing.T) { |
| 449 | attrDef, omciErr := me.GetAttributesDefinitions(me.Onu2GClassID) |
| 450 | assert.NotNil(t, attrDef) |
| 451 | assert.NotNil(t, omciErr) |
| 452 | assert.Equal(t, me.Success, omciErr.StatusCode()) |
| 453 | |
| 454 | attributes := []interface{}{ |
| 455 | toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), // 1: MultiByteField - "EquipmentId" (20 zeros) |
| 456 | byte(0xb4), // 2: ByteField - "OpticalNetworkUnitManagementAndControlChannelOmccVersion" |
| 457 | uint16(0x1234), // 3: Uint16Field - "VendorProductCode" |
| 458 | byte(1), // 4: ByteField - "SecurityCapability" |
| 459 | byte(1), // 5: ByteField - "SecurityMode" |
| 460 | uint16(0x5678), // 6: Uint16Field - "TotalPriorityQueueNumber" |
| 461 | byte(0x44), // 7: ByteField - "TotalTrafficSchedulerNumber" |
| 462 | byte(1), // 8: ByteField - "Deprecated" |
| 463 | uint16(0x55aa), // 9: Uint16Field - "TotalGemPortIdNumber" |
| 464 | uint32(0xC4108011), // 10: Uint32Field - "Sysuptime" |
| 465 | uint16(0x6), // 11: Uint16Field - "ConnectivityCapability" |
| 466 | byte(6), // 12: ByteField - "CurrentConnectivityMode" |
| 467 | uint16(2), // 13: Uint16Field - "QualityOfServiceQosConfigurationFlexibility" |
| 468 | uint16(0x1234), // 14: Uint16Field - "PriorityQueueScaleFactor" |
| 469 | } |
| 470 | attributeData := make([]byte, 0) |
| 471 | |
| 472 | // Walk through all attributes and encode them |
| 473 | for _, value := range attributes { |
| 474 | //attrDef, err := meDef.GetAttributeByIndex(index) |
| 475 | var buf []byte |
| 476 | u8, ok := value.(byte) |
| 477 | if ok { |
| 478 | buf = []byte{u8} |
| 479 | } else { |
| 480 | u16, ok := value.(uint16) |
| 481 | if ok { |
| 482 | buf = make([]byte, 2) |
| 483 | binary.BigEndian.PutUint16(buf, u16) |
| 484 | } else { |
| 485 | u32, ok := value.(uint32) |
| 486 | if ok { |
| 487 | buf = make([]byte, 4) |
| 488 | binary.BigEndian.PutUint32(buf, u32) |
| 489 | } else { |
| 490 | bytes, ok := value.([]byte) |
| 491 | if ok { |
| 492 | buf = bytes |
| 493 | } else { |
| 494 | assert.True(t, false) // Unknown attribute type |
| 495 | } |
| 496 | } |
| 497 | } |
| 498 | } |
| 499 | attributeData = append(attributeData, buf...) |
| 500 | } |
| 501 | attributeMask := 0xfffc |
| 502 | msgLength := len(attributeData) + 7 |
| 503 | // Results is 0 ("00"), and the two optional attribute masks are 0 ("00000000") as well |
| 504 | goodMessage := "035e290b01010000" + fmt.Sprintf("%04x", msgLength) + |
| 505 | "00" + fmt.Sprintf("%04x", attributeMask) + "00000000" + packetToString(attributeData) |
| 506 | |
| 507 | data, err := stringToPacket(goodMessage) |
| 508 | assert.NotNil(t, data) |
| 509 | assert.Nil(t, err) |
| 510 | |
| 511 | packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy) |
| 512 | assert.NotNil(t, packet) |
| 513 | |
| 514 | omciLayer := packet.Layer(LayerTypeOMCI) |
| 515 | assert.NotNil(t, omciLayer) |
| 516 | |
| 517 | omciMsg, ok := omciLayer.(*OMCI) |
| 518 | assert.True(t, ok) |
| 519 | assert.NotNil(t, omciMsg) |
| 520 | assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType()) |
| 521 | assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode()) |
| 522 | assert.Equal(t, LayerTypeGetResponse, omciMsg.NextLayerType()) |
| 523 | assert.Equal(t, uint16(0x035e), omciMsg.TransactionID) |
| 524 | assert.Equal(t, GetResponseType, omciMsg.MessageType) |
| 525 | assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier) |
| 526 | assert.Equal(t, uint16(msgLength), omciMsg.Length) |
| 527 | |
| 528 | msgLayer := packet.Layer(LayerTypeGetResponse) |
| 529 | assert.NotNil(t, msgLayer) |
| 530 | |
| 531 | response, ok2 := msgLayer.(*GetResponse) |
| 532 | assert.True(t, ok2) |
| 533 | assert.NotNil(t, response) |
| 534 | assert.Equal(t, LayerTypeGetResponse, response.LayerType()) |
| 535 | assert.Equal(t, LayerTypeGetResponse, response.CanDecode()) |
| 536 | assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType()) |
| 537 | assert.Equal(t, me.Success, response.Result) |
| 538 | assert.Equal(t, uint16(attributeMask), response.AttributeMask) |
| 539 | assert.Equal(t, uint16(0), response.FailedAttributeMask) |
| 540 | assert.Equal(t, uint16(0), response.UnsupportedAttributeMask) |
| 541 | |
| 542 | assert.Equal(t, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), response.Attributes["EquipmentId"]) |
| 543 | assert.Equal(t, byte(0xb4), response.Attributes["OpticalNetworkUnitManagementAndControlChannelOmccVersion"]) |
| 544 | assert.Equal(t, uint16(0x1234), response.Attributes["VendorProductCode"]) |
| 545 | assert.Equal(t, byte(1), response.Attributes["SecurityCapability"]) |
| 546 | assert.Equal(t, byte(1), response.Attributes["SecurityMode"]) |
| 547 | assert.Equal(t, uint16(0x5678), response.Attributes["TotalPriorityQueueNumber"]) |
| 548 | assert.Equal(t, byte(0x44), response.Attributes["TotalTrafficSchedulerNumber"]) |
| 549 | assert.Equal(t, byte(1), response.Attributes["Deprecated"]) |
| 550 | assert.Equal(t, uint16(0x55aa), response.Attributes["TotalGemPortIdNumber"]) |
| 551 | assert.Equal(t, uint32(0xC4108011), response.Attributes["Sysuptime"]) |
| 552 | assert.Equal(t, uint16(0x6), response.Attributes["ConnectivityCapability"]) |
| 553 | assert.Equal(t, byte(6), response.Attributes["CurrentConnectivityMode"]) |
| 554 | assert.Equal(t, uint16(2), response.Attributes["QualityOfServiceQosConfigurationFlexibility"]) |
| 555 | assert.Equal(t, uint16(0x1234), response.Attributes["PriorityQueueScaleFactor"]) |
| 556 | |
| 557 | // Verify string output for message |
| 558 | packetString := packet.String() |
| 559 | assert.NotZero(t, len(packetString)) |
| 560 | } |
| 561 | |
| 562 | func TestExtendedGetResponseSerialize(t *testing.T) { |
| 563 | goodMessage := "035e290b01010000003100fffc" + |
| 564 | "000000000000000000000000000000000000000000000000" + |
| 565 | "b4123401015678440155aac410801100060600021234" |
| 566 | |
| 567 | omciLayer := &OMCI{ |
| 568 | TransactionID: 0x035e, |
| 569 | MessageType: GetResponseType, |
| 570 | DeviceIdentifier: ExtendedIdent, |
| 571 | // Length parameter is optional for Extended message format serialization |
| 572 | // and if present it will be overwritten during the serialization with the |
| 573 | // actual value. |
| 574 | } |
| 575 | request := &GetResponse{ |
| 576 | MeBasePacket: MeBasePacket{ |
| 577 | EntityClass: me.Onu2GClassID, |
| 578 | EntityInstance: uint16(0), |
| 579 | Extended: true, |
| 580 | }, |
| 581 | Result: 0, |
| 582 | AttributeMask: uint16(0xfffc), |
| 583 | Attributes: me.AttributeValueMap{ |
| 584 | "EquipmentId": toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), |
| 585 | "OpticalNetworkUnitManagementAndControlChannelOmccVersion": byte(0xb4), |
| 586 | "VendorProductCode": uint16(0x1234), |
| 587 | "SecurityCapability": byte(1), |
| 588 | "SecurityMode": byte(1), |
| 589 | "TotalPriorityQueueNumber": uint16(0x5678), |
| 590 | "TotalTrafficSchedulerNumber": byte(0x44), |
| 591 | "Deprecated": byte(1), |
| 592 | "TotalGemPortIdNumber": uint16(0x55aa), |
| 593 | "Sysuptime": uint32(0xC4108011), |
| 594 | "ConnectivityCapability": uint16(0x6), |
| 595 | "CurrentConnectivityMode": byte(6), |
| 596 | "QualityOfServiceQosConfigurationFlexibility": uint16(2), |
| 597 | "PriorityQueueScaleFactor": uint16(0x1234), |
| 598 | }, |
| 599 | } |
| 600 | // Test serialization back to former string |
| 601 | var options gopacket.SerializeOptions |
| 602 | options.FixLengths = true |
| 603 | |
| 604 | buffer := gopacket.NewSerializeBuffer() |
| 605 | err := gopacket.SerializeLayers(buffer, options, omciLayer, request) |
| 606 | assert.NoError(t, err) |
| 607 | |
| 608 | outgoingPacket := buffer.Bytes() |
| 609 | reconstituted := packetToString(outgoingPacket) |
| 610 | assert.Equal(t, strings.ToLower(goodMessage), reconstituted) |
| 611 | } |