ovn-sbctl: Use environment var OVN_SB_DB to find the database by default.
[cascardo/ovs.git] / tests / ovn.at
index 261e32a..1eb6d0b 100644 (file)
@@ -1,4 +1,4 @@
-AT_BANNER([OVN])
+AT_BANNER([OVN components])
 
 AT_SETUP([ovn -- lexer])
 dnl For lines without =>, input and expected output are identical.
@@ -81,7 +81,8 @@ ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains unmasked 1-bits.")
 fe:x => error("Invalid numeric constant.")
 00:01:02:03:04:x => error("Invalid numeric constant.")
 
-(){}[[]]==!=<<=>>=!&&||..,;= => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; =
+# Test that operators are tokenized as expected, even without white space.
+(){}[[]]==!=<<=>>=!&&||..,;=<-> => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = <->
 & => error("`&' is only valid as part of `&&'.")
 | => error("`|' is only valid as part of `||'.")
 
@@ -255,6 +256,8 @@ eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and != operators may be
 ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field ip4.src.
 
 1 == eth.type == 2 => Range expressions must have the form `x < field < y' or `x > field > y', with each `<' optionally replaced by `<=' or `>' by `>=').
+
+eth.dst[40] x => Extra tokens at end of input.
 ]])
 sed 's/ =>.*//' test-cases.txt > input.txt
 sed 's/.* => //' test-cases.txt > expout
@@ -298,51 +301,99 @@ sed 's/.* => //' test-cases.txt > expout
 AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout])
 AT_CLEANUP
 
-AT_SETUP([ovn -- expression conversion (1)])
+AT_SETUP([ovn -- 1-term expression conversion])
 AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0],
-  [Tested converting all 1-terminal expressions with 2 vars each of 3 bits in terms of operators == != < <= > >=.
+  [Tested converting all 1-terminal expressions with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- expression conversion (2)])
+AT_SETUP([ovn -- 2-term expression conversion])
 AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0],
-  [Tested converting 562 expressions of 2 terminals with 2 vars each of 3 bits in terms of operators == != < <= > >=.
+  [Tested converting 570 expressions of 2 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 2 string vars.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- expression conversion (3)])
+AT_SETUP([ovn -- 3-term expression conversion])
 AT_CHECK([ovstest test-ovn exhaustive --operation=convert --bits=2 3], [0],
-  [Tested converting 57618 expressions of 3 terminals with 2 vars each of 2 bits in terms of operators == != < <= > >=.
+  [Tested converting 62418 expressions of 3 terminals with 2 numeric vars (each 2 bits) in terms of operators == != < <= > >= and 2 string vars.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 3-term numeric expression simplification])
+AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=2 --svars=0 3], [0],
+  [Tested simplifying 477138 expressions of 3 terminals with 2 numeric vars (each 3 bits) in terms of operators == != < <= > >=.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 4-term string expression simplification])
+AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=0 --svars=4 4], [0],
+  [Tested simplifying 21978 expressions of 4 terminals with 4 string vars.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 3-term mixed expression simplification])
+AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --nvars=1 --svars=1 3], [0],
+  [Tested simplifying 124410 expressions of 3 terminals with 1 numeric vars (each 3 bits) in terms of operators == != < <= > >= and 1 string vars.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 4-term numeric expression normalization])
+AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 4], [0],
+  [Tested normalizing 1207162 expressions of 4 terminals with 3 numeric vars (each 1 bits) in terms of operators == != < <= > >=.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 4-term string expression normalization])
+AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 4], [0],
+  [Tested normalizing 11242 expressions of 4 terminals with 3 string vars.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- expression simplification])
-AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --vars=2 3], [0],
-  [Tested simplifying 477138 expressions of 3 terminals with 2 vars each of 3 bits in terms of operators == != < <= > >=.
+AT_SETUP([ovn -- 4-term mixed expression normalization])
+AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --bits=1 --svars=2 4], [0],
+  [Tested normalizing 128282 expressions of 4 terminals with 1 numeric vars (each 1 bits) in terms of operators == != < <= > >= and 2 string vars.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- expression normalization (1)])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --vars=3 --bits=1 4], [0],
-  [Tested normalizing 1207162 expressions of 4 terminals with 3 vars each of 1 bits in terms of operators == != < <= > >=.
+AT_SETUP([ovn -- 5-term numeric expression normalization])
+AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=3 --svars=0 --bits=1 --relops='==' 5], [0],
+  [Tested normalizing 368550 expressions of 5 terminals with 3 numeric vars (each 1 bits) in terms of operators ==.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- expression normalization (1)])
-AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --vars=3 --bits=1 --relops='==' 5], [0],
-  [Tested normalizing 368550 expressions of 5 terminals with 3 vars each of 1 bits in terms of operators ==.
+AT_SETUP([ovn -- 5-term string expression normalization])
+AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=0 --svars=3 --bits=1 --relops='==' 5], [0],
+  [Tested normalizing 368550 expressions of 5 terminals with 3 string vars.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- converting expressions to flows (1)])
-AT_CHECK([ovstest test-ovn exhaustive --operation=flow --vars=2 --bits=2 --relops='==' 4], [0],
-  [Tested converting to flows 128282 expressions of 4 terminals with 2 vars each of 2 bits in terms of operators ==.
+AT_SETUP([ovn -- 5-term mixed expression normalization])
+AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --nvars=1 --svars=1 --bits=1 --relops='==' 5], [0],
+  [Tested normalizing 116550 expressions of 5 terminals with 1 numeric vars (each 1 bits) in terms of operators == and 1 string vars.
 ])
 AT_CLEANUP
 
