[ovs-dev] [L3 In-Band 7/9] netdev: Add netdev_get_next_hop call

Justin Pettit jpettit at nicira.com
Mon Aug 31 23:17:39 UTC 2009


Add ability to determine the next hop IP address and device used to
reach a given host.
---
 lib/netdev.c |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/netdev.h |    2 ++
 2 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/lib/netdev.c b/lib/netdev.c
index 58764c2..083b100 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -1345,6 +1345,63 @@ netdev_find_dev_by_in4(const struct in_addr *in4, char **netdev_name)
     return false;
 }
 
+/* Looks up the next hop for 'ip'.  If it can be found, the address is
+ * stored in 'next_hop', the name of the device to reach it is stored in 
+ * 'netdev_name', and 0 is returned.  If a gateway is not required to 
+ * reach 'ip', the value of 'ip' is stored in 'next_hop'.  If a route 
+ * could not be determined, a positive errno is returned. */
+int
+netdev_get_next_hop(const struct in_addr *host, struct in_addr *next_hop, 
+                    char *netdev_name) {
+    static const char fn[] = "/proc/net/route";
+    FILE *stream;
+    char line[256];
+    int ln;
+
+    stream = fopen(fn, "r");
+    if (stream == NULL) {
+        VLOG_WARN_RL(&rl, "%s: open failed: %s", fn, strerror(errno));
+        return errno;
+    }
+
+    ln = 0;
+    while (fgets(line, sizeof line, stream)) {
+        if (++ln >= 2) {
+            uint32_t dest, gateway, mask;
+            int refcnt, metric, mtu;
+            unsigned int flags, use, window, irtt;
+
+            if (sscanf(line,
+                       "%16s %08X %08X %04X %d %u %d %08X %d %u %u\n",
+                       netdev_name, &dest, &gateway, &flags, &refcnt,
+                       &use, &metric, &mask, &mtu, &window, &irtt) != 11) {
+
+                VLOG_WARN_RL(&rl, "%s: could not parse output", fn);
+                continue;
+            }
+            if (!(flags & RTF_UP)) {
+                /* Skip routes that aren't up. */
+                continue;
+            }
+
+            if ((dest & mask) == (host->s_addr & mask)) {
+                if (!gateway) {
+                    /* The host is directly reachable. */
+                    next_hop->s_addr = host->s_addr;
+                } else {
+                    /* To reach the host, we must go through a gateway. */
+                    next_hop->s_addr = gateway;
+                }
+                fclose(stream);
+                return 0;
+            }
+        }
+    }
+
+    fclose(stream);
+    return ENXIO;
+}
+
 /* Obtains the current flags for the network device named 'netdev_name' and
  * stores them into '*flagsp'.  Returns 0 if successful, otherwise a positive
  * errno value.  On error, stores 0 into '*flagsp'.
diff --git a/lib/netdev.h b/lib/netdev.h
index 9a55619..f14f473 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -107,6 +107,8 @@ int netdev_set_policing(struct netdev *, uint32_t kbits_rate,
 
 void netdev_enumerate(struct svec *);
 bool netdev_find_dev_by_in4(const struct in_addr *in4, char **netdev_name);
+int netdev_get_next_hop(const struct in_addr *host, struct in_addr *gateway,
+                        char *netdev_name);
 int netdev_nodev_get_flags(const char *netdev_name, enum netdev_flags *);
 bool netdev_nodev_get_in4(const char *netdev_name, struct in_addr *in4,
                           struct in_addr *mask);
-- 
1.5.5





More information about the dev mailing list