1*** Settings *** 2Documentation Network interface IPv6 configuration and verification 3 ... tests. 4 5Resource ../../lib/bmc_redfish_resource.robot 6Resource ../../lib/openbmc_ffdc.robot 7Resource ../../lib/bmc_ipv6_utils.robot 8Resource ../../lib/external_intf/vmi_utils.robot 9Library ../../lib/bmc_network_utils.py 10Library Collections 11Library Process 12 13Test Setup Test Setup Execution 14Test Teardown Test Teardown Execution 15Suite Setup Suite Setup Execution 16Suite Teardown Redfish.Logout 17 18Test Tags BMC_IPv6 19 20*** Variables *** 21${test_ipv6_addr} 2001:db8:3333:4444:5555:6666:7777:8888 22${test_ipv6_invalid_addr} 2001:db8:3333:4444:5555:6666:7777:JJKK 23${test_ipv6_addr1} 2001:db8:3333:4444:5555:6666:7777:9999 24${invalid_hexadec_ipv6} x:x:x:x:x:x:10.5.5.6 25${ipv6_multi_short} 2001::33::111 26# Valid prefix length is a integer ranges from 1 to 128. 27${test_prefix_length} 64 28${ipv6_gw_addr} 2002:903:15F:32:9:3:32:1 29${prefix_length_def} None 30${invalid_staticv6_gateway} 9.41.164.1 31${linklocal_addr_format} fe80::[0-9a-f:]+$ 32 33*** Test Cases *** 34 35Get IPv6 Address And Verify 36 [Documentation] Get IPv6 Address And Verify. 37 [Tags] Get_IPv6_Address_And_Verify 38 39 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 40 Verify IPv6 On BMC ${ipv6_network_configuration['Address']} 41 END 42 43 44Get PrefixLength And Verify 45 [Documentation] Get IPv6 prefix length and verify. 46 [Tags] Get_PrefixLength_And_Verify 47 48 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 49 Verify IPv6 On BMC ${ipv6_network_configuration['PrefixLength']} 50 END 51 52 53Get IPv6 Default Gateway And Verify 54 [Documentation] Get IPv6 default gateway and verify. 55 [Tags] Get_IPv6_Default_Gateway_And_Verify 56 57 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 58 ${ipv6_gateway}= Get From Dictionary ${resp.dict} IPv6DefaultGateway 59 Verify IPv6 Default Gateway On BMC ${ipv6_gateway} 60 61 62Verify All Configured IPv6 And PrefixLength On BMC 63 [Documentation] Verify IPv6 address and its prefix length on BMC. 64 [Tags] Verify_All_Configured_IPv6_And_PrefixLength_On_BMC 65 66 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 67 Verify IPv6 And PrefixLength ${ipv6_network_configuration['Address']} 68 ... ${ipv6_network_configuration['PrefixLength']} 69 END 70 71 72Configure IPv6 Address And Verify 73 [Documentation] Configure IPv6 address and verify. 74 [Tags] Configure_IPv6_Address_And_Verify 75 [Teardown] Run Keywords 76 ... Delete IPv6 Address ${test_ipv6_addr} AND Test Teardown Execution 77 [Template] Configure IPv6 Address On BMC 78 79 80 # IPv6 address Prefix length 81 ${test_ipv6_addr} ${test_prefix_length} 82 83 84Delete IPv6 Address And Verify 85 [Documentation] Delete IPv6 address and verify. 86 [Tags] Delete_IPv6_Address_And_Verify 87 88 Configure IPv6 Address On BMC ${test_ipv6_addr} ${test_prefix_length} 89 90 Delete IPv6 Address ${test_ipv6_addr} 91 92 93Modify IPv6 Address And Verify 94 [Documentation] Modify IPv6 address and verify. 95 [Tags] Modify_IPv6_Address_And_Verify 96 [Teardown] Run Keywords 97 ... Delete IPv6 Address ${test_ipv6_addr1} AND Test Teardown Execution 98 99 Configure IPv6 Address On BMC ${test_ipv6_addr} ${test_prefix_length} 100 101 Modify IPv6 Address ${test_ipv6_addr} ${test_ipv6_addr1} ${test_prefix_length} 102 103 104Verify Persistency Of IPv6 After BMC Reboot 105 [Documentation] Verify persistency of IPv6 after BMC reboot. 106 [Tags] Verify_Persistency_Of_IPv6_After_BMC_Reboot 107 [Teardown] Run Keywords 108 ... Delete IPv6 Address ${test_ipv6_addr} AND Test Teardown Execution 109 110 Configure IPv6 Address On BMC ${test_ipv6_addr} ${test_prefix_length} 111 112 Redfish OBMC Reboot (off) stack_mode=skip 113 114 # Verifying persistency of IPv6. 115 Verify IPv6 On BMC ${test_ipv6_addr} 116 117 118Enable SLAAC On BMC And Verify 119 [Documentation] Enable SLAAC on BMC and verify. 120 [Tags] Enable_SLAAC_On_BMC_And_Verify 121 122 Set SLAAC Configuration State And Verify ${True} 123 124 125Enable DHCPv6 Property On BMC And Verify 126 [Documentation] Enable DHCPv6 property on BMC and verify. 127 [Tags] Enable_DHCPv6_Property_On_BMC_And_Verify 128 129 Set And Verify DHCPv6 Property Enabled 130 131 132Disable DHCPv6 Property On BMC And Verify 133 [Documentation] Disable DHCPv6 property on BMC and verify. 134 [Tags] Disable_DHCPv6_Property_On_BMC_And_Verify 135 136 Set And Verify DHCPv6 Property Disabled 137 138 139Verify Persistency Of DHCPv6 On Reboot 140 [Documentation] Verify persistency of DHCPv6 property on reboot. 141 [Tags] Verify_Persistency_Of_DHCPv6_On_Reboot 142 143 Set And Verify DHCPv6 Property Enabled 144 Redfish OBMC Reboot (off) stack_mode=skip 145 Verify DHCPv6 Property Enabled 146 147 148Configure Invalid Static IPv6 And Verify 149 [Documentation] Configure invalid static IPv6 and verify. 150 [Tags] Configure_Invalid_Static_IPv6_And_Verify 151 [Template] Configure IPv6 Address On BMC 152 153 #invalid_ipv6 prefix length valid_status_code 154 ${ipv4_hexword_addr} ${test_prefix_length} ${HTTP_BAD_REQUEST} 155 ${invalid_hexadec_ipv6} ${test_prefix_length} ${HTTP_BAD_REQUEST} 156 ${ipv6_multi_short} ${test_prefix_length} ${HTTP_BAD_REQUEST} 157 158 159 160Configure IPv6 Static Default Gateway And Verify 161 [Documentation] Configure IPv6 static default gateway and verify. 162 [Tags] Configure_IPv6_Static_Default_Gateway_And_Verify 163 [Template] Configure IPv6 Static Default Gateway On BMC 164 165 # static_def_gw prefix length valid_status_code 166 ${ipv6_gw_addr} ${prefix_length_def} ${HTTP_OK} 167 ${invalid_staticv6_gateway} ${test_prefix_length} ${HTTP_BAD_REQUEST} 168 169 170Modify Static Default Gateway And Verify 171 [Documentation] Modify static default gateway and verify. 172 [Tags] Modify_Static_Default_Gateway_And_Verify 173 [Setup] Configure IPv6 Static Default Gateway On BMC ${ipv6_gw_addr} ${prefix_length_def} 174 175 Modify IPv6 Static Default Gateway On BMC ${test_ipv6_addr1} ${prefix_length_def} ${HTTP_OK} ${ipv6_gw_addr} 176 177 178Delete IPv6 Static Default Gateway And Verify 179 [Documentation] Delete IPv6 static default gateway and verify. 180 [Tags] Delete_IPv6_Static_Default_Gateway_And_Verify 181 [Setup] Configure IPv6 Static Default Gateway On BMC ${ipv6_gw_addr} ${prefix_length_def} 182 183 Delete IPv6 Static Default Gateway ${ipv6_gw_addr} 184 185 186Verify Coexistence Of Linklocalv6 And Static IPv6 On BMC 187 [Documentation] Verify linklocalv6 And static IPv6 both exist. 188 [Tags] Verify_Coexistence_Of_Linklocalv6_And_Static_IPv6_On_BMC 189 [Setup] Configure IPv6 Address On BMC ${test_ipv6_addr} ${test_prefix_length} 190 [Teardown] Delete IPv6 Address ${test_ipv6_addr} 191 192 Check Coexistence Of Linklocalv6 And Static IPv6 193 194 195Verify IPv6 Linklocal Address Is In Corrrect Format 196 [Documentation] Verify linklocal address has network part as fe80 and host part as EUI64. 197 [Tags] Verify_IPv6_Linklocal_Address_Is_In_Correct_Format 198 199 Check If Linklocal Address Is In Correct Format 200 201 202Verify BMC Gets SLAAC Address On Enabling SLAAC 203 [Documentation] On enabling SLAAC verify SLAAC address comes up. 204 [Tags] Verify_BMC_Gets_SLAAC_Address_On_Enabling_SLAAC 205 [Setup] Set SLAAC Configuration State And Verify ${False} 206 207 Set SLAAC Configuration State And Verify ${True} 208 Sleep ${NETWORK_TIMEOUT} 209 Check BMC Gets SLAAC Address 210 211 212Enable And Verify DHCPv6 Property On Eth1 When DHCPv6 Property Enabled On Eth0 213 [Documentation] Verify DHCPv6 on eth1 when DHCPv6 property is enabled on eth0. 214 [Tags] Enable_And_Verify_DHCPv6_Property_On_Eth1_When_DHCPv6_Property_Enabled_On_Eth0 215 [Setup] Get The Initial DHCPv6 Settings 216 [Teardown] Run Keywords Set And Verify DHCPv6 Property ${dhcpv6_channel_1} ${1} 217 ... AND Set And Verify DHCPv6 Property ${dhcpv6_channel_2} ${2} 218 219 Set And Verify DHCPv6 Property Enabled ${1} 220 Set And Verify DHCPv6 Property Enabled ${2} 221 222 223Enable And Verify SLAAC Property On Eth1 When SLAAC Property Enabled On Eth0 224 [Documentation] Enable and verify SLAAC property on Eth1 when SLAAC property enabled on Eth0. 225 [Tags] Enable_And_Verify_SLAAC_Property_On_Eth1_When_SLAAC_Property_Enabled_On_Eth0 226 [Setup] Get The Initial SLAAC Settings 227 [Teardown] Run Keywords Set SLAAC Configuration State And Verify ${slaac_channel_1} [${HTTP_OK}] ${1} 228 ... AND Set SLAAC Configuration State And Verify ${slaac_channel_2} [${HTTP_OK}] ${2} 229 230 Set SLAAC Configuration State And Verify ${True} [${HTTP_OK}] ${1} 231 Set SLAAC Configuration State And Verify ${True} [${HTTP_OK}] ${2} 232 233 # Check all the addresses and address origins remain intact. 234 Verify All The Addresses Are Intact 235 236 237Verify Autoconfig Is Present On Ethernet Interface 238 [Documentation] Verify autoconfig is present on ethernet interface. 239 [Tags] Verify_Autoconfig_Is_Present_On_Ethernet_Interface 240 241 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 242 Should Contain ${resp.dict} StatelessAddressAutoConfig 243 244 245Verify Interface ID Of SLAAC And LinkLocal Addresses Are Same 246 [Documentation] Validate interface id of SLAAC and link-local addresses are same. 247 [Tags] Verify_Interface_ID_Of_SLAAC_And_LinkLocal_Addresses_Are_Same 248 249 @{ipv6_addressorigin_list} ${ipv6_linklocal_addr}= Get Address Origin List And Address For Type LinkLocal 250 @{ipv6_addressorigin_list} ${ipv6_slaac_addr}= Get Address Origin List And Address For Type SLAAC 251 252 ${linklocal_interface_id}= Get Interface ID Of IPv6 ${ipv6_linklocal_addr} 253 ${slaac_interface_id}= Get Interface ID Of IPv6 ${ipv6_slaac_addr} 254 255 Should Be Equal ${linklocal_interface_id} ${slaac_interface_id} 256 257 258*** Keywords *** 259 260Suite Setup Execution 261 [Documentation] Do suite setup execution. 262 263 Redfish.Login 264 ${active_channel_config}= Get Active Channel Config 265 Set Suite Variable ${active_channel_config} 266 267 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 268 269 Set Suite variable ${ethernet_interface} 270 271 ${initial_ipv4_addressorigin_list} ${initial_ipv4_addr_list}= Get Address Origin List And IPv4 or IPv6 Address IPv4Addresses 272 ${initial_ipv6_addressorigin_list} ${initial_ipv6_addr_list}= Get Address Origin List And IPv4 or IPv6 Address IPv6Addresses 273 274 Set Suite Variable ${initial_ipv4_addressorigin_list} 275 Set Suite Variable ${initial_ipv4_addr_list} 276 Set Suite Variable ${initial_ipv6_addressorigin_list} 277 Set Suite Variable ${initial_ipv6_addr_list} 278 279 280Test Setup Execution 281 [Documentation] Test setup execution. 282 283 @{ipv6_network_configurations}= Get IPv6 Network Configuration 284 Set Test Variable @{ipv6_network_configurations} 285 286 # Get BMC IPv6 address and prefix length. 287 ${ipv6_data}= Get BMC IPv6 Info 288 Set Test Variable ${ipv6_data} 289 290 291Test Teardown Execution 292 [Documentation] Test teardown execution. 293 294 FFDC On Test Case Fail 295 296 297Get IPv6 Network Configuration 298 [Documentation] Get Ipv6 network configuration. 299 # Sample output: 300 # { 301 # "@odata.id": "/redfish/v1/Managers/${MANAGER_ID}/EthernetInterfaces/eth0", 302 # "@odata.type": "#EthernetInterface.v1_4_1.EthernetInterface", 303 # "DHCPv4": { 304 # "DHCPEnabled": false, 305 # "UseDNSServers": false, 306 # "UseDomainName": true, 307 # "UseNTPServers": false 308 # }, 309 # "DHCPv6": { 310 # "OperatingMode": "Disabled", 311 # "UseDNSServers": false, 312 # "UseDomainName": true, 313 # "UseNTPServers": false 314 # }, 315 # "Description": "Management Network Interface", 316 # "FQDN": "localhost", 317 # "HostName": "localhost", 318 # "IPv4Addresses": [ 319 # { 320 # "Address": "xx.xx.xx.xx", 321 # "AddressOrigin": "Static", 322 # "Gateway": "xx.xx.xx.1", 323 # "SubnetMask": "xx.xx.xx.0" 324 # }, 325 # { 326 # "Address": "169.254.xx.xx", 327 # "AddressOrigin": "IPv4LinkLocal", 328 # "Gateway": "0.0.0.0", 329 # "SubnetMask": "xx.xx.0.0" 330 # }, 331 # ], 332 # "IPv4StaticAddresses": [ 333 # { 334 # "Address": "xx.xx.xx.xx", 335 # "AddressOrigin": "Static", 336 # "Gateway": "xx.xx.xx.1", 337 # "SubnetMask": "xx.xx.0.0" 338 # } 339 # } 340 # ], 341 # "IPv6AddressPolicyTable": [], 342 # "IPv6Addresses": [ 343 # { 344 # "Address": "fe80::xxxx:xxxx:xxxx:xxxx", 345 # "AddressOrigin": "LinkLocal", 346 # "AddressState": null, 347 # "PrefixLength": xx 348 # } 349 # ], 350 # "IPv6DefaultGateway": "", 351 # "IPv6StaticAddresses": [ 352 # { "Address": "xxxx:xxxx:xxxx:xxxx::xxxx", 353 # "AddressOrigin": "Static", 354 # "AddressState": null, 355 # "PrefixLength": xxx 356 # } 357 # ], 358 # "Id": "eth0", 359 # "InterfaceEnabled": true, 360 # "LinkStatus": "LinkUp", 361 # "MACAddress": "xx:xx:xx:xx:xx:xx", 362 # "Name": "Manager Ethernet Interface", 363 # "NameServers": [], 364 # "SpeedMbps": 0, 365 # "StaticNameServers": [], 366 # "Status": { 367 # "Health": "OK", 368 # "HealthRollup": "OK", 369 # "State": "Enabled" 370 # }, 371 # "VLANs": { 372 # "@odata.id": "/redfish/v1/Managers/${MANAGER_ID}/EthernetInterfaces/eth0/VLANs" 373 374 375 ${active_channel_config}= Get Active Channel Config 376 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${active_channel_config['${CHANNEL_NUMBER}']['name']} 377 378 @{ipv6_network_configurations}= Get From Dictionary ${resp.dict} IPv6StaticAddresses 379 RETURN @{ipv6_network_configurations} 380 381 382Verify IPv6 And PrefixLength 383 [Documentation] Verify IPv6 address and prefix length on BMC. 384 [Arguments] ${ipv6_addr} ${prefix_len} 385 386 # Description of the argument(s): 387 # ipv6_addr IPv6 address to be verified. 388 # prefix_len PrefixLength value to be verified. 389 390 # Catenate IPv6 address and its prefix length. 391 ${ipv6_with_prefix}= Catenate ${ipv6_addr}/${prefix_len} 392 393 # Get IPv6 address details on BMC using IP command. 394 @{ip_data}= Get BMC IPv6 Info 395 396 # Verify if IPv6 and prefix length is configured on BMC. 397 398 Should Contain ${ip_data} ${ipv6_with_prefix} 399 ... msg=IPv6 and prefix length pair does not exist. 400 401 402Configure IPv6 Address On BMC 403 [Documentation] Add IPv6 Address on BMC. 404 [Arguments] ${ipv6_addr} ${prefix_len} ${valid_status_codes}=${HTTP_OK} 405 406 # Description of argument(s): 407 # ipv6_addr IPv6 address to be added (e.g. "2001:EEEE:2222::2022"). 408 # prefix_len Prefix length for the IPv6 to be added 409 # (e.g. "64"). 410 # valid_status_codes Expected return code from patch operation 411 # (e.g. "200"). 412 413 ${prefix_length}= Convert To Integer ${prefix_len} 414 ${empty_dict}= Create Dictionary 415 ${ipv6_data}= Create Dictionary Address=${ipv6_addr} 416 ... PrefixLength=${prefix_length} 417 418 ${patch_list}= Create List 419 420 # Get existing static IPv6 configurations on BMC. 421 ${ipv6_network_configurations}= Get IPv6 Network Configuration 422 ${num_entries}= Get Length ${ipv6_network_configurations} 423 424 FOR ${INDEX} IN RANGE 0 ${num_entries} 425 Append To List ${patch_list} ${empty_dict} 426 END 427 428 ${valid_status_codes}= Set Variable If '${valid_status_codes}' == '${HTTP_OK}' 429 ... ${HTTP_OK},${HTTP_NO_CONTENT} 430 ... ${valid_status_codes} 431 432 # We need not check for existence of IPv6 on BMC while adding. 433 Append To List ${patch_list} ${ipv6_data} 434 ${data}= Create Dictionary IPv6StaticAddresses=${patch_list} 435 436 ${active_channel_config}= Get Active Channel Config 437 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 438 439 Redfish.patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} body=&{data} 440 ... valid_status_codes=[${valid_status_codes}] 441 442 Return From Keyword If '${valid_status_codes}' != '${HTTP_OK},${HTTP_NO_CONTENT}' 443 444 # Note: Network restart takes around 15-18s after patch request processing. 445 Sleep ${NETWORK_TIMEOUT}s 446 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 447 448 Verify IPv6 And PrefixLength ${ipv6_addr} ${prefix_len} 449 450 # Verify if existing static IPv6 addresses still exist. 451 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 452 Verify IPv6 On BMC ${ipv6_network_configuration['Address']} 453 END 454 455 Validate IPv6 Network Config On BMC 456 457 458Validate IPv6 Network Config On BMC 459 [Documentation] Check that IPv6 network info obtained via redfish matches info 460 ... obtained via CLI. 461 462 @{ipv6_network_configurations}= Get IPv6 Network Configuration 463 ${ipv6_data}= Get BMC IPv6 Info 464 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 465 Should Contain Match ${ipv6_data} ${ipv6_network_configuration['Address']}/* 466 ... msg=IPv6 address does not exist. 467 END 468 469 470Delete IPv6 Address 471 [Documentation] Delete IPv6 address of BMC. 472 [Arguments] ${ipv6_addr} 473 ... ${valid_status_codes}=[${HTTP_OK},${HTTP_ACCEPTED},${HTTP_NO_CONTENT}] 474 475 # Description of argument(s): 476 # ipv6_addr IPv6 address to be deleted (e.g. "2001:1234:1234:1234::1234"). 477 # valid_status_codes Expected return code from patch operation 478 # (e.g. "200"). See prolog of rest_request 479 # method in redfish_plus.py for details. 480 481 ${empty_dict}= Create Dictionary 482 ${patch_list}= Create List 483 484 @{ipv6_network_configurations}= Get IPv6 Network Configuration 485 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 486 IF '${ipv6_network_configuration['Address']}' == '${ipv6_addr}' 487 Append To List ${patch_list} ${null} 488 ELSE 489 Append To List ${patch_list} ${empty_dict} 490 END 491 END 492 493 ${ip_found}= Run Keyword And Return Status List Should Contain Value 494 ... ${patch_list} ${null} msg=${ipv6_addr} does not exist on BMC 495 Pass Execution If ${ip_found} == ${False} ${ipv6_addr} does not exist on BMC 496 497 # Run patch command only if given IP is found on BMC 498 ${data}= Create Dictionary IPv6StaticAddresses=${patch_list} 499 500 ${active_channel_config}= Get Active Channel Config 501 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 502 503 Redfish.patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} body=&{data} 504 ... valid_status_codes=${valid_status_codes} 505 506 # Note: Network restart takes around 15-18s after patch request processing 507 Sleep ${NETWORK_TIMEOUT}s 508 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 509 510 # IPv6 address that is deleted should not be there on BMC. 511 ${delete_status}= Run Keyword And Return Status Verify IPv6 On BMC ${ipv6_addr} 512 IF '${valid_status_codes}' == '[${HTTP_OK},${HTTP_ACCEPTED},${HTTP_NO_CONTENT}]' 513 Should Be True '${delete_status}' == '${False}' 514 ELSE 515 Should Be True '${delete_status}' == '${True}' 516 END 517 518 Validate IPv6 Network Config On BMC 519 520 521Modify IPv6 Address 522 [Documentation] Modify and verify IPv6 address of BMC. 523 [Arguments] ${ipv6} ${new_ipv6} ${prefix_len} 524 ... ${valid_status_codes}=[${HTTP_OK}, ${HTTP_NO_CONTENT}] 525 526 # Description of argument(s): 527 # ipv6 IPv6 address to be replaced (e.g. "2001:AABB:CCDD::AAFF"). 528 # new_ipv6 New IPv6 address to be configured. 529 # prefix_len Prefix length value (Range 1 to 128). 530 # valid_status_codes Expected return code from patch operation 531 # (e.g. "200", "201"). 532 533 ${empty_dict}= Create Dictionary 534 ${patch_list}= Create List 535 ${prefix_length}= Convert To Integer ${prefix_len} 536 ${ipv6_data}= Create Dictionary 537 ... Address=${new_ipv6} PrefixLength=${prefix_length} 538 539 # Sample IPv6 network configurations: 540 # "IPv6AddressPolicyTable": [], 541 # "IPv6Addresses": [ 542 # { 543 # "Address": "X002:db8:0:2::XX0", 544 # "AddressOrigin": "DHCPv6", 545 # "PrefixLength": 128 546 # }, 547 # { 548 # "Address": “X002:db8:0:2:a94:XXff:fe82:XXXX", 549 # "AddressOrigin": "SLAAC", 550 # "PrefixLength": 64 551 # }, 552 # { 553 # "Address": “Y002:db8:0:2:a94:efff:fe82:5000", 554 # "AddressOrigin": "Static", 555 # "PrefixLength": 56 556 # }, 557 # { 558 # "Address": “Z002:db8:0:2:a94:efff:fe82:5000", 559 # "AddressOrigin": "Static", 560 # "PrefixLength": 56 561 # }, 562 # { 563 # "Address": “Xe80::a94:efff:YYYY:XXXX", 564 # "AddressOrigin": "LinkLocal", 565 # "PrefixLength": 64 566 # }, 567 # { 568 # "Address": “X002:db8:1:2:eff:233:fee:546", 569 # "AddressOrigin": "Static", 570 # "PrefixLength": 56 571 # } 572 # ], 573 # "IPv6DefaultGateway": “XXXX::ab2e:80fe:87df:XXXX”, 574 # "IPv6StaticAddresses": [ 575 # { 576 # "Address": “X002:db8:0:2:a94:efff:fe82:5000", 577 # "PrefixLength": 56 578 # }, 579 # { 580 # "Address": “Y002:db8:0:2:a94:efff:fe82:5000", 581 # "PrefixLength": 56 582 # }, 583 # { 584 # "Address": “Z002:db8:1:2:eff:233:fee:546", 585 # "PrefixLength": 56 586 # } 587 # ], 588 # "IPv6StaticDefaultGateways": [], 589 590 # Find the position of IPv6 address to be modified. 591 @{ipv6_network_configurations}= Get IPv6 Network Configuration 592 FOR ${ipv6_network_configuration} IN @{ipv6_network_configurations} 593 IF '${ipv6_network_configuration['Address']}' == '${ipv6}' 594 Append To List ${patch_list} ${ipv6_data} 595 ELSE 596 Append To List ${patch_list} ${empty_dict} 597 END 598 END 599 600 # Modify the IPv6 address only if given IPv6 is found 601 ${ip_found}= Run Keyword And Return Status List Should Contain Value 602 ... ${patch_list} ${ipv6_data} msg=${ipv6} does not exist on BMC 603 Pass Execution If ${ip_found} == ${False} ${ipv6} does not exist on BMC 604 605 ${data}= Create Dictionary IPv6StaticAddresses=${patch_list} 606 607 ${active_channel_config}= Get Active Channel Config 608 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 609 610 Redfish.patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 611 ... body=&{data} valid_status_codes=${valid_status_codes} 612 613 # Note: Network restart takes around 15-18s after patch request processing. 614 Sleep ${NETWORK_TIMEOUT}s 615 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 616 617 # Verify if new IPv6 address is configured on BMC. 618 Verify IPv6 On BMC ${new_ipv6} 619 620 # Verify if old IPv6 address is erased. 621 ${cmd_status}= Run Keyword And Return Status 622 ... Verify IPv6 On BMC ${ipv6} 623 Should Be Equal ${cmd_status} ${False} msg=Old IPv6 address is not deleted. 624 625 Validate IPv6 Network Config On BMC 626 627 628Set SLAAC Configuration State And Verify 629 [Documentation] Set SLAAC configuration state and verify. 630 [Arguments] ${slaac_state} ${valid_status_codes}=[${HTTP_OK},${HTTP_ACCEPTED},${HTTP_NO_CONTENT}] 631 ... ${channel_number}=${CHANNEL_NUMBER} 632 633 # Description of argument(s): 634 # slaac_state SLAAC state('True' or 'False'). 635 # valid_status_code Expected valid status codes. 636 # channel_number Channel number 1(eth0) or 2(eth1). 637 638 ${active_channel_config}= Get Active Channel Config 639 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 640 641 ${data}= Set Variable If ${slaac_state} == ${False} ${DISABLE_SLAAC} ${ENABLE_SLAAC} 642 ${resp}= Redfish.Patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 643 ... body=${data} valid_status_codes=${valid_status_codes} 644 645 # Verify SLAAC is set correctly. 646 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 647 ${slaac_verify}= Get From Dictionary ${resp.dict} StatelessAddressAutoConfig 648 649 IF '${slaac_verify['IPv6AutoConfigEnabled']}' != '${slaac_state}' 650 Fail msg=SLAAC not set properly. 651 END 652 653Set And Verify DHCPv6 Property 654 [Documentation] Set DHCPv6 property and verify. 655 [Arguments] ${dhcpv6_operating_mode}=${Disabled} ${channel_number}=${CHANNEL_NUMBER} 656 657 # Description of argument(s): 658 # dhcpv6_operating_mode Enabled if user wants to enable DHCPv6('Enabled' or 'Disabled'). 659 # channel_number Channel number 1 or 2. 660 661 Set DHCPv6 Property ${dhcpv6_operating_mode} ${channel_number} 662 Verify DHCPv6 Property ${dhcpv6_operating_mode} ${channel_number} 663 664 665Set DHCPv6 Property 666 [Documentation] Set DHCPv6 attribute is enables or disabled. 667 [Arguments] ${dhcpv6_operating_mode}=${Disabled} ${channel_number}=${CHANNEL_NUMBER} 668 669 # Description of argument(s): 670 # dhcpv6_operating_mode Enabled if user wants to enable DHCPv6('Enabled' or 'Disabled'). 671 # channel_number Channel number 1 or 2. 672 673 ${data}= Set Variable If '${dhcpv6_operating_mode}' == 'Disabled' ${DISABLE_DHCPv6} ${ENABLE_DHCPv6} 674 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 675 676 Redfish.Patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 677 ... body=${data} valid_status_codes=[${HTTP_OK},${HTTP_NO_CONTENT}] 678 679 680Verify DHCPv6 Property 681 [Documentation] Verify DHCPv6 settings is enabled or disabled. 682 [Arguments] ${dhcpv6_operating_mode} ${channel_number}=${CHANNEL_NUMBER} 683 684 # Description of Argument(s): 685 # dhcpv6_operating_mode Enable/ Disable DHCPv6. 686 # channel_number Channel number 1 or 2. 687 688 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 689 690 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 691 ${dhcpv6_verify}= Get From Dictionary ${resp.dict} DHCPv6 692 693 Should Be Equal '${dhcpv6_verify['OperatingMode']}' '${dhcpv6_operating_mode}' 694 695 696Get IPv6 Static Default Gateway 697 [Documentation] Get IPv6 static default gateway. 698 699 ${active_channel_config}= Get Active Channel Config 700 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${active_channel_config['${CHANNEL_NUMBER}']['name']} 701 702 @{ipv6_static_defgw_configurations}= Get From Dictionary ${resp.dict} IPv6StaticDefaultGateways 703 RETURN @{ipv6_static_defgw_configurations} 704 705 706Configure IPv6 Static Default Gateway On BMC 707 [Documentation] Configure IPv6 static default gateway on BMC. 708 [Arguments] ${ipv6_gw_addr} ${prefix_length_def} 709 ... ${valid_status_codes}=${HTTP_OK} 710 711 # Description of argument(s): 712 # ipv6_gw_addr IPv6 Static Default Gateway address to be configured. 713 # prefix_len_def Prefix length value (Range 1 to 128). 714 # valid_status_codes Expected return code from patch operation 715 # (e.g. "200", "204".) 716 717 # Prefix Length is passed as None. 718 IF '${prefix_length_def}' == '${None}' 719 ${ipv6_gw}= Create Dictionary Address=${ipv6_gw_addr} 720 ELSE 721 ${ipv6_gw}= Create Dictionary Address=${ipv6_gw_addr} Prefix Length=${prefix_length_def} 722 END 723 724 ${ipv6_static_def_gw}= Get IPv6 Static Default Gateway 725 726 ${num_entries}= Get Length ${ipv6_static_def_gw} 727 728 ${patch_list}= Create List 729 ${empty_dict}= Create Dictionary 730 731 FOR ${INDEX} IN RANGE 0 ${num_entries} 732 Append To List ${patch_list} ${empty_dict} 733 END 734 735 ${valid_status_codes}= Set Variable If '${valid_status_codes}' == '${HTTP_OK}' 736 ... ${HTTP_OK},${HTTP_NO_CONTENT} 737 ... ${valid_status_codes} 738 739 Append To List ${patch_list} ${ipv6_gw} 740 ${data}= Create Dictionary IPv6StaticDefaultGateways=${patch_list} 741 742 Redfish.Patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 743 ... body=${data} valid_status_codes=[${valid_status_codes}] 744 745 # Verify the added static default gateway is present in Redfish Get Output. 746 ${ipv6_staticdef_gateway}= Get IPv6 Static Default Gateway 747 748 ${ipv6_static_def_gw_list}= Create List 749 FOR ${ipv6_staticdef_gateway} IN @{ipv6_staticdef_gateway} 750 ${value}= Get From Dictionary ${ipv6_staticdef_gateway} Address 751 Append To List ${ipv6_static_def_gw_list} ${value} 752 END 753 754 IF '${valid_status_codes}' != '${HTTP_OK},${HTTP_NO_CONTENT}' 755 Should Not Contain ${ipv6_static_def_gw_list} ${ipv6_gw_addr} 756 ELSE 757 Should Contain ${ipv6_static_def_gw_list} ${ipv6_gw_addr} 758 END 759 760 761Modify IPv6 Static Default Gateway On BMC 762 [Documentation] Modify and verify IPv6 address of BMC. 763 [Arguments] ${ipv6_gw_addr} ${new_static_def_gw} ${prefix_length} 764 ... ${valid_status_codes}=[${HTTP_OK},${HTTP_ACCEPTED}] 765 766 # Description of argument(s): 767 # ipv6_gw_addr IPv6 static default gateway address to be replaced (e.g. "2001:AABB:CCDD::AAFF"). 768 # new_static_def_gw New static default gateway address to be configured. 769 # prefix_length Prefix length value (Range 1 to 128). 770 # valid_status_codes Expected return code from patch operation 771 # (e.g. "200", "204"). 772 773 ${empty_dict}= Create Dictionary 774 ${patch_list}= Create List 775 # Prefix Length is passed as None. 776 IF '${prefix_length_def}' == '${None}' 777 ${modified_ipv6_gw_addripv6_data}= Create Dictionary Address=${new_static_def_gw} 778 ELSE 779 ${modified_ipv6_gw_addripv6_data}= Create Dictionary Address=${new_static_def_gw} Prefix Length=${prefix_length_def} 780 END 781 782 @{ipv6_static_def_gw_list}= Get IPv6 Static Default Gateway 783 784 FOR ${ipv6_static_def_gw} IN @{ipv6_static_def_gw_list} 785 IF '${ipv6_static_def_gw['Address']}' == '${ipv6_gw_addr}' 786 Append To List ${patch_list} ${modified_ipv6_gw_addripv6_data} 787 ELSE 788 Append To List ${patch_list} ${empty_dict} 789 END 790 END 791 792 # Modify the IPv6 address only if given IPv6 static default gateway is found. 793 ${ip_static_def_gw_found}= Run Keyword And Return Status List Should Contain Value 794 ... ${patch_list} ${modified_ipv6_gw_addripv6_data} msg=${ipv6_gw_addr} does not exist on BMC 795 Pass Execution If ${ip_static_def_gw_found} == ${False} ${ipv6_gw_addr} does not exist on BMC 796 797 ${data}= Create Dictionary IPv6StaticDefaultGateways=${patch_list} 798 799 Redfish.Patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 800 ... body=&{data} valid_status_codes=${valid_status_codes} 801 802 ${ipv6_staticdef_gateway}= Get IPv6 Static Default Gateway 803 804 ${ipv6_static_def_gw_list}= Create List 805 FOR ${ipv6_staticdef_gateway} IN @{ipv6_staticdef_gateway} 806 ${value}= Get From Dictionary ${ipv6_staticdef_gateway} Address 807 Append To List ${ipv6_static_def_gw_list} ${value} 808 END 809 810 Should Contain ${ipv6_static_def_gw_list} ${new_static_def_gw} 811 # Verify if old static default gateway address is erased. 812 Should Not Contain ${ipv6_static_def_gw_list} ${ipv6_gw_addr} 813 814 815Delete IPv6 Static Default Gateway 816 [Documentation] Delete IPv6 static default gateway on BMC. 817 [Arguments] ${ipv6_gw_addr} 818 ... ${valid_status_codes}=[${HTTP_OK},${HTTP_ACCEPTED},${HTTP_NO_CONTENT}] 819 820 # Description of argument(s): 821 # ipv6_gw_addr IPv6 Static Default Gateway address to be deleted. 822 # valid_status_codes Expected return code from patch operation 823 # (e.g. "200"). 824 825 ${patch_list}= Create List 826 ${empty_dict}= Create Dictionary 827 828 ${ipv6_static_def_gw_list}= Create List 829 @{ipv6_static_defgw_configurations}= Get IPv6 Static Default Gateway 830 831 FOR ${ipv6_staticdef_gateway} IN @{ipv6_static_defgw_configurations} 832 ${value}= Get From Dictionary ${ipv6_staticdef_gateway} Address 833 Append To List ${ipv6_static_def_gw_list} ${value} 834 END 835 836 ${defgw_found}= Run Keyword And Return Status List Should Contain Value 837 ... ${ipv6_static_def_gw_list} ${ipv6_gw_addr} msg=${ipv6_gw_addr} does not exist on BMC 838 Skip If ${defgw_found} == ${False} ${ipv6_gw_addr} does not exist on BMC 839 840 FOR ${ipv6_static_def_gw} IN @{ipv6_static_defgw_configurations} 841 IF '${ipv6_static_def_gw['Address']}' == '${ipv6_gw_addr}' 842 Append To List ${patch_list} ${null} 843 ELSE 844 Append To List ${patch_list} ${empty_dict} 845 END 846 END 847 848 # Run patch command only if given IP is found on BMC. 849 ${data}= Create Dictionary IPv6StaticDefaultGateways=${patch_list} 850 851 Redfish.Patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} body=&{data} 852 ... valid_status_codes=${valid_status_codes} 853 854 ${data}= Create Dictionary IPv6StaticDefaultGateways=${patch_list} 855 856 @{ipv6_static_defgw_configurations}= Get IPv6 Static Default Gateway 857 Should Not Contain Match ${ipv6_static_defgw_configurations} ${ipv6_gw_addr} 858 ... msg=IPv6 Static default gateway does not exist. 859 860 861Check Coexistence Of Linklocalv6 And Static IPv6 862 [Documentation] Verify both linklocalv6 and static IPv6 exist. 863 864 # Verify the address origin contains static and linklocal. 865 @{ipv6_addressorigin_list} ${ipv6_linklocal_addr}= Get Address Origin List And Address For Type LinkLocal 866 867 Should Match Regexp ${ipv6_linklocal_addr} ${linklocal_addr_format} 868 Should Contain ${ipv6_addressorigin_list} Static 869 870 871Check If Linklocal Address Is In Correct Format 872 [Documentation] Linklocal address has network part fe80 and host part EUI64. 873 874 # Fetch the linklocal address. 875 @{ipv6_addressorigin_list} ${ipv6_linklocal_addr}= Get Address Origin List And Address For Type LinkLocal 876 877 # Follow EUI64 from MAC. 878 ${system_mac}= Get BMC MAC Address 879 ${split_octets}= Split String ${system_mac} : 880 ${first_octet}= Evaluate int('${split_octets[0]}', 16) 881 ${flipped_hex}= Evaluate format(${first_octet} ^ 2, '02x') 882 ${grp1}= Evaluate re.sub(r'^0+', '', '${flipped_hex}${split_octets[1]}') modules=re 883 ${grp2}= Evaluate re.sub(r'^0+', '', '${split_octets[2]}ff') modules=re 884 ${grp3}= Evaluate re.sub(r'^0+', '', '${split_octets[4]}${split_octets[5]}') modules=re 885 ${linklocal}= Set Variable fe80::${grp1}:${grp2}:fe${split_octets[3]}:${grp3} 886 887 # Verify the linklocal obtained is the same as on the machine. 888 Should Be Equal ${linklocal} ${ipv6_linklocal_addr} 889 890 891Check BMC Gets SLAAC Address 892 [Documentation] Check BMC gets slaac address. 893 894 @{ipv6_addressorigin_list} ${ipv6_slaac_addr}= Get Address Origin List And Address For Type SLAAC 895 896 897Get The Initial DHCPv6 Setting On Each Interface 898 [Documentation] Get the initial DHCPv6 setting of each interface. 899 [Arguments] ${channel_number} 900 901 # Description of the argument(s): 902 # channel_number Channel number 1 or 2. 903 904 ${ethernet_interface}= Set Variable ${active_channel_config['${channel_number}']['name']} 905 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 906 ${initial_dhcpv6_iface}= Get From Dictionary ${resp.dict} DHCPv6 907 IF ${channel_number}==${1} 908 Set Test Variable ${dhcpv6_channel_1} ${initial_dhcpv6_iface['OperatingMode']} 909 ELSE 910 Set Test Variable ${dhcpv6_channel_2} ${initial_dhcpv6_iface['OperatingMode']} 911 END 912 913 914Get The Initial DHCPv6 Settings 915 [Documentation] Get the initial DHCPv6 settings of both the interfaces. 916 917 Get The Initial DHCPv6 Setting On Each Interface ${1} 918 Get The Initial DHCPv6 Setting On Each Interface ${2} 919 920 921Get The Initial SLAAC Settings 922 [Documentation] Get the initial SLAAC settings of both the interfaces. 923 924 Get The Initial SLAAC Setting On Each Interface ${1} 925 Get The Initial SLAAC Setting On Each Interface ${2} 926 927 928Get The Initial SLAAC Setting On Each Interface 929 [Documentation] Get the initial SLAAC setting of the interface. 930 [Arguments] ${channel_number} 931 932 # Description of the argument(s): 933 # channel_number Channel number 1 or 2. 934 935 ${ethernet_interface}= Set Variable ${active_channel_config['${channel_number}']['name']} 936 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${ethernet_interface} 937 ${initial_slaac_iface}= Get From Dictionary ${resp.dict} StatelessAddressAutoConfig 938 IF ${channel_number}==${1} 939 Set Test Variable ${slaac_channel_1} ${initial_slaac_iface['IPv6AutoConfigEnabled']} 940 ELSE 941 Set Test Variable ${slaac_channel_2} ${initial_slaac_iface['IPv6AutoConfigEnabled']} 942 END 943 944 945Get Address Origin List And Address For Type 946 [Documentation] Get address origin list and address for type. 947 [Arguments] ${ipv6_address_type} 948 949 # Description of the argument(s): 950 # ipv6_address_type Type of IPv6 address to be checked. 951 952 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${active_channel_config['${CHANNEL_NUMBER}']['name']} 953 @{ipv6_addresses}= Get From Dictionary ${resp.dict} IPv6Addresses 954 955 ${ipv6_addressorigin_list}= Create List 956 ${ipv6_slaac_addr}= Set Variable ${None} 957 FOR ${ipv6_address} IN @{ipv6_addresses} 958 ${ipv6_addressorigin}= Get From Dictionary ${ipv6_address} AddressOrigin 959 Append To List ${ipv6_addressorigin_list} ${ipv6_addressorigin} 960 IF '${ipv6_addressorigin}' == '${ipv6_address_type}' 961 Set Test Variable ${ipv6_type_addr} ${ipv6_address['Address']} 962 END 963 END 964 Should Contain ${ipv6_addressorigin_list} ${ipv6_address_type} 965 Should Not Be Empty ${ipv6_type_addr} msg=${ipv6_address_type} address is not present 966 RETURN @{ipv6_addressorigin_list} ${ipv6_type_addr} 967 968 969Get Address Origin List And IPv4 or IPv6 Address 970 [Documentation] Get address origin list and address for type. 971 [Arguments] ${ip_address_type} 972 973 # Description of the argument(s): 974 # ip_address_type Type of IPv4 or IPv6 address to be checked. 975 976 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${active_channel_config['${CHANNEL_NUMBER}']['name']} 977 @{ip_addresses}= Get From Dictionary ${resp.dict} ${ip_address_type} 978 979 ${ip_addressorigin_list}= Create List 980 ${ip_addr_list}= Create List 981 FOR ${ip_address} IN @{ip_addresses} 982 ${ip_addressorigin}= Get From Dictionary ${ip_address} AddressOrigin 983 Append To List ${ip_addressorigin_list} ${ip_addressorigin} 984 Append To List ${ip_addr_list} ${ip_address['Address']} 985 END 986 RETURN ${ip_addressorigin_list} ${ip_addr_list} 987 988 989Verify All The Addresses Are Intact 990 [Documentation] Verify all the addresses and address origins remain intact. 991 992 # Verify that it will not impact the IPv4 configuration. 993 Sleep ${NETWORK_TIMEOUT} 994 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 995 996 # IPv6 address must be present. 997 @{ipv6_addressorigin_list} ${ipv6_slaac_addr}= Get Address Origin List And Address For Type SLAAC 998 @{ipv6_addressorigin_list} ${ipv6_linklocal_addr}= Get Address Origin List And Address For Type LinkLocal 999 1000 # IPv4 and IPv6 addresses must remain intact. 1001 ${ipv4_addressorigin_list} ${ipv4_addr_list}= Get Address Origin List And IPv4 or IPv6 Address IPv4Addresses 1002 ${ipv6_addressorigin_list} ${ipv6_addr_list}= Get Address Origin List And IPv4 or IPv6 Address IPv6Addresses 1003 1004 ${ipv6_is_subset}= Evaluate set(${initial_ipv6_addr_list}).issubset(set(${ipv6_addr_list})) 1005 Should Be True ${ipv6_is_subset} 1006 1007 Should be Equal ${initial_ipv4_addressorigin_list} ${ipv4_addressorigin_list} 1008 Should be Equal ${initial_ipv4_addr_list} ${ipv4_addr_list} 1009 1010 1011Get Interface ID Of IPv6 1012 [Documentation] Get interface id of IPv6 address. 1013 [Arguments] ${ipv6_address} 1014 1015 # Description of the argument(s): 1016 # ${ipv6_address} IPv6 Address to extract the last 4 hextets. 1017 1018 # Last 64 bits of SLAAC and Linklocal must be the same. 1019 # Sample IPv6 network configurations. 1020 #"IPv6AddressPolicyTable": [], 1021 # "IPv6Addresses": [ 1022 # { 1023 # "Address": "fe80::xxxx:xxxx:xxxx:xxxx", 1024 # "AddressOrigin": "LinkLocal", 1025 # "AddressState": null, 1026 # "PrefixLength": xx 1027 # } 1028 # ], 1029 # { 1030 # "Address": "2002:xxxx:xxxx:xxxx:xxxx", 1031 # "AddressOrigin": "SLAAC", 1032 # "PrefixLength": 64 1033 # } 1034 # ], 1035 1036 ${split_ip_address}= Split String ${ipv6_address} : 1037 ${missing_ip}= Evaluate 8 - len(${split_ip_address}) + 1 1038 ${expanded_ip}= Create List 1039 1040 FOR ${hextet} IN @{split_ip_address} 1041 IF '${hextet}' == '' 1042 FOR ${i} IN RANGE ${missing_ip} 1043 Append To List ${expanded_ip} 0000 1044 END 1045 ELSE 1046 Append To List ${expanded_ip} ${hextet} 1047 END 1048 END 1049 ${interface_id}= Evaluate ':'.join(${expanded_ip}[-4:]) 1050 RETURN ${interface_id} 1051