--- /dev/null
+*** Settings ***
+Documentation Basic tests for iBGP peers.
+...
+... Copyright (c) 2015-2016 Cisco Systems, Inc. and others. All rights reserved.
+...
+... This program and the accompanying materials are made available under the
+... terms of the Eclipse Public License v1.0 which accompanies this distribution,
+... and is available at http://www.eclipse.org/legal/epl-v10.html
+...
+... Test suite performs basic iBGP functional test cases for
+... BGP peers in different roles (iBGP, iBGP RR-client):
+...
+... Test Case 1: Two iBGP RR-client peers introduce prefixes
+... Expected result: controller forwards updates towards both peers
+...
+... Test Case 2: Two iBGP peers: one RR client and one non-client introduces prefixes
+... Expected result: controller forwards updates towards both peers
+...
+... Test Case 3: Two iBGP RR non-client peers introduce prefixes
+... Expected result: controller does not forward any update towards peers
+...
+... For polices see: https://wiki.opendaylight.org/view/BGP_LS_PCEP:BGP
+...
+... Covered bugs:
+... Bug 4791 - BGPSessionImpl: Failed to send message Update logged even all UPDATE mesages received by iBGP peer
+... Bug 4819 - No routes advertised to one of newly configured iBGP RR-client peer
+Suite Setup Setup_Everything
+Suite Teardown Teardown_Everything
+Test Setup SetupUtils.Setup_Test_With_Logging_And_Without_Fast_Failing
+Test Teardown FailFast.Start_Failing_Fast_If_This_Failed
+Library OperatingSystem
+Library RequestsLibrary
+Library DateTime
+Library ${CURDIR}/../../../libraries/HsfJson/hsf_json.py
+Variables ${CURDIR}/../../../variables/Variables.py
+Variables ${CURDIR}/../../../variables/bgpuser/variables.py ${ODL_SYSTEM_PROMPT}
+Resource ${CURDIR}/../../../libraries/BGPSpeaker.robot
+Resource ${CURDIR}/../../../libraries/ConfigViaRestconf.robot
+Resource ${CURDIR}/../../../libraries/FailFast.robot
+Resource ${CURDIR}/../../../libraries/KarafKeywords.robot
+Resource ${CURDIR}/../../../libraries/KillPythonTool.robot
+Resource ${CURDIR}/../../../libraries/SetupUtils.robot
+Resource ${CURDIR}/../../../libraries/SSHKeywords.robot
+Resource ${CURDIR}/../../../libraries/Utils.robot
+Resource ${CURDIR}/../../../libraries/WaitForFailure.robot
+
+*** Variables ***
+${BGP_VARIABLES_FOLDER} ${CURDIR}/../../../variables/bgpuser/
+${HOLDTIME} 180
+${BGP_PEER_LOG_LEVEL} debug
+${CONTROLLER_LOG_LEVEL} INFO
+${CONTROLLER_BGP_LOG_LEVEL} DEFAULT
+${BGP_PEER1_IP} 127.0.0.1
+${BGP_PEER2_IP} 127.0.0.2
+${BGP_PEER1_FIRST_PREFIX_IP} 8.1.0.0
+${BGP_PEER2_FIRST_PREFIX_IP} 8.2.0.0
+${PREFIX_LEN} 28
+${BGP_PEER1_PREFIX_LEN} ${PREFIX_LEN}
+${BGP_PEER2_PREFIX_LEN} ${PREFIX_LEN}
+${PREFIX_COUNT} 3
+${BGP_PEER1_PREFIX_COUNT} ${PREFIX_COUNT}
+${BGP_PEER2_PREFIX_COUNT} ${PREFIX_COUNT}
+${BGP_PEER1_LOG_FILE} bgp_peer1.log
+${BGP_PEER2_LOG_FILE} bgp_peer2.log
+${BGP_PEER1_COMMAND} python play.py --firstprefix ${BGP_PEER1_FIRST_PREFIX_IP} --prefixlen ${BGP_PEER1_PREFIX_LEN} --amount ${BGP_PEER1_PREFIX_COUNT} --myip=${BGP_PEER1_IP} --myport=${BGP_TOOL_PORT} --peerip=${ODL_SYSTEM_IP} --peerport=${ODL_BGP_PORT} --${BGP_PEER_LOG_LEVEL} --logfile ${BGP_PEER1_LOG_FILE}
+${BGP_PEER2_COMMAND} python play.py --firstprefix ${BGP_PEER2_FIRST_PREFIX_IP} --prefixlen ${BGP_PEER2_PREFIX_LEN} --amount ${BGP_PEER2_PREFIX_COUNT} --myip=${BGP_PEER2_IP} --myport=${BGP_TOOL_PORT} --peerip=${ODL_SYSTEM_IP} --peerport=${ODL_BGP_PORT} --${BGP_PEER_LOG_LEVEL} --logfile ${BGP_PEER2_LOG_FILE}
+${BGP_PEER1_OPTIONS} &>${BGP_PEER1_LOG_FILE}
+${BGP_PEER2_OPTIONS} &>${BGP_PEER2_LOG_FILE}
+${DEFAULT_LOG_CHECK_TIMEOUT} 20s
+${DEFAULT_LOG_CHECK_PERIOD} 1s
+${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} 10s
+${DEFAULT_TOPOLOGY_CHECK_PERIOD} 1s
+
+*** Test Cases ***
+TC1_Configure_Two_iBGP_Route_Reflector_Client_Peers
+ [Documentation] Configure two iBGP peers as routing reflector clients.
+ [Tags] critical
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1', 'IP': '${BGP_PEER1_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}','PEER_ROLE': 'rr-client', 'INITIATE': 'false'}
+ ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2', 'IP': '${BGP_PEER2_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}','PEER_ROLE': 'rr-client', 'INITIATE': 'false'}
+ ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1'}
+ ${result}= ConfigViaRestconf.Get_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ BuiltIn.Log ${result}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2'}
+ ${result}= ConfigViaRestconf.Get_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ BuiltIn.Log ${result}
+
+TC1_Connect_BGP_Peer1
+ [Documentation] Connect BGP peer
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ Start_Console_Tool ${BGP_PEER1_COMMAND} ${BGP_PEER1_OPTIONS}
+ Read_And_Fail_If_Prompt_Is_Seen
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Content {"prefix":"${BGP_PEER1_FIRST_PREFIX_IP}/${PREFIX_LEN}"}
+
+TC1_Connect_BGP_Peer2
+ [Documentation] Connect BGP peer
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ Start_Console_Tool ${BGP_PEER2_COMMAND} ${BGP_PEER2_OPTIONS}
+ Read_And_Fail_If_Prompt_Is_Seen
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Content {"prefix":"${BGP_PEER2_FIRST_PREFIX_IP}/${PREFIX_LEN}"}
+
+TC1_BGP_Peer1_Check_Log_For_Introduced_Prefixes
+ [Documentation] Check incomming updates for new routes
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} nlri_prefix_received: ${BGP_PEER2_PREFIX_COUNT}
+ Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} nlri_prefix_received: ${BGP_PEER2_FIRST_PREFIX_IP}/${BGP_PEER2_PREFIX_LEN} 1
+ Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} withdrawn_prefix_received: 0
+ [Teardown] Report_Failure_Due_To_Bug 4819
+
+TC1_BGP_Peer2_Check_Log_For_Introduced_Prefixes
+ [Documentation] Check incomming updates for new routes
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} nlri_prefix_received: ${BGP_PEER1_PREFIX_COUNT}
+ Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} nlri_prefix_received: ${BGP_PEER1_FIRST_PREFIX_IP}/${BGP_PEER1_PREFIX_LEN} 1
+ Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} withdrawn_prefix_received: 0
+ [Teardown] Report_Failure_Due_To_Bug 4819
+
+TC1_Disconnect_BGP_Peer1
+ [Documentation] Stop BGP peer & store logs
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ Stop_Console_Tool
+ Store_File_To_Workspace ${BGP_PEER1_LOG_FILE} tc1_${BGP_PEER1_LOG_FILE}
+
+TC1_BGP_Peer2_Check_Log_For_Withdrawn_Prefixes
+ [Documentation] Check incomming updates for withdrawn routes
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} withdrawn_prefix_received: ${BGP_PEER1_PREFIX_COUNT}
+ Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} withdrawn_prefix_received: ${BGP_PEER1_FIRST_PREFIX_IP}/${BGP_PEER1_PREFIX_LEN} 1
+ [Teardown] Report_Failure_Due_To_Bug 4819
+
+TC1_Disconnect_BGP_Peer2
+ [Documentation] Stop BGP peer & store logs
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ Stop_Console_Tool
+ Store_File_To_Workspace ${BGP_PEER2_LOG_FILE} tc1_${BGP_PEER2_LOG_FILE}
+
+TC_1_Check_for_Empty_IPv4_Topology
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Does_Not_Contain prefix
+
+TC1_Delete_BGP_Peers_Configuration
+ [Documentation] Delete all previously configured BGP peers.
+ [Tags] critical
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1'}
+ ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2'}
+ ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+
+TC2_Configure_One_iBGP_Route_Reflector_Client_And_One_iBGP_Non_Client
+ [Documentation] Configure iBGP peers: 1st one as RR client, 2nd one as RR non-client.
+ [Tags] critical
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1', 'IP': '${BGP_PEER1_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}','PEER_ROLE': 'rr-client', 'INITIATE': 'false'}
+ ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2', 'IP': '${BGP_PEER2_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}','PEER_ROLE': 'ibgp', 'INITIATE': 'false'}
+ ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1'}
+ ${result}= ConfigViaRestconf.Get_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ BuiltIn.Log ${result}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2'}
+ ${result}= ConfigViaRestconf.Get_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ BuiltIn.Log ${result}
+
+TC2_Connect_BGP_Peer1
+ [Documentation] Connect BGP peer
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ Start_Console_Tool ${BGP_PEER1_COMMAND} ${BGP_PEER1_OPTIONS}
+ Read_And_Fail_If_Prompt_Is_Seen
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Content {"prefix":"${BGP_PEER1_FIRST_PREFIX_IP}/${PREFIX_LEN}"}
+
+TC2_Connect_BGP_Peer2
+ [Documentation] Connect BGP peer
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ Start_Console_Tool ${BGP_PEER2_COMMAND} ${BGP_PEER2_OPTIONS}
+ Read_And_Fail_If_Prompt_Is_Seen
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Content {"prefix":"${BGP_PEER2_FIRST_PREFIX_IP}/${PREFIX_LEN}"}
+
+TC2_BGP_Peer1_Check_Log_For_Introduced_Prefixes
+ [Documentation] Check incomming updates for new routes
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} nlri_prefix_received: ${BGP_PEER2_PREFIX_COUNT}
+ Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} nlri_prefix_received: ${BGP_PEER2_FIRST_PREFIX_IP}/${BGP_PEER2_PREFIX_LEN} 1
+ Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} withdrawn_prefix_received: 0
+
+TC2_BGP_Peer2_Check_Log_For_Introduced_Prefixes
+ [Documentation] Check incomming updates for new routes
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} nlri_prefix_received: ${BGP_PEER1_PREFIX_COUNT}
+ Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} nlri_prefix_received: ${BGP_PEER1_FIRST_PREFIX_IP}/${BGP_PEER1_PREFIX_LEN} 1
+ Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} withdrawn_prefix_received: 0
+ [Teardown] Report_Failure_Due_To_Bug 4791
+
+TC2_Disconnect_BGP_Peer1
+ [Documentation] Stop BGP peer & store logs
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ Stop_Console_Tool
+ Store_File_To_Workspace ${BGP_PEER1_LOG_FILE} tc2_${BGP_PEER1_LOG_FILE}
+
+TC2_BGP_Peer2_Check_Log_For_Withdrawn_Prefixes
+ [Documentation] Check incomming updates for withdrawn routes
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} withdrawn_prefix_received: ${BGP_PEER1_PREFIX_COUNT}
+ Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} withdrawn_prefix_received: ${BGP_PEER1_FIRST_PREFIX_IP}/${BGP_PEER1_PREFIX_LEN} 1
+
+TC2_Disconnect_BGP_Peer2
+ [Documentation] Stop BGP peer & store logs
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ Stop_Console_Tool
+ Store_File_To_Workspace ${BGP_PEER2_LOG_FILE} tc2_${BGP_PEER2_LOG_FILE}
+
+TC_2_Check_for_Empty_IPv4_Topology
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Does_Not_Contain prefix
+
+TC2_Delete_BGP_Peers_Configuration
+ [Documentation] Delete all previously configured BGP peers.
+ [Tags] critical
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1'}
+ ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2'}
+ ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+
+TC3_Configure_Two_iBGP_Non_Client_Peers
+ [Documentation] Configure iBGP peers: 1st one as RR client, 2nd one as RR non-client.
+ [Tags] critical
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1', 'IP': '${BGP_PEER1_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}','PEER_ROLE': 'ibgp', 'INITIATE': 'false'}
+ ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2', 'IP': '${BGP_PEER2_IP}', 'HOLDTIME': '${HOLDTIME}', 'PEER_PORT': '${BGP_TOOL_PORT}','PEER_ROLE': 'ibgp', 'INITIATE': 'false'}
+ ConfigViaRestconf.Put_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1'}
+ ${result}= ConfigViaRestconf.Get_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ BuiltIn.Log ${result}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2'}
+ ${result}= ConfigViaRestconf.Get_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ BuiltIn.Log ${result}
+
+TC3_Connect_BGP_Peer1
+ [Documentation] Connect BGP peer
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ Start_Console_Tool ${BGP_PEER1_COMMAND} ${BGP_PEER1_OPTIONS}
+ Read_And_Fail_If_Prompt_Is_Seen
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Content {"prefix":"${BGP_PEER1_FIRST_PREFIX_IP}/${PREFIX_LEN}"}
+
+TC3_Connect_BGP_Peer2
+ [Documentation] Connect BGP peer
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ Start_Console_Tool ${BGP_PEER2_COMMAND} ${BGP_PEER2_OPTIONS}
+ Read_And_Fail_If_Prompt_Is_Seen
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Content {"prefix":"${BGP_PEER2_FIRST_PREFIX_IP}/${PREFIX_LEN}"}
+
+TC3_BGP_Peer1_Check_Log_For_No_Updates
+ [Documentation] Check for no updates received by iBGP peer No. 1
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_LOG_CHECK_TIMEOUT} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER1_LOG_FILE} total_received_update_message_counter: 0 2
+
+TC3_Disconnect_BGP_Peer1
+ [Documentation] Stop BGP peer & store logs
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer1_console
+ Stop_Console_Tool
+ Store_File_To_Workspace ${BGP_PEER1_LOG_FILE} tc3_${BGP_PEER1_LOG_FILE}
+
+TC3_BGP_Peer2_Check_Log_For_No_Updates
+ [Documentation] Consequent check for no updates received by iBGP peer No. 2
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ ${log_check_timeout}= DateTime.Convert_Time ${DEFAULT_LOG_CHECK_TIMEOUT} result_format=number
+ BuiltIn.Wait_Until_Keyword_Succeeds ${log_check_timeout*2} ${DEFAULT_LOG_CHECK_PERIOD} Check_File_For_Word_Count ${BGP_PEER2_LOG_FILE} total_received_update_message_counter: 0 4
+
+TC3_Disconnect_BGP_Peer2
+ [Documentation] Stop BGP peer & store logs
+ [Tags] critical
+ SSHLibrary.Switch Connection bgp_peer2_console
+ Stop_Console_Tool
+ Store_File_To_Workspace ${BGP_PEER2_LOG_FILE} tc3_${BGP_PEER2_LOG_FILE}
+
+TC_3_Check_for_Empty_IPv4_Topology
+ BuiltIn.Wait_Until_Keyword_Succeeds ${DEFAULT_TOPOLOGY_CHECK_TIMEOUT} ${DEFAULT_TOPOLOGY_CHECK_PERIOD} Check_Example_IPv4_Topology_Does_Not_Contain prefix
+
+TC3_Delete_BGP_Peers_Configuration
+ [Documentation] Delete all previously configured BGP peers.
+ [Tags] critical
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer1'}
+ ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+ ${template_as_string}= BuiltIn.Set_Variable {'NAME': 'example-bgp-peer2'}
+ ConfigViaRestconf.Delete_Xml_Template_Folder_Config_Via_Restconf ${BGP_VARIABLES_FOLDER}${/}ibgp_peers ${template_as_string}
+
+*** Keywords ***
+Setup_Everything
+ [Documentation] SSH-login to mininet machine, create HTTP session,
+ ... prepare directories for responses, put Python tool to mininet machine, setup imported resources.
+ # TODO: Choose keywords used by more than one test suite to be placed in a common place.
+ SetupUtils.Setup_Utils_For_Setup_And_Teardown
+ SSHLibrary.Set_Default_Configuration prompt=${ODL_SYSTEM_PROMPT}
+ SSHLibrary.Open_Connection ${ODL_SYSTEM_IP} alias=bgp_peer1_console
+ Utils.Flexible_Controller_Login
+ SSHLibrary.Open_Connection ${ODL_SYSTEM_IP} alias=bgp_peer2_console
+ Utils.Flexible_Controller_Login
+ SSHKeywords.Require_Python
+ SSHKeywords.Assure_Library_Ipaddr target_dir=.
+ SSHLibrary.Put_File ${CURDIR}/../../../../tools/fastbgp/play.py
+ RequestsLibrary.Create_Session operational http://${ODL_SYSTEM_IP}:${RESTCONFPORT}${OPERATIONAL_TOPO_API} auth=${AUTH}
+ ConfigViaRestconf.Setup_Config_Via_Restconf
+ KarafKeywords.Execute_Controller_Karaf_Command_On_Background log:set ${CONTROLLER_LOG_LEVEL}
+ KarafKeywords.Execute_Controller_Karaf_Command_On_Background log:set ${CONTROLLER_BGP_LOG_LEVEL} org.opendaylight.bgpcep
+ KarafKeywords.Execute_Controller_Karaf_Command_On_Background log:set ${CONTROLLER_BGP_LOG_LEVEL} org.opendaylight.protocol
+
+Teardown_Everything
+ [Documentation] Create and Log the diff between expected and actual responses, make sure Python tool was killed.
+ ... Tear down imported Resources.
+ KillPythonTool.Search_And_Kill_Remote_Python 'play\.py'
+ ConfigViaRestconf.Teardown_Config_Via_Restconf
+ RequestsLibrary.Delete_All_Sessions
+ SSHLibrary.Close_All_Connections
+
+Start_Console_Tool
+ [Arguments] ${command} ${tool_opt}
+ [Documentation] Start the tool ${command} ${tool_opt}
+ BuiltIn.Log ${command}
+ ${output}= SSHLibrary.Write ${command} ${tool_opt}
+ BuiltIn.Log ${output}
+
+Wait_Until_Console_Tool_Finish
+ [Arguments] ${timeout}
+ [Documentation] Wait ${timeout} for the tool exit.
+ BuiltIn.Wait Until Keyword Succeeds ${timeout} 1s SSHLibrary.Read Until Prompt
+
+Stop_Console_Tool
+ [Documentation] Stop the tool if still running.
+ Utils.Write_Bare_Ctrl_C
+ BuiltIn.Wait Until Keyword Succeeds 10s 1s SSHLibrary.Read Until Prompt
+
+Check_Example_IPv4_Topology_Content
+ [Arguments] ${string_to_check}=${EMPTY}
+ [Documentation] Check the example-ipv4-topology content for string
+ ${response}= RequestsLibrary.Get Request operational topology/example-ipv4-topology
+ BuiltIn.Log ${response.status_code}
+ BuiltIn.Log ${response.text}
+ BuiltIn.Should_Contain ${response.text} ${string_to_check}
+
+Check_Example_IPv4_Topology_Does_Not_Contain
+ [Arguments] ${string_to_check}
+ [Documentation] Check the example-ipv4-topology does not contain the string
+ ${response}= RequestsLibrary.Get Request operational topology/example-ipv4-topology
+ BuiltIn.Log ${response.status_code}
+ BuiltIn.Log ${response.text}
+ BuiltIn.Should_Not_Contain ${response.text} ${string_to_check}
+
+Read_And_Fail_If_Prompt_Is_Seen
+ [Documentation] Try to read SSH to see prompt, but expect to see no prompt within SSHLibrary's timeout.
+ ${passed}= BuiltIn.Run_Keyword_And_Return_Status BuiltIn.Run_Keyword_And_Expect_Error No match found for '${ODL_SYSTEM_PROMPT}' in *. Read_Text_Before_Prompt
+ BuiltIn.Return_From_Keyword_If ${passed}
+ BGPSpeaker.Dump_BGP_Speaker_Logs
+ Builtin.Fail The prompt was seen but it was not expected yet
+
+Read_Text_Before_Prompt
+ [Documentation] Log text gathered by SSHLibrary.Read_Until_Prompt.
+ ... This needs to be a separate keyword just because how Read_And_Fail_If_Prompt_Is_Seen is implemented.
+ ${text}= SSHLibrary.Read_Until_Prompt
+ BuiltIn.Log ${text}
+
+Store_File_To_Workspace
+ [Arguments] ${source_file_name} ${target_file_name}
+ [Documentation] Store the ${source_file_name} to the workspace as ${target_file_name}.
+ ${output_log}= SSHLibrary.Execute_Command cat ${source_file_name}
+ BuiltIn.Log ${output_log}
+ Create File ${target_file_name} ${output_log}
+
+Check_File_For_Word_Count
+ [Arguments] ${file_name} ${word} ${expected_count}
+ [Documentation] Count ${word} in ${file_name}. Expect ${expected_count} occurence(s)
+ ${output_log}= SSHLibrary.Execute_Command grep -o '${word}' ${file_name} | wc -l
+ BuiltIn.Log ${output_log}
+ BuiltIn.Should_Be_Equal_As_Strings ${output_log} ${expected_count}
+
+Check_File_For_Occurence
+ [Arguments] ${file_name} ${keyword} ${value}=''
+ [Documentation] Check file for ${keyword} or ${keyword} ${value} pair and returns number of occurences
+ ${output_log}= SSHLibrary.Execute_Command grep '${keyword}' ${file_name} | grep -c ${value}
+ ${count}= Convert To Integer ${output_log}
+ [Return] ${count}
str_help = "The IP of the next hop to be placed into the update messages."
parser.add_argument("--nexthop", default="192.0.2.1",
type=ipaddr.IPv4Address, dest="nexthop", help=str_help)
+ str_help = "Identifier of the route originator."
+ parser.add_argument("--originator", default=None,
+ type=ipaddr.IPv4Address, dest="originator", help=str_help)
+ str_help = "Cluster list item identifier."
+ parser.add_argument("--cluster", default=None,
+ type=ipaddr.IPv4Address, dest="cluster", help=str_help)
str_help = ("Numeric IP Address to try to connect to." +
"Currently no effect in listening mode.")
parser.add_argument("--peerip", default="127.0.0.2",
self.hold_time_default = args.holdtime # Local hold time.
self.bgp_identifier_default = int(args.myip)
self.next_hop_default = args.nexthop
+ self.originator_id_default = args.originator
+ self.cluster_list_item_default = args.cluster
self.single_update_default = args.updates == "single"
self.randomize_updates_default = args.updates == "random"
self.prefix_count_to_add_default = args.insert
logger.info(" My Hold Time: " + str(self.hold_time_default))
logger.info(" My BGP Identifier: " + str(self.bgp_identifier_default))
logger.info(" Next Hop: " + str(self.next_hop_default))
+ logger.info(" Originator ID: " + str(self.originator_id_default))
+ logger.info(" Cluster list: " + str(self.cluster_list_item_default))
logger.info(" Prefix count to be inserted at once: " +
str(self.prefix_count_to_add_default))
logger.info(" Prefix count to be withdrawn at once: " +
:return: n/a
"""
# default values handling
+ # TODO optimize default values handling (use e.g. dicionary.update() approach)
if file_name is None:
file_name = self.results_file_name_default
if threshold is None:
Created just as a fame for future generator enhancement.
"""
# default values handling
+ # TODO optimize default values handling (use e.g. dicionary.update() approach)
if lowest is None:
lowest = self.randomize_lowest_default
if highest is None:
:return: list of generated IP address prefixes
"""
# default values handling
+ # TODO optimize default values handling (use e.g. dicionary.update() approach)
if slot_size is None:
slot_size = self.slot_size_default
if prefix_base is None:
Updates global counters.
"""
# default values handling
+ # TODO optimize default values handling (use e.g. dicionary.update() approach)
if prefix_count_to_add is None:
prefix_count_to_add = self.prefix_count_to_add_default
if prefix_count_to_del is None:
:return: encoded OPEN message in HEX
"""
- # Default values handling
+ # default values handling
+ # TODO optimize default values handling (use e.g. dicionary.update() approach)
if version is None:
version = self.version_default
if my_autonomous_system is None:
def update_message(self, wr_prefixes=None, nlri_prefixes=None,
wr_prefix_length=None, nlri_prefix_length=None,
- my_autonomous_system=None, next_hop=None):
+ my_autonomous_system=None, next_hop=None,
+ originator_id=None, cluster_list_item=None):
"""Generates an UPDATE Message (rfc4271#section-4.3)
Arguments:
:return: encoded UPDATE message in HEX
"""
- # Default values handling
+ # default values handling
+ # TODO optimize default values handling (use e.g. dicionary.update() approach)
if wr_prefixes is None:
wr_prefixes = self.wr_prefixes_default
if nlri_prefixes is None:
my_autonomous_system = self.my_autonomous_system_default
if next_hop is None:
next_hop = self.next_hop_default
+ if originator_id is None:
+ originator_id = self.originator_id_default
+ if cluster_list_item is None:
+ cluster_list_item = self.cluster_list_item_default
# Marker
marker_hex = "\xFF" * 16
# TODO: to replace hardcoded string by encoding?
# Path Attributes
+ path_attributes_hex = ""
if nlri_prefixes != []:
- path_attributes_hex = (
+ path_attributes_hex += (
"\x40" # Flags ("Well-Known")
"\x01" # Type (ORIGIN)
"\x01" # Length (1)
"\x00" # Origin: IGP
+ )
+ path_attributes_hex += (
"\x40" # Flags ("Well-Known")
"\x02" # Type (AS_PATH)
"\x06" # Length (6)
path_attributes_hex += (
next_hop_hex # IP address of the next hop (4 bytes)
)
- else:
- path_attributes_hex = ""
+ if originator_id is not None:
+ path_attributes_hex += (
+ "\x80" # Flags ("Optional, non-transitive")
+ "\x09" # Type (ORIGINATOR_ID)
+ "\x04" # Length (4)
+ # ORIGINATOR_ID (4 bytes)
+ + struct.pack(">I", int(originator_id))
+ )
+ if cluster_list_item is not None:
+ path_attributes_hex += (
+ "\x80" # Flags ("Optional, non-transitive")
+ "\x09" # Type (CLUSTER_LIST)
+ "\x04" # Length (4)
+ # one CLUSTER_LIST item (4 bytes)
+ + struct.pack(">I", int(cluster_list_item))
+ )
# Total Path Attributes Length
total_path_attributes_length = len(path_attributes_hex)
logger.debug(" Withdrawn_Routes=" + str(wr_prefixes) + "/" +
str(wr_prefix_length) + " (0x" +
binascii.hexlify(withdrawn_routes_hex) + ")")
- logger.debug(" Total Path Attributes Length=" +
- str(total_path_attributes_length) + " (0x" +
- binascii.hexlify(total_path_attributes_length_hex) +
- ")")
- logger.debug(" Path Attributes=" + "(0x" +
- binascii.hexlify(path_attributes_hex) + ")")
+ if total_path_attributes_length:
+ logger.debug(" Total Path Attributes Length=" +
+ str(total_path_attributes_length) + " (0x" +
+ binascii.hexlify(total_path_attributes_length_hex) + ")")
+ logger.debug(" Path Attributes=" + "(0x" +
+ binascii.hexlify(path_attributes_hex) + ")")
+ logger.debug(" Origin=IGP")
+ logger.debug(" AS path=" + str(my_autonomous_system))
+ logger.debug(" Next hop=" + str(next_hop))
+ if originator_id is not None:
+ logger.debug(" Originator id=" + str(originator_id))
+ if cluster_list_item is not None:
+ logger.debug(" Cluster list=" + str(cluster_list_item))
logger.debug(" Network Layer Reachability Information=" +
str(nlri_prefixes) + "/" + str(nlri_prefix_length) +
" (0x" + binascii.hexlify(nlri_hex) + ")")
hex_to_decode = hex_to_decode[3 + attr_length:]
if attr_type_code == 1:
- logger.debug("Attribute type = 1 (ORIGIN, flags:0x%s)",
+ logger.debug("Attribute type=1 (ORIGIN, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 2:
- logger.debug("Attribute type = 2 (AS_PATH, flags:0x%s)",
+ logger.debug("Attribute type=2 (AS_PATH, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 3:
- logger.debug("Attribute type = 3 (NEXT_HOP, flags:0x%s)",
+ logger.debug("Attribute type=3 (NEXT_HOP, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 4:
- logger.debug("Attribute type = 4 (MULTI_EXIT_DISC, flags:0x%s)",
+ logger.debug("Attribute type=4 (MULTI_EXIT_DISC, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 5:
- logger.debug("Attribute type = 5 (LOCAL_PREF, flags:0x%s)",
+ logger.debug("Attribute type=5 (LOCAL_PREF, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 6:
- logger.debug("Attribute type = 6 (ATOMIC_AGGREGATE, flags:0x%s)",
+ logger.debug("Attribute type=6 (ATOMIC_AGGREGATE, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 7:
- logger.debug("Attribute type = 7 (AGGREGATOR, flags:0x%s)",
+ logger.debug("Attribute type=7 (AGGREGATOR, flags:0x%s)",
+ binascii.b2a_hex(attr_flags_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
+ elif attr_type_code == 9: # rfc4456#section-8
+ logger.debug("Attribute type=9 (ORIGINATOR_ID, flags:0x%s)",
+ binascii.b2a_hex(attr_flags_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
+ elif attr_type_code == 10: # rfc4456#section-8
+ logger.debug("Attribute type=10 (CLUSTER_LIST, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
elif attr_type_code == 14: # rfc4760#section-3
- logger.debug("Attribute type = 14 (MP_REACH_NLRI, flags:0x%s)",
+ logger.debug("Attribute type=14 (MP_REACH_NLRI, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
address_family_identifier_hex = attr_value_hex[0:2]
- logger.debug(" Address Family Identifier = 0x%s",
+ logger.debug(" Address Family Identifier=0x%s",
binascii.b2a_hex(address_family_identifier_hex))
subsequent_address_family_identifier_hex = attr_value_hex[2]
- logger.debug(" Subsequent Address Family Identifier = 0x%s",
+ logger.debug(" Subsequent Address Family Identifier=0x%s",
binascii.b2a_hex(subsequent_address_family_identifier_hex))
next_hop_netaddr_len_hex = attr_value_hex[3]
next_hop_netaddr_len = int(binascii.b2a_hex(next_hop_netaddr_len_hex), 16)
- logger.debug(" Length of Next Hop Network Address = 0x%s (%s)",
- binascii.b2a_hex(next_hop_netaddr_len_hex),
- next_hop_netaddr_len)
+ logger.debug(" Length of Next Hop Network Address=%s (0x%s)",
+ next_hop_netaddr_len,
+ binascii.b2a_hex(next_hop_netaddr_len_hex))
next_hop_netaddr_hex = attr_value_hex[4:4 + next_hop_netaddr_len]
- logger.debug(" Network Address of Next Hop = 0x%s",
- binascii.b2a_hex(next_hop_netaddr_hex))
+ next_hop_netaddr = ".".join(str(i) for i in struct.unpack("BBBB", next_hop_netaddr_hex))
+ logger.debug(" Network Address of Next Hop=%s (0x%s)",
+ next_hop_netaddr, binascii.b2a_hex(next_hop_netaddr_hex))
reserved_hex = attr_value_hex[4 + next_hop_netaddr_len]
- logger.debug(" Reserved = 0x%s",
+ logger.debug(" Reserved=0x%s",
binascii.b2a_hex(reserved_hex))
nlri_hex = attr_value_hex[4 + next_hop_netaddr_len + 1:]
- logger.debug(" Network Layer Reachability Information = 0x%s",
+ logger.debug(" Network Layer Reachability Information=0x%s",
binascii.b2a_hex(nlri_hex))
nlri_prefix_list = get_prefix_list_from_hex(nlri_hex)
logger.debug(" NLRI prefix list: %s", nlri_prefix_list)
logger.debug(" nlri_prefix_received: %s", prefix)
self.prefixes_introduced += len(nlri_prefix_list) # update counter
elif attr_type_code == 15: # rfc4760#section-4
- logger.debug("Attribute type = 15 (MP_UNREACH_NLRI, flags:0x%s)",
+ logger.debug("Attribute type=15 (MP_UNREACH_NLRI, flags:0x%s)",
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
address_family_identifier_hex = attr_value_hex[0:2]
- logger.debug(" Address Family Identifier = 0x%s",
+ logger.debug(" Address Family Identifier=0x%s",
binascii.b2a_hex(address_family_identifier_hex))
subsequent_address_family_identifier_hex = attr_value_hex[2]
- logger.debug(" Subsequent Address Family Identifier = 0x%s",
+ logger.debug(" Subsequent Address Family Identifier=0x%s",
binascii.b2a_hex(subsequent_address_family_identifier_hex))
wd_hex = attr_value_hex[3:]
- logger.debug(" Withdrawn Routes = 0x%s",
+ logger.debug(" Withdrawn Routes=0x%s",
binascii.b2a_hex(wd_hex))
wdr_prefix_list = get_prefix_list_from_hex(wd_hex)
logger.debug(" Withdrawn routes prefix list: %s",
logger.debug(" withdrawn_prefix_received: %s", prefix)
self.prefixes_withdrawn += len(wdr_prefix_list) # update counter
else:
- logger.debug("Unknown attribute type = %s, flags:0x%s)", attr_type_code,
+ logger.debug("Unknown attribute type=%s, flags:0x%s)", attr_type_code,
binascii.b2a_hex(attr_flags_hex))
- logger.debug("Unknown attribute value = 0x%s", binascii.b2a_hex(attr_value_hex))
+ logger.debug("Unknown attribute value=0x%s", binascii.b2a_hex(attr_value_hex))
return None
def decode_update_message(self, msg):