For dnat_and_snat rules which are meant to be stateless instead of using ct_snat/dnat OVN actions, we will use ip4.src/ip4.dst.
This actions will do 1:1 mapping to inner ip to external ip, while recalculating the checksums. Signed-off-by: Ankur Sharma <ankur.sha...@nutanix.com> --- northd/ovn-northd.8.xml | 34 ++++-- northd/ovn-northd.c | 86 +++++++++++-- tests/ovn-northd.at | 57 +++++++++ tests/ovn.at | 311 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 472 insertions(+), 16 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index d3e0e5e..87a6909 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1807,7 +1807,9 @@ icmp6 { to change the source IP address of a packet from <var>A</var> to <var>B</var>, a priority-90 flow matches <code>ip && ip4.dst == <var>B</var></code> with an action - <code>ct_snat; </code>. + <code>ct_snat; </code>. If the NAT rule is of type dnat_and_snat + and has <code>stateless=true</code> in the options, then the action + would be <code>ip4.dst=(<var>B</var>)</code>. </p> <p> @@ -1827,7 +1829,10 @@ icmp6 { <var>B</var>, a priority-100 flow matches <code>ip && ip4.dst == <var>B</var> && inport == <var>GW</var></code>, where <var>GW</var> is the logical router gateway port, with an - action <code>ct_snat;</code>. + action <code>ct_snat;</code>. If the NAT rule is of type + dnat_and_snat and has <code>stateless=true</code> in the + options, then the action would be <code>ip4.dst= + (<var>B</var>)</code>. </p> <p> @@ -1947,7 +1952,10 @@ icmp6 { Gateway router is configured to force SNAT any DNATed packet, the above action will be replaced by <code>flags.force_snat_for_dnat = 1; flags.loopback = 1; - ct_dnat(<var>B</var>);</code>. + ct_dnat(<var>B</var>);</code>. If the NAT rule is of type + dnat_and_snat and has <code>stateless=true</code> in the + options, then the action would be <code>ip4.dst= + (<var>B</var>)</code>. </li> <li> @@ -1979,7 +1987,10 @@ icmp6 { <var>B</var>, a priority-100 flow matches <code>ip && ip4.dst == <var>B</var> && inport == <var>GW</var></code>, where <var>GW</var> is the logical router gateway port, with an - action <code>ct_dnat(<var>B</var>);</code>. + action <code>ct_dnat(<var>B</var>);</code>. If the NAT rule is of + type dnat_and_snat and has <code>stateless=true</code> in the + options, then the action would be <code>ip4.dst= + (<var>B</var>)</code>. </p> <p> @@ -2653,7 +2664,10 @@ nd_ns { matches <code>ip && ip4.src == <var>B</var> && outport == <var>GW</var></code>, where <var>GW</var> is the logical router gateway port, with an action - <code>ct_dnat;</code>. + <code>ct_dnat;</code>. If the NAT rule is of type + dnat_and_snat and has <code>stateless=true</code> in the + options, then the action would be <code>ip4.src= + (<var>B</var>)</code>. </p> <p> @@ -2711,7 +2725,10 @@ nd_ns { <code>ip && ip4.src == <var>A</var></code> with an action <code>ct_snat(<var>B</var>);</code>. The priority of the flow is calculated based on the mask of <var>A</var>, with matches - having larger masks getting higher priorities. + having larger masks getting higher priorities. If the NAT rule is + of type dnat_and_snat and has <code>stateless=true</code> in the + options, then the action would be <code>ip4.src= + (<var>B</var>)</code>. </p> <p> A priority-0 logical flow with match <code>1</code> has actions @@ -2734,7 +2751,10 @@ nd_ns { logical router gateway port, with an action <code>ct_snat(<var>B</var>);</code>. The priority of the flow is calculated based on the mask of <var>A</var>, with matches - having larger masks getting higher priorities. + having larger masks getting higher priorities. If the NAT rule + is of type dnat_and_snat and has <code>stateless=true</code> + in the options, then the action would be <code>ip4.src= + (<var>B</var>)</code>. </p> <p> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 194e4bf..4431659 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -6500,6 +6500,18 @@ copy_ra_to_sb(struct ovn_port *op, const char *address_mode) smap_destroy(&options); } +static inline bool +lrouter_nat_is_stateless(const struct nbrec_nat *nat) +{ + const char *stateless = smap_get(&nat->options, "stateless"); + + if (stateless && !strcmp(stateless, "true")) { + return true; + } + + return false; +} + static void build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, struct hmap *lflows, struct shash *meter_groups) @@ -7261,6 +7273,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, nat = od->nbr->nat[i]; ovs_be32 ip, mask; + bool stateless = lrouter_nat_is_stateless(nat); char *error = ip_parse_masked(nat->external_ip, &ip, &mask); if (error || mask != OVS_BE32_MAX) { @@ -7326,15 +7339,26 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, if (!od->l3dgw_port) { /* Gateway router. */ ds_clear(&match); + ds_clear(&actions); ds_put_format(&match, "ip && ip4.dst == %s", nat->external_ip); + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "ip4.dst=%s; next;", + nat->logical_ip); + } else { + ds_put_cstr(&actions, "ct_snat;"); + } + ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 90, - ds_cstr(&match), "ct_snat;"); + ds_cstr(&match), ds_cstr(&actions)); } else { /* Distributed router. */ /* Traffic received on l3dgw_port is subject to NAT. */ ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "ip && ip4.dst == %s" " && inport == %s", nat->external_ip, @@ -7345,8 +7369,16 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ds_put_format(&match, " && is_chassis_resident(%s)", od->l3redirect_port->json_key); } + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "ip4.dst=%s; next;", + nat->logical_ip); + } else { + ds_put_cstr(&actions, "ct_snat;"); + } + ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 100, - ds_cstr(&match), "ct_snat;"); + ds_cstr(&match), ds_cstr(&actions)); /* Traffic received on other router ports must be * redirected to the central instance of the l3dgw_port @@ -7381,8 +7413,16 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ds_put_format(&actions, "flags.force_snat_for_dnat = 1; "); } - ds_put_format(&actions, "flags.loopback = 1; ct_dnat(%s);", - nat->logical_ip); + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "flags.loopback = 1; " + "ip4.dst=%s; next;", + nat->logical_ip); + } else { + ds_put_format(&actions, "flags.loopback = 1; " + "ct_dnat(%s);", nat->logical_ip); + } + ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100, ds_cstr(&match), ds_cstr(&actions)); } else { @@ -7401,8 +7441,15 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, od->l3redirect_port->json_key); } ds_clear(&actions); - ds_put_format(&actions, "ct_dnat(%s);", - nat->logical_ip); + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "ip4.dst=%s; next;", + nat->logical_ip); + } else { + ds_put_format(&actions, "ct_dnat(%s);", + nat->logical_ip); + } + ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100, ds_cstr(&match), ds_cstr(&actions)); @@ -7444,7 +7491,14 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ds_put_format(&actions, "eth.src = "ETH_ADDR_FMT"; ", ETH_ADDR_ARGS(mac)); } - ds_put_format(&actions, "ct_dnat;"); + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "ip4.src=%s; next;", + nat->external_ip); + } else { + ds_put_format(&actions, "ct_dnat;"); + } + ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 100, ds_cstr(&match), ds_cstr(&actions)); } @@ -7460,7 +7514,14 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ds_put_format(&match, "ip && ip4.src == %s", nat->logical_ip); ds_clear(&actions); - ds_put_format(&actions, "ct_snat(%s);", nat->external_ip); + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "ip4.src=%s; next;", + nat->external_ip); + } else { + ds_put_format(&actions, "ct_snat(%s);", + nat->external_ip); + } /* The priority here is calculated such that the * nat->logical_ip with the longest mask gets a higher @@ -7489,7 +7550,14 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ds_put_format(&actions, "eth.src = "ETH_ADDR_FMT"; ", ETH_ADDR_ARGS(mac)); } - ds_put_format(&actions, "ct_snat(%s);", nat->external_ip); + + if (!strcmp(nat->type, "dnat_and_snat") && stateless) { + ds_put_format(&actions, "ip4.src=%s; next;", + nat->external_ip); + } else { + ds_put_format(&actions, "ct_snat(%s);", + nat->external_ip); + } /* The priority here is calculated such that the * nat->logical_ip with the longest mask gets a higher diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 42033d5..60b3d11 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -966,3 +966,60 @@ OVS_WAIT_UNTIL([ovn-sbctl get Port_Binding ${uuid} options:redirect-type], [0], ]) AT_CLEANUP + +AT_SETUP([ovn -- check stateless dnat_and_snat rule]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) +ovn_start + +ovn-sbctl chassis-add gw1 geneve 127.0.0.1 + +ovn-nbctl lr-add R1 +ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24 + +ovn-nbctl ls-add S1 +ovn-nbctl lsp-add S1 S1-R1 +ovn-nbctl lsp-set-type S1-R1 router +ovn-nbctl lsp-set-addresses S1-R1 router +ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 + +ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1 + +uuid=`ovn-sbctl --columns=_uuid --bare find Port_Binding logical_port=cr-R1-S1` +echo "CR-LRP UUID is: " $uuid + +ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 + +OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows R1 | grep lr_in_unsnat | \ +wc -l`]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_snat | wc -l], [0], [2 +]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_dnat | wc -l], [0], [2 +]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ip4.dst=| wc -l], [0], [0 +]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ip4.src=| wc -l], [0], [0 +]) + +ovn-nbctl lr-nat-del R1 dnat_and_snat 172.16.1.1 + +ovn-nbctl --stateless lr-nat-add R1 dnat_and_snat 172.16.1.1 50.0.0.11 +OVS_WAIT_UNTIL([test 3 = `ovn-sbctl dump-flows R1 | grep lr_in_unsnat | \ +wc -l`]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_snat | wc -l], [0], [0 +]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ct_dnat | wc -l], [0], [0 +]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ip4.dst=| wc -l], [0], [2 +]) + +AT_CHECK([ovn-sbctl dump-flows R1 | grep ip4.src=| wc -l], [0], [2 +]) + +AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 9f06059..0922bf6 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -16359,3 +16359,314 @@ grep 101 | wc -l`]) OVN_CLEANUP([hv1]) AT_CLEANUP + +AT_SETUP([ovn -- Stateless Floating IP]) +ovn_start + +# In this test cases we create 3 switches, all connected to same +# physical network (through br-phys on each HV). LS1 and LS2 have +# 1 VIF each. Each HV has 1 VIF port. The first digit +# of VIF port name indicates the hypervisor it is bound to, e.g. +# lp23 means VIF 3 on hv2. +# +# All the switches are connected to a logical router "router". +# +# There is an external logical switch, ls-north. +# This test validates the stateless floating ip implementation. +# +# Each switch's VLAN tag and their logical switch ports are: +# - ls1: +# - tagged with VLAN 101 +# - ports: lp11 +# - ls2: +# - tagged with VLAN 201 +# - ports: lp22 +# - ls-north: +# - tagged with VLAN 1000 +# Note: a localnet port is created for each switch to connect to +# physical network. + +for i in 1 2; do + ls_name=ls$i + ovn-nbctl ls-add $ls_name + ln_port_name=ln$i + if test $i -eq 1; then + ovn-nbctl lsp-add $ls_name $ln_port_name "" 101 + elif test $i -eq 2; then + ovn-nbctl lsp-add $ls_name $ln_port_name "" 201 + fi + ovn-nbctl lsp-set-addresses $ln_port_name unknown + ovn-nbctl lsp-set-type $ln_port_name localnet + ovn-nbctl lsp-set-options $ln_port_name network_name=phys +done + +# lsp_to_ls LSP +# +# Prints the name of the logical switch that contains LSP. +lsp_to_ls () { + case $1 in dnl ( + lp?[[11]]) echo ls1 ;; dnl ( + lp?[[12]]) echo ls2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_hv () { + case $1 in dnl ( + vif[[1]]?) echo hv1 ;; dnl ( + vif[[2]]?) echo hv2 ;; dnl ( + vif?[[north]]?) echo hv4 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +ip_to_hex() { + printf "%02x%02x%02x%02x" "$@" +} + +net_add n1 +for i in 1 2; do + sim_add hv$i + as hv$i + ovs-vsctl add-br br-phys + ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys + ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i" + ovn_attach n1 br-phys 192.168.0.$i + + ovs-vsctl add-port br-int vif$i$i -- \ + set Interface vif$i$i external-ids:iface-id=lp$i$i \ + options:tx_pcap=hv$i/vif$i$i-tx.pcap \ + options:rxq_pcap=hv$i/vif$i$i-rx.pcap \ + ofport-request=$i$i + + lsp_name=lp$i$i + ls_name=$(lsp_to_ls $lsp_name) + + ovn-nbctl lsp-add $ls_name $lsp_name + ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i 192.168.$i.$i" + ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i + + OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup]) + +done + +ovn-nbctl ls-add ls-underlay +ovn-nbctl lsp-add ls-underlay ln3 "" 1000 +ovn-nbctl lsp-set-addresses ln3 unknown +ovn-nbctl lsp-set-type ln3 localnet +ovn-nbctl lsp-set-options ln3 network_name=phys + +ovn-nbctl ls-add ls-north +ovn-nbctl lsp-add ls-north ln4 "" 1000 +ovn-nbctl lsp-set-addresses ln4 unknown +ovn-nbctl lsp-set-type ln4 localnet +ovn-nbctl lsp-set-options ln4 network_name=phys + +# Add a VM on ls-north +ovn-nbctl lsp-add ls-north lp-north +ovn-nbctl lsp-set-addresses lp-north "f0:f0:00:00:00:11 172.31.0.10" +ovn-nbctl lsp-set-port-security lp-north f0:f0:00:00:00:11 + +# Add 3rd hypervisor +sim_add hv3 +as hv3 ovs-vsctl add-br br-phys +as hv3 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys +as hv3 ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:33" +as hv3 ovn_attach n1 br-phys 192.168.0.3 + +# Add 4th hypervisor +sim_add hv4 +as hv4 ovs-vsctl add-br br-phys +as hv4 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys +as hv4 ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:44" +as hv4 ovn_attach n1 br-phys 192.168.0.4 + +as hv4 ovs-vsctl add-port br-int vif-north -- \ + set Interface vif-north external-ids:iface-id=lp-north \ + options:tx_pcap=hv4/vif-north-tx.pcap \ + options:rxq_pcap=hv4/vif-north-rx.pcap \ + ofport-request=44 + +ovn-nbctl lr-add router +ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03 192.168.1.3/24 +ovn-nbctl lrp-add router router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 +ovn-nbctl lrp-add router router-to-underlay 00:00:01:01:02:07 172.31.0.1/24 + +ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port ls1-to-router type=router \ + options:router-port=router-to-ls1 -- lsp-set-addresses ls1-to-router router +ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port ls2-to-router type=router \ + options:router-port=router-to-ls2 -- lsp-set-addresses ls2-to-router router +ovn-nbctl lsp-add ls-underlay underlay-to-router -- set Logical_Switch_Port \ + underlay-to-router type=router \ + options:router-port=router-to-underlay \ + -- lsp-set-addresses underlay-to-router router + +ovn-nbctl lrp-set-gateway-chassis router-to-underlay hv3 +ovn-nbctl --stateless lr-nat-add router dnat_and_snat 172.31.0.100 192.168.1.1 +ovn-nbctl lrp-set-redirect-type router-to-underlay bridged + +ovn-nbctl --wait=sb sync + + +OVN_POPULATE_ARP + +# lsp_to_ls LSP +# +# Prints the name of the logical switch that contains LSP. +lsp_to_ls () { + case $1 in dnl ( + lp?[[11]]) echo ls1 ;; dnl ( + lp?[[12]]) echo ls2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_ls () { + case $1 in dnl ( + vif?[[11]]) echo ls1 ;; dnl ( + vif?[[12]]) echo ls2 ;; dnl ( + vif-north) echo ls-north ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +hv_to_num () { + case $1 in dnl ( + hv1) echo 1 ;; dnl ( + hv2) echo 2 ;; dnl ( + hv3) echo 3 ;; dnl ( + hv4) echo 4 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_num () { + case $1 in dnl ( + vif22) echo 22 ;; dnl ( + vif21) echo 21 ;; dnl ( + vif11) echo 11 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_hv () { + case $1 in dnl ( + vif[[1]]?) echo hv1 ;; dnl ( + vif[[2]]?) echo hv2 ;; dnl ( + vif-north) echo hv4 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_lrp () { + echo router-to-`vif_to_ls $1` +} + +ip_to_hex() { + printf "%02x%02x%02x%02x" "$@" +} + + +test_ip() { + # This packet has bad checksums but logical L3 routing doesn't check. + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 outport=$6 + local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 + shift; shift; shift; shift; shift + hv=`vif_to_hv $inport` + as $hv ovs-appctl netdev-dummy/receive $inport $packet + in_ls=`vif_to_ls $inport` + for outport; do + out_ls=`vif_to_ls $outport` + if test $in_ls = $out_ls; then + # Ports on the same logical switch receive exactly the same packet. + echo $packet + else + # Routing decrements TTL and updates source and dest MAC + # (and checksum). + out_lrp=`vif_to_lrp $outport` + # For North-South, packet will come via gateway chassis, i.e hv3 + if test $inport = vif-north; then + echo f0000000001100000101020308004500001c000000003f110100${src_ip}${dst_ip}0035111100080000 >> $outport.expected + fi + if test $outport = vif-north; then + echo f0f00000001100000101020708004500001c000000003e111726ac1f0064${dst_ip}0035111100080000 >> $outport.expected + fi + fi >> $outport.expected + done +} + +# Dump a bunch of info helpful for debugging if there's a failure. + +echo "------ OVN dump ------" +ovn-nbctl show +ovn-nbctl lr-nat-list router +ovn-sbctl show +ovn-sbctl list port_binding +ovn-sbctl list mac_binding +ovn-sbctl dump-flows + +echo "------ hv1 dump ------" +as hv1 ovs-vsctl show +as hv1 ovs-vsctl list Open_Vswitch + +echo "------ hv2 dump ------" +as hv2 ovs-vsctl show +as hv2 ovs-vsctl list Open_Vswitch + +echo "------ hv3 dump ------" +as hv3 ovs-vsctl show +as hv3 ovs-vsctl list Open_Vswitch + +echo "------ hv4 dump ------" +as hv4 ovs-vsctl show +as hv4 ovs-vsctl list Open_Vswitch + +echo "Send traffic South to Nouth" +sip=`ip_to_hex 192 168 1 1` +dip=`ip_to_hex 172 31 0 10` +test_ip vif11 f00000000011 000001010203 $sip $dip vif-north + +# Confirm that South to North traffic works fine. +OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv4/vif-north-tx.pcap], [vif-north.expected]) + +# Confirm that NATing happened without connection tracker + +AT_CHECK([ovn-sbctl dump-flows router | grep ct_snat | wc -l], [0], [0 +]) + +AT_CHECK([ovn-sbctl dump-flows router | grep ct_dnat | wc -l], [0], [0 +]) + +AT_CHECK([ovn-sbctl dump-flows router | grep ip4.dst=| wc -l], [0], [2 +]) + +AT_CHECK([ovn-sbctl dump-flows router | grep ip4.src=| wc -l], [0], [2 +]) + +echo "----------- Post Traffic hv1 dump -----------" +as hv1 ovs-ofctl dump-flows br-int +as hv1 ovs-ofctl show br-phys +as hv1 ovs-appctl fdb/show br-phys +as hv1 ovs-dpctl dump-flows + +echo "----------- Post Traffic hv2 dump -----------" +as hv2 ovs-ofctl dump-flows br-int +as hv2 ovs-ofctl show br-phys +as hv2 ovs-appctl fdb/show br-phys + +echo "----------- Post Traffic hv3 dump -----------" +as hv3 ovs-ofctl dump-flows br-int +as hv3 ovs-ofctl show br-phys +as hv3 ovs-appctl dpctl/dump-conntrack +as hv3 ovs-appctl fdb/show br-phys +as hv3 ovs-dpctl dump-flows +as hv3 ovs-ofctl dump-flows br-int + +echo "----------- Post Traffic hv4 dump -----------" +as hv4 ovs-ofctl dump-flows br-int +as hv4 ovs-ofctl show br-phys +as hv4 ovs-appctl fdb/show br-phys + +OVN_CLEANUP([hv1],[hv2],[hv3],[hv4]) + +AT_CLEANUP -- 1.8.3.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev