[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