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
8Library        ../../lib/bmc_network_utils.py
9Library        Collections
10
11Test Setup     Test Setup Execution
12Test Teardown  Test Teardown Execution
13Suite Setup    Suite Setup Execution
14
15Test Tags     BMC_IPv6
16
17*** Variables ***
18${test_ipv6_addr}          2001:db8:3333:4444:5555:6666:7777:8888
19${test_ipv6_invalid_addr}  2001:db8:3333:4444:5555:6666:7777:JJKK
20${test_ipv6_addr1}         2001:db8:3333:4444:5555:6666:7777:9999
21
22# Valid prefix length is a integer ranges from 1 to 128.
23${test_prefix_length}     64
24
25
26*** Test Cases ***
27
28Get IPv6 Address And Verify
29    [Documentation]  Get IPv6 Address And Verify.
30    [Tags]  Get_IPv6_Address_And_Verify
31
32    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
33      Verify IPv6 On BMC  ${ipv6_network_configuration['Address']}
34    END
35
36
37Get PrefixLength And Verify
38    [Documentation]  Get IPv6 prefix length and verify.
39    [Tags]  Get_PrefixLength_And_Verify
40
41    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
42      Verify IPv6 On BMC  ${ipv6_network_configuration['PrefixLength']}
43    END
44
45
46Get IPv6 Default Gateway And Verify
47    [Documentation]  Get IPv6 default gateway and verify.
48    [Tags]  Get_IPv6_Default_Gateway_And_Verify
49
50    ${resp}=  Redfish.Get  ${REDFISH_NW_ETH_IFACE}${ethernet_interface}
51    ${ipv6_gateway}=  Get From Dictionary  ${resp.dict}  IPv6DefaultGateway
52    Verify IPv6 Default Gateway On BMC  ${ipv6_gateway}
53
54
55Verify All Configured IPv6 And PrefixLength On BMC
56    [Documentation]  Verify IPv6 address and its prefix length on BMC.
57    [Tags]  Verify_All_Configured_IPv6_And_PrefixLength_On_BMC
58
59    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
60      Verify IPv6 And PrefixLength  ${ipv6_network_configuration['Address']}
61      ...  ${ipv6_network_configuration['PrefixLength']}
62    END
63
64
65Configure IPv6 Address And Verify
66    [Documentation]  Configure IPv6 address and verify.
67    [Tags]  Configure_IPv6_Address_And_Verify
68    [Template]  Configure IPv6 Address On BMC
69
70
71    # IPv6 address     Prefix length
72    ${test_ipv6_addr}  ${test_prefix_length}
73
74
75Delete IPv6 Address And Verify
76    [Documentation]  Delete IPv6 address and verify.
77    [Tags]  Delete_IPv6_Address_And_Verify
78
79    Configure IPv6 Address On BMC  ${test_ipv6_addr}  ${test_prefix_length}
80
81    Delete IPv6 Address  ${test_ipv6_addr}
82
83
84
85Modify IPv6 Address And verify
86    [Documentation]  Modify IPv6 address and verify.
87    [Tags]  Modify_IPv6_Address_And_Verify
88
89    Configure IPv6 Address On BMC  ${test_ipv6_addr}  ${test_prefix_length}
90
91    Modify IPv6 Address  ${test_ipv6_addr}  ${test_ipv6_addr1}  ${test_prefix_length}
92
93
94*** Keywords ***
95
96Suite Setup Execution
97    [Documentation]  Do suite setup execution.
98
99    ${active_channel_config}=  Get Active Channel Config
100    ${ethernet_interface}=  Set Variable  ${active_channel_config['${CHANNEL_NUMBER}']['name']}
101
102    Set Suite variable  ${ethernet_interface}
103
104
105Test Setup Execution
106    [Documentation]  Test setup execution.
107
108    Redfish.Login
109
110    @{ipv6_network_configurations}=  Get IPv6 Network Configuration
111    Set Test Variable  @{ipv6_network_configurations}
112
113    # Get BMC IPv6 address and prefix length.
114    ${ipv6_data}=  Get BMC IPv6 Info
115    Set Test Variable  ${ipv6_data}
116
117
118Test Teardown Execution
119    [Documentation]  Test teardown execution.
120
121    FFDC On Test Case Fail
122    Redfish.Logout
123
124
125Get IPv6 Network Configuration
126    [Documentation]  Get Ipv6 network configuration.
127    # Sample output:
128    # {
129    #  "@odata.id": "/redfish/v1/Managers/${MANAGER_ID}/EthernetInterfaces/eth0",
130    #  "@odata.type": "#EthernetInterface.v1_4_1.EthernetInterface",
131    #   "DHCPv4": {
132    #    "DHCPEnabled": false,
133    #    "UseDNSServers": false,
134    #    "UseDomainName": true,
135    #    "UseNTPServers": false
136    #  },
137    #  "DHCPv6": {
138    #    "OperatingMode": "Disabled",
139    #    "UseDNSServers": false,
140    #    "UseDomainName": true,
141    #    "UseNTPServers": false
142    #  },
143    #  "Description": "Management Network Interface",
144    #  "FQDN": "localhost",
145    #  "HostName": "localhost",
146    #  "IPv4Addresses": [
147    #    {
148    #      "Address": "xx.xx.xx.xx",
149    #      "AddressOrigin": "Static",
150    #      "Gateway": "xx.xx.xx.1",
151    #      "SubnetMask": "xx.xx.xx.0"
152    #    },
153    #    {
154    #      "Address": "169.254.xx.xx",
155    #      "AddressOrigin": "IPv4LinkLocal",
156    #      "Gateway": "0.0.0.0",
157    #      "SubnetMask": "xx.xx.0.0"
158    #    },
159    #  ],
160    #  "IPv4StaticAddresses": [
161    #    {
162    #      "Address": "xx.xx.xx.xx",
163    #      "AddressOrigin": "Static",
164    #      "Gateway": "xx.xx.xx.1",
165    #      "SubnetMask": "xx.xx.0.0"
166    #    }
167    # }
168    #  ],
169    #  "IPv6AddressPolicyTable": [],
170    #  "IPv6Addresses": [
171    #    {
172    #      "Address": "fe80::xxxx:xxxx:xxxx:xxxx",
173    #      "AddressOrigin": "LinkLocal",
174    #      "AddressState": null,
175    #      "PrefixLength": xx
176    #    }
177    #  ],
178    #  "IPv6DefaultGateway": "",
179    #  "IPv6StaticAddresses": [
180    #    { "Address": "xxxx:xxxx:xxxx:xxxx::xxxx",
181    #      "AddressOrigin": "Static",
182    #      "AddressState": null,
183    #      "PrefixLength": xxx
184    #    }
185    #  ],
186    #  "Id": "eth0",
187    #  "InterfaceEnabled": true,
188    #  "LinkStatus": "LinkUp",
189    #  "MACAddress": "xx:xx:xx:xx:xx:xx",
190    #  "Name": "Manager Ethernet Interface",
191    #  "NameServers": [],
192    #  "SpeedMbps": 0,
193    #  "StaticNameServers": [],
194    #  "Status": {
195    #    "Health": "OK",
196    #    "HealthRollup": "OK",
197    #    "State": "Enabled"
198    #  },
199    #  "VLANs": {
200    #    "@odata.id": "/redfish/v1/Managers/${MANAGER_ID}/EthernetInterfaces/eth0/VLANs"
201
202
203    ${active_channel_config}=  Get Active Channel Config
204    ${resp}=  Redfish.Get  ${REDFISH_NW_ETH_IFACE}${active_channel_config['${CHANNEL_NUMBER}']['name']}
205
206    @{ipv6_network_configurations}=  Get From Dictionary  ${resp.dict}  IPv6StaticAddresses
207    RETURN  @{ipv6_network_configurations}
208
209
210Verify IPv6 And PrefixLength
211    [Documentation]  Verify IPv6 address and prefix length on BMC.
212    [Arguments]  ${ipv6_addr}  ${prefix_len}
213
214    # Description of the argument(s):
215    # ipv6_addr   IPv6 address to be verified.
216    # prefix_len  PrefixLength value to be verified.
217
218    # Catenate IPv6 address and its prefix length.
219    ${ipv6_with_prefix}=  Catenate  ${ipv6_addr}/${prefix_len}
220
221    # Get IPv6 address details on BMC using IP command.
222    @{ip_data}=  Get BMC IPv6 Info
223
224    # Verify if IPv6 and prefix length is configured on BMC.
225
226    Should Contain  ${ip_data}  ${ipv6_with_prefix}
227    ...  msg=IPv6 and prefix length pair does not exist.
228
229
230Configure IPv6 Address On BMC
231    [Documentation]  Add IPv6 Address on BMC.
232    [Arguments]  ${ipv6_addr}  ${prefix_len}  ${valid_status_codes}=${HTTP_OK}
233
234    # Description of argument(s):
235    # ipv6_addr           IPv6 address to be added (e.g. "2001:EEEE:2222::2022").
236    # prefix_len          Prefix length for the IPv6 to be added
237    #                     (e.g. "64").
238    # valid_status_codes  Expected return code from patch operation
239    #                     (e.g. "200").
240
241    ${prefix_length}=  Convert To Integer  ${prefix_len}
242    ${empty_dict}=  Create Dictionary
243    ${ipv6_data}=  Create Dictionary  Address=${ipv6_addr}
244    ...  PrefixLength=${prefix_length}
245
246    ${patch_list}=  Create List
247
248    # Get existing static IPv6 configurations on BMC.
249    ${ipv6_network_configurations}=  Get IPv6 Network Configuration
250    ${num_entries}=  Get Length  ${ipv6_network_configurations}
251
252    FOR  ${INDEX}  IN RANGE  0  ${num_entries}
253      Append To List  ${patch_list}  ${empty_dict}
254    END
255
256    ${valid_status_codes}=  Run Keyword If  '${valid_status_codes}' == '${HTTP_OK}'
257    ...  Set Variable   ${HTTP_OK},${HTTP_NO_CONTENT}
258    ...  ELSE  Set Variable  ${valid_status_codes}
259
260    # We need not check for existence of IPv6 on BMC while adding.
261    Append To List  ${patch_list}  ${ipv6_data}
262    ${data}=  Create Dictionary  IPv6StaticAddresses=${patch_list}
263
264    ${active_channel_config}=  Get Active Channel Config
265    ${ethernet_interface}=  Set Variable  ${active_channel_config['${CHANNEL_NUMBER}']['name']}
266
267    Redfish.patch  ${REDFISH_NW_ETH_IFACE}${ethernet_interface}  body=&{data}
268    ...  valid_status_codes=[${valid_status_codes}]
269
270    Return From Keyword If  '${valid_status_codes}' != '${HTTP_OK},${HTTP_NO_CONTENT}'
271
272    # Note: Network restart takes around 15-18s after patch request processing.
273    Sleep  ${NETWORK_TIMEOUT}s
274    Wait For Host To Ping  ${OPENBMC_HOST}  ${NETWORK_TIMEOUT}
275
276    Verify IPv6 And PrefixLength  ${ipv6_addr}  ${prefix_len}
277
278    # Verify if existing static IPv6 addresses still exist.
279    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
280      Verify IPv6 On BMC  ${ipv6_network_configuration['Address']}
281    END
282
283    Validate IPv6 Network Config On BMC
284
285
286Validate IPv6 Network Config On BMC
287    [Documentation]  Check that IPv6 network info obtained via redfish matches info
288    ...              obtained via CLI.
289    @{ipv6_network_configurations}=  Get IPv6 Network Configuration
290    ${ipv6_data}=  Get BMC IPv6 Info
291    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
292      Should Contain Match  ${ipv6_data}  ${ipv6_network_configuration['Address']}/*
293      ...  msg=IPv6 address does not exist.
294    END
295
296
297Delete IPv6 Address
298    [Documentation]  Delete IPv6 address of BMC.
299    [Arguments]  ${ipv6_addr}  ${valid_status_codes}=${HTTP_OK}
300
301    # Description of argument(s):
302    # ipv6_addr           IPv6 address to be deleted (e.g. "2001:1234:1234:1234::1234").
303    # valid_status_codes  Expected return code from patch operation
304    #                     (e.g. "200").  See prolog of rest_request
305    #                     method in redfish_plus.py for details.
306
307    ${empty_dict}=  Create Dictionary
308    ${patch_list}=  Create List
309
310    @{ipv6_network_configurations}=  Get IPv6 Network Configuration
311    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
312        IF  '${ipv6_network_configuration['Address']}' == '${ipv6_addr}'
313            Append To List  ${patch_list}  ${null}
314        ELSE
315            Append To List  ${patch_list}  ${empty_dict}
316        END
317    END
318
319    ${ip_found}=  Run Keyword And Return Status  List Should Contain Value
320    ...  ${patch_list}  ${null}  msg=${ipv6_addr} does not exist on BMC
321    Pass Execution If  ${ip_found} == ${False}  ${ipv6_addr} does not exist on BMC
322
323    # Run patch command only if given IP is found on BMC
324    ${data}=  Create Dictionary  IPv6StaticAddresses=${patch_list}
325
326    ${active_channel_config}=  Get Active Channel Config
327    ${ethernet_interface}=  Set Variable  ${active_channel_config['${CHANNEL_NUMBER}']['name']}
328
329    Redfish.patch  ${REDFISH_NW_ETH_IFACE}${ethernet_interface}  body=&{data}
330    ...  valid_status_codes=[${valid_status_codes}]
331
332    # Note: Network restart takes around 15-18s after patch request processing
333    Sleep  ${NETWORK_TIMEOUT}s
334    Wait For Host To Ping  ${OPENBMC_HOST}  ${NETWORK_TIMEOUT}
335
336    # IPv6 address that is deleted should not be there on BMC.
337    ${delete_status}=  Run Keyword And Return Status  Verify IPv6 On BMC  ${ipv6_addr}
338    IF  '${valid_status_codes}' == '${HTTP_OK}'
339        Should Be True  '${delete_status}' == '${False}'
340    ELSE
341        Should Be True  '${delete_status}' == '${True}'
342    END
343
344    Validate IPv6 Network Config On BMC
345
346
347Modify IPv6 Address
348    [Documentation]  Modify and verify IPv6 address of BMC.
349    [Arguments]  ${ipv6}  ${new_ipv6}  ${prefix_len}
350    ...  ${valid_status_codes}=[${HTTP_OK}, ${HTTP_NO_CONTENT}]
351
352    # Description of argument(s):
353    # ipv6                  IPv6 address to be replaced (e.g. "2001:AABB:CCDD::AAFF").
354    # new_ipv6              New IPv6 address to be configured.
355    # prefix_len            Prefix length value (Range 1 to 128).
356    # valid_status_codes    Expected return code from patch operation
357    #                       (e.g. "200", "201").
358
359    ${empty_dict}=  Create Dictionary
360    ${patch_list}=  Create List
361    ${prefix_length}=  Convert To Integer  ${prefix_len}
362    ${ipv6_data}=  Create Dictionary
363    ...  Address=${new_ipv6}  PrefixLength=${prefix_length}
364
365    # Sample IPv6 network configurations:
366    #  "IPv6AddressPolicyTable": [],
367    #  "IPv6Addresses": [
368    #    {
369    #      "Address": "X002:db8:0:2::XX0",
370    #      "AddressOrigin": "DHCPv6",
371    #      "PrefixLength": 128
372    #    },
373    #    {
374    #      "Address": “X002:db8:0:2:a94:XXff:fe82:XXXX",
375    #      "AddressOrigin": "SLAAC",
376    #      "PrefixLength": 64
377    #    },
378    #    {
379    #      "Address": “Y002:db8:0:2:a94:efff:fe82:5000",
380    #      "AddressOrigin": "Static",
381    #      "PrefixLength": 56
382    #    },
383    #    {
384    #      "Address": “Z002:db8:0:2:a94:efff:fe82:5000",
385    #      "AddressOrigin": "Static",
386    #      "PrefixLength": 56
387    #    },
388    #    {
389    #      "Address": “Xe80::a94:efff:YYYY:XXXX",
390    #      "AddressOrigin": "LinkLocal",
391    #      "PrefixLength": 64
392    #    },
393    #    {
394    #     "Address": “X002:db8:1:2:eff:233:fee:546",
395    #      "AddressOrigin": "Static",
396    #      "PrefixLength": 56
397    #    }
398    #  ],
399    #  "IPv6DefaultGateway": “XXXX::ab2e:80fe:87df:XXXX”,
400    #  "IPv6StaticAddresses": [
401    #    {
402    #      "Address": “X002:db8:0:2:a94:efff:fe82:5000",
403    #      "PrefixLength": 56
404    #    },
405    #    {
406    #      "Address": “Y002:db8:0:2:a94:efff:fe82:5000",
407    #      "PrefixLength": 56
408    #    },
409    #    {
410    #      "Address": “Z002:db8:1:2:eff:233:fee:546",
411    #      "PrefixLength": 56
412    #    }
413    #  ],
414    #  "IPv6StaticDefaultGateways": [],
415
416    # Find the position of IPv6 address to be modified.
417    @{ipv6_network_configurations}=  Get IPv6 Network Configuration
418    FOR  ${ipv6_network_configuration}  IN  @{ipv6_network_configurations}
419      Run Keyword If  '${ipv6_network_configuration['Address']}' == '${ipv6}'
420      ...  Append To List  ${patch_list}  ${ipv6_data}
421      ...  ELSE  Append To List  ${patch_list}  ${empty_dict}
422    END
423
424    # Modify the IPv6 address only if given IPv6 is found
425    ${ip_found}=  Run Keyword And Return Status  List Should Contain Value
426    ...  ${patch_list}  ${ipv6_data}  msg=${ipv6} does not exist on BMC
427    Pass Execution If  ${ip_found} == ${False}  ${ipv6} does not exist on BMC
428
429    ${data}=  Create Dictionary  IPv6StaticAddresses=${patch_list}
430
431    ${active_channel_config}=  Get Active Channel Config
432    ${ethernet_interface}=  Set Variable  ${active_channel_config['${CHANNEL_NUMBER}']['name']}
433
434    Redfish.patch  ${REDFISH_NW_ETH_IFACE}${ethernet_interface}
435    ...  body=&{data}  valid_status_codes=${valid_status_codes}
436
437    # Note: Network restart takes around 15-18s after patch request processing.
438    Sleep  ${NETWORK_TIMEOUT}s
439    Wait For Host To Ping  ${OPENBMC_HOST}  ${NETWORK_TIMEOUT}
440
441    # Verify if new IPv6 address is configured on BMC.
442    Verify IPv6 On BMC  ${new_ipv6}
443
444    # Verify if old IPv6 address is erased.
445    ${cmd_status}=  Run Keyword And Return Status
446    ...  Verify IPv6 On BMC  ${ipv6}
447    Should Be Equal  ${cmd_status}  ${False}  msg=Old IPv6 address is not deleted.
448
449    Validate IPv6 Network Config On BMC
450