diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 4d95a3d9d..c98bf2ab6 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -3548,6 +3548,17 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows)
     }
 }
 
+/* Return to whether Port is only configured cidr. */
+static bool
+op_is_v4_network_cidr(const struct ipv4_netaddr *ipv4_addrs)
+{
+    if ((ipv4_addrs->plen != 32) &&
+        (ipv4_addrs->addr == ipv4_addrs->network)) {
+        return true;
+    }
+    return false;
+}
+
 static void
 build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
                     struct hmap *lflows, struct hmap *mcgroups)
@@ -3679,6 +3690,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
 
         for (size_t i = 0; i < op->n_lsp_addrs; i++) {
             for (size_t j = 0; j < op->lsp_addrs[i].n_ipv4_addrs; j++) {
+                if (!strcmp(op->nbsp->type, "router") &&
+                    op_is_v4_network_cidr(&op->lsp_addrs[i].ipv4_addrs[j])) {
+                        continue;
+                }
                 ds_clear(&match);
                 ds_put_format(&match, "arp.tpa == %s && arp.op == 1",
                               op->lsp_addrs[i].ipv4_addrs[j].addr_s);
@@ -4100,8 +4115,32 @@ lrport_is_enabled(const struct nbrec_logical_router_port *lrport)
     return !lrport->enabled || *lrport->enabled;
 }
 
+/* Returns a string of the net external_ip of the router port 'op'.
+ * If one is not found, returns NULL.
+ *
+ * The caller must not free the returned string. */
+static const char *
+find_lrp_external_ip(const struct ovn_port *op)
+{
+    for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
+        const struct ipv4_netaddr *na = &op->lrp_networks.ipv4_addrs[i];
+        for (size_t j = 0; j < op->od->nbr->n_nat; j++) {
+            const struct nbrec_nat *nat = op->od->nbr->nat[j];
+            ovs_be32 external_ip;
+            if (!ip_parse(nat->external_ip, &external_ip)) {
+                continue;
+            }
+            if (!((na->network ^ external_ip) & na->mask)) {
+                return nat->external_ip;
+            }
+        }
+    }
+    return NULL;
+}
+
 /* Returns a string of the IP address of the router port 'op' that
- * overlaps with 'ip_s".  If one is not found, returns NULL.
+ * overlaps with 'ip_s". Or Returns a string of the nat external_ip
+ * address of the router port 'op', If one is not found, returns NULL.
  *
  * The caller must not free the returned string. */
 static const char *
@@ -4118,15 +4157,27 @@ find_lrp_member_ip(const struct ovn_port *op, const char *ip_s)
             return NULL;
         }
 
+        bool find_port = false;
         for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
             const struct ipv4_netaddr *na = &op->lrp_networks.ipv4_addrs[i];
 
             if (!((na->network ^ ip) & na->mask)) {
+                find_port = true;
                 /* There should be only 1 interface that matches the
                  * supplied IP.  Otherwise, it's a configuration error,
                  * because subnets of a router's interfaces should NOT
                  * overlap. */
-                return na->addr_s;
+                if (na->addr != na->network) {
+                    return na->addr_s;
+                }
+            }
+        }
+
+        if (find_port) {
+            /* Get NAT external IP addresses. */
+            const char *external_ip = find_lrp_external_ip(op);
+            if (external_ip) {
+                return external_ip;
             }
         }
     } else {
@@ -4156,6 +4207,20 @@ find_lrp_member_ip(const struct ovn_port *op, const char *ip_s)
     return NULL;
 }
 
+static int
+op_get_v4_ip_number(const struct ovn_port *op)
+{
+    int n = 0;
+    if (op->lrp_networks.n_ipv4_addrs) {
+        for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
+            if (!op_is_v4_network_cidr(&op->lrp_networks.ipv4_addrs[i])) {
+                n++;
+            }
+        }
+    }
+    return n;
+}
+
 static void
 add_route(struct hmap *lflows, const struct ovn_port *op,
           const char *lrp_addr_s, const char *network_s, int plen,
@@ -4296,12 +4361,19 @@ build_static_route_flow(struct hmap *lflows, struct ovn_datapath *od,
             /* There are no IP networks configured on the router's port via
              * which 'route->nexthop' is theoretically reachable.  But since
              * 'out_port' has been specified, we honor it by trying to reach
-             * 'route->nexthop' via the first IP address of 'out_port'.
+             * 'route->nexthop' via the first IP address  of 'out_port' or
+             * nat external IP addresses of 'out_port'.
              * (There are cases, e.g in GCE, where each VM gets a /32 IP
              * address and the default gateway is still reachable from it.) */
             if (is_ipv4) {
                 if (out_port->lrp_networks.n_ipv4_addrs) {
-                    lrp_addr_s = out_port->lrp_networks.ipv4_addrs[0].addr_s;
+                    struct lport_addresses *address = &out_port->lrp_networks;
+                    for (int i = 0; i < address->n_ipv4_addrs; i++) {
+                        if (!op_is_v4_network_cidr(&address->ipv4_addrs[i])) {
+                            lrp_addr_s = address->ipv4_addrs[i].addr_s;
+                            break;
+                        }
+                    }
                 }
             } else {
                 if (out_port->lrp_networks.n_ipv6_addrs) {
@@ -4328,7 +4400,7 @@ build_static_route_flow(struct hmap *lflows, struct ovn_datapath *od,
         }
     }
 
-    if (!out_port || !lrp_addr_s) {
+    if (!out_port) {
         /* There is no matched out port. */
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
         VLOG_WARN_RL(&rl, "No path for static route %s; next hop %s",
@@ -4336,6 +4408,14 @@ build_static_route_flow(struct hmap *lflows, struct ovn_datapath *od,
         goto free_prefix_s;
     }
 
+    if (!lrp_addr_s) {
+        /* There is no matched lrp_addr_s. */
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+        VLOG_DBG_RL(&rl, "No source ip for static route %s; next hop %s",
+                     route->ip_prefix, route->nexthop);
+        goto free_prefix_s;
+    }
+
     char *policy = route->policy ? route->policy : "dst-ip";
     add_route(lflows, out_port, lrp_addr_s, prefix_s, plen, route->nexthop,
               policy);
@@ -4347,14 +4427,16 @@ free_prefix_s:
 static void
 op_put_v4_networks(struct ds *ds, const struct ovn_port *op, bool add_bcast)
 {
-    if (!add_bcast && op->lrp_networks.n_ipv4_addrs == 1) {
+    if (!add_bcast && op_get_v4_ip_number(op) == 1) {
         ds_put_format(ds, "%s", op->lrp_networks.ipv4_addrs[0].addr_s);
         return;
     }
 
     ds_put_cstr(ds, "{");
     for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
-        ds_put_format(ds, "%s, ", op->lrp_networks.ipv4_addrs[i].addr_s);
+        if (!op_is_v4_network_cidr(&op->lrp_networks.ipv4_addrs[i])) {
+            ds_put_format(ds, "%s, ", op->lrp_networks.ipv4_addrs[i].addr_s);
+        }
         if (add_bcast) {
             ds_put_format(ds, "%s, ", op->lrp_networks.ipv4_addrs[i].bcast_s);
         }
@@ -4685,7 +4767,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
             continue;
         }
 
-        if (op->lrp_networks.n_ipv4_addrs) {
+        if (op_get_v4_ip_number(op)) {
             /* L3 admission control: drop packets that originate from an
              * IPv4 address owned by the router or a broadcast address
              * known to the router (priority 100). */
@@ -4720,6 +4802,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
         /* ARP reply.  These flows reply to ARP requests for the router's own
          * IP address. */
         for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
+            if (op_is_v4_network_cidr(&op->lrp_networks.ipv4_addrs[i])) {
+                continue;
+            }
             ds_clear(&match);
             ds_put_format(&match,
                           "inport == %s && arp.tpa == %s && arp.op == 1",
@@ -5660,7 +5745,14 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
         }
 
         for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
-            add_route(lflows, op, op->lrp_networks.ipv4_addrs[i].addr_s,
+            const char *lrp_addr_s = op->lrp_networks.ipv4_addrs[i].addr_s;
+            if (op_is_v4_network_cidr(&op->lrp_networks.ipv4_addrs[i])) {
+                lrp_addr_s = find_lrp_member_ip(op, lrp_addr_s);
+                if (!lrp_addr_s) {
+                    continue;
+                }
+            }
+            add_route(lflows, op, lrp_addr_s,
                       op->lrp_networks.ipv4_addrs[i].network_s,
                       op->lrp_networks.ipv4_addrs[i].plen, NULL, NULL);
         }
@@ -5709,7 +5801,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
              * The packet is still in peer's logical pipeline. So the match
              * should be on peer's outport. */
             if (op->peer && op->nbrp->peer) {
-                if (op->lrp_networks.n_ipv4_addrs) {
+                if (op_get_v4_ip_number(op)) {
                     ds_clear(&match);
                     ds_put_format(&match, "outport == %s && reg0 == ",
                                   op->peer->json_key);
@@ -5846,7 +5938,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
                    continue;
                 }
 
-                if (router_port->lrp_networks.n_ipv4_addrs) {
+                if (op_get_v4_ip_number(router_port)) {
                     ds_clear(&match);
                     ds_put_format(&match, "outport == %s && reg0 == ",
                                   peer->json_key);
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index b7a5b6bf2..fc9fd42ff 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -1345,6 +1345,13 @@
       </p>
 
       <p>
+        A logical router port who is gateway port also can configure CIDR,
+        For example, <code>192.168.0.0/24</code>. This means that traffic
+        to the external network can only pass NAT's external_ip. This
+        does not make sense for normal logical router port.
+      </p>
+
+      <p>
         A logical router port always adds a link-local IPv6 address
         (fe80::/64) automatically generated from the interface's MAC
         address using the modified EUI-64 format.
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 638c0b661..5bca5e3d2 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -1347,6 +1347,14 @@ sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
 icmp,orig=(src=192.168.2.2,dst=172.16.1.2,id=<cleared>,type=8,code=0),reply=(src=172.16.1.2,dst=172.16.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
 ])
 
+ovn-nbctl set Logical_Router_Port alice networks=172.16.1.0/24
+
+# North-South DNAT without gatewayIp: 'alice1' pings 'foo1' using 172.16.1.3.
+NS_CHECK_EXEC([alice1], [ping -q -c 3 -i 0.3 -w 2 172.16.1.3 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
 OVS_APP_EXIT_AND_WAIT([ovn-controller])
 
 as ovn-sb
