Introduce icmp6_error logical flows in router pipeline if gateway_mtu has been added to logical router port option column in order to perform IPv6 PMTU discovery
Signed-off-by: Lorenzo Bianconi <[email protected]> --- northd/ovn-northd.8.xml | 24 +++++++++--- northd/ovn-northd.c | 84 ++++++++++++++++++++++++++++------------- tests/ovn.at | 48 +++++++++++++++++++++-- 3 files changed, 120 insertions(+), 36 deletions(-) diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index a7639f33a..97985a757 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -2856,11 +2856,11 @@ REGBIT_PKT_LARGER = check_pkt_larger(<var>L</var>); next; For distributed logical routers with distributed gateway port configured with <code>options:gateway_mtu</code> to a valid integer value, this table adds the following priority-50 logical flow for each - logical router port with the match <code>ip4 && - inport == <var>LRP</var> && outport == <var>GW_PORT</var> - && REGBIT_PKT_LARGER</code>, where <var>LRP</var> is the logical - router port and <var>GW_PORT</var> is the distributed gateway router port - and applies the following action + logical router port with the match <code>inport == <var>LRP</var> + && outport == <var>GW_PORT</var> && + REGBIT_PKT_LARGER</code>, where <var>LRP</var> is the logical + router port and <var>GW_PORT</var> is the distributed gateway router + port and applies the following action for ipv4 and ipv6 respectively: </p> <pre> @@ -2875,6 +2875,18 @@ icmp4 { REGBIT_EGRESS_LOOPBACK = 1; next(pipeline=ingress, table=0); }; + +icmp6 { + icmp6.type = 2; + icmp6.code = 0; + icmp6.frag_mtu = <var>M</var>; + eth.dst = <var>E</var>; + ip6.dst = ip6.src; + ip6.src = <var>I</var>; + ip.ttl = 255; + REGBIT_EGRESS_LOOPBACK = 1; + next(pipeline=ingress, table=0); +}; </pre> <ul> @@ -2890,7 +2902,7 @@ icmp4 { </li> <li> - <var>I</var> is the IPv4 address of the logical router port. + <var>I</var> is the IPv4/IPv6 address of the logical router port. </li> </ul> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 417dbb603..234bbd99a 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -10117,8 +10117,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, } ds_clear(&match); - ds_put_format(&match, "outport == %s && ip4", - od->l3dgw_port->json_key); + ds_put_format(&match, "outport == %s", od->l3dgw_port->json_key); ds_clear(&actions); ds_put_format(&actions, @@ -10131,34 +10130,65 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, for (size_t i = 0; i < od->nbr->n_ports; i++) { struct ovn_port *rp = ovn_port_find(ports, od->nbr->ports[i]->name); - if (!rp || rp == od->l3dgw_port || - !rp->lrp_networks.ipv4_addrs) { + if (!rp || rp == od->l3dgw_port) { continue; } - ds_clear(&match); - ds_put_format(&match, "inport == %s && outport == %s && ip4 " - "&& "REGBIT_PKT_LARGER, - rp->json_key, od->l3dgw_port->json_key); - ds_clear(&actions); - /* Set icmp4.frag_mtu to gw_mtu */ - ds_put_format(&actions, - "icmp4_error {" - REGBIT_EGRESS_LOOPBACK" = 1; " - "eth.dst = %s; " - "ip4.dst = ip4.src; " - "ip4.src = %s; " - "ip.ttl = 255; " - "icmp4.type = 3; /* Destination Unreachable. */ " - "icmp4.code = 4; /* Frag Needed and DF was Set. */ " - "icmp4.frag_mtu = %d; " - "next(pipeline=ingress, table=0); };", - rp->lrp_networks.ea_s, - rp->lrp_networks.ipv4_addrs[0].addr_s, - gw_mtu); - ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_LARGER_PKTS, - 50, ds_cstr(&match), ds_cstr(&actions), - &rp->nbrp->header_); + if (rp->lrp_networks.ipv4_addrs) { + ds_clear(&match); + ds_put_format(&match, "inport == %s && outport == %s" + " && ip4 && "REGBIT_PKT_LARGER, + rp->json_key, od->l3dgw_port->json_key); + + ds_clear(&actions); + /* Set icmp4.frag_mtu to gw_mtu */ + ds_put_format(&actions, + "icmp4_error {" + REGBIT_EGRESS_LOOPBACK" = 1; " + "eth.dst = %s; " + "ip4.dst = ip4.src; " + "ip4.src = %s; " + "ip.ttl = 255; " + "icmp4.type = 3; /* Destination Unreachable. */ " + "icmp4.code = 4; /* Frag Needed and DF was Set. */ " + "icmp4.frag_mtu = %d; " + "next(pipeline=ingress, table=0); };", + rp->lrp_networks.ea_s, + rp->lrp_networks.ipv4_addrs[0].addr_s, + gw_mtu); + ovn_lflow_add_with_hint(lflows, od, + S_ROUTER_IN_LARGER_PKTS, 50, + ds_cstr(&match), ds_cstr(&actions), + &rp->nbrp->header_); + } + + if (rp->lrp_networks.ipv6_addrs) { + ds_clear(&match); + ds_put_format(&match, "inport == %s && outport == %s" + " && ip6 && "REGBIT_PKT_LARGER, + rp->json_key, od->l3dgw_port->json_key); + + ds_clear(&actions); + /* Set icmp6.frag_mtu to gw_mtu */ + ds_put_format(&actions, + "icmp6_error {" + REGBIT_EGRESS_LOOPBACK" = 1; " + "eth.dst = %s; " + "ip6.dst = ip6.src; " + "ip6.src = %s; " + "ip.ttl = 255; " + "icmp6.type = 2; " + "icmp6.code = 0; " + "icmp6.frag_mtu = %d; " + "next(pipeline=ingress, table=0); };", + rp->lrp_networks.ea_s, + rp->lrp_networks.ipv6_addrs[0].addr_s, + gw_mtu); + ovn_lflow_add_with_hint(lflows, od, + S_ROUTER_IN_LARGER_PKTS, 50, + ds_cstr(&match), ds_cstr(&actions), + &rp->nbrp->header_); + } } } } diff --git a/tests/ovn.at b/tests/ovn.at index 124dd78d2..020ed17c0 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -15015,17 +15015,17 @@ ovn_start ovn-nbctl ls-add sw0 ovn-nbctl lsp-add sw0 sw0-port1 -ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3" +ovn-nbctl lsp-set-addresses sw0-port1 "50:54:00:00:00:01 10.0.0.3 1000::3" ovn-nbctl lr-add lr0 -ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 +ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24 1000::1/64 ovn-nbctl lsp-add sw0 sw0-lr0 ovn-nbctl lsp-set-type sw0-lr0 router ovn-nbctl lsp-set-addresses sw0-lr0 router ovn-nbctl lsp-set-options sw0-lr0 router-port=lr0-sw0 ovn-nbctl ls-add public -ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24 +ovn-nbctl lrp-add lr0 lr0-public 00:00:20:20:12:13 172.168.0.100/24 2000::1/64 ovn-nbctl lsp-add public public-lr0 ovn-nbctl lsp-set-type public-lr0 router ovn-nbctl lsp-set-addresses public-lr0 router @@ -15039,6 +15039,7 @@ ovn-nbctl lsp-set-options ln-public network_name=phys ovn-nbctl lrp-set-gateway-chassis lr0-public hv1 20 ovn-nbctl lr-nat-add lr0 snat 172.168.0.100 10.0.0.0/24 +ovn-nbctl lr-nat-add lr0 snat 2000::1 1000::/64 net_add n1 @@ -15149,6 +15150,41 @@ test_ip_packet_larger() { fi } +test_ip6_packet_larger() { + local icmp_pmtu_reply_expected=$1 + + local eth_src=505400000001 + local eth_dst=00000000ff01 + + local ipv6_src=10000000000000000000000000000003 + local ipv6_dst=20000000000000000000000000000002 + local ipv6_rt=10000000000000000000000000000001 + + local payload=0000000000000000000000000000000000000000 + local payload=${payload}0000000000000000000000000000000000000000 + local payload=${payload}0000000000000000000000000000000000000000 + local payload=${payload}0000000000000000000000000000000000000000 + + local ip6_hdr=6000000000583aff${ipv6_src}${ipv6_dst} + local packet=${eth_dst}${eth_src}86dd${ip6_hdr}8000ec7662f00001${payload} + + as hv1 reset_pcap_file br-phys_n1 hv1/br-phys_n1 + as hv1 reset_pcap_file hv1-vif1 hv1/vif1 + + # Send packet from sw0-port1 to outside + as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet + + if test $icmp_pmtu_reply_expected = 1; then + icmp6_reply=${eth_src}${eth_dst}86dd6000000000883afe + icmp6_reply=${icmp6_reply}${ipv6_rt}${ipv6_src}020041ff00000076 + icmp6_reply=${icmp6_reply}6000000000583afe${ipv6_src}${ipv6_dst} + icmp6_reply=${icmp6_reply}8000ec7662f00001${payload} + echo $icmp6_reply > hv1-vif1.expected + + OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [hv1-vif1.expected]) + fi +} + ovn-nbctl show ovn-sbctl show @@ -15183,6 +15219,12 @@ OVS_WAIT_UNTIL([ # Now the packet should be sent via the localnet port to br-phys. icmp_reply_expected=0 test_ip_packet_larger $icmp_reply_expected + +# Set the gateway mtu to 118 +ovn-nbctl --wait=hv set logical_router_port lr0-public options:gateway_mtu=118 +icmp_reply_expected=1 +test_ip6_packet_larger $icmp_reply_expected + OVN_CLEANUP([hv1]) AT_CLEANUP -- 2.26.2 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
