Tidied new and updated test suites
[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     Log    ${flow_match_criteria}
123     Log    ${flow_action_criteria}
124     Fail    Flow not found!
125
126 Get Matches Part
127     [Arguments]    ${ovs-dpctl_flow}
128     [Documentation]    Returns matches part of a flow captured with 'ovs-dpctl dump-flows'.
129     @{matches_actions}    Split String    ${ovs-dpctl_flow}    actions
130     Log    ${matches_actions[0]}
131     [Return]    ${matches_actions[0]}
132
133 Get Actions Part
134     [Arguments]    ${ovs-dpctl_flow}
135     [Documentation]    Returns actions part of a flow captured with 'ovs-dpctl dump-flows'.
136     @{matches_actions}    Split String    ${ovs-dpctl_flow}    actions
137     [Return]    ${matches_actions[1]}
138
139 Check Match
140     [Arguments]    ${string}    @{match_criteria}
141     [Documentation]    Applies 'grep' on the string argument for each criterion.
142     ${conditions}    Set Variable
143     : FOR    ${criterio}    IN    @{match_criteria}
144     \    ${grep_criterio}    Catenate    | grep    ${criterio}
145     \    ${conditions}    Catenate    ${conditions}    ${grep_criterio}
146     \    ${debug_output}    OperatingSystem.Run    echo "${string}" ${conditions}
147     \    Log    ${debug_output}
148     \    Run Keyword If    "${debug_output}" == "${EMPTY}"    Log    ${criterio}
149     ${output}    OperatingSystem.Run    echo "${string}" ${conditions}
150     Log    ${output}
151     Run Keyword If    "${output}" == "${EMPTY}"    Return From Keyword    FALSE
152     ...    ELSE    Return From Keyword    TRUE
153
154 Append Proto Check
155     [Arguments]    ${list}    ${proto}
156     [Documentation]    Returns proto part of flow can be captured with 'ovs-dpctl dump-flows'.
157     Append To List    ${list}    proto=${proto}
158
159 Append Inner MAC Check
160     [Arguments]    ${list}    ${src_addr}=${EMPTY}    ${dst_addr}=${EMPTY}
161     [Documentation]    Returns encapsulated MAC addresses part of flow can be captured with 'ovs-dpctl dump-flows'.
162     Run Keyword If    "${src_addr}" != "${EMPTY}" and "${dst_addr}" != "${EMPTY}"    Append To List    ${list}    "eth(src=${src_addr},dst=${dst_addr})"
163     ...    ELSE IF    "${src_addr}" != "${EMPTY}"    Append To List    ${list}    "eth(src=${src_addr},dst=.*)"
164     ...    ELSE IF    "${dst_addr}" != "${EMPTY}"    Append To List    ${list}    "eth(src=.*,dst=${dst_addr})"
165     ...    ELSE    Fail    Specify at liest src or dest IP!
166
167 Append Inner IPs Check
168     [Arguments]    ${list}    ${src_ip}=${EMPTY}    ${dst_ip}=${EMPTY}
169     [Documentation]    Returns encapsulated IP addresses part of flow can be captured with 'ovs-dpctl dump-flows'.
170     Run Keyword If    "${src_ip}" != "${EMPTY}" and "${dst_ip}" != "${EMPTY}"    Append To List    ${list}    "ipv4(src=${src_ip},dst=${dst_ip}"
171     ...    ELSE IF    "${src_ip}" != "${EMPTY}"    Append To List    ${list}    "ipv4(src=${src_ip},dst=.*"
172     ...    ELSE IF    "${dst_ip}" != "${EMPTY}"    Append To List    ${list}    "ipv4(src=.*,dst=${dst_ip}"
173     ...    ELSE    Fail    Specify at liest src or dest IP!
174
175 Append Outer IPs Check
176     [Arguments]    ${list}    ${src_ip}=${EMPTY}    ${dst_ip}=${EMPTY}
177     [Documentation]    Returns packet IP addresses part of flow can be captured with 'ovs-dpctl dump-flows'.
178     Run Keyword If    "${src_ip}" != "${EMPTY}"    Append To List    ${list}    src=${src_ip}
179     ...    ELSE IF    "${dst_ip}" != "${EMPTY}"    Append To List    ${list}    dst=${dst_ip}
180     ...    ELSE    Fail    Specify at liest src or dest IP!
181
182 Append In Port Check
183     [Arguments]    ${list}    ${in_port}
184     [Documentation]    Returns ingress port part of flow can be captured with 'ovs-dpctl dump-flows'.
185     Append To List    ${list}    "in_port(${in_port})"
186
187 Append Out Port Check
188     [Arguments]    ${list}    ${out_port}
189     [Documentation]    Returns egress port part of flow can be captured with 'ovs-dpctl dump-flows'.
190     Append To List    ${list}    ,${out_port}
191
192 Append L4 Check
193     [Arguments]    ${list}    ${src_port}=${EMPTY}    ${dst_port}=${EMPTY}
194     [Documentation]    Returns L4 port part of flow can be captured with 'ovs-dpctl dump-flows'.
195     Run Keyword If    "${src_port}" != "${EMPTY}"    Append To List    ${list}    src=${src_port}
196     ...    ELSE IF    "${dst_port}" != "${EMPTY}"    Append To List    ${list}    dst=${dst_port}
197     ...    ELSE    Fail    Specify at liest src or dest port!
198
199 Append NSI Check
200     [Arguments]    ${list}    ${nsi}
201     [Documentation]    Returns NSI part of flow can be captured with 'ovs-dpctl dump-flows'.
202     Append To List    ${list}    nsi=${nsi}
203
204 Append NSP Check
205     [Arguments]    ${list}    ${nsp}
206     [Documentation]    Returns NSP part of flow can be captured with 'ovs-dpctl dump-flows'.
207     Append To List    ${list}    nsp=${nsp}
208
209 Append Ether-Type Check
210     [Arguments]    ${list}    ${eth_type}
211     [Documentation]    Returns Ether-Type part of flow can be captured with 'ovs-dpctl dump-flows'.
212     Append To List    ${list}    "eth_type(${eth_type})"
213
214 Append Tunnel Set Check
215     [Arguments]    ${list}
216     [Documentation]    Tunnel ID is locally significant to neighbouring nodes and it is not
217     ...    statically determined. By checking it's presence in match ( or action) fields,
218     ...    we can say whether a packet was received (or send out) via tunnel port.
219     Append To List    ${list}    tun_id
220
221 Append Tunnel Not Set Check
222     [Arguments]    ${list}
223     [Documentation]    Tunnel ID is locally significant to neighbouring nodes and it is not
224     ...    statically determined. By checking it's presence in match ( or action) fields,
225     ...    we can say whether a packet was received (or send out) via tunnel port.
226     Append To List    ${list}    -v tun_id
227
228 Get NSP Value From Flow
229     [Arguments]    ${flow}
230     [Documentation]    Reads and returns nsp value from flow captured with 'ovs-dpctl dump-flows'.
231     ${flow}    Get Actions Part    ${flow}
232     ${output}    OperatingSystem.Run    echo "\$${flow}" | sed 's/.*nsp=/nsp=/' | sed 's/,.*//' | sed 's/.*=//'
233     [Return]    ${output}
234
235 Manager is Connected
236     ${output}    SSHLibrary.Execute Command    sudo ovs-vsctl show
237     Should Contain    ${output}    is_connected: true
238
239 Manager and Switch Connected
240     [Arguments]    ${sw_name}
241     ${output}    SSHLibrary.Execute Command    sudo ovs-vsctl show
242     Should Contain    ${output}    ${sw_name}
243     Should Contain x Times    ${output}    is_connected: true    2
244
245 Wait For Flows On Switch
246     [Arguments]    ${switch_ip}    ${switch_name}
247     [Documentation]    Counts flows on switch, fails if 0
248     ConnUtils.Connect and Login    ${switch_ip}
249     # check for OVS errors first
250     ${stdout}    ${stderr}    SSHLibrary.Execute Command    sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13    return_stderr=True
251     Run Keyword If    "${stderr}" != "${EMPTY}"    Fatal Error    ${stderr}
252     Wait Until Keyword Succeeds    120s    20s    Count Flows On Switch    ${switch_name}
253     SSHLibrary.Close Connection
254
255 Count Flows On Switch
256     [Arguments]    ${switch_name}
257     ${out}    SSHLibrary.Execute Command    printf "%d" $(($(sudo ovs-ofctl dump-flows ${switch_name} -OOpenFlow13 | wc -l)-1))
258     Should Be True    ${out}>0