]> git.proxmox.com Git - ovs.git/commitdiff
ovn: Fix gateway load balancing.
authorDarrell Ball <dlu998@gmail.com>
Thu, 28 Jun 2018 05:15:43 +0000 (22:15 -0700)
committerGurucharan Shetty <guru@ovn.org>
Fri, 29 Jun 2018 04:04:38 +0000 (21:04 -0700)
Non-distributed and distributed gateway load balancing is broken.
Recent changes for port unreachable handling broke the associated
unsnat functionality.  The fix approach is check for gateway
contexts and accept packets directed to gateway router IPs.

Fixes: 86558ac2e476 ("OVN: add UDP port unreachable support to OVN logical router.")
Fixes: 159932c9e4ea ("OVN: add TCP port unreachable support to OVN logical router.")
Fixes: 0e858e05f76b ("OVN: add protocol unreachable support to OVN router ports.")
CC: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Darrell Ball <dlu998@gmail.com>
Signed-off-by: Gurucharan Shetty <guru@ovn.org>
ovn/northd/ovn-northd.8.xml
ovn/northd/ovn-northd.c

index cfd35115ed0b47cdc77b72a6ca7091e250584e37..8030f1170bd17e4a82dba12f8e6c274e9b9a4bbb 100644 (file)
@@ -1310,8 +1310,9 @@ nd_na {
         <p>
           UDP port unreachable.  Priority-80 flows generate ICMP port
           unreachable messages in reply to UDP datagrams directed to the
-          router's IP address.  The logical router doesn't accept any UDP
-          traffic so it always generates such a reply.
+          router's IP address, except in the special case of gateways,
+          which accept traffic directed to a router IP for load balancing
+          and NAT purposes.
         </p>
 
         <p>
@@ -1321,10 +1322,10 @@ nd_na {
 
       <li>
         <p>
-          TCP reset.  Priority-80 flows generate TCP reset messages in reply to
-          TCP datagrams directed to the router's IP address.  The logical
-          router doesn't accept any TCP traffic so it always generates such a
-          reply.
+          TCP reset.  Priority-80 flows generate TCP reset messages in reply
+          to TCP datagrams directed to the router's IP address, except in
+          the special case of gateways, which accept traffic directed to a
+          router IP for load balancing and NAT purposes.
         </p>
 
         <p>
@@ -1336,7 +1337,9 @@ nd_na {
         <p>
           Protocol unreachable.  Priority-70 flows generate ICMP protocol
           unreachable messages in reply to packets directed to the router's IP
-          address on IP protocols other than UDP, TCP, and ICMP.
+          address on IP protocols other than UDP, TCP, and ICMP, except in the
+          special case of gateways, which accept traffic directed to a router
+          IP for load balancing purposes.
         </p>
 
         <p>
index 72fe4e795871a9a92d6e4ba34364f682b46cc263..7648bcee744b1f88a919dcb8cccb0f1c471fb785 100644 (file)
@@ -5141,48 +5141,49 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
                           ds_cstr(&match), ds_cstr(&actions));
         }
 
-        /* UDP/TCP port unreachable */
-        for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
-            const char *action;
-
-            ds_clear(&match);
-            ds_put_format(&match,
-                          "ip4 && ip4.dst == %s && !ip.later_frag && udp",
-                          op->lrp_networks.ipv4_addrs[i].addr_s);
-            action = "icmp4 {"
-                        "eth.dst <-> eth.src; "
-                        "ip4.dst <-> ip4.src; "
-                        "ip.ttl = 255; "
-                        "icmp4.type = 3; "
-                        "icmp4.code = 3; "
-                        "next; };";
-            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
-                          ds_cstr(&match), action);
+        if (!smap_get(&op->od->nbr->options, "chassis")
+            && !op->od->l3dgw_port) {
+            /* UDP/TCP port unreachable. */
+            for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
+                ds_clear(&match);
+                ds_put_format(&match,
+                              "ip4 && ip4.dst == %s && !ip.later_frag && udp",
+                              op->lrp_networks.ipv4_addrs[i].addr_s);
+                const char *action = "icmp4 {"
+                                     "eth.dst <-> eth.src; "
+                                     "ip4.dst <-> ip4.src; "
+                                     "ip.ttl = 255; "
+                                     "icmp4.type = 3; "
+                                     "icmp4.code = 3; "
+                                     "next; };";
+                ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
+                              ds_cstr(&match), action);
 
-            ds_clear(&match);
-            ds_put_format(&match,
-                          "ip4 && ip4.dst == %s && !ip.later_frag && tcp",
-                          op->lrp_networks.ipv4_addrs[i].addr_s);
-            action = "tcp_reset {"
-                        "eth.dst <-> eth.src; "
-                        "ip4.dst <-> ip4.src; "
-                        "next; };";
-            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
-                          ds_cstr(&match), action);
+                ds_clear(&match);
+                ds_put_format(&match,
+                              "ip4 && ip4.dst == %s && !ip.later_frag && tcp",
+                              op->lrp_networks.ipv4_addrs[i].addr_s);
+                action = "tcp_reset {"
+                         "eth.dst <-> eth.src; "
+                         "ip4.dst <-> ip4.src; "
+                         "next; };";
+                ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
+                              ds_cstr(&match), action);
 
-            ds_clear(&match);
-            ds_put_format(&match,
-                          "ip4 && ip4.dst == %s && !ip.later_frag",
-                          op->lrp_networks.ipv4_addrs[i].addr_s);
-            action = "icmp4 {"
-                        "eth.dst <-> eth.src; "
-                        "ip4.dst <-> ip4.src; "
-                        "ip.ttl = 255; "
-                        "icmp4.type = 3; "
-                        "icmp4.code = 2; "
-                        "next; };";
-            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 70,
-                          ds_cstr(&match), action);
+                ds_clear(&match);
+                ds_put_format(&match,
+                              "ip4 && ip4.dst == %s && !ip.later_frag",
+                              op->lrp_networks.ipv4_addrs[i].addr_s);
+                action = "icmp4 {"
+                         "eth.dst <-> eth.src; "
+                         "ip4.dst <-> ip4.src; "
+                         "ip.ttl = 255; "
+                         "icmp4.type = 3; "
+                         "icmp4.code = 2; "
+                         "next; };";
+                ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 70,
+                              ds_cstr(&match), action);
+            }
         }
 
         ds_clear(&match);
@@ -5306,19 +5307,20 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
         }
 
         /* TCP port unreachable */
-        for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
-            const char *action;
-
-            ds_clear(&match);
-            ds_put_format(&match,
-                          "ip6 && ip6.dst == %s && !ip.later_frag && tcp",
-                          op->lrp_networks.ipv6_addrs[i].addr_s);
-            action = "tcp_reset {"
-                        "eth.dst <-> eth.src; "
-                        "ip6.dst <-> ip6.src; "
-                        "next; };";
-            ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
+        if (!smap_get(&op->od->nbr->options, "chassis")
+            && !op->od->l3dgw_port) {
+            for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
+                ds_clear(&match);
+                ds_put_format(&match,
+                              "ip6 && ip6.dst == %s && !ip.later_frag && tcp",
+                              op->lrp_networks.ipv6_addrs[i].addr_s);
+                const char *action = "tcp_reset {"
+                                     "eth.dst <-> eth.src; "
+                                     "ip6.dst <-> ip6.src; "
+                                     "next; };";
+                ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
                           ds_cstr(&match), action);
+            }
         }
     }