Skip to content

Commit

Permalink
netdev-windows: Add ARP lookup and next hop functionality.
Browse files Browse the repository at this point in the history
This patch implements two functionalities needed for an active manager:
1. ARP lookup
2. Next hop

The first uses the Windows GetIpNetTable() function:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365956%28v=vs.85%29.aspx

The second one uses GetAdaptersAddresses() function:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915%28v=vs.85%29.aspx

Both API's are found in the Iphlpapi library. We need to add this library when compiling.

Documentation and appveyor config has been updated to match the use of the new library.

Tested using opendaylight.

Signed-off-by: Alin Gabriel Serdean <[email protected]>
Reported-by: Alin Gabriel Serdean <[email protected]>
Reported-at: openvswitch/ovs-issues#63
Acked-by: Eitan Eliahu <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
Alin Serdean authored and blp committed May 27, 2015
1 parent b519432 commit 694ebbc
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 12 deletions.
25 changes: 13 additions & 12 deletions INSTALL.Windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ or from a distribution tar ball.
the right compiler, linker, libraries, Open vSwitch component installation
directories, etc. For example,

% ./configure CC=./build-aux/cccl LD="`which link`" LIBS="-lws2_32" \
--prefix="C:/openvswitch/usr" --localstatedir="C:/openvswitch/var" \
--sysconfdir="C:/openvswitch/etc" --with-pthread="C:/pthread"
% ./configure CC=./build-aux/cccl LD="`which link`" \
LIBS="-lws2_32 -liphlpapi" --prefix="C:/openvswitch/usr" \
--localstatedir="C:/openvswitch/var" --sysconfdir="C:/openvswitch/etc" \
--with-pthread="C:/pthread"

By default, the above enables compiler optimization for fast code.
For default compiler optimization, pass the "--with-debug" configure
Expand Down Expand Up @@ -114,10 +115,10 @@ Note down the directory where OpenSSL is installed (e.g.: C:/OpenSSL-Win32).
* While configuring the package, specify the OpenSSL directory path.
For example,

% ./configure CC=./build-aux/cccl LD="`which link`" LIBS="-lws2_32" \
--prefix="C:/openvswitch/usr" --localstatedir="C:/openvswitch/var" \
--sysconfdir="C:/openvswitch/etc" --with-pthread="C:/pthread" \
--enable-ssl --with-openssl="C:/OpenSSL-Win32"
% ./configure CC=./build-aux/cccl LD="`which link`" \
LIBS="-lws2_32 -liphlpapi" --prefix="C:/openvswitch/usr" \
--localstatedir="C:/openvswitch/var" --sysconfdir="C:/openvswitch/etc" \
--with-pthread="C:/pthread" --enable-ssl --with-openssl="C:/OpenSSL-Win32"

* Run make for the ported executables.

Expand All @@ -131,11 +132,11 @@ level 'make' will invoke building the kernel datapath, if the
'--with-vstudioddk' argument is specified while configuring the package.
For example,

% ./configure CC=./build-aux/cccl LD="`which link`" LIBS="-lws2_32" \
--prefix="C:/openvswitch/usr" --localstatedir="C:/openvswitch/var" \
--sysconfdir="C:/openvswitch/etc" --with-pthread="C:/pthread" \
--enable-ssl --with-openssl="C:/OpenSSL-Win32" \
--with-vstudioddk="<WDK to use>"
% ./configure CC=./build-aux/cccl LD="`which link`" \
LIBS="-lws2_32 -liphlpapi" --prefix="C:/openvswitch/usr" \
--localstatedir="C:/openvswitch/var" --sysconfdir="C:/openvswitch/etc" \
--with-pthread="C:/pthread" --enable-ssl \
--with-openssl="C:/OpenSSL-Win32" --with-vstudioddk="<WDK to use>"

Possible values for "<WDK to use>" are:
"Win8.1 Debug", "Win8.1 Release", "Win8 Debug" and "Win8 Release".
Expand Down
114 changes: 114 additions & 0 deletions lib/netdev-windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <stdlib.h>
#include <config.h>
#include <errno.h>
#include <iphlpapi.h>

#include <net/if.h>

Expand Down Expand Up @@ -373,6 +374,117 @@ netdev_windows_update_flags(struct netdev *netdev_,
return 0;
}

/* Looks up in the ARP table entry for a given 'ip'. If it is found, the
* corresponding MAC address will be copied in 'mac' and return 0. If no
* matching entry is found or an error occurs it will log it and return ENXIO.
*/
static int
netdev_windows_arp_lookup(const struct netdev *netdev,
ovs_be32 ip, uint8_t mac[ETH_ADDR_LEN])
{
PMIB_IPNETTABLE arp_table = NULL;
/* The buffer length of all ARP entries */
uint32_t buffer_length = 0;
uint32_t ret_val = 0;
uint32_t counter = 0;

ret_val = GetIpNetTable(arp_table, &buffer_length, false);

if (ret_val != ERROR_INSUFFICIENT_BUFFER ) {
VLOG_ERR("Call to GetIpNetTable failed with error: %s",
ovs_format_message(ret_val));
return ENXIO;
}

arp_table = (MIB_IPNETTABLE *) malloc(buffer_length);

if (arp_table == NULL) {
VLOG_ERR("Could not allocate memory for all the interfaces");
return ENXIO;
}

ret_val = GetIpNetTable(arp_table, &buffer_length, false);

if (ret_val == NO_ERROR) {
for (counter = 0; counter < arp_table->dwNumEntries; counter++) {
if (arp_table->table[counter].dwAddr == ip) {
memcpy(mac, arp_table->table[counter].bPhysAddr, ETH_ADDR_LEN);

free(arp_table);
return 0;
}
}
} else {
VLOG_ERR("Call to GetIpNetTable failed with error: %s",
ovs_format_message(ret_val));
}

free(arp_table);
return ENXIO;
}

static int
netdev_windows_get_next_hop(const struct in_addr *host,
struct in_addr *next_hop,
char **netdev_name)
{
uint32_t ret_val = 0;
/* The buffer length of all addresses */
uint32_t buffer_length = 1000;
PIP_ADAPTER_ADDRESSES all_addr = NULL;
PIP_ADAPTER_ADDRESSES cur_addr = NULL;

ret_val = GetAdaptersAddresses(AF_INET,
GAA_FLAG_INCLUDE_PREFIX |
GAA_FLAG_INCLUDE_GATEWAYS,
NULL, all_addr, &buffer_length);

if (ret_val != ERROR_INSUFFICIENT_BUFFER ) {
VLOG_ERR("Call to GetAdaptersAddresses failed with error: %s",
ovs_format_message(ret_val));
return ENXIO;
}

all_addr = (IP_ADAPTER_ADDRESSES *) malloc(buffer_length);

if (all_addr == NULL) {
VLOG_ERR("Could not allocate memory for all the interfaces");
return ENXIO;
}

ret_val = GetAdaptersAddresses(AF_INET,
GAA_FLAG_INCLUDE_PREFIX |
GAA_FLAG_INCLUDE_GATEWAYS,
NULL, all_addr, &buffer_length);

if (ret_val == NO_ERROR) {
cur_addr = all_addr;
while (cur_addr) {
if(cur_addr->FirstGatewayAddress &&
cur_addr->FirstGatewayAddress->Address.lpSockaddr) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)
cur_addr->FirstGatewayAddress->Address.lpSockaddr;
next_hop->s_addr = ipv4->sin_addr.S_un.S_addr;
*netdev_name = xstrdup((char *)cur_addr->FriendlyName);

free(all_addr);

return 0;
}

cur_addr = cur_addr->Next;
}
} else {
VLOG_ERR("Call to GetAdaptersAddresses failed with error: %s",
ovs_format_message(ret_val));
}

if (all_addr) {
free(all_addr);
}
return ENXIO;
}

static int
netdev_windows_internal_construct(struct netdev *netdev_)
{
Expand All @@ -390,6 +502,8 @@ netdev_windows_internal_construct(struct netdev *netdev_)
.get_etheraddr = netdev_windows_get_etheraddr, \
.set_etheraddr = netdev_windows_set_etheraddr, \
.update_flags = netdev_windows_update_flags, \
.get_next_hop = netdev_windows_get_next_hop, \
.arp_lookup = netdev_windows_arp_lookup, \
}

const struct netdev_class netdev_windows_class =
Expand Down

0 comments on commit 694ebbc

Please sign in to comment.