Route-table implementation for (Free)BSD
authorEd Maste <emaste@freebsd.org>
Fri, 29 Jun 2012 21:11:24 +0000 (21:11 +0000)
committerBen Pfaff <blp@nicira.com>
Fri, 29 Jun 2012 21:42:38 +0000 (14:42 -0700)
This is a trivial implementation of the route-table functionality for
FreeBSD, as needed by ofproto/ofproto-dpif-sflow.c.  It has not yet
been extensively tested.

Signed-off-by: Ed Maste <emaste@freebsd.org>
Signed-off-by: Ben Pfaff <blp@nicira.com>
acinclude.m4
configure.ac
lib/automake.mk
lib/route-table-bsd.c [new file with mode: 0644]

index d33653d..43f044a 100644 (file)
@@ -287,6 +287,17 @@ AC_DEFUN([OVS_CHECK_IF_PACKET],
                 [Define to 1 if net/if_packet.h is available.])
    fi])
 
+dnl Checks for net/if_dl.h
+AC_DEFUN([OVS_CHECK_IF_DL],
+  [AC_CHECK_HEADER([net/if_dl.h],
+                   [HAVE_IF_DL=yes],
+                   [HAVE_IF_DL=no])
+   AM_CONDITIONAL([HAVE_IF_DL], [test "$HAVE_IF_DL" = yes])
+   if test "$HAVE_IF_DL" = yes; then
+      AC_DEFINE([HAVE_IF_DL], [1],
+                [Define to 1 if net/if_dl.h is available.])
+   fi])
+
 dnl Checks for buggy strtok_r.
 dnl
 dnl Some versions of glibc 2.7 has a bug in strtok_r when compiling
index 222b502..c89c60a 100644 (file)
@@ -52,6 +52,7 @@ OVS_CHECK_PYUIC4
 OVS_CHECK_OVSDBMONITOR
 OVS_CHECK_DOT
 OVS_CHECK_IF_PACKET
+OVS_CHECK_IF_DL
 OVS_CHECK_STRTOK_R
 AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec],
   [], [], [[#include <sys/stat.h>]])
index 9d8b426..feac1d4 100644 (file)
@@ -238,6 +238,11 @@ lib_libopenvswitch_a_SOURCES += \
        lib/route-table.h
 endif
 
+if HAVE_IF_DL
+lib_libopenvswitch_a_SOURCES += \
+       lib/route-table-bsd.c
+endif
+
 if HAVE_OPENSSL
 lib_libopenvswitch_a_SOURCES += lib/stream-ssl.c
 nodist_lib_libopenvswitch_a_SOURCES += lib/dhparams.c
diff --git a/lib/route-table-bsd.c b/lib/route-table-bsd.c
new file mode 100644 (file)
index 0000000..c145091
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012 Ed Maste. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "route-table.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+
+#include <string.h>
+#include <unistd.h>
+
+VLOG_DEFINE_THIS_MODULE(route_table);
+
+static int pid;
+static unsigned int register_count = 0;
+
+bool
+route_table_get_name(ovs_be32 ip, char name[IFNAMSIZ])
+{
+    struct {
+        struct rt_msghdr rtm;
+        char space[512];
+    } rtmsg;
+
+    struct rt_msghdr *rtm = &rtmsg.rtm;
+    struct sockaddr_dl *ifp = NULL;
+    struct sockaddr_in *sin;
+    struct sockaddr *sa;
+    static int seq;
+    int i, len, namelen, rtsock;
+
+    rtsock = socket(PF_ROUTE, SOCK_RAW, 0);
+    if (rtsock < 0)
+        return false;
+
+    memset(&rtmsg, 0, sizeof(rtmsg));
+
+    rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
+    rtm->rtm_version = RTM_VERSION;
+    rtm->rtm_type = RTM_GET;
+    rtm->rtm_addrs = RTA_DST | RTA_IFP;
+    rtm->rtm_seq = ++seq;
+
+    sin = (struct sockaddr_in *)(rtm + 1);
+    sin->sin_len = len = sizeof(struct sockaddr_in);
+    sin->sin_family = AF_INET;
+    sin->sin_addr.s_addr = ip;
+
+    if ((write(rtsock, (char *)&rtmsg, rtm->rtm_msglen)) < 0) {
+        close(rtsock);
+        return false;
+    }
+
+    do {
+        len = read(rtsock, (char *)&rtmsg, sizeof(rtmsg));
+    } while (len > 0 && (rtmsg.rtm.rtm_seq != seq ||
+        rtmsg.rtm.rtm_pid != pid));
+
+    close(rtsock);
+
+    if (len < 0) {
+        return false;
+    }
+
+    sa = (struct sockaddr *)(rtm + 1);
+    for (i = 1; i; i <<= 1) {
+        if (rtm->rtm_addrs & i) {
+            if (i == RTA_IFP && sa->sa_family == AF_LINK &&
+              ((struct sockaddr_dl *)sa)->sdl_nlen) {
+                ifp = (struct sockaddr_dl *)sa;
+                namelen = ifp->sdl_nlen;
+                if (namelen > IFNAMSIZ - 1)
+                    namelen = IFNAMSIZ - 1;
+                memcpy(name, ifp->sdl_data, namelen);
+                name[namelen] = '\0';
+                return true;
+            }
+            sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
+        }
+    }
+    return false;
+}
+
+void
+route_table_register()
+{
+    if (!register_count)
+    {
+        pid = getpid();
+    }
+
+    register_count++;
+}
+
+void
+route_table_unregister()
+{
+    register_count--;
+}
+
+void
+route_table_run(void)
+{
+}
+
+void
+route_table_wait(void)
+{
+}