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