-AT_SETUP([ovn -- converting expressions to flows (2)])
-AT_CHECK([ovstest test-ovn exhaustive --operation=flow --vars=3 --bits=3 --relops='==' 3], [0],
-  [Tested converting to flows 38394 expressions of 3 terminals with 3 vars each of 3 bits in terms of operators ==.
+AT_SETUP([ovn -- 4-term numeric expressions to flows])
+AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=2 --svars=0 --bits=2 --relops='==' 4], [0],
+  [Tested converting to flows 128282 expressions of 4 terminals with 2 numeric vars (each 2 bits) in terms of operators ==.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 4-term string expressions to flows])
+AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=0 --svars=4 4], [0],
+  [Tested converting to flows 21978 expressions of 4 terminals with 4 string vars.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 4-term mixed expressions to flows])
+AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=1 --bits=2 --svars=1 --relops='==' 4], [0],
+  [Tested converting to flows 37994 expressions of 4 terminals with 1 numeric vars (each 2 bits) in terms of operators == and 1 string vars.
+])
+AT_CLEANUP
+
+AT_SETUP([ovn -- 3-term numeric expressions to flows])
+AT_CHECK([ovstest test-ovn exhaustive --operation=flow --nvars=3 --svars=0 --bits=3 --relops='==' 3], [0],
+  [Tested converting to flows 38394 expressions of 3 terminals with 3 numeric vars (each 3 bits) in terms of operators ==.
 ])
 AT_CLEANUP
 
@@ -377,6 +428,9 @@ ip,reg6=0x6
 ipv6,reg6=0x5
 ipv6,reg6=0x6
 ])
+AT_CHECK([expr_to_flow 'inport == "eth0" && inport == "eth1"'], [0], [dnl
+(no flows)
+])
 AT_CLEANUP
 
 AT_SETUP([ovn -- action parsing])
@@ -391,6 +445,17 @@ tcp.dst=80; => actions=set_field:80->tcp_dst, prereqs=ip.proto == 0x6 && (eth.ty
 eth.dst[40] = 1; => actions=set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst, prereqs=1
 vlan.pcp = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=vlan.tci[12]
 vlan.tci[13..15] = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=1
+reg0 = reg1; => actions=move:OXM_OF_PKT_REG0[0..31]->OXM_OF_PKT_REG0[32..63], prereqs=1
+vlan.pcp = reg0[0..2]; => actions=move:OXM_OF_PKT_REG0[32..34]->NXM_OF_VLAN_TCI[13..15], prereqs=vlan.tci[12]
+reg0[10] = vlan.pcp[1]; => actions=move:NXM_OF_VLAN_TCI[14]->OXM_OF_PKT_REG0[42], prereqs=vlan.tci[12]
+outport = inport; => actions=move:NXM_NX_REG6[]->NXM_NX_REG7[], prereqs=1
+reg0 <-> reg1; => actions=push:OXM_OF_PKT_REG0[0..31],push:OXM_OF_PKT_REG0[32..63],pop:OXM_OF_PKT_REG0[0..31],pop:OXM_OF_PKT_REG0[32..63], prereqs=1
+vlan.pcp <-> reg0[0..2]; => actions=push:OXM_OF_PKT_REG0[32..34],push:NXM_OF_VLAN_TCI[13..15],pop:OXM_OF_PKT_REG0[32..34],pop:NXM_OF_VLAN_TCI[13..15], prereqs=vlan.tci[12]
+reg0[10] <-> vlan.pcp[1]; => actions=push:NXM_OF_VLAN_TCI[14],push:OXM_OF_PKT_REG0[42],pop:NXM_OF_VLAN_TCI[14],pop:OXM_OF_PKT_REG0[42], prereqs=vlan.tci[12]
+outport <-> inport; => actions=push:NXM_NX_REG6[],push:NXM_NX_REG7[],pop:NXM_NX_REG6[],pop:NXM_NX_REG7[], prereqs=1
+# Contradictionary prerequisites (allowed but not useful):
+ip4.src = ip6.src[0..31]; => actions=move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[], prereqs=eth.type == 0x800 && eth.type == 0x86dd
+ip4.src <-> ip6.src[0..31]; => actions=push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[], prereqs=eth.type == 0x800 && eth.type == 0x86dd
 
 ## Negative tests.
 
@@ -409,15 +474,195 @@ next => Syntax error at end of input expecting ';'.
 inport[1] = 1; => Cannot select subfield of string field inport.
 ip.proto[1] = 1; => Cannot select subfield of nominal field ip.proto.
 eth.dst[40] == 1; => Syntax error at `==' expecting `='.
-ip = 1; => Can't assign to predicate symbol ip.
+ip = 1; => Predicate symbol ip cannot be used in assignment.
 ip.proto = 6; => Field ip.proto is not modifiable.
 inport = {"a", "b"}; => Assignments require a single value.
 inport = {}; => Syntax error at `}' expecting constant.
 bad_prereq = 123; => Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name.
 self_recurse = 123; => Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'.
-vlan.present = 0; => Can't assign to predicate symbol vlan.present.
+vlan.present = 0; => Predicate symbol vlan.present cannot be used in assignment.
+reg0[0] = vlan.present; => Predicate symbol vlan.present cannot be used in assignment.
+reg0 = reg1[0..10]; => Can't assign 11-bit value to 32-bit destination.
+inport = reg0; => Can't assign integer field (reg0) to string field (inport).
+inport = big_string; => String fields inport and big_string are incompatible for assignment.
+ip.proto = reg0[0..7]; => Field ip.proto is not modifiable.
+reg0[0] <-> vlan.present; => Predicate symbol vlan.present cannot be used in exchange.
+reg0 <-> reg1[0..10]; => Can't exchange 32-bit field with 11-bit field.
+inport <-> reg0; => Can't exchange string field (inport) with integer field (reg0).
+inport <-> big_string; => String fields inport and big_string are incompatible for exchange.
+ip.proto <-> reg0[0..7]; => Field ip.proto is not modifiable.
+reg0[0..7] <-> ip.proto; => Field ip.proto is not modifiable.
 ]])
 sed 's/ =>.*//' test-cases.txt > input.txt
 sed 's/.* => //' test-cases.txt > expout
 AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], [expout])
 AT_CLEANUP
+
+AT_BANNER([OVN end-to-end tests])
+
+AT_SETUP([ovn -- 3 HVs, 3 VIFs/HV, 1 logical switch])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+ovn_start
+
+# Create hypervisors hv[123].
+# Add vif1[123] to hv1, vif2[123] to hv2, vif3[123].
+# Add all of the vifs to a single logical switch lsw0.
+# Turn on port security on all the vifs except vif[123]1.
+# Make vif13, vif2[23], vif3[123] destinations for unknown MACs.
+# Add some ACLs for Ethertypes 1234, 1235, 1236.
+ovn-nbctl lswitch-add lsw0
+net_add n1
+for i in 1 2 3; do
+    sim_add hv$i
+    as hv$i
+    ovs-vsctl add-br br-phys
+    ovn_attach n1 br-phys 192.168.0.$i
+
+    for j in 1 2 3; do
+        ovs-vsctl add-port br-int vif$i$j -- set Interface vif$i$j external-ids:iface-id=lp$i$j options:tx_pcap=hv$i/vif$i$j-tx.pcap options:rxq_pcap=hv$i/vif$i$j-rx.pcap ofport-request=$i$j
+        ovn-nbctl lport-add lsw0 lp$i$j
+       if test $j = 1; then
+            ovn-nbctl lport-set-macs lp$i$j f0:00:00:00:00:$i$j unknown
+        else
+            ovn-nbctl lport-set-macs lp$i$j f0:00:00:00:00:$i$j
+            ovn-nbctl lport-set-port-security lp$i$j f0:00:00:00:00:$i$j
+        fi
+    done
+done
+ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1234' drop
+ovn-nbctl acl-add lsw0 from-lport 1000 'eth.type == 0x1235 && inport == "lp11"' drop
+ovn-nbctl acl-add lsw0 to-lport 1000 'eth.type == 0x1236 && outport == "lp33"' drop
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+ovn_populate_arp
+
+# Allow some time for ovn-northd and ovn-controller to catch up.
+# XXX This should be more systematic.
+sleep 1
+ovn-sbctl dump-flows -- list multicast_group
+
+# test_packet INPORT DST SRC ETHTYPE OUTPORT...
+#
+# This shell function causes a packet to be received on INPORT.  The packet's
+# content has Ethernet destination DST and source SRC (each exactly 12 hex
+# digits) and Ethernet type ETHTYPE (4 hex digits).  The OUTPORTs (zero or
+# more) list the VIFs on which the packet should be received.  INPORT and the
+# OUTPORTs are specified as lport numbers, e.g. 11 for vif11.
+trim_zeros() {
+    sed 's/\(00\)\{1,\}$//'
+}
+for i in 1 2 3; do
+    for j in 1 2 3; do
+        : > $i$j.expected
+    done
+done
+test_packet() {
+    local inport=$1 packet=$2$3$4; shift; shift; shift; shift
+    hv=hv`echo $inport | sed 's/^\(.\).*/\1/'`
+    vif=vif$inport
+    as $hv ovs-appctl netdev-dummy/receive $vif $packet
+    for outport; do
+        echo $packet | trim_zeros >> $outport.expected
+    done
+}
+
+# Send packets between all pairs of source and destination ports:
+#
+# 1. Unicast packets are delivered to exactly one lport (except that packets
+#    destined to their input ports are dropped).
+#
+# 2. Broadcast and multicast are delivered to all lports except the input port.
+#
+# 3. When port security is turned on, the lswitch drops packets from the wrong
+#    MAC address.
+#
+# 4. The lswitch drops all packets with a VLAN tag.
+#
+# 5. The lswitch drops all packets with a multicast source address.  (This only
+#    affects behavior when port security is turned off, since otherwise port
+#    security would drop the packet anyway.)
+#
+# 6. The lswitch delivers packets with an unknown destination to lports with
+#    "unknown" among their MAC addresses (and port security disabled).
+#
+# 7. The lswitch drops unicast packets that violate an ACL.
+#
+# 8. The lswitch drops multicast and broadcast packets that violate an ACL.
+for is in 1 2 3; do
+    for js in 1 2 3; do
+        s=$is$js
+        bcast=
+       unknown=
+       bacl2=
+       bacl3=
+        for id in 1 2 3; do
+            for jd in 1 2 3; do
+                d=$id$jd
+
+                if test $d != $s; then unicast=$d; else unicast=; fi
+                test_packet $s f000000000$d f000000000$s $s$d $unicast     #1
+
+                if test $d != $s && test $js = 1; then
+                   impersonate=$d
+               else
+                   impersonate=
+               fi
+                test_packet $s f000000000$d f00000000055 55$d $impersonate #3
+
+               if test $d != $s && test $s != 11; then acl2=$d; else acl2=; fi
+               if test $d != $s && test $d != 33; then acl3=$d; else acl3=; fi
+                test_packet $s f000000000$d f000000000$s 1234        #7, acl1
+                test_packet $s f000000000$d f000000000$s 1235 $acl2  #7, acl2
+                test_packet $s f000000000$d f000000000$s 1236 $acl3  #7, acl3
+
+                test_packet $s f000000000$d f00000000055 810000091234      #4
+                test_packet $s f000000000$d 0100000000$s $s$d              #5
+
+               if test $d != $s && test $jd = 1; then
+                   unknown="$unknown $d"
+               fi
+                bcast="$bcast $unicast"
+                bacl2="$bacl2 $acl2"
+                bacl3="$bacl3 $acl3"
+            done
+        done
+
+       # Broadcast and multicast.
+        test_packet $s ffffffffffff f000000000$s ${s}ff $bcast             #2
+        test_packet $s 010000000000 f000000000$s ${s}ff $bcast             #2
+       if test $js = 1; then
+            bcast_impersonate=$bcast
+        else
+           bcast_impersonate=
+       fi
+        test_packet $s 010000000000 f00000000044 44ff $bcast_impersonate   #3
+
+        test_packet $s f0000000ffff f000000000$s ${s}66 $unknown           #6
+
+        test_packet $s ffffffffffff f000000000$s 1234                #8, acl1
+        test_packet $s ffffffffffff f000000000$s 1235 $bacl2         #8, acl2
+        test_packet $s ffffffffffff f000000000$s 1236 $bacl3         #8, acl3
+        test_packet $s 010000000000 f000000000$s 1234                #8, acl1
+        test_packet $s 010000000000 f000000000$s 1235 $bacl2         #8, acl2
+        test_packet $s 010000000000 f000000000$s 1236 $bacl3         #8, acl3
+    done
+done
+
+# Allow some time for packet forwarding.
+# XXX This can be improved.
+sleep 1
+
+# Now check the packets actually received against the ones expected.
+for i in 1 2 3; do
+    for j in 1 2 3; do
+        file=hv$i/vif$i$j-tx.pcap
+        echo $file
+        $PYTHON "$top_srcdir/utilities/ovs-pcap.in" $file | trim_zeros > $i$j.packets
+        cp $i$j.expected expout
+        AT_CHECK([cat $i$j.packets], [0], [expout])
+        echo
+    done
+done
+AT_CLEANUP