Upgrade RF syntax for v3.2 compatibility
[integration/test.git] / csit / libraries / GBP / OpenFlowUtils.robot
1 *** Settings ***
2 Documentation     Operations on Docker containers for GBP
3 Library           SSHLibrary
4 Library           Collections
5 Resource          ../Utils.robot
6 Resource          ConnUtils.robot
7 Resource          DockerUtils.robot
8 Variables         ../../variables/Variables.py
9 Library           OperatingSystem
10
11 *** Keywords ***
12 Inspect Service Function
13     [Arguments]    ${in_port}    ${out_port}    ${outer_src_ip}    ${outer_dst_ip}    ${eth_type}    ${inner_src_ip}
14     ...    ${inner_dst_ip}    ${next_hop_ip}    ${nsp}    ${received_nsi}    ${proto}=${EMPTY}
15     [Documentation]    Inspects traffic passing through service function node.
16     @{matches}    Create List
17     @{actions}    Create List
18     Append In Port Check    ${matches}    ${in_port}
19     Append Ether-Type Check    ${matches}    ${eth_type}
20     Append Tunnel Set Check    ${matches}
21     Append Outer IPs Check    ${matches}    src_ip=${outer__src_ip}/255.255.255.255    dst_ip=${outer_dst_ip}/255.255.255.255
22     Append NSI Check    ${matches}    ${received_nsi}
23     Append NSP Check    ${matches}    ${nsp}
24     Append Inner IPs Check    ${matches}    ${inner_src_ip}/0.0.0.0    ${inner_dst_ip}/0.0.0.0
25     Run Keyword If    "${proto}" != "${EMPTY}"    Append Proto Check    ${matches}    ${proto}
26     Append Tunnel Set Check    ${actions}
27     Append Outer IPs Check    ${actions}    dst_ip=${next_hop_ip}
28     ${rewritten_nsi}    Evaluate    ${received_nsi} -1
29     Append NSI Check    ${actions}    ${rewritten_nsi}
30     Append NSP Check    ${actions}    ${nsp}
31     Append Out Port Check    ${actions}    ${out_port}
32     ${flow}    Find Flow in DPCTL Output    ${matches}    ${actions}
33     [Return]    ${flow}
34
35 Inspect Service Function Forwarder
36     [Arguments]    ${in_port}    ${out_port}    ${outer_src_ip}    ${outer_dst_ip}    ${eth_type}    ${inner_src_ip}
37     ...    ${inner_dst_ip}    ${next_hop_ip}    ${nsp}    ${nsi}    ${proto}=${EMPTY}
38     [Documentation]    Inspects traffic passing through service function forwarder node.
39     @{matches}    Create List
40     @{actions}    Create List
41     Append In Port Check    ${matches}    ${in_port}
42     Append Ether-Type Check    ${matches}    ${eth_type}
43     Append Tunnel Set Check    ${matches}
44     Append Outer IPs Check    ${matches}    src_ip=${outer_src_ip}    dst_ip=${outer_dst_ip}
45     Append NSI Check    ${matches}    ${nsi}
46     Append NSP Check    ${matches}    ${nsp}
47     Append Inner IPs Check    ${matches}    ${inner_src_ip}/255.255.255.255    ${inner_dst_ip}/255.255.255.255
48     Run Keyword If    "${proto}" != "${EMPTY}"    Append Proto Check    ${matches}    ${proto}
49     Append Tunnel Set Check    ${actions}
50     Append Outer IPs Check    ${actions}    dst_ip=${next_hop_ip}
51     Append NSI Check    ${actions}    ${nsi}
52     Append NSP Check    ${actions}    ${nsp}
53     Append Out Port Check    ${actions}    ${out_port}
54     ${flow}    Find Flow in DPCTL Output    ${matches}    ${actions}
55     [Return]    ${flow}
56
57 Inspect Classifier Outbound
58     [Arguments]    ${in_port}    ${out_port}    ${eth_type}    ${inner_src_ip}    ${inner_dst_ip}    ${next_hop_ip}=${EMPTY}
59     ...    ${nsi}=${EMPTY}    ${proto}=${EMPTY}    ${src_port}=${EMPTY}    ${dst_port}=${EMPTY}
60     [Documentation]    Inspects outbound traffic of a classifier. Traffic source should be located on the classifier.
61     ...    If traffic destination is located on the same VM, do not specify neither of next_hop_ip and nsi.
62     ...    If traffic destination is located on different VM and the traffic is not forwarded into a chain, specify
63     ...    next_hop_ip and don't specify nsi.
64     ...    If traffic destination is located on different VM and the traffic is forwarded into a chain, specify both
65     ...    next_hop_ip and nsi.
66     @{matches}    Create List
67     @{actions}    Create List
68     Append In Port Check    ${matches}    ${in_port}
69     Append Ether-Type Check    ${matches}    ${eth_type}
70     Run Keyword If    "${proto}" != "${EMPTY}"    Append Proto Check    ${matches}    ${proto}
71     Run Keyword If    "${src_port}"!="${EMPTY}" or "${dst_port}"!="${EMPTY}"    Append L4 Check    ${matches}    src_port=${src_port}    dst_port=${dst_port}
72     Append Out Port Check    ${actions}    ${out_port}
73     Append Inner IPs Check    ${actions}    ${inner_src_ip}    ${inner_dst_ip}
74     Run Keyword If    "${next_hop_ip}"!="${EMPTY}"    Run Keywords    Append Tunnel Set Check    ${actions}
75     ...    AND    Append Outer IPs Check    ${actions}    dst_ip=${next_hop_ip}
76     ...    ELSE    Append Tunnel Not Set Check    ${actions}
77     Run Keyword If    "${nsi}"!="${EMPTY}"    Append NSI Check    ${actions}    255
78     ${flow}    Find Flow in DPCTL Output    ${matches}    ${actions}
79     [Return]    ${flow}
80
81 Inspect Classifier Inbound
82     [Arguments]    ${in_port}    ${out_port}    ${eth_type}    ${inner_src_ip}    ${inner_dst_ip}    ${outer_src_ip}
83     ...    ${outer_dst_ip}    ${nsp}=${EMPTY}    ${nsi}=${EMPTY}    ${proto}=${EMPTY}    ${src_port}=${EMPTY}    ${dst_port}=${EMPTY}
84     [Documentation]    Inspects inbound traffic of a classifier. Traffic destination should be located on the classifier.
85     ...    If traffic source is located on different VM and the traffic comes out of a chain, specify nsi and nsp values.
86     ...    If traffic source is located on different VM and the traffic does not comes out of a chain, do not specify
87     ...    neither of nsi and nsp values.
88     @{matches}    Create List
89     @{actions}    Create List
90     Append In Port Check    ${matches}    ${in_port}
91     Append Ether-Type Check    ${matches}    ${eth_type}
92     Append Outer IPs Check    ${matches}    src_ip=${outer_src_ip}    dst_ip=${outer_dst_ip}
93     Append Inner IPs Check    ${matches}    ${inner_src_ip}    ${inner_dst_ip}
94     Run Keyword If    "${src_port}"!="${EMPTY}" or "${dst_port}"!="${EMPTY}"    Append L4 Check    ${matches}    src_port=${src_port}    dst_port=${dst_port}
95     Append Tunnel Set Check    ${matches}
96     Run Keyword If    "${nsi}"!="${EMPTY}" and "${nsp}"!="${EMPTY}"    Run Keywords    Append NSI Check    ${matches}    ${nsi}
97     ...    AND    Append NSP Check    ${matches}    ${nsp}
98     Run Keyword If    "${proto}" != "${EMPTY}"    Run Keywords    Append Proto Check    ${matches}    ${proto}
99     ...    AND    Append Proto Check    ${actions}    ${proto}
100     Append Out Port Check    ${actions}    ${out_port}
101     Append Inner IPs Check    ${actions}    ${inner_src_ip}    ${inner_dst_ip}
102     ${flow}    Find Flow in DPCTL Output    ${matches}    ${actions}
103     [Return]    ${flow}
104
105 Find Flow in DPCTL Output
106     [Arguments]    ${flow_match_criteria}    ${flow_action_criteria}
107     [Documentation]    Executes 'ovs-dpctl dump-flows' on remote system and goes through each output line.
108     ...    A line is returned if all the criterias in actions part and matches part are matched. This is
109     ...    done by calling 'Check Match' keyword. If no match is found for any of the flows, caller test case
110     ...    will be failed.
111     ${output}    SSHLibrary.Execute Command    sudo ovs-dpctl dump-flows
112     Log    ${output}
113     @{lines}    Split To Lines    ${output}
114     ${match_result}    Set Variable
115     ${action_result}    Set Variable
116     FOR    ${line}    IN    @{lines}
117         ${match}    Get Matches Part    ${line}
118         ${action}    Get Actions Part    ${line}
119         ${match_result}    Check Match    ${match}    @{flow_match_criteria}
120         ${action_result}    Check Match    ${action}    @{flow_action_criteria}
121         Run Keyword If    "${match_result}" == "TRUE" and "${action_result}" == "TRUE"    Return From Keyword    ${line}
122     END
123     Log    ${flow_match_criteria}
124     Log    ${flow_action_criteria}
125     Fail    Flow not found!
126
127 Get Matches Part
128     [Arguments]    ${ovs-dpctl_flow}
129     [Documentation]    Returns matches part of a flow captured with 'ovs-dpctl dump-flows'.
130     @{matches_actions}    Split String    ${ovs-dpctl_flow}    actions
131     Log    ${matches_actions[0]}
132     [Return]    ${matches_actions[0]}
133
134 Get Actions Part
135     [Arguments]    ${ovs-dpctl_flow}
136     [Documentation]    Returns actions part of a flow captured with 'ovs-dpctl dump-flows'.
137     @{matches_actions}    Split String    ${ovs-dpctl_flow}    actions
138     [Return]    ${matches_actions[1]}
139
140 Check Match
141     [Arguments]    ${string}    @{match_criteria}
142     [Documentation]    Applies 'grep' on the string argument for each criterion.
143     ${conditions}    Set Variable
144     FOR    ${criterio}    IN    @{match_criteria}
145         ${grep_criterio}    Catenate    | grep    ${criterio}
146         ${conditions}    Catenate    ${conditions}    ${grep_criterio}
147         ${debug_output}    OperatingSystem.Run    echo "${string}" ${conditions}
148         Log    ${debug_output}
149         Run Keyword If    "${debug_output}" == "${EMPTY}"    Log    ${criterio}
150     END
151     ${output}    OperatingSystem.Run    echo "${string}" ${conditions}
152     Log    ${output}
153     Run Keyword If    "${output}" == "${EMPTY}"    Return From Keyword    FALSE
154     ...    ELSE    Return From Keyword    TRUE
155
156 Append Proto Check
157     [Arguments]    ${list}    ${proto}
158     [Documentation]    Returns proto part of flow can be captured with 'ovs-dpctl dump-flows'.
159     Append To List    ${list}    proto=${proto}
160
161 Append Inner MAC Check
162     [Arguments]    ${list}    ${src_addr}=${EMPTY}    ${dst_addr}=${EMPTY}
163     [Documentation]    Returns encapsulated MAC addresses part of flow can be captured with 'ovs-dpctl dump-flows'.
164     Run Keyword If    "${src_addr}" != "${EMPTY}" and "${dst_addr}" != "${EMPTY}"    Append To List    ${list}    "eth(src=${src_addr},dst=${dst_addr})"
165     ...    ELSE IF    "${src_addr}" != "${EMPTY}"    Append To List    ${list}    "eth(src=${src_addr},dst=.*)"
166     ...    ELSE IF    "${dst_addr}" != "${EMPTY}"    Append To List    ${list}    "eth(src=.*,dst=${dst_addr})"
167     ...    ELSE    Fail    Specify at liest src or dest IP!
168
169 Append Inner IPs Check
170     [Arguments]    ${list}    ${src_ip}=${EMPTY}    ${dst_ip}=${EMPTY}
171     [Documentation]    Returns encapsulated IP addresses part of flow can be captured with 'ovs-dpctl dump-flows'.
172     Run Keyword If    "${src_ip}" != "${EMPTY}" and "${dst_ip}" != "${EMPTY}"    Append To List    ${list}    "ipv4(src=${src_ip},dst=${dst_ip}"
173     ...    ELSE IF    "${src_ip}" != "${EMPTY}"    Append To List    ${list}    "ipv4(src=${src_ip},dst=.*"
174     ...    ELSE IF    "${dst_ip}" != "${EMPTY}"    Append To List    ${list}    "ipv4(src=.*,dst=${dst_ip}"
175     ...    ELSE    Fail    Specify at liest src or dest IP!
176
177 Append Outer IPs Check
178     [Arguments]    ${list}    ${src_ip}=${EMPTY}    ${dst_ip}=${EMPTY}
179     [Documentation]    Returns packet IP addresses part of flow can be captured with 'ovs-dpctl dump-flows'.
180     Run Keyword If    "${src_ip}" != "${EMPTY}"    Append To List    ${list}    src=${src_ip}
181     ...    ELSE IF    "${dst_ip}" != "${EMPTY}"    Append To List    ${list}    dst=${dst_ip}
182     ...    ELSE    Fail    Specify at liest src or dest IP!
183
184 Append In Port Check
185     [Arguments]    ${list}    ${in_port}
186     [Documentation]    Returns ingress port part of flow can be captured with 'ovs-dpctl dump-flows'.
187     Append To List    ${list}    "in_port(${in_port})"
188
189 Append Out Port Check
190     [Arguments]    ${list}    ${out_port}
191     [Documentation]    Returns egress port part of flow can be captured with 'ovs-dpctl dump-flows'.
192     Append To List    ${list}    ,${out_port}
193
194 Append L4 Check
195     [Arguments]    ${list}    ${src_port}=${EMPTY}    ${dst_port}=${EMPTY}
196     [Documentation]    Returns L4 port part of flow can be captured with 'ovs-dpctl dump-flows'.
197     Run Keyword If    "${src_port}" != "${EMPTY}"    Append To List    ${list}    src=${src_port}
198     ...    ELSE IF    "${dst_port}" != "${EMPTY}"    Append To List    ${list}    dst=${dst_port}
199     ...    ELSE    Fail    Specify at liest src or dest port!
200
201 Append NSI Check
202     [Arguments]    ${list}    ${nsi}
203     [Documentation]    Returns NSI part of flow can be captured with 'ovs-dpctl dump-flows'.
204     Append To List    ${list}    nsi=${nsi}
205
206 Append NSP Check
207     [Arguments]    ${list}    ${nsp}
208     [Documentation]    Returns NSP part of flow can be captured with 'ovs-dpctl dump-flows'.
209     Append To List    ${list}    nsp=${nsp}
210
211 Append Ether-Type Check
212     [Arguments]    ${list}    ${eth_type}
213     [Documentation]    Returns Ether-Type part of flow can be captured with 'ovs-dpctl dump-flows'.
214     Append To List    ${list}    "eth_type(${eth_type})"
215
216 Append Tunnel Set Check
217     [Arguments]    ${list}
218     [Documentation]    Tunnel ID is locally significant to neighbouring nodes and it is not
219     ...    statically determined. By checking it's presence in match ( or action) fields,
220     ...    we can say whether a packet was received (or send out) via tunnel port.
221     Append To List    ${list}    tun_id
222
223 Append Tunnel Not Set Check
224     [Arguments]    ${list}
225     [Documentation]    Tunnel ID is locally significant to neighbouring nodes and it is not
226     ...    statically determined. By checking it's presence in match ( or action) fields,
227     ...    we can say whether a packet was received (or send out) via tunnel port.
228     Append To List    ${list}    -v tun_id
229
230 Get NSP Value From Flow
231     [Arguments]    ${flow}
232     [Documentation]    Reads and returns nsp value from flow captured with 'ovs-dpctl dump-flows'.
233     ${flow}    Get Actions Part    ${flow}
234     ${output}    OperatingSystem.Run    echo "\$${flow}" | sed 's/.*nsp=/nsp=/' | sed 's/,.*//' | sed 's/.*=//'
235     [Return]    ${output}
236
237 Manager is Connected
238     ${output}    SSHLibrary.Execute Command    sudo ovs-vsctl show
239     Should Contain    ${output}    is_connected: true
240
241 Manager and Switch Connected
242     [Arguments]    ${sw_name}
243     ${output}    SSHLibrary.Execute Command    sudo ovs-vsctl show
244     Should Contain    ${output}    ${sw_name}
245     Should Contain x Times    ${output}    is_connected: true    2
246
247 Wait For Flows On Switch
248     [Arguments]    ${switch_ip}    ${switch_name}
249     [Documentation]    Counts flows on switch, fails if 0
250     ConnUtils.Connect and Login    ${switch_ip}
251     # check for OVS errors first
252     ${stdout}    ${stderr}    SSHLibrary.Execute Command    sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13    return_stderr=True
253     Run Keyword If    "${stderr}" != "${EMPTY}"    Fatal Error    ${stderr}
254     Wait Until Keyword Succeeds    120s    20s    Count Flows On Switch    ${switch_name}
255     SSHLibrary.Close Connection
256
257 Show Switch Status
258     [Arguments]    ${switch_name}
259     [Documentation]    Shows status of a switch for easier debugging.
260     ${stdout}    ${stderr}    SSHLibrary.Execute Command    sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13    return_stderr=True
261     Log    ${stdout}
262     ${stdout}    ${stderr}    SSHLibrary.Execute Command    sudo ovs-vsctl show    return_stderr=True
263     Log    ${stdout}
264
265 Count Flows On Switch
266     [Arguments]    ${switch_name}
267     ${out}    SSHLibrary.Execute Command    printf "%d" $(($(sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 | wc -l)-1))
268     Should Be True    ${out}>0