[ovs-dev] [PATCH] ARP lookup and next hop functionality on windows

Gurucharan Shetty shettyg at nicira.com
Fri Jun 5 18:00:04 UTC 2015


On Tue, May 19, 2015 at 10:02 AM, Alin Serdean
<aserdean at cloudbasesolutions.com> wrote:
> 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 <aserdean at cloudbasesolutions.com>
> Reported-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>
Alin,
 This commit has broken the appveyor build tests. Can you please
update appveyor.yml in the repo to include the necessary configure
changes?


> Reported-at: https://github.com/openvswitch/ovs-issues/issues/63
> ---
> v2: call GetIpNetTable and GetAdaptersAddresses with a zero length buffer.
>     add pretty printing
> ---
> ---
>  INSTALL.Windows.md   |  25 +++++------
>  lib/netdev-windows.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 127 insertions(+), 12 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/lib/netdev-windows.c b/lib/netdev-windows.c
> index 1fc1da7..1eb8727 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,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_)
>  {
> @@ -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 =
> --
> 1.9.5.msysgit.0
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list