Hi Alin,
It looks good besides some minor comments.
Thanks,
Eitan

-----Original Message-----
From: dev [mailto:dev-boun...@openvswitch.org] On Behalf Of Alin Serdean
Sent: Monday, May 04, 2015 8:35 AM
To: dev@openvswitch.org
Subject: [ovs-dev] [PATCH] ARP lookup and next hop functionality on windows

This patch implements two functionalities needed for an active manager:
1. ARP lookup
2. Next hop

The first functionality relies on the internal Windows API:
https://urldefense.proofpoint.com/v2/url?u=https-3A__msdn.microsoft.com_en-2Dus_library_windows_desktop_aa365956-2528v-3Dvs.85-2529.aspx&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=CWsgHUxi6ExLXY798tmo3LJ4e3geGYp56lkcH-5cLCY&m=tQfMAkM2SjeoDNgJA5lzr3VUDfYRDmjOR3QrymbowLc&s=AjthuTJGRGkQqO4iaxxvp5uVrWnSngSiynyZFrmI4fM&e=
 

The second one:
https://urldefense.proofpoint.com/v2/url?u=https-3A__msdn.microsoft.com_en-2Dus_library_windows_desktop_aa365915-2528v-3Dvs.85-2529.aspx&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=CWsgHUxi6ExLXY798tmo3LJ4e3geGYp56lkcH-5cLCY&m=tQfMAkM2SjeoDNgJA5lzr3VUDfYRDmjOR3QrymbowLc&s=cYblpE7EGRgk2wDKdIc9MFjjG9U-91iBWzp2rstlaH4&e=
 

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 <aserd...@cloudbasesolutions.com>
Reported-by: Alin Gabriel Serdean <aserd...@cloudbasesolutions.com>
Reported-at: 
https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_openvswitch_ovs-2Dissues_issues_63&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=CWsgHUxi6ExLXY798tmo3LJ4e3geGYp56lkcH-5cLCY&m=tQfMAkM2SjeoDNgJA5lzr3VUDfYRDmjOR3QrymbowLc&s=L3JZ3eRbqh48NNmq_mcC2elPy7pBrI0pLWhhDEnepuk&e=
---
 INSTALL.Windows.md   |  25 ++++++-----
 appveyor.yml         |   2 +-
 lib/netdev-windows.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 139 insertions(+), 13 deletions(-)

diff --git a/INSTALL.Windows.md b/INSTALL.Windows.md index 78af0a1..0ec0af0 
100644
--- a/INSTALL.Windows.md
+++ b/INSTALL.Windows.md
@@ -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 @@ 
-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.
 
@@ -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".
diff --git a/appveyor.yml b/appveyor.yml index a14f0fc..863b561 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -39,5 +39,5 @@ build_script:
 - C:\MinGW\msys\1.0\bin\bash -lc "cp 
/c/pthreads-win32/Pre-built.2/dll/x86/*.dll /c/openvswitch/."
 - C:\MinGW\msys\1.0\bin\bash -lc "mv /bin/link.exe /bin/link_copy.exe"
 - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./boot.sh"
-- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure 
CC=build-aux/cccl LD=\"`which link`\" LIBS=-lws2_32 
--with-pthread=C:/pthreads-win32/Pre-built.2 --with-openssl=C:/OpenSSL-Win32 
--with-vstudioddk=\"Win8.1 Debug\""
+- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure 
CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi\" 
--with-pthread=C:/pthreads-win32/Pre-built.2 --with-openssl=C:/OpenSSL-Win32 
--with-vstudioddk=\"Win8.1 Debug\""
 - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && make"
diff --git a/lib/netdev-windows.c b/lib/netdev-windows.c index 1fc1da7..47e12df 
100644
--- a/lib/netdev-windows.c
+++ b/lib/netdev-windows.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <config.h>
 #include <errno.h>
+#include <iphlpapi.h>
 
 #include <net/if.h>
 
@@ -373,6 +374,128 @@ netdev_windows_update_flags(struct netdev *netdev_,
     return 0;
 }
 
+/* Number of times to retry the doubling of the length of the buffer 
+which is
+ * used to get all interfaces/ARP table */ #define MAX_RETRIES 10
+
+/* 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 = 1000;
+    uint32_t ret_val = 0;
+    uint32_t counter = 0;
+    uint8_t retries = 0;
+
+    do {
+        arp_table = (MIB_IPNETTABLE *) malloc(buffer_length);
+
+        if (arp_table == NULL) {
+            VLOG_ERR("Could not allocate memory for all the interfaces");
+            return ENXIO;
+        }
+
EITAN
        Please consider to call it with buffer_length = 0 and you'll get the 
needed buffer size on output.
              This way you could avoid the loop.
EITAN
+        ret_val = GetIpNetTable(arp_table, &buffer_length, false);
+
+        if (ret_val == ERROR_INSUFFICIENT_BUFFER ) {
+            free(arp_table);
+            arp_table = NULL;
+            buffer_length = buffer_length * 2;
+        }
+
+        retries++;
+    } while ((ret_val == ERROR_INSUFFICIENT_BUFFER ) &&
+             (retries < MAX_RETRIES));
+
+    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 {

EITAN
Can we call here:  ovs_format_message(int error)
EITAN

+        VLOG_ERR("Call to GetAdaptersAddresses failed with error: %d",
+                 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;
+    uint8_t retries = 0;
+    PIP_ADAPTER_ADDRESSES all_addr = NULL;
+    PIP_ADAPTER_ADDRESSES cur_addr = NULL;
+
+    do {
+        all_addr = (IP_ADAPTER_ADDRESSES *) malloc(buffer_length);
+
+        if (all_addr == NULL) {
+            VLOG_ERR("Could not allocate memory for all the interfaces");
+            return ENXIO;
+        }
+
EITAN
        Please consider to call it with buffer_length = 0 and you'll get the 
needed buffer size on output.
              This way you could avoid the loop.
EITAN
+        ret_val = GetAdaptersAddresses(AF_INET,
+                                       GAA_FLAG_INCLUDE_PREFIX |
+                                       GAA_FLAG_INCLUDE_GATEWAYS,
+                                       NULL, all_addr, &buffer_length);
+
+        if (ret_val == ERROR_BUFFER_OVERFLOW) {
+            ovs_assert(all_addr);
+            free(all_addr);
+            all_addr = NULL;
+            buffer_length = buffer_length * 2;
+        }
+
+        retries++;
+
+    } while ((ret_val == ERROR_BUFFER_OVERFLOW) && (retries < 
+ MAX_RETRIES));
+
+    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);
+
EITAN
        Don't have to check all_addr here
EITAN
+                if (all_addr) {
+                    free(all_addr);
+                }
+                return 0;
+            }
+
+            cur_addr = cur_addr->Next;
+        }
+    } else {
EITAN
        We can call ovs_format_message
EITAN
+        VLOG_ERR("Call to GetAdaptersAddresses failed with error: %d",
+                 ret_val);
+    }
+
+    if (all_addr) {
+        free(all_addr);
+    }
+    return ENXIO;
+}
+
 static int
 netdev_windows_internal_construct(struct netdev *netdev_)  { @@ -390,6 +513,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 =
--
1.9.5.msysgit.0
_______________________________________________
dev mailing list
dev@openvswitch.org
https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailman_listinfo_dev&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=CWsgHUxi6ExLXY798tmo3LJ4e3geGYp56lkcH-5cLCY&m=tQfMAkM2SjeoDNgJA5lzr3VUDfYRDmjOR3QrymbowLc&s=FiFxjaG_D_gasqb35rjHZQsi8jSIcga9rLDma-F35tY&e=
 
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to