On Fri, Jul 15, 2022 at 4:35 AM Lorenzo Bianconi < lorenzo.bianc...@redhat.com> wrote: > > Rely on the following new actions for ecmp-symmetric routing: > - chk_ecmp_nh_mac > - chk_ecmp_nh > - commit_ecmp_nh > > In this way OVN is able to keep up if for any reason the ECMP traffic > source changes L2 address and keeps old L3 addresses.
Hi Lorenzo, do you have more details of the problem scenario? It seems the bugzilla access is limited. > > Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2096233 > Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com> > --- > northd/northd.c | 102 +++++++++++++++++++++++++++++++++++----- > northd/ovn-northd.8.xml | 25 ++++++---- > tests/ovn-northd.at | 18 ++++++- > tests/ovn.at | 4 +- > tests/system-ovn.at | 79 ++++++++++++++++++++++++++----- > 5 files changed, 191 insertions(+), 37 deletions(-) > > diff --git a/northd/northd.c b/northd/northd.c > index d31cb1688..57ec3675b 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -227,6 +227,7 @@ enum ovn_stage { > #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]" > #define REGBIT_LOOKUP_NEIGHBOR_IP_RESULT "reg9[3]" > #define REGBIT_DST_NAT_IP_LOCAL "reg9[4]" > +#define REGBIT_KNOWN_ECMP_NH "reg9[5]" > > /* Register to store the eth address associated to a router port for packets > * received in S_ROUTER_IN_ADMISSION. > @@ -327,7 +328,8 @@ enum ovn_stage { > * | | EGRESS_LOOPBACK/ | G | UNUSED | > * | R9 | PKT_LARGER/ | 4 | | > * | | LOOKUP_NEIGHBOR_RESULT/| | | > - * | | SKIP_LOOKUP_NEIGHBOR} | | | > + * | | SKIP_LOOKUP_NEIGHBOR/ | | | > + * | | KNOWN_ECMP_NH} | | | > * | | | | | > * | | REG_ORIG_TP_DPORT_ROUTER | | | > * | | | | | > @@ -9437,6 +9439,7 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, > struct ds *route_match) > { > const struct nbrec_logical_router_static_route *st_route = route->route; > + struct ds base_match = DS_EMPTY_INITIALIZER; > struct ds match = DS_EMPTY_INITIALIZER; > struct ds actions = DS_EMPTY_INITIALIZER; > struct ds ecmp_reply = DS_EMPTY_INITIALIZER; > @@ -9448,20 +9451,22 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, > /* If symmetric ECMP replies are enabled, then packets that arrive over > * an ECMP route need to go through conntrack. > */ > - ds_put_format(&match, "inport == %s && ip%s.%s == %s", > + ds_put_format(&base_match, "inport == %s && ip%s.%s == %s", > out_port->json_key, > IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "4" : "6", > route->is_src_route ? "dst" : "src", > cidr); > free(cidr); > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG, 100, > - ds_cstr(&match), "ct_next;", > - &st_route->header_); > + ds_cstr(&base_match), > + REGBIT_KNOWN_ECMP_NH" = chk_ecmp_nh_mac(); ct_next;", > + &st_route->header_); > > /* And packets that go out over an ECMP route need conntrack */ > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG, 100, > - ds_cstr(route_match), "ct_next;", > - &st_route->header_); > + ds_cstr(route_match), > + REGBIT_KNOWN_ECMP_NH" = chk_ecmp_nh(); ct_next;", > + &st_route->header_); > > /* Save src eth and inport in ct_label for packets that arrive over > * an ECMP route. > @@ -9469,11 +9474,84 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, > * NOTE: we purposely are not clearing match before this > * ds_put_cstr() call. The previous contents are needed. > */ > - ds_put_cstr(&match, " && (ct.new && !ct.est)"); > + ds_put_format(&match, "%s && (ct.new && !ct.est) && tcp", > + ds_cstr(&base_match)); > + ds_put_format(&actions, > + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " > + " %s = %" PRId64 ";}; " > + "commit_ecmp_nh(ipv6 = %s, proto = tcp); next;", > + ct_ecmp_reply_port_match, out_port->sb->tunnel_key, > + IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, > + ds_cstr(&match), ds_cstr(&actions), > + &st_route->header_); > + ds_clear(&match); > + ds_put_format(&match, "%s && (ct.new && !ct.est) && udp", > + ds_cstr(&base_match)); > + ds_clear(&actions); > + ds_put_format(&actions, > + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " > + " %s = %" PRId64 ";}; " > + "commit_ecmp_nh(ipv6 = %s, proto = udp); next;", > + ct_ecmp_reply_port_match, out_port->sb->tunnel_key, > + IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, > + ds_cstr(&match), ds_cstr(&actions), > + &st_route->header_); > + ds_clear(&match); > + ds_put_format(&match, "%s && (ct.new && !ct.est) && sctp", > + ds_cstr(&base_match)); > + ds_clear(&actions); > + ds_put_format(&actions, > + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " > + " %s = %" PRId64 ";}; " > + "commit_ecmp_nh(ipv6 = %s, proto = sctp); next;", > + ct_ecmp_reply_port_match, out_port->sb->tunnel_key, > + IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, > + ds_cstr(&match), ds_cstr(&actions), > + &st_route->header_); > > - ds_put_format(&actions, "ct_commit { ct_label.ecmp_reply_eth = eth.src;" > - " %s = %" PRId64 ";}; next;", > - ct_ecmp_reply_port_match, out_port->sb->tunnel_key); > + ds_clear(&match); > + ds_put_format(&match, > + "%s && (!ct.rpl && ct.est) && tcp && "REGBIT_KNOWN_ECMP_NH" == 0", > + ds_cstr(&base_match)); > + ds_clear(&actions); > + ds_put_format(&actions, > + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " > + " %s = %" PRId64 ";}; " > + "commit_ecmp_nh(ipv6 = %s, proto = tcp); next;", > + ct_ecmp_reply_port_match, out_port->sb->tunnel_key, > + IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, > + ds_cstr(&match), ds_cstr(&actions), > + &st_route->header_); > + > + ds_clear(&match); > + ds_put_format(&match, > + "%s && (!ct.rpl && ct.est) && udp && "REGBIT_KNOWN_ECMP_NH" == 0", > + ds_cstr(&base_match)); > + ds_clear(&actions); > + ds_put_format(&actions, > + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " > + " %s = %" PRId64 ";}; " Sorry that I haven't reviewed the details yet, but this flow would break HW offload again, which was fixed in 22.03 and backported to 21.12. cc @Mark Michelson <mmich...@redhat.com> Thanks, Han > + "commit_ecmp_nh(ipv6 = %s, proto = udp); next;", > + ct_ecmp_reply_port_match, out_port->sb->tunnel_key, > + IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); > + ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, > + ds_cstr(&match), ds_cstr(&actions), > + &st_route->header_); > + ds_clear(&match); > + ds_put_format(&match, > + "%s && (!ct.rpl && ct.est) && sctp && "REGBIT_KNOWN_ECMP_NH" == 0", > + ds_cstr(&base_match)); > + ds_clear(&actions); > + ds_put_format(&actions, > + "ct_commit { ct_label.ecmp_reply_eth = eth.src; " > + " %s = %" PRId64 ";}; " > + "commit_ecmp_nh(ipv6 = %s, proto = sctp); next;", > + ct_ecmp_reply_port_match, out_port->sb->tunnel_key, > + IN6_IS_ADDR_V4MAPPED(&route->prefix) ? "false" : "true"); > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ECMP_STATEFUL, 100, > ds_cstr(&match), ds_cstr(&actions), > &st_route->header_); > @@ -9481,7 +9559,8 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, > /* Bypass ECMP selection if we already have ct_label information > * for where to route the packet. > */ > - ds_put_format(&ecmp_reply, "ct.rpl && %s == %"PRId64, > + ds_put_format(&ecmp_reply, > + "ct.rpl && "REGBIT_KNOWN_ECMP_NH" == 1 && %s == %"PRId64, > ct_ecmp_reply_port_match, out_port->sb->tunnel_key); > ds_clear(&match); > ds_put_format(&match, "%s && %s", ds_cstr(&ecmp_reply), > @@ -9517,6 +9596,7 @@ add_ecmp_symmetric_reply_flows(struct hmap *lflows, > 200, ds_cstr(&ecmp_reply), > action, &st_route->header_); > > + ds_destroy(&base_match); > ds_destroy(&match); > ds_destroy(&actions); > ds_destroy(&ecmp_reply); > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml > index a87df24bd..aa7196a92 100644 > --- a/northd/ovn-northd.8.xml > +++ b/northd/ovn-northd.8.xml > @@ -3166,8 +3166,12 @@ icmp6 { > configured. The matching logic for these ports essentially reverses the > configured logic of the ECMP route. So for instance, a route with a > destination routing policy will instead match if the source IP address > - matches the static route's prefix. The flow uses the action > - <code>ct_next</code> to send IP packets to the connection tracker for > + matches the static route's prefix. The flow uses the actions > + <code>chk_ecmp_nh_mac(); ct_next</code> or > + <code>chk_ecmp_nh(); ct_next</code> to send IP packets to table > + <code>OFTABLE_ECMP_NH_MAC</code> or to table > + <code>OFTABLE_ECMP_NH</code> in order to check if source info are already > + stored by OVN and then to the connection tracker for > packet de-fragmentation and tracking before sending it to the next table. > </p> > > @@ -3426,10 +3430,11 @@ icmp6 { > route with a destination routing policy will instead match if the > source IP address matches the static route's prefix. The flow uses > the action <code>ct_commit { ct_label.ecmp_reply_eth = eth.src;" > - " ct_mark.ecmp_reply_port = <var>K</var>;}; next; </code> to commit > - the connection and storing <code>eth.src</code> and the ECMP > - reply port binding tunnel key <var>K</var> in the > - <code>ct_label</code>. > + " ct_mark.ecmp_reply_port = <var>K</var>;}; commit_ecmp_nh(); next; > + </code> to commit the connection and storing <code>eth.src</code> and > + the ECMP reply port binding tunnel key <var>K</var> in the > + <code>ct_label</code> and the traffic pattern to table > + <code>OFTABLE_ECMP_NH_MAC</code> or <code>OFTABLE_ECMP_NH</code>. > </li> > </ul> > > @@ -3568,10 +3573,10 @@ output; > which the packet should be sent. The <code>ct_mark.ecmp_reply_port</code> > tells the logical router port on which the packet should be sent. These > values saved to the conntrack fields when the initial ingress traffic is > - received over the ECMP route and committed to conntrack. The > - priority-10300 flows in this stage set the <code>outport</code>, > - while the <code>eth.dst</code> is set by flows at the ARP/ND Resolution > - stage. > + received over the ECMP route and committed to conntrack. > + If <code>REGBIT_KNOWN_ECMP_NH</code> is set, the priority-10300 > + flows in this stage set the <code>outport</code>, while the > + <code>eth.dst</code> is set by flows at the ARP/ND Resolution stage. > </p> > > <p> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at > index 610a5ce12..0c7b24816 100644 > --- a/tests/ovn-northd.at > +++ b/tests/ovn-northd.at > @@ -5644,10 +5644,24 @@ AT_CHECK([grep -e "lr_in_ip_routing_ecmp" lr0flows | sed 's/192\.168\.0\..0/192. > table=??(lr_in_ip_routing_ecmp), priority=150 , match=(reg8[[0..15]] == 0), action=(next;) > ]) > > +AT_CHECK([grep -e "lr_in_ecmp_stateful".*commit_ecmp_nh lr0flows | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (!ct.rpl && ct.est) && sctp && reg9[[5]] == 0), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = sctp); next;) > + table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (!ct.rpl && ct.est) && tcp && reg9[[5]] == 0), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = tcp); next;) > + table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (!ct.rpl && ct.est) && udp && reg9[[5]] == 0), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = udp); next;) > + table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (ct.new && !ct.est) && sctp), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = sctp); next;) > + table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (ct.new && !ct.est) && tcp), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = tcp); next;) > + table=??(lr_in_ecmp_stateful), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1 && (ct.new && !ct.est) && udp), action=(ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_label.ecmp_reply_port = 1;}; commit_ecmp_nh(ipv6 = false, proto = udp); next;) > +]) > + > +AT_CHECK([grep -e "lr_in_defrag".*chk_ecmp_nh* lr0flows | sed 's/table=../table=??/' | sort], [0], [dnl > + table=??(lr_in_defrag ), priority=100 , match=(inport == "lr0-public" && ip4.src == 1.0.0.1), action=(reg9[[5]] = chk_ecmp_nh_mac(); ct_next;) > + table=??(lr_in_defrag ), priority=100 , match=(reg7 == 0 && ip4.dst == 1.0.0.1/32), action=(reg9[[5]] = chk_ecmp_nh(); ct_next;) > +]) > + > dnl The chassis was created with other_config:ct-no-masked-label=false, the flows > dnl should be using ct_label.ecmp_reply_port. > AT_CHECK([grep -e "lr_in_arp_resolve.*ecmp" lr0flows | sed 's/table=../table=??/'], [0], [dnl > - table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && ct_label.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) > + table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && reg9[[5]] == 1 && ct_label.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) > ]) > > dnl Simulate an ovn-controller upgrade to a version that supports > @@ -5657,7 +5671,7 @@ check ovn-sbctl set chassis ch1 other_config:ct-no-masked-label=true > check ovn-nbctl --wait=sb sync > ovn-sbctl dump-flows lr0 > lr0flows > AT_CHECK([grep -e "lr_in_arp_resolve.*ecmp" lr0flows | sed 's/table=../table=??/'], [0], [dnl > - table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && ct_mark.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) > + table=??(lr_in_arp_resolve ), priority=200 , match=(ct.rpl && reg9[[5]] == 1 && ct_mark.ecmp_reply_port == 1), action=(push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[[32..79]]; pop(xxreg1); next;) > ]) > > # add ecmp route with wrong nexthop > diff --git a/tests/ovn.at b/tests/ovn.at > index 91dc3b9d6..12ba3f6d0 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -27173,7 +27173,7 @@ AT_CHECK([ > grep "priority=200" | \ > grep -c "move:NXM_NX_CT_LABEL\\[[\\]]->NXM_NX_XXREG1\\[[\\]],move:NXM_NX_XXREG1\\[[32..79\\]]->NXM_OF_ETH_DST" > done; :], [0], [dnl > -1 > +6 > 1 > 0 > 0 > @@ -27298,7 +27298,7 @@ AT_CHECK([ > grep "priority=200" | \ > grep -c "move:NXM_NX_CT_LABEL\\[[\\]]->NXM_NX_XXREG1\\[[\\]],move:NXM_NX_XXREG1\\[[32..79\\]]->NXM_OF_ETH_DST" > done; :], [0], [dnl > -1 > +6 > 1 > 0 > 0 > diff --git a/tests/system-ovn.at b/tests/system-ovn.at > index 4a8fdede8..b3096deb3 100644 > --- a/tests/system-ovn.at > +++ b/tests/system-ovn.at > @@ -5956,11 +5956,8 @@ ovn-nbctl --wait=hv sync > > on_exit 'ovs-ofctl dump-flows br-int' > > -# 'bob1' should be able to ping 'alice1' directly. > -NS_CHECK_EXEC([bob1], [ping -q -c 20 -i 0.3 -w 15 10.0.0.2 | FORMAT_PING], \ > -[0], [dnl > -20 packets transmitted, 20 received, 0% packet loss, time 0ms > -]) > +NETNS_DAEMONIZE([alice1], [nc -l -k 80], [alice1.pid]) > +NS_CHECK_EXEC([bob1], [nc -z 10.0.0.2 80], [0]) > > # Ensure conntrack entry is present. We should not try to predict > # the tunnel key for the output port, so we strip it from the labels > @@ -5968,7 +5965,7 @@ NS_CHECK_EXEC([bob1], [ping -q -c 20 -i 0.3 -w 15 10.0.0.2 | FORMAT_PING], \ > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(172.16.0.1) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | > sed -e 's/mark=[[0-9]]*/mark=<cleared>/'], [0], [dnl > -icmp,orig=(src=172.16.0.1,dst=10.0.0.2,id=<cleared>,type=8,code=0),reply=(src=10.0.0.2,dst=172.16.0.1,id=<cleared>,type=0,code=0),zone=<cleared>,mark=<cleared>,labels=0x401020400000000 > +tcp,orig=(src=172.16.0.1,dst=10.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=10.0.0.2,dst=172.16.0.1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x401020400000000,protoinfo=(state=<cleared>) > ]) > > # Ensure datapaths show conntrack states as expected > @@ -5981,6 +5978,36 @@ AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_state(-new+est+rpl+trk).*ct_lab > 1 > ]) > > +# Flush conntrack entries for easier output parsing of next test. > +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > + > +# Change bob1 L2 address anche check the reply is properly updated. > +ovn-nbctl set Logical_Router_Port R2_ext mac='"00:00:10:01:02:04"' > +ovn-nbctl set Logical_Switch_Port r2-ext \ > + type=router options:router-port=R2_ext addresses='"00:00:10:01:02:04"' > + > +NS_CHECK_EXEC([bob1], [nc -z 10.0.0.2 80], [0]) > +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_state(+new-est-rpl+trk).*ct(.*label=0x1001020400000000/.*)' -c], [0], [dnl > +1 > +]) > +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_state(-new+est+rpl+trk).*ct_label(0x1001020400000000)' -c], [0], [dnl > +1 > +]) > + > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 0x1001020400000000 | FORMAT_CT(172.16.0.1) | \ > +sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | > +sed -e 's/mark=[[0-9]]*/mark=<cleared>/'], [0], [dnl > +tcp,orig=(src=172.16.0.1,dst=10.0.0.2,sport=<cleared>,dport=<cleared>),reply=(src=10.0.0.2,dst=172.16.0.1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000,protoinfo=(state=<cleared>) > +]) > + > +# Check entries in table 76 and 77 expires w/o traffic > +OVS_WAIT_UNTIL([ > +test $(ovs-ofctl dump-flows br-int | grep -c 'table=76, n_packets') -eq 0 > +]) > +OVS_WAIT_UNTIL([ > +test $(ovs-ofctl dump-flows br-int | grep -c 'table=77, n_packets') -eq 0 > +]) > + > ovs-ofctl dump-flows br-int > > OVS_APP_EXIT_AND_WAIT([ovn-controller]) > @@ -6122,11 +6149,8 @@ ovn-nbctl --wait=hv sync > > on_exit 'ovs-ofctl dump-flows br-int' > > -# 'bob1' should be able to ping 'alice1' directly. > -NS_CHECK_EXEC([bob1], [ping -q -c 20 -i 0.3 -w 15 fd01::2 | FORMAT_PING], \ > -[0], [dnl > -20 packets transmitted, 20 received, 0% packet loss, time 0ms > -]) > +NETNS_DAEMONIZE([alice1], [nc -6 -l -k 80], [alice1.pid]) > +NS_CHECK_EXEC([bob1], [nc -6 -z fd01::2 80], [0]) > > # Ensure datapaths show conntrack states as expected > # Like with conntrack entries, we shouldn't try to predict > @@ -6145,7 +6169,38 @@ AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_state(-new+est+rpl+trk).*ct_lab > AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fd01::2) | \ > sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | > sed -e 's/mark=[[0-9]]*/mark=<cleared>/'], [0], [dnl > -icmpv6,orig=(src=fd07::1,dst=fd01::2,id=<cleared>,type=128,code=0),reply=(src=fd01::2,dst=fd07::1,id=<cleared>,type=129,code=0),zone=<cleared>,mark=<cleared>,labels=0x401020400000000 > +tcp,orig=(src=fd07::1,dst=fd01::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd07::1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x401020400000000,protoinfo=(state=<cleared>) > +]) > + > +# Flush conntrack entries for easier output parsing of next test. > +AT_CHECK([ovs-appctl dpctl/flush-conntrack]) > + > +# Change bob1 L2 address anche check the reply is properly updated. > +ovn-nbctl set Logical_Router_Port R2_ext mac='"00:00:10:01:02:04"' > +ovn-nbctl set Logical_Switch_Port r2-ext \ > + type=router options:router-port=R2_ext addresses='"00:00:10:01:02:04"' > + > +NS_CHECK_EXEC([bob1], [nc -6 -z fd01::2 80], [0]) > + > +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_state(+new-est-rpl+trk).*ct(.*label=0x1001020400000000/.*)' -c], [0], [dnl > +1 > +]) > +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_state(-new+est+rpl+trk).*ct_label(0x1001020400000000)' -c], [0], [dnl > +1 > +]) > + > +AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 0x1001020400000000 | FORMAT_CT(fd01::2) | \ > +sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | > +sed -e 's/mark=[[0-9]]*/mark=<cleared>/'], [0], [dnl > +tcp,orig=(src=fd07::1,dst=fd01::2,sport=<cleared>,dport=<cleared>),reply=(src=fd01::2,dst=fd07::1,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=<cleared>,labels=0x1001020400000000,protoinfo=(state=<cleared>) > +]) > + > +# Check entries in table 76 and 77 expires w/o traffic > +OVS_WAIT_UNTIL([ > +test $(ovs-ofctl dump-flows br-int | grep -c 'table=76, n_packets') -eq 0 > +]) > +OVS_WAIT_UNTIL([ > +test $(ovs-ofctl dump-flows br-int | grep -c 'table=77, n_packets') -eq 0 > ]) > > ovs-ofctl dump-flows br-int > -- > 2.36.1 > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev