[ovs-dev] [PATCH 18/18] implement get_next_hop for NetBSD

Reid Price rprice at nicira.com
Thu Jan 31 20:54:53 UTC 2013


> +the in-band support as the following.

Perhaps change 'as the following' to 'with the following command'

  -Reid

On Thu, Jan 31, 2013 at 2:49 AM, YAMAMOTO Takashi
<yamamoto at valinux.co.jp> wrote:
> From: YAMAMOTO Takashi <yamt at mwd.biglobe.ne.jp>
>
> Signed-off-by: YAMAMOTO Takashi <yamamoto at valinux.co.jp>
> ---
>  INSTALL.userspace |   6 +--
>  lib/netdev-bsd.c  | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 152 insertions(+), 5 deletions(-)
>
> diff --git a/INSTALL.userspace b/INSTALL.userspace
> index 65ad499..5f9a9d8 100644
> --- a/INSTALL.userspace
> +++ b/INSTALL.userspace
> @@ -51,9 +51,9 @@ ovs-vswitchd will create a TAP device as the bridge's local interface,
>  named the same as the bridge, as well as for each configured internal
>  interface.
>
> -Currently, on FreeBSD and NetBSD, the functionality required for in-band
> -control support is not implemented.  To avoid related errors, you can
> -disable the in-band support as the following.
> +Currently, on FreeBSD, the functionality required for in-band control
> +support is not implemented.  To avoid related errors, you can disable
> +the in-band support as the following.
>
>      ovs-vsctl set bridge br0 other_config:disable-in-band=true
>
> diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
> index 1cb1d8b..f35ca71 100644
> --- a/lib/netdev-bsd.c
> +++ b/lib/netdev-bsd.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (c) 2011 Gaetano Catalli.
> + * Copyright (c) 2013 YAMAMOTO Takashi.
>   *
>   * Licensed under the Apache License, Version 2.0 (the "License");
>   * you may not use this file except in compliance with the License.
> @@ -38,6 +39,9 @@
>  #include <string.h>
>  #include <unistd.h>
>  #include <sys/sysctl.h>
> +#if defined(__NetBSD__)
> +#include <net/route.h>
> +#endif
>
>  #include "rtbsd.h"
>  #include "coverage.h"
> @@ -1244,6 +1248,149 @@ netdev_bsd_get_in6(const struct netdev *netdev_, struct in6_addr *in6)
>      return 0;
>  }
>
> +#if defined(__NetBSD__)
> +static struct netdev_dev *
> +find_netdev_by_kernel_name(const char *kernel_name)
> +{
> +    struct shash device_shash;
> +    struct shash_node *node;
> +
> +    shash_init(&device_shash);
> +    netdev_dev_get_devices(&netdev_tap_class, &device_shash);
> +    SHASH_FOR_EACH(node, &device_shash) {
> +        struct netdev_dev_bsd * const dev = node->data;
> +
> +        if (!strcmp(dev->kernel_name, kernel_name)) {
> +            shash_destroy(&device_shash);
> +            return &dev->netdev_dev;
> +        }
> +    }
> +    shash_destroy(&device_shash);
> +    return NULL;
> +}
> +
> +static const char *
> +netdev_bsd_convert_kernel_name_to_ovs_name(const char *kernel_name)
> +{
> +    const struct netdev_dev * const netdev_dev =
> +      find_netdev_by_kernel_name(kernel_name);
> +
> +    if (netdev_dev == NULL) {
> +        return NULL;
> +    }
> +    return netdev_dev_get_name(netdev_dev);
> +}
> +#endif
> +
> +static int
> +netdev_bsd_get_next_hop(const struct in_addr *host, struct in_addr *next_hop,
> +                        char **netdev_name)
> +{
> +#if defined(__NetBSD__)
> +    static int seq = 0;
> +    struct sockaddr_in sin;
> +    struct sockaddr_dl sdl;
> +    int s;
> +    int i;
> +    struct {
> +        struct rt_msghdr h;
> +        char space[512];
> +    } buf;
> +    struct rt_msghdr *rtm = &buf.h;
> +    const pid_t pid = getpid();
> +    char *cp;
> +    ssize_t ssz;
> +    bool gateway = false;
> +    char *ifname = NULL;
> +    int saved_errno;
> +
> +    memset(next_hop, 0, sizeof(*next_hop));
> +    *netdev_name = NULL;
> +
> +    memset(&sin, 0, sizeof(sin));
> +    sin.sin_len = sizeof(sin);
> +    sin.sin_family = AF_INET;
> +    sin.sin_port = 0;
> +    sin.sin_addr = *host;
> +
> +    memset(&sdl, 0, sizeof(sdl));
> +    sdl.sdl_len = sizeof(sdl);
> +    sdl.sdl_family = AF_LINK;
> +
> +    s = socket(PF_ROUTE, SOCK_RAW, 0);
> +    memset(&buf, 0, sizeof(buf));
> +    rtm->rtm_flags = RTF_HOST|RTF_UP;
> +    rtm->rtm_version = RTM_VERSION;
> +    rtm->rtm_addrs = RTA_DST|RTA_IFP;
> +    cp = (void *)&buf.space;
> +    memcpy(cp, &sin, sizeof(sin));
> +    RT_ADVANCE(cp, (struct sockaddr *)(void *)&sin);
> +    memcpy(cp, &sdl, sizeof(sdl));
> +    RT_ADVANCE(cp, (struct sockaddr *)(void *)&sdl);
> +    rtm->rtm_msglen = cp - (char *)(void *)rtm;
> +    rtm->rtm_seq = ++seq;
> +    rtm->rtm_type = RTM_GET;
> +    rtm->rtm_pid = pid;
> +    write(s, rtm, rtm->rtm_msglen);
> +    memset(&buf, 0, sizeof(buf));
> +    do {
> +        ssz = read(s, &buf, sizeof(buf));
> +    } while (ssz > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
> +    saved_errno = errno;
> +    close(s);
> +    if (ssz <= 0) {
> +        if (ssz < 0) {
> +            return saved_errno;
> +        }
> +        return EPIPE; /* XXX */
> +    }
> +    cp = (void *)&buf.space;
> +    for (i = 1; i; i <<= 1) {
> +        if ((rtm->rtm_addrs & i) != 0) {
> +            const struct sockaddr *sa = (const void *)cp;
> +
> +            if ((i == RTA_GATEWAY) && sa->sa_family == AF_INET) {
> +                const struct sockaddr_in * const sin =
> +                  (const struct sockaddr_in *)sa;
> +
> +                *next_hop = sin->sin_addr;
> +                gateway = true;
> +            }
> +            if ((i == RTA_IFP) && sa->sa_family == AF_LINK) {
> +                const struct sockaddr_dl * const sdl =
> +                  (const struct sockaddr_dl *)sa;
> +                const size_t nlen = sdl->sdl_nlen;
> +                char * const kernel_name = xmalloc(nlen + 1);
> +                const char *name;
> +
> +                memcpy(kernel_name, sdl->sdl_data, nlen);
> +                kernel_name[nlen] = 0;
> +                name = netdev_bsd_convert_kernel_name_to_ovs_name(kernel_name);
> +                if (name == NULL) {
> +                    ifname = xstrdup(kernel_name);
> +                } else {
> +                    ifname = xstrdup(name);
> +                }
> +                free(kernel_name);
> +            }
> +            RT_ADVANCE(cp, sa);
> +        }
> +    }
> +    if (ifname == NULL) {
> +        return ENXIO;
> +    }
> +    if (!gateway) {
> +        *next_hop = *host;
> +    }
> +    *netdev_name = ifname;
> +    VLOG_DBG("host " IP_FMT " next-hop " IP_FMT " if %s",
> +      IP_ARGS(host->s_addr), IP_ARGS(next_hop->s_addr), *netdev_name);
> +    return 0;
> +#else
> +    return ENOTSUP;
> +#endif
> +}
> +
>  static void
>  make_in4_sockaddr(struct sockaddr *sa, struct in_addr addr)
>  {
> @@ -1373,7 +1520,7 @@ const struct netdev_class netdev_bsd_class = {
>      netdev_bsd_set_in4,
>      netdev_bsd_get_in6,
>      NULL, /* add_router */
> -    NULL, /* get_next_hop */
> +    netdev_bsd_get_next_hop,
>      NULL, /* get_status */
>      NULL, /* arp_lookup */
>
> @@ -1434,7 +1581,7 @@ const struct netdev_class netdev_tap_class = {
>      netdev_bsd_set_in4,
>      netdev_bsd_get_in6,
>      NULL, /* add_router */
> -    NULL, /* get_next_hop */
> +    netdev_bsd_get_next_hop,
>      NULL, /* get_status */
>      NULL, /* arp_lookup */
>
> --
> 1.7.12
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list