Merge commit 'origin/citrix'
authorJustin Pettit <jpettit@nicira.com>
Wed, 1 Jul 2009 18:31:37 +0000 (11:31 -0700)
committerJustin Pettit <jpettit@nicira.com>
Wed, 1 Jul 2009 18:31:37 +0000 (11:31 -0700)
40 files changed:
INSTALL.Linux
INSTALL.SSL
INSTALL.XenServer
README
configure.ac
datapath/brc_sysfs.h
datapath/brc_sysfs_dp.c
datapath/brc_sysfs_if.c
datapath/brcompat.c
datapath/datapath.c
datapath/datapath.h
datapath/linux-2.6/Modules.mk
datapath/linux-2.6/compat-2.6/include/linux/kobject.h [new file with mode: 0644]
datapath/linux-2.6/compat-2.6/include/linux/netdevice.h
datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h
debian/changelog
debian/control
debian/control.modules.in
debian/po/templates.pot
lib/netdev.c
lib/socket-util.c
lib/socket-util.h
lib/vconn-ssl.c
lib/vconn-stream.c
lib/vconn-tcp.c
lib/vconn-unix.c
lib/vconn.c
secchan/discovery.c
secchan/main.c
secchan/secchan.8.in
tests/automake.mk
tests/test-vconn.c [new file with mode: 0644]
utilities/ovs-controller.8.in
utilities/ovs-discover.8.in
utilities/ovs-discover.c
utilities/ovs-ofctl.8.in
vswitchd/ovs-vswitchd.8.in
vswitchd/ovs-vswitchd.c
vswitchd/ovs-vswitchd.conf.5.in
xenserver/vswitch-xen.spec

index 2683940..817c9ab 100644 (file)
@@ -168,4 +168,4 @@ complete.
 Bug Reporting
 -------------
 
-Please report problems to ovs-bugs@openvswitch.org.
+Please report problems to bugs@openvswitch.org.
index d672d62..8df47bc 100644 (file)
@@ -314,4 +314,4 @@ configured, so for security you should use only "ssl:" connections.
 Reporting Bugs
 --------------
 
-Please report problems to ovs-bugs@openvswitch.org.
+Please report problems to bugs@openvswitch.org.
index bdfc26a..83c7605 100644 (file)
@@ -67,4 +67,4 @@ rebooted as soon as possible.
 Reporting Bugs
 --------------
 
-Please report problems to ovs-bugs@openvswitch.org.
+Please report problems to bugs@openvswitch.org.
diff --git a/README b/README
index 7311292..3e986a4 100644 (file)
--- a/README
+++ b/README
@@ -3,7 +3,7 @@
 What is Open vSwitch?
 ---------------------
 
-Open vSwitch is an Ethernet switch for virtual servers with the
+Open vSwitch is a versatile software-based Ethernet switch with the 
 following features:
 
        * NIC bonding with automatic fail-over and source MAC-based TX
@@ -15,8 +15,7 @@ following features:
 
        * NetFlow v5 flow logging.
 
-       * Connectivity to an external OpenFlow controller, such as
-          NOX.
+       * Connectivity to an external OpenFlow controller, such as NOX.
 
 Open vSwitch supports Linux 2.6.15 and up, with testing focused on
 2.6.18 with Centos and Xen patches and version 2.6.26 from kernel.org.
@@ -27,43 +26,39 @@ What's here?
 
 The main components of this distribution are:
 
-        - ovs-vswitchd, a daemon that implements the virtual switch,
-          along with a companion Linux kernel module for flow-based
-          switching.
+    * ovs-vswitchd, a daemon that implements the switch, along with 
+      a companion Linux kernel module for flow-based switching.
 
-        - ovs-brcompatd, a daemon that allows ovs-vswitchd to act as a
-          drop-in replacement for the Linux bridge in many
-          environments, along with a companion Linux kernel module to
-          intercept bridge ioctls.
+    * ovs-brcompatd, a daemon that allows ovs-vswitchd to act as a
+      drop-in replacement for the Linux bridge in many environments, 
+      along with a companion Linux kernel module to intercept bridge 
+      ioctls.
 
-       - ovs-dpctl, a tool for configuring the virtual switch kernel
-          module.
+    * ovs-dpctl, a tool for configuring the switch kernel module.
 
-        - Scripts and specs for building RPMs that allow Open vSwitch
-          to be installed on a Citrix XenServer host as a drop-in
-          replacement for its virtual switch, with additional
-          functionality.
+    * Scripts and specs for building RPMs that allow Open vSwitch
+      to be installed on a Citrix XenServer host as a drop-in
+      replacement for its switch, with additional functionality.
 
-       - vlog-appctl, a utility that can control Open vSwitch daemons,
-          adjusting their logging levels among other uses.
+    * vlog-appctl, a utility that can control Open vSwitch daemons,
+      adjusting their logging levels among other uses.
 
 Open vSwitch also provides an OpenFlow implementation and tools for
 those interested in OpenFlow but not additional Open vSwitch features:
 
-       - secchan, a program that implements a simple OpenFlow switch
-          (without the special features provided by ovs-vswitchd) using
-          the same kernel module as ovs-vswitchd.
+    * secchan, a program that implements a simple OpenFlow switch
+      (without the special features provided by ovs-vswitchd) using
+      the same kernel module as ovs-vswitchd.
 
-       - ovs-controller, a simple OpenFlow controller.
+    * ovs-controller, a simple OpenFlow controller.
 
-       - ovs-ofctl, a utility for querying and controlling OpenFlow
-          switches and controllers.
+    * ovs-ofctl, a utility for querying and controlling OpenFlow
+      switches and controllers.
 
-       - ovs-pki, a utility for creating and managing the public-key
-          infrastructure for OpenFlow switches.
+    * ovs-pki, a utility for creating and managing the public-key
+      infrastructure for OpenFlow switches.
 
-       - A patch to tcpdump that enables it to parse OpenFlow
-          messages.
+    * A patch to tcpdump that enables it to parse OpenFlow messages.
 
 What other documentation is available?
 --------------------------------------
@@ -83,5 +78,5 @@ the manpages.
 Contact 
 -------
 
-ovs-bugs@openvswitch.org
+bugs@openvswitch.org
 http://openvswitch.org/
index 30d2dc5..8b22d48 100644 (file)
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 AC_PREREQ(2.60)
-AC_INIT(openvswitch, 0.90.0, ovs-bugs@openvswitch.org)
+AC_INIT(openvswitch, 0.90.1, bugs@openvswitch.org)
 NX_BUILDNR
 AC_CONFIG_SRCDIR([datapath/datapath.c])
 AC_CONFIG_MACRO_DIR([m4])
index 526f5fa..78540d5 100644 (file)
@@ -20,14 +20,5 @@ int brc_sysfs_del_dp(struct datapath *dp);
 int brc_sysfs_add_if(struct net_bridge_port *p);
 int brc_sysfs_del_if(struct net_bridge_port *p);
 
-#include <linux/version.h>
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
-#define SUPPORT_SYSFS 1
-#else
-/* We only support sysfs on Linux 2.6.18 because that's the only place we
- * really need it (on Xen, for brcompat) and it's a big pain to try to support
- * multiple versions. */
-#endif
-
 #endif /* brc_sysfs.h */
 
index bb779b6..c1e82eb 100644 (file)
 #include "datapath.h"
 #include "dp_dev.h"
 
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
 #define to_dev(obj)    container_of(obj, struct device, kobj)
 
 /* Hack to attempt to build on more platforms. */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
-#define to_kobj(d) &(d)->class_dev.kobj
 #define BRC_DEVICE_ATTR CLASS_DEVICE_ATTR
+#define DEVICE_PARAMS struct class_device *d
+#define DEVICE_ARGS d
+#define DEV_ATTR(NAME) class_device_attr_##NAME
 #else
-#define to_kobj(d) &(d)->dev.kobj
 #define BRC_DEVICE_ATTR DEVICE_ATTR
+#define DEVICE_PARAMS struct device *d, struct device_attribute *attr
+#define DEVICE_ARGS d, attr
+#define DEV_ATTR(NAME) dev_attr_##NAME
 #endif
 
 /*
  * Common code for storing bridge parameters.
  */
-static ssize_t store_bridge_parm(struct class_device *d,
+static ssize_t store_bridge_parm(DEVICE_PARAMS,
                                 const char *buf, size_t len,
                                 void (*set)(struct datapath *, unsigned long))
 {
@@ -76,8 +80,7 @@ static ssize_t store_bridge_parm(struct class_device *d,
 }
 
 
-static ssize_t show_forward_delay(struct class_device *d,
-                                 char *buf)
+static ssize_t show_forward_delay(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -99,15 +102,15 @@ static void set_forward_delay(struct datapath *dp, unsigned long val)
 #endif
 }
 
-static ssize_t store_forward_delay(struct class_device *d,
+static ssize_t store_forward_delay(DEVICE_PARAMS,
                                   const char *buf, size_t len)
 {
-       return store_bridge_parm(d, buf, len, set_forward_delay);
+       return store_bridge_parm(DEVICE_ARGS, buf, len, set_forward_delay);
 }
 static BRC_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
                   show_forward_delay, store_forward_delay);
 
-static ssize_t show_hello_time(struct class_device *d, char *buf)
+static ssize_t show_hello_time(DEVICE_PARAMS, char *buf)
 {
 #if 0
        return sprintf(buf, "%lu\n",
@@ -129,17 +132,16 @@ static void set_hello_time(struct datapath *dp, unsigned long val)
 #endif
 }
 
-static ssize_t store_hello_time(struct class_device *d,
+static ssize_t store_hello_time(DEVICE_PARAMS,
                                const char *buf,
                                size_t len)
 {
-       return store_bridge_parm(d, buf, len, set_hello_time);
+       return store_bridge_parm(DEVICE_ARGS, buf, len, set_hello_time);
 }
 static BRC_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
                   store_hello_time);
 
-static ssize_t show_max_age(struct class_device *d, 
-                           char *buf)
+static ssize_t show_max_age(DEVICE_PARAMS, char *buf)
 {
 #if 0
        return sprintf(buf, "%lu\n",
@@ -161,15 +163,14 @@ static void set_max_age(struct datapath *dp, unsigned long val)
 #endif
 }
 
-static ssize_t store_max_age(struct class_device *d, 
+static ssize_t store_max_age(DEVICE_PARAMS,
                             const char *buf, size_t len)
 {
-       return store_bridge_parm(d, buf, len, set_max_age);
+       return store_bridge_parm(DEVICE_ARGS, buf, len, set_max_age);
 }
 static BRC_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
 
-static ssize_t show_ageing_time(struct class_device *d,
-                               char *buf)
+static ssize_t show_ageing_time(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -188,16 +189,15 @@ static void set_ageing_time(struct datapath *dp, unsigned long val)
 #endif
 }
 
-static ssize_t store_ageing_time(struct class_device *d,
+static ssize_t store_ageing_time(DEVICE_PARAMS,
                                 const char *buf, size_t len)
 {
-       return store_bridge_parm(d, buf, len, set_ageing_time);
+       return store_bridge_parm(DEVICE_ARGS, buf, len, set_ageing_time);
 }
 static BRC_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
                   store_ageing_time);
 
-static ssize_t show_stp_state(struct class_device *d,
-                             char *buf)
+static ssize_t show_stp_state(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -208,7 +208,7 @@ static ssize_t show_stp_state(struct class_device *d,
 }
 
 
-static ssize_t store_stp_state(struct class_device *d,
+static ssize_t store_stp_state(DEVICE_PARAMS,
                               const char *buf,
                               size_t len)
 {
@@ -236,8 +236,7 @@ static ssize_t store_stp_state(struct class_device *d,
 static BRC_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
                   store_stp_state);
 
-static ssize_t show_priority(struct class_device *d, 
-                            char *buf)
+static ssize_t show_priority(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -257,15 +256,14 @@ static void set_priority(struct datapath *dp, unsigned long val)
 #endif
 }
 
-static ssize_t store_priority(struct class_device *d, 
+static ssize_t store_priority(DEVICE_PARAMS,
                               const char *buf, size_t len)
 {
-       return store_bridge_parm(d, buf, len, set_priority);
+       return store_bridge_parm(DEVICE_ARGS, buf, len, set_priority);
 }
 static BRC_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
 
-static ssize_t show_root_id(struct class_device *d, 
-                           char *buf)
+static ssize_t show_root_id(DEVICE_PARAMS, char *buf)
 {
 #if 0
        return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
@@ -275,8 +273,7 @@ static ssize_t show_root_id(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
 
-static ssize_t show_bridge_id(struct class_device *d, 
-                             char *buf)
+static ssize_t show_bridge_id(DEVICE_PARAMS, char *buf)
 {
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
        const unsigned char *addr = dp->ports[ODPP_LOCAL]->dev->dev_addr;
@@ -287,8 +284,7 @@ static ssize_t show_bridge_id(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
 
-static ssize_t show_root_port(struct class_device *d, 
-                             char *buf)
+static ssize_t show_root_port(DEVICE_PARAMS, char *buf)
 {
 #if 0
        return sprintf(buf, "%d\n", to_bridge(d)->root_port);
@@ -298,8 +294,7 @@ static ssize_t show_root_port(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
 
-static ssize_t show_root_path_cost(struct class_device *d,
-                                  char *buf)
+static ssize_t show_root_path_cost(DEVICE_PARAMS, char *buf)
 {
 #if 0
        return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
@@ -309,8 +304,7 @@ static ssize_t show_root_path_cost(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
 
-static ssize_t show_topology_change(struct class_device *d,
-                                   char *buf)
+static ssize_t show_topology_change(DEVICE_PARAMS, char *buf)
 {
 #if 0
        return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
@@ -320,8 +314,7 @@ static ssize_t show_topology_change(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
 
-static ssize_t show_topology_change_detected(struct class_device *d,
-                                            char *buf)
+static ssize_t show_topology_change_detected(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -333,8 +326,7 @@ static ssize_t show_topology_change_detected(struct class_device *d,
 static BRC_DEVICE_ATTR(topology_change_detected, S_IRUGO,
                   show_topology_change_detected, NULL);
 
-static ssize_t show_hello_timer(struct class_device *d,
-                               char *buf)
+static ssize_t show_hello_timer(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -345,8 +337,7 @@ static ssize_t show_hello_timer(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
 
-static ssize_t show_tcn_timer(struct class_device *d, 
-                             char *buf)
+static ssize_t show_tcn_timer(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -357,8 +348,7 @@ static ssize_t show_tcn_timer(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
 
-static ssize_t show_topology_change_timer(struct class_device *d,
-                                         char *buf)
+static ssize_t show_topology_change_timer(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -370,8 +360,7 @@ static ssize_t show_topology_change_timer(struct class_device *d,
 static BRC_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
                   NULL);
 
-static ssize_t show_gc_timer(struct class_device *d, 
-                            char *buf)
+static ssize_t show_gc_timer(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -382,8 +371,7 @@ static ssize_t show_gc_timer(struct class_device *d,
 }
 static BRC_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
 
-static ssize_t show_group_addr(struct class_device *d,
-                              char *buf)
+static ssize_t show_group_addr(DEVICE_PARAMS, char *buf)
 {
 #if 0
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -396,7 +384,7 @@ static ssize_t show_group_addr(struct class_device *d,
 #endif
 }
 
-static ssize_t store_group_addr(struct class_device *d,
+static ssize_t store_group_addr(DEVICE_PARAMS,
                                const char *buf, size_t len)
 {
        struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -439,23 +427,23 @@ static BRC_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
                   show_group_addr, store_group_addr);
 
 static struct attribute *bridge_attrs[] = {
-       &class_device_attr_forward_delay.attr,
-       &class_device_attr_hello_time.attr,
-       &class_device_attr_max_age.attr,
-       &class_device_attr_ageing_time.attr,
-       &class_device_attr_stp_state.attr,
-       &class_device_attr_priority.attr,
-       &class_device_attr_bridge_id.attr,
-       &class_device_attr_root_id.attr,
-       &class_device_attr_root_path_cost.attr,
-       &class_device_attr_root_port.attr,
-       &class_device_attr_topology_change.attr,
-       &class_device_attr_topology_change_detected.attr,
-       &class_device_attr_hello_timer.attr,
-       &class_device_attr_tcn_timer.attr,
-       &class_device_attr_topology_change_timer.attr,
-       &class_device_attr_gc_timer.attr,
-       &class_device_attr_group_addr.attr,
+       &DEV_ATTR(forward_delay).attr,
+       &DEV_ATTR(hello_time).attr,
+       &DEV_ATTR(max_age).attr,
+       &DEV_ATTR(ageing_time).attr,
+       &DEV_ATTR(stp_state).attr,
+       &DEV_ATTR(priority).attr,
+       &DEV_ATTR(bridge_id).attr,
+       &DEV_ATTR(root_id).attr,
+       &DEV_ATTR(root_path_cost).attr,
+       &DEV_ATTR(root_port).attr,
+       &DEV_ATTR(topology_change).attr,
+       &DEV_ATTR(topology_change_detected).attr,
+       &DEV_ATTR(hello_timer).attr,
+       &DEV_ATTR(tcn_timer).attr,
+       &DEV_ATTR(topology_change_timer).attr,
+       &DEV_ATTR(gc_timer).attr,
+       &DEV_ATTR(group_addr).attr,
        NULL
 };
 
@@ -476,7 +464,7 @@ static struct attribute_group bridge_group = {
  */
 int brc_sysfs_add_dp(struct datapath *dp)
 {
-       struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
+       struct kobject *kobj = &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj;
        int err;
 
        err = sysfs_create_group(kobj, &bridge_group);
@@ -495,12 +483,12 @@ int brc_sysfs_add_dp(struct datapath *dp)
        err = kobject_register(&dp->ifobj);
        if (err) {
                pr_info("%s: can't add kobject (directory) %s/%s\n",
-                               __FUNCTION__, dp_name(dp), dp->ifobj.name);
+                       __FUNCTION__, dp_name(dp), kobject_name(&dp->ifobj));
                goto out2;
        }
 #else
-       br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, kobj);
-       if (!br->ifobj) {
+       dp->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, kobj);
+       if (!dp->ifobj) {
                pr_info("%s: can't add kobject (directory) %s/%s\n",
                        __func__, dp_name(dp), SYSFS_BRIDGE_PORT_SUBDIR);
                goto out2;
@@ -516,7 +504,7 @@ int brc_sysfs_add_dp(struct datapath *dp)
 
 int brc_sysfs_del_dp(struct datapath *dp)
 {
-       struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
+       struct kobject *kobj = &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj;
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
        kobject_unregister(&dp->ifobj);
@@ -527,7 +515,7 @@ int brc_sysfs_del_dp(struct datapath *dp)
 
        return 0;
 }
-#else /* !SUPPORT_SYSFS */
+#else /* !CONFIG_SYSFS */
 int brc_sysfs_add_dp(struct datapath *dp) { return 0; }
 int brc_sysfs_del_dp(struct datapath *dp) { return 0; }
 int brc_sysfs_add_if(struct net_bridge_port *p) { return 0; }
@@ -537,4 +525,4 @@ int brc_sysfs_del_if(struct net_bridge_port *p)
        kfree(p);
        return 0;
 }
-#endif /* !SUPPORT_SYSFS */
+#endif /* !CONFIG_SYSFS */
index ceda129..7a9b8b8 100644 (file)
@@ -21,7 +21,7 @@
 #include "brc_sysfs.h"
 #include "datapath.h"
 
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
 
 struct brport_attribute {
        struct attribute        attr;
@@ -289,18 +289,14 @@ int brc_sysfs_add_if(struct net_bridge_port *p)
        struct brport_attribute **a;
        int err;
 
-       kobject_init(&p->kobj);
-       kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
-       p->kobj.ktype = &brport_ktype;
-       p->kobj.kset = NULL;
-       p->kobj.parent = &(p->dev->class_dev.kobj);
-
-       err = kobject_add(&p->kobj);
+       err = kobject_init_and_add(&p->kobj, &brport_ktype,
+                                  &(p->dev->NETDEV_DEV_MEMBER.kobj),
+                                  SYSFS_BRIDGE_PORT_ATTR);
        if (err)
-               goto err_put;
+               goto err;
 
        err = sysfs_create_link(&p->kobj,
-                               &dp->ports[ODPP_LOCAL]->dev->class_dev.kobj,
+                               &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj,
                                SYSFS_BRIDGE_PORT_LINK);
        if (err)
                goto err_del;
@@ -311,7 +307,11 @@ int brc_sysfs_add_if(struct net_bridge_port *p)
                        goto err_del;
        }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
        err = sysfs_create_link(&dp->ifobj, &p->kobj, p->dev->name);
+#else
+       err = sysfs_create_link(dp->ifobj, &p->kobj, p->dev->name);
+#endif
        if (err)
                goto err_del;
 
@@ -321,8 +321,8 @@ int brc_sysfs_add_if(struct net_bridge_port *p)
 
 err_del:
        kobject_del(&p->kobj);
-err_put:
        kobject_put(&p->kobj);
+err:
        return err;
 }
 
@@ -339,4 +339,4 @@ int brc_sysfs_del_if(struct net_bridge_port *p)
 
        return 0;
 }
-#endif /* SUPPORT_SYSFS */
+#endif /* CONFIG_SYSFS */
index 47805bc..42479e8 100644 (file)
@@ -412,18 +412,14 @@ int brc_add_dp(struct datapath *dp)
 {
        if (!try_module_get(THIS_MODULE))
                return -ENODEV;
-#ifdef SUPPORT_SYSFS
        brc_sysfs_add_dp(dp);
-#endif
 
        return 0;
 }
 
 int brc_del_dp(struct datapath *dp) 
 {
-#ifdef SUPPORT_SYSFS
        brc_sysfs_del_dp(dp);
-#endif
        module_put(THIS_MODULE);
 
        return 0;
@@ -458,10 +454,8 @@ __init brc_init(void)
        dp_del_dp_hook = brc_del_dp;
 
        /* Register hooks for interface adds and deletes */
-#ifdef SUPPORT_SYSFS
        dp_add_if_hook = brc_sysfs_add_if;
        dp_del_if_hook = brc_sysfs_del_if;
-#endif
 
        /* Randomize the initial sequence number.  This is not a security
         * feature; it only helps avoid crossed wires between userspace and
index fc73cac..14d83cd 100644 (file)
@@ -177,7 +177,8 @@ static void dp_ifinfo_notify(int event, struct net_bridge_port *port)
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+       return;
 errout:
        if (err < 0)
                rtnl_set_sk_err(net, RTNLGRP_LINK, err);
@@ -276,19 +277,19 @@ static void do_destroy_dp(struct datapath *dp, struct list_head *dp_devs)
        struct net_bridge_port *p, *n;
        int i;
 
+       list_for_each_entry_safe (p, n, &dp->port_list, node)
+               if (p->port_no != ODPP_LOCAL)
+                       dp_del_port(p, dp_devs);
+
        if (dp_del_dp_hook)
                dp_del_dp_hook(dp);
 
-       /* Drop references to DP. */
-       list_for_each_entry_safe (p, n, &dp->port_list, node)
-               dp_del_port(p, dp_devs);
-
        rcu_assign_pointer(dps[dp->dp_idx], NULL);
-       synchronize_rcu();
 
-       /* Wait until no longer in use, then destroy it. */
-       synchronize_rcu();
+       dp_del_port(dp->ports[ODPP_LOCAL], dp_devs);
+
        dp_table_destroy(dp->table, 1);
+
        for (i = 0; i < DP_N_QUEUES; i++)
                skb_queue_purge(&dp->queues[i]);
        for (i = 0; i < DP_MAX_GROUPS; i++)
@@ -424,10 +425,13 @@ int dp_del_port(struct net_bridge_port *p, struct list_head *dp_devs)
 {
        ASSERT_RTNL();
 
-#ifdef SUPPORT_SYSFS
-       if (p->port_no != ODPP_LOCAL && dp_del_if_hook)
+       if (p->port_no != ODPP_LOCAL && dp_del_if_hook) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
                sysfs_remove_link(&p->dp->ifobj, p->dev->name);
+#else
+               sysfs_remove_link(p->dp->ifobj, p->dev->name);
 #endif
+       }
        dp_ifinfo_notify(RTM_DELLINK, p);
 
        p->dp->n_ports--;
@@ -577,6 +581,7 @@ static int dp_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
 #endif
 
 #ifdef CONFIG_XEN
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
 /* This code is copied verbatim from net/dev/core.c in Xen's
  * linux-2.6.18-92.1.10.el5.xs5.0.0.394.644.  We can't call those functions
  * directly because they aren't exported. */
@@ -623,7 +628,8 @@ int skb_checksum_setup(struct sk_buff *skb)
 out:
        return -EPROTO;
 }
-#endif
+#endif /* linux == 2.6.18 */
+#endif /* CONFIG_XEN */
 
 int
 dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
@@ -1464,6 +1470,7 @@ static int dp_has_packet_of_interest(struct datapath *dp, int listeners)
 ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes,
                      loff_t *ppos)
 {
+       /* XXX is there sufficient synchronization here? */
        int listeners = (int) f->private_data;
        int dp_idx = iminor(f->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
@@ -1518,6 +1525,7 @@ error:
 
 static unsigned int openvswitch_poll(struct file *file, poll_table *wait)
 {
+       /* XXX is there sufficient synchronization here? */
        int dp_idx = iminor(file->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
        unsigned int mask;
index db24349..3706219 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/netdevice.h>
 #include <linux/workqueue.h>
 #include <linux/skbuff.h>
+#include <linux/version.h>
 #include "flow.h"
 #include "brc_sysfs.h"
 
@@ -66,8 +67,12 @@ struct datapath {
        struct mutex mutex;
        int dp_idx;
 
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
        struct kobject ifobj;
+#else
+       struct kobject *ifobj;
+#endif
 #endif
 
        int drop_frags;
@@ -96,7 +101,7 @@ struct net_bridge_port {
        u16 port_no;
        struct datapath *dp;
        struct net_device *dev;
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
        struct kobject kobj;
 #endif
        struct list_head node;   /* Element in datapath.ports. */
index bbc4c72..e7359a4 100644 (file)
@@ -12,6 +12,7 @@ openvswitch_headers += \
        linux-2.6/compat-2.6/include/linux/ipv6.h \
        linux-2.6/compat-2.6/include/linux/jiffies.h \
        linux-2.6/compat-2.6/include/linux/kernel.h \
+       linux-2.6/compat-2.6/include/linux/kobject.h \
        linux-2.6/compat-2.6/include/linux/log2.h \
        linux-2.6/compat-2.6/include/linux/lockdep.h \
        linux-2.6/compat-2.6/include/linux/mutex.h \
diff --git a/datapath/linux-2.6/compat-2.6/include/linux/kobject.h b/datapath/linux-2.6/compat-2.6/include/linux/kobject.h
new file mode 100644 (file)
index 0000000..7dbb010
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __LINUX_KOBJECT_WRAPPER_H
+#define __LINUX_KOBJECT_WRAPPER_H 1
+
+#include_next <linux/kobject.h>
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+static inline int kobject_init_and_add(struct kobject *kobj,
+                                       struct kobj_type *ktype,
+                                       struct kobject *parent,
+                                       const char *name)
+{
+       kobject_init(kobj);
+       kobject_set_name(kobj, "%s", name);
+       kobj->ktype = ktype;
+       kobj->kset = NULL;
+       kobj->parent = parent;
+
+       return kobject_add(kobj);
+}
+#endif
+
+#endif /* linux/kobject.h wrapper */
index 32e1735..d291513 100644 (file)
@@ -5,8 +5,19 @@
 
 struct net;
 
+/* Before 2.6.21, struct net_device has a "struct class_device" member named
+ * class_dev.  Beginning with 2.6.21, struct net_device instead has a "struct
+ * device" member named dev.  Otherwise the usage of these members is pretty
+ * much the same. */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
+#define NETDEV_DEV_MEMBER class_dev
+#else
+#define NETDEV_DEV_MEMBER dev
+#endif
+
 #ifndef to_net_dev
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_net_dev(class) \
+       container_of(class, struct net_device, NETDEV_DEV_MEMBER)
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
index 8bc5156..4d7bd78 100644 (file)
@@ -4,7 +4,7 @@
 #include_next <linux/rtnetlink.h>
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-static inline int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
+static inline void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
                              u32 group, struct nlmsghdr *nlh, gfp_t flags)
 {
        BUG_ON(nlh);            /* not implemented */
@@ -12,7 +12,6 @@ static inline int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
                /* errors reported via destination sk->sk_err */
                nlmsg_multicast(rtnl, skb, 0, group);
        }
-       return 0;
 }
 
 static inline void rtnl_set_sk_err(struct net *net, u32 group, int error)
@@ -20,10 +19,15 @@ static inline void rtnl_set_sk_err(struct net *net, u32 group, int error)
        netlink_set_err(rtnl, 0, group, error);
 }
 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+/* No 'net' parameter in these versions. */
 #define rtnl_notify(skb, net, pid, group, nlh, flags) \
-       ((void) (net), rtnl_notify(skb, pid, group, nlh, flags))
+       ((void) (net), (void) rtnl_notify(skb, pid, group, nlh, flags))
 #define rtnl_set_sk_err(net, group, error) \
        ((void) (net), rtnl_set_sk_err(group, error))
-#endif /* linux kernel < 2.6.25 */
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+/* Make the return type effectively 'void' to match Linux 2.6.30+. */
+#define rtnl_notify(skb, net, pid, group, nlh, flags) \
+       ((void) rtnl_notify(skb, net, pid, group, nlh, flags))
+#endif
 
 #endif /* linux/rtnetlink.h wrapper */
index 4aa1f90..76ed626 100644 (file)
@@ -2,4 +2,4 @@ openvswitch (0.90.0) unstable; urgency=low
 
   * Development version.
 
- -- Open vSwitch developers <ovs-dev@openvswitch.org>  Mon, 19 Nov 2007 14:57:52 -0800
+ -- Open vSwitch developers <dev@openvswitch.org>  Mon, 19 Nov 2007 14:57:52 -0800
index 09eda11..a59dcd3 100644 (file)
@@ -1,7 +1,7 @@
 Source: openvswitch
 Section: net
 Priority: extra
-Maintainer: Open vSwitch developers <ovs-dev@openvswitch.org>
+Maintainer: Open vSwitch developers <dev@openvswitch.org>
 Build-Depends: debhelper (>= 5), autoconf (>= 2.60), automake1.10, libssl-dev, pkg-config (>= 0.21), po-debconf, bzip2, openssl, libncurses5-dev, libpcre3-dev
 Standards-Version: 3.7.3
 
@@ -15,8 +15,7 @@ Description: Source code for Open vSwitch datapath Linux module
  from it using module-assistant or make-kpkg.  README.Debian in this
  package provides further instructions.
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: openvswitch-common
 Architecture: any
@@ -25,8 +24,7 @@ Description: Open vSwitch common components
  openvswitch-common provides components required by both openvswitch-switch
  and openvswitch-controller.
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: openvswitch-switch
 Architecture: any
@@ -36,8 +34,7 @@ Description: Open vSwitch switch implementations
  openvswitch-switch provides the userspace components and utilities for
  the Open vSwitch kernel-based switch.  
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: openvswitch-switch-config
 Architecture: any
@@ -46,8 +43,7 @@ Description: Open vSwitch switch implementations
  openvswitch-switch-config provides a utility for interactively configuring
  the Open vSwitch switch provided in the openvswitch-switch package.
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: openvswitch-switchui
 Architecture: any
@@ -71,8 +67,7 @@ Description: Open vSwitch public key infrastructure
  Open vSwitch switches and controllers, reducing the risk of
  man-in-the-middle attacks on the Open vSwitch network infrastructure.
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: openvswitch-pki-server
 Architecture: all
@@ -84,8 +79,7 @@ Description: Open vSwitch public key infrastructure (HTTP server support)
  convenient OpenFlow switch setup using the ovs-switch-setup program
  in the openvswitch-switch package.
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: openvswitch-controller
 Architecture: any
@@ -94,8 +88,7 @@ Description: Open vSwitch controller implementation
  The Open vSwitch controller enables OpenFlow switches that connect to it
  to act as MAC-learning Ethernet switches.
  .
- Open vSwitch is a software-based Ethernet switch targeted at virtual
- servers.
+ Open vSwitch is a full-featured software-based Ethernet switch.
 
 Package: corekeeper
 Architecture: all
index 4da85b4..af44a58 100644 (file)
@@ -1,7 +1,7 @@
 Source: openvswitch
 Section: net
 Priority: extra
-Maintainer: Open vSwitch developers <ovs-dev@openvswitch.org>
+Maintainer: Open vSwitch developers <dev@openvswitch.org>
 Build-Depends: debhelper (>= 5.0.37)
 Standards-Version: 3.7.3
 
index 119e558..ec14b8c 100644 (file)
@@ -7,7 +7,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: ovs-dev@openvswitch.org\n"
+"Report-Msgid-Bugs-To: dev@openvswitch.org\n"
 "POT-Creation-Date: 2009-05-11 13:38-0700\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
index 8c14dd3..3d93e37 100644 (file)
@@ -729,6 +729,7 @@ netdev_get_features(struct netdev *netdev,
                            peer ? peer : &dummy[3]);
 }
 
+/* Set the features advertised by 'netdev' to 'advertise'. */
 int
 netdev_set_advertisements(struct netdev *netdev, uint32_t advertise)
 {
@@ -1113,6 +1114,8 @@ get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats)
     return ENODEV;
 }
 
+/* Sets 'carrier' to true if carrier is active (link light is on) on 
+ * 'netdev'. */
 int
 netdev_get_carrier(const struct netdev *netdev, bool *carrier)
 {
@@ -1169,6 +1172,7 @@ exit:
     return error;
 }
 
+/* Retrieves current device stats for 'netdev'. */
 int
 netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 {
index 33e179e..e5b86e4 100644 (file)
@@ -23,6 +23,7 @@
 #include <poll.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/resource.h>
 #include <sys/un.h>
@@ -299,6 +300,172 @@ guess_netmask(uint32_t ip)
             : htonl(0));                          /* ??? */
 }
 
+/* Opens a non-blocking TCP socket and connects to 'target', which should be a
+ * string in the format "<host>[:<port>]", where <host> is required and <port>
+ * is optional, with 'default_port' assumed if <port> is omitted.
+ *
+ * On success, returns 0 (indicating connection complete) or EAGAIN (indicating
+ * connection in progress), in which case the new file descriptor is stored
+ * into '*fdp'.  On failure, returns a positive errno value other than EAGAIN
+ * and stores -1 into '*fdp'.
+ *
+ * If 'sinp' is non-null, then on success the target address is stored into
+ * '*sinp'. */
+int
+tcp_open_active(const char *target_, uint16_t default_port,
+                struct sockaddr_in *sinp, int *fdp)
+{
+    char *target = xstrdup(target_);
+    char *save_ptr = NULL;
+    const char *host_name;
+    const char *port_string;
+    struct sockaddr_in sin;
+    int fd = -1;
+    int error;
+
+    /* Defaults. */
+    memset(&sin, 0, sizeof sin);
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(default_port);
+
+    /* Tokenize. */
+    host_name = strtok_r(target, ":", &save_ptr);
+    port_string = strtok_r(NULL, ":", &save_ptr);
+    if (!host_name) {
+        ovs_error(0, "%s: bad peer name format", target_);
+        error = EAFNOSUPPORT;
+        goto exit;
+    }
+
+    /* Look up IP, port. */
+    error = lookup_ip(host_name, &sin.sin_addr);
+    if (error) {
+        goto exit;
+    }
+    if (port_string && atoi(port_string)) {
+        sin.sin_port = htons(atoi(port_string));
+    }
+
+    /* Create non-blocking socket. */
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd < 0) {
+        VLOG_ERR("%s: socket: %s", target_, strerror(errno));
+        error = errno;
+        goto exit;
+    }
+    error = set_nonblocking(fd);
+    if (error) {
+        goto exit_close;
+    }
+
+    /* Connect. */
+    error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno;
+    if (error == EINPROGRESS) {
+        error = EAGAIN;
+    } else if (error && error != EAGAIN) {
+        goto exit_close;
+    }
+
+    /* Success: error is 0 or EAGAIN. */
+    goto exit;
+
+exit_close:
+    close(fd);
+exit:
+    if (!error || error == EAGAIN) {
+        if (sinp) {
+            *sinp = sin;
+        }
+        *fdp = fd;
+    } else {
+        *fdp = -1;
+    }
+    free(target);
+    return error;
+}
+
+/* Opens a non-blocking TCP socket, binds to 'target', and listens for incoming
+ * connections.  'target' should be a string in the format "[<port>][:<ip>]",
+ * where both <port> and <ip> are optional.  If <port> is omitted, it defaults
+ * to 'default_port'; if <ip> is omitted it defaults to the wildcard IP
+ * address.
+ *
+ * The socket will have SO_REUSEADDR turned on.
+ *
+ * On success, returns a non-negative file descriptor.  On failure, returns a
+ * negative errno value. */
+int
+tcp_open_passive(const char *target_, uint16_t default_port)
+{
+    char *target = xstrdup(target_);
+    char *string_ptr = target;
+    struct sockaddr_in sin;
+    const char *host_name;
+    const char *port_string;
+    int fd, error;
+    unsigned int yes  = 1;
+
+    /* Address defaults. */
+    memset(&sin, 0, sizeof sin);
+    sin.sin_family = AF_INET;
+    sin.sin_addr.s_addr = htonl(INADDR_ANY);
+    sin.sin_port = htons(default_port);
+
+    /* Parse optional port number. */
+    port_string = strsep(&string_ptr, ":");
+    if (port_string && atoi(port_string)) {
+        sin.sin_port = htons(atoi(port_string));
+    }
+
+    /* Parse optional bind IP. */
+    host_name = strsep(&string_ptr, ":");
+    if (host_name && host_name[0]) {
+        error = lookup_ip(host_name, &sin.sin_addr);
+        if (error) {
+            goto exit;
+        }
+    }
+
+    /* Create non-blocking socket, set SO_REUSEADDR. */
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd < 0) {
+        error = errno;
+        VLOG_ERR("%s: socket: %s", target_, strerror(error));
+        goto exit;
+    }
+    error = set_nonblocking(fd);
+    if (error) {
+        goto exit_close;
+    }
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
+        error = errno;
+        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", target_, strerror(error));
+        goto exit_close;
+    }
+
+    /* Bind. */
+    if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
+        error = errno;
+        VLOG_ERR("%s: bind: %s", target_, strerror(error));
+        goto exit_close;
+    }
+
+    /* Listen. */
+    if (listen(fd, 10) < 0) {
+        error = errno;
+        VLOG_ERR("%s: listen: %s", target_, strerror(error));
+        goto exit_close;
+    }
+    error = 0;
+    goto exit;
+
+exit_close:
+    close(fd);
+exit:
+    free(target);
+    return error ? -error : fd;
+}
+
 int
 read_fully(int fd, void *p_, size_t size, size_t *bytes_read)
 {
index 34dc92f..d808838 100644 (file)
@@ -33,6 +33,10 @@ int make_unix_socket(int style, bool nonblock, bool passcred,
 int get_unix_name_len(socklen_t sun_len);
 uint32_t guess_netmask(uint32_t ip);
 
+int tcp_open_active(const char *target, uint16_t default_port,
+                    struct sockaddr_in *sinp, int *fdp);
+int tcp_open_passive(const char *target, uint16_t default_port);
+
 int read_fully(int fd, void *, size_t, size_t *bytes_read);
 int write_fully(int fd, const void *, size_t, size_t *bytes_written);
 
index 905996f..1a32903 100644 (file)
@@ -269,58 +269,21 @@ ssl_vconn_cast(struct vconn *vconn)
 static int
 ssl_open(const char *name, char *suffix, struct vconn **vconnp)
 {
-    char *save_ptr, *host_name, *port_string;
     struct sockaddr_in sin;
-    int retval;
-    int fd;
-
-    retval = ssl_init();
-    if (retval) {
-        return retval;
-    }
-
-    host_name = strtok_r(suffix, ":", &save_ptr);
-    port_string = strtok_r(NULL, ":", &save_ptr);
-    if (!host_name) {
-        ovs_error(0, "%s: bad peer name format", name);
-        return EAFNOSUPPORT;
-    }
-
-    memset(&sin, 0, sizeof sin);
-    sin.sin_family = AF_INET;
-    if (lookup_ip(host_name, &sin.sin_addr)) {
-        return ENOENT;
-    }
-    sin.sin_port = htons(port_string && *port_string ? atoi(port_string)
-                         : OFP_SSL_PORT);
+    int error, fd;
 
-    /* Create socket. */
-    fd = socket(AF_INET, SOCK_STREAM, 0);
-    if (fd < 0) {
-        VLOG_ERR("%s: socket: %s", name, strerror(errno));
-        return errno;
-    }
-    retval = set_nonblocking(fd);
-    if (retval) {
-        close(fd);
-        return retval;
+    error = ssl_init();
+    if (error) {
+        return error;
     }
 
-    /* Connect socket. */
-    retval = connect(fd, (struct sockaddr *) &sin, sizeof sin);
-    if (retval < 0) {
-        if (errno == EINPROGRESS) {
-            return new_ssl_vconn(name, fd, CLIENT, STATE_TCP_CONNECTING,
-                                 &sin, vconnp);
-        } else {
-            int error = errno;
-            VLOG_ERR("%s: connect: %s", name, strerror(error));
-            close(fd);
-            return error;
-        }
+    error = tcp_open_active(suffix, OFP_SSL_PORT, &sin, &fd);
+    if (fd >= 0) {
+        int state = error ? STATE_TCP_CONNECTING : STATE_SSL_CONNECTING;
+        return new_ssl_vconn(name, fd, CLIENT, state, &sin, vconnp);
     } else {
-        return new_ssl_vconn(name, fd, CLIENT, STATE_SSL_CONNECTING,
-                             &sin, vconnp);
+        VLOG_ERR("%s: connect: %s", name, strerror(error));
+        return error;
     }
 }
 
@@ -793,55 +756,18 @@ pssl_pvconn_cast(struct pvconn *pvconn)
 static int
 pssl_open(const char *name, char *suffix, struct pvconn **pvconnp)
 {
-    struct sockaddr_in sin;
     struct pssl_pvconn *pssl;
     int retval;
     int fd;
-    unsigned int yes = 1;
 
     retval = ssl_init();
     if (retval) {
         return retval;
     }
 
-    /* Create socket. */
-    fd = socket(AF_INET, SOCK_STREAM, 0);
+    fd = tcp_open_passive(suffix, OFP_SSL_PORT);
     if (fd < 0) {
-        int error = errno;
-        VLOG_ERR("%s: socket: %s", name, strerror(error));
-        return error;
-    }
-
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
-        int error = errno;
-        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", name, strerror(errno));
-        return error;
-    }
-
-    memset(&sin, 0, sizeof sin);
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = htonl(INADDR_ANY);
-    sin.sin_port = htons(atoi(suffix) ? atoi(suffix) : OFP_SSL_PORT);
-    retval = bind(fd, (struct sockaddr *) &sin, sizeof sin);
-    if (retval < 0) {
-        int error = errno;
-        VLOG_ERR("%s: bind: %s", name, strerror(error));
-        close(fd);
-        return error;
-    }
-
-    retval = listen(fd, 10);
-    if (retval < 0) {
-        int error = errno;
-        VLOG_ERR("%s: listen: %s", name, strerror(error));
-        close(fd);
-        return error;
-    }
-
-    retval = set_nonblocking(fd);
-    if (retval) {
-        close(fd);
-        return retval;
+        return -fd;
     }
 
     pssl = xmalloc(sizeof *pssl);
index a9fcd98..f5a8602 100644 (file)
@@ -270,23 +270,7 @@ new_pstream_pvconn(const char *name, int fd,
                                    size_t sa_len, struct vconn **),
                   struct pvconn **pvconnp)
 {
-    struct pstream_pvconn *ps;
-    int retval;
-
-    retval = set_nonblocking(fd);
-    if (retval) {
-        close(fd);
-        return retval;
-    }
-
-    if (listen(fd, 10) < 0) {
-        int error = errno;
-        VLOG_ERR("%s: listen: %s", name, strerror(error));
-        close(fd);
-        return error;
-    }
-
-    ps = xmalloc(sizeof *ps);
+    struct pstream_pvconn *ps = xmalloc(sizeof *ps);
     pvconn_init(&ps->pvconn, &pstream_pvconn_class, name);
     ps->fd = fd;
     ps->accept_cb = accept_cb;
index 911fe6d..9451322 100644 (file)
@@ -57,51 +57,15 @@ new_tcp_vconn(const char *name, int fd, int connect_status,
 static int
 tcp_open(const char *name, char *suffix, struct vconn **vconnp)
 {
-    char *save_ptr;
-    const char *host_name;
-    const char *port_string;
     struct sockaddr_in sin;
-    int retval;
-    int fd;
-
-    host_name = strtok_r(suffix, ":", &save_ptr);
-    port_string = strtok_r(NULL, ":", &save_ptr);
-    if (!host_name) {
-        ovs_error(0, "%s: bad peer name format", name);
-        return EAFNOSUPPORT;
-    }
-
-    memset(&sin, 0, sizeof sin);
-    sin.sin_family = AF_INET;
-    if (lookup_ip(host_name, &sin.sin_addr)) {
-        return ENOENT;
-    }
-    sin.sin_port = htons(port_string ? atoi(port_string) : OFP_TCP_PORT);
-
-    fd = socket(AF_INET, SOCK_STREAM, 0);
-    if (fd < 0) {
-        VLOG_ERR("%s: socket: %s", name, strerror(errno));
-        return errno;
-    }
-
-    retval = set_nonblocking(fd);
-    if (retval) {
-        close(fd);
-        return retval;
-    }
+    int fd, error;
 
-    retval = connect(fd, (struct sockaddr *) &sin, sizeof sin);
-    if (retval < 0) {
-        if (errno == EINPROGRESS) {
-            return new_tcp_vconn(name, fd, EAGAIN, &sin, vconnp);
-        } else {
-            int error = errno;
-            VLOG_ERR("%s: connect: %s", name, strerror(error));
-            close(fd);
-            return error;
-        }
+    error = tcp_open_active(suffix, OFP_TCP_PORT, NULL, &fd);
+    if (fd >= 0) {
+        return new_tcp_vconn(name, fd, error, &sin, vconnp);
     } else {
-        return new_tcp_vconn(name, fd, 0, &sin, vconnp);
+        VLOG_ERR("%s: connect: %s", name, strerror(error));
+        return error;
     }
 }
 
@@ -121,37 +85,16 @@ static int ptcp_accept(int fd, const struct sockaddr *sa, size_t sa_len,
                        struct vconn **vconnp);
 
 static int
-ptcp_open(const char *name, char *suffix, struct pvconn **pvconnp)
+ptcp_open(const char *name UNUSED, char *suffix, struct pvconn **pvconnp)
 {
-    struct sockaddr_in sin;
-    int retval;
     int fd;
-    unsigned int yes  = 1;
 
-    fd = socket(AF_INET, SOCK_STREAM, 0);
+    fd = tcp_open_passive(suffix, OFP_TCP_PORT);
     if (fd < 0) {
-        VLOG_ERR("%s: socket: %s", name, strerror(errno));
-        return errno;
-    }
-
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
-        VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", name, strerror(errno));
-        return errno;
-    }
-
-    memset(&sin, 0, sizeof sin);
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = htonl(INADDR_ANY);
-    sin.sin_port = htons(atoi(suffix) ? atoi(suffix) : OFP_TCP_PORT);
-    retval = bind(fd, (struct sockaddr *) &sin, sizeof sin);
-    if (retval < 0) {
-        int error = errno;
-        VLOG_ERR("%s: bind: %s", name, strerror(error));
-        close(fd);
-        return error;
+        return -fd;
+    } else {
+        return new_pstream_pvconn("ptcp", fd, ptcp_accept, pvconnp);
     }
-
-    return new_pstream_pvconn("ptcp", fd, ptcp_accept, pvconnp);
 }
 
 static int
index aec2e31..baa9861 100644 (file)
@@ -81,7 +81,7 @@ static int punix_accept(int fd, const struct sockaddr *sa, size_t sa_len,
 static int
 punix_open(const char *name UNUSED, char *suffix, struct pvconn **pvconnp)
 {
-    int fd;
+    int fd, error;
 
     fd = make_unix_socket(SOCK_STREAM, true, true, suffix, NULL);
     if (fd < 0) {
@@ -89,6 +89,19 @@ punix_open(const char *name UNUSED, char *suffix, struct pvconn **pvconnp)
         return errno;
     }
 
+    error = set_nonblocking(fd);
+    if (error) {
+        close(fd);
+        return error;
+    }
+
+    if (listen(fd, 10) < 0) {
+        error = errno;
+        VLOG_ERR("%s: listen: %s", name, strerror(error));
+        close(fd);
+        return error;
+    }
+
     return new_pstream_pvconn("punix", fd, punix_accept, pvconnp);
 }
 
index a006efb..1999d74 100644 (file)
@@ -139,12 +139,12 @@ vconn_usage(bool active, bool passive, bool bootstrap UNUSED)
 
     if (passive) {
         printf("Passive OpenFlow connection methods:\n");
-        printf("  ptcp:[PORT]             "
-               "listen to TCP PORT (default: %d)\n",
+        printf("  ptcp:[PORT][:IP]        "
+               "listen to TCP PORT (default: %d) on IP\n",
                OFP_TCP_PORT);
 #ifdef HAVE_OPENSSL
-        printf("  pssl:[PORT]             "
-               "listen for SSL on PORT (default: %d)\n",
+        printf("  pssl:[PORT][:IP]        "
+               "listen for SSL on PORT (default: %d) on IP\n",
                OFP_SSL_PORT);
 #endif
         printf("  punix:FILE              "
@@ -339,7 +339,7 @@ vcs_recv_hello(struct vconn *vconn)
 
     if (retval != EAGAIN) {
         vconn->state = VCS_DISCONNECTED;
-        vconn->error = retval;
+        vconn->error = retval == EOF ? ECONNRESET : retval;
     }
 }
 
@@ -433,10 +433,7 @@ vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
 static int
 do_recv(struct vconn *vconn, struct ofpbuf **msgp)
 {
-    int retval;
-
-again:
-    retval = (vconn->class->recv)(vconn, msgp);
+    int retval = (vconn->class->recv)(vconn, msgp);
     if (!retval) {
         struct ofp_header *oh;
 
@@ -456,20 +453,6 @@ again:
             && oh->type != OFPT_VENDOR)
         {
             if (vconn->version < 0) {
-                if (oh->type == OFPT_PACKET_IN
-                    || oh->type == OFPT_FLOW_EXPIRED
-                    || oh->type == OFPT_PORT_STATUS) {
-                    /* The kernel datapath is stateless and doesn't really
-                     * support version negotiation, so it can end up sending
-                     * these asynchronous message before version negotiation
-                     * is complete.  Just ignore them.
-                     *
-                     * (After we move OFPT_PORT_STATUS messages from the kernel
-                     * into secchan, we won't get those here, since secchan
-                     * does proper version negotiation.) */
-                    ofpbuf_delete(*msgp);
-                    goto again;
-                }
                 VLOG_ERR_RL(&bad_ofmsg_rl,
                             "%s: received OpenFlow message type %"PRIu8" "
                             "before version negotiation complete",
index da52482..0c08de3 100644 (file)
@@ -168,7 +168,7 @@ discovery_set_accept_controller_re(struct discovery *d, const char *re_)
     int error;
     char *re;
 
-    re = (!re_ ? xstrdup(vconn_ssl_is_configured() ? "^ssl:.*" : ".*")
+    re = (!re_ ? xstrdup(vconn_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*")
           : re_[0] == '^' ? xstrdup(re_) : xasprintf("^%s", re_));
     regex = xmalloc(sizeof *regex);
     error = regcomp(regex, re, REG_NOSUB | REG_EXTENDED);
index b3192ab..d1037a8 100644 (file)
@@ -497,7 +497,8 @@ parse_options(int argc, char *argv[], struct ofsettings *s)
 
     /* Set accept_controller_regex. */
     if (!s->accept_controller_re) {
-        s->accept_controller_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*";
+        s->accept_controller_re
+            = vconn_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*";
     }
 
     /* Mode of operation. */
index b40842a..3b781ae 100644 (file)
@@ -182,8 +182,8 @@ names match the regular expression will be accepted.
 The default regular expression is \fBssl:.*\fR (meaning that only SSL
 controller connections will be accepted) when any of the SSL
 configuration options \fB--private-key\fR, \fB--certificate\fR, or
-\fB--ca-cert\fR is specified.  The default is \fB.*\fR otherwise
-(meaning that any controller will be accepted).
+\fB--ca-cert\fR is specified.  The default is \fB^tcp:.*\fR otherwise
+(meaning that only TCP controller connections will be accepted).
 
 The \fIregex\fR is implicitly anchored at the beginning of the
 controller location string, as if it begins with \fB^\fR.
@@ -307,14 +307,20 @@ multiple connection methods.
 
 .RS
 .TP
-\fBpssl:\fR[\fIport\fR]
+\fBpssl:\fR[\fIport\fR][\fB:\fIip\fR]
 Listens for SSL connections on \fIport\fR (default: 6633).  The
 \fB--private-key\fR, \fB--certificate\fR, and \fB--ca-cert\fR options
 are mandatory when this form is used.
+By default, \fB\*(PN\fR listens for connections to any local IP
+address, but \fIip\fR may be specified to listen only for connections
+to the given \fIip\fR.
 
 .TP
-\fBptcp:\fR[\fIport\fR]
+\fBptcp:\fR[\fIport\fR][\fB:\fIip\fR]
 Listens for TCP connections on \fIport\fR (default: 6633).
+By default, \fB\*(PN\fR listens for connections to any local IP
+address, but \fIip\fR may be specified to listen only for connections
+to the given \fIip\fR.
 
 .TP
 \fBpunix:\fIfile\fR
index 3a417c7..e251317 100644 (file)
@@ -64,3 +64,9 @@ stp_files = \
 TESTS_ENVIRONMENT += stp_files='$(stp_files)'
 
 EXTRA_DIST += $(stp_files)
+
+TESTS += tests/test-vconn
+noinst_PROGRAMS += tests/test-vconn
+tests_test_vconn_SOURCES = tests/test-vconn.c
+tests_test_vconn_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+
diff --git a/tests/test-vconn.c b/tests/test-vconn.c
new file mode 100644 (file)
index 0000000..7f85137
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2009 Nicira Networks.
+ *
+ * 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 "vconn.h"
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "poll-loop.h"
+#include "socket-util.h"
+#include "timeval.h"
+#include "util.h"
+#include "vlog.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+struct fake_pvconn {
+    const char *type;
+    char *pvconn_name;
+    char *vconn_name;
+    int fd;
+};
+
+static void
+fpv_create(const char *type, struct fake_pvconn *fpv)
+{
+    fpv->type = type;
+    if (!strcmp(type, "unix")) {
+        static int unix_count = 0;
+        char *bind_path;
+        int fd;
+
+        bind_path = xasprintf("fake-pvconn.%d", unix_count++);
+        fd = make_unix_socket(SOCK_STREAM, false, false, bind_path, NULL);
+        if (fd < 0) {
+            ovs_fatal(-fd, "%s: could not bind to Unix domain socket",
+                      bind_path);
+        }
+
+        fpv->pvconn_name = xasprintf("punix:%s", bind_path);
+        fpv->vconn_name = xasprintf("unix:%s", bind_path);
+        fpv->fd = fd;
+        free(bind_path);
+    } else if (!strcmp(type, "tcp")) {
+        struct sockaddr_in sin;
+        socklen_t sin_len;
+        int fd;
+
+        /* Create TCP socket. */
+        fd = socket(PF_INET, SOCK_STREAM, 0);
+        if (fd < 0) {
+            ovs_fatal(errno, "failed to create TCP socket");
+        }
+
+        /* Bind TCP socket to localhost on any available port. */
+        sin.sin_family = AF_INET;
+        sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+        sin.sin_port = htons(0);
+        if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
+            ovs_fatal(errno, "failed to bind TCP socket");
+        }
+
+        /* Retrieve socket's port number. */
+        sin_len = sizeof sin;
+        if (getsockname(fd, &sin, &sin_len) < 0) {
+            ovs_fatal(errno, "failed to read TCP socket name");
+        }
+        if (sin_len != sizeof sin || sin.sin_family != AF_INET) {
+            ovs_fatal(errno, "bad TCP socket name");
+        }
+
+        /* Save info. */
+        fpv->pvconn_name = xasprintf("ptcp:%"PRIu16":127.0.0.1",
+                                    ntohs(sin.sin_port));
+        fpv->vconn_name = xasprintf("tcp:127.0.0.1:%"PRIu16,
+                                    ntohs(sin.sin_port));
+        fpv->fd = fd;
+    } else {
+        abort();
+    }
+
+    /* Listen. */
+    if (listen(fpv->fd, 0) < 0) {
+        ovs_fatal(errno, "%s: listen failed", fpv->vconn_name);
+    }
+}
+
+static int
+fpv_accept(struct fake_pvconn *fpv)
+{
+    int fd;
+
+    fd = accept(fpv->fd, NULL, NULL);
+    if (fd < 0) {
+        ovs_fatal(errno, "%s: accept failed", fpv->pvconn_name);
+    }
+    return fd;
+}
+
+static void
+fpv_close(struct fake_pvconn *fpv)
+{
+    if (fpv->fd >= 0) {
+        if (close(fpv->fd) < 0) {
+            ovs_fatal(errno, "failed to close %s fake pvconn", fpv->type);
+        }
+        fpv->fd = -1;
+    }
+}
+
+static void
+fpv_destroy(struct fake_pvconn *fpv)
+{
+    fpv_close(fpv);
+    free(fpv->pvconn_name);
+    free(fpv->vconn_name);
+}
+
+/* Connects to a fake_pvconn with vconn_open(), then closes the listener and
+ * verifies that vconn_connect() reports 'expected_error'. */
+static void
+test_refuse_connection(const char *type, int expected_error)
+{
+    struct fake_pvconn fpv;
+    struct vconn *vconn;
+
+    fpv_create(type, &fpv);
+    assert(!vconn_open(fpv.vconn_name, OFP_VERSION, &vconn));
+    fpv_close(&fpv);
+    assert(vconn_connect(vconn) == expected_error);
+    vconn_close(vconn);
+    fpv_destroy(&fpv);
+}
+
+/* Connects to a fake_pvconn with vconn_open(), accepts that connection and
+ * closes it immediately, and verifies that vconn_connect() reports
+ * 'expected_error'. */
+static void
+test_accept_then_close(const char *type, int expected_error)
+{
+    struct fake_pvconn fpv;
+    struct vconn *vconn;
+
+    fpv_create(type, &fpv);
+    assert(!vconn_open(fpv.vconn_name, OFP_VERSION, &vconn));
+    close(fpv_accept(&fpv));
+    fpv_close(&fpv);
+    assert(vconn_connect(vconn) == expected_error);
+    vconn_close(vconn);
+    fpv_destroy(&fpv);
+}
+
+/* Connects to a fake_pvconn with vconn_open(), accepts that connection and
+ * reads the hello message from it, then closes the connection and verifies
+ * that vconn_connect() reports 'expected_error'. */
+static void
+test_read_hello(const char *type, int expected_error)
+{
+    struct fake_pvconn fpv;
+    struct vconn *vconn;
+    int fd;
+
+    fpv_create(type, &fpv);
+    assert(!vconn_open(fpv.vconn_name, OFP_VERSION, &vconn));
+    fd = fpv_accept(&fpv);
+    fpv_destroy(&fpv);
+    assert(!set_nonblocking(fd));
+    for (;;) {
+       struct ofp_header hello;
+       int retval;
+
+       retval = read(fd, &hello, sizeof hello);
+       if (retval == sizeof hello) {
+           assert(hello.version == OFP_VERSION);
+           assert(hello.type == OFPT_HELLO);
+           assert(hello.length == htons(sizeof hello));
+           break;
+       } else {
+           assert(errno == EAGAIN);
+       }
+
+       assert(vconn_connect(vconn) == EAGAIN);
+       vconn_connect_wait(vconn);
+       poll_fd_wait(fd, POLLIN);
+       poll_block();
+    }
+    close(fd);
+    assert(vconn_connect(vconn) == expected_error);
+    vconn_close(vconn);
+}
+
+/* Connects to a fake_pvconn with vconn_open(), accepts that connection and
+ * sends the 'out' bytes in 'out_size' to it (presumably an OFPT_HELLO
+ * message), then verifies that vconn_connect() reports
+ * 'expect_connect_error'. */
+static void
+test_send_hello(const char *type, const void *out, size_t out_size,
+                int expect_connect_error)
+{
+    struct fake_pvconn fpv;
+    struct vconn *vconn;
+    bool read_hello, connected;
+    struct ofpbuf *msg;
+    int fd;
+
+    fpv_create(type, &fpv);
+    assert(!vconn_open(fpv.vconn_name, OFP_VERSION, &vconn));
+    fd = fpv_accept(&fpv);
+    fpv_destroy(&fpv);
+
+    write(fd, out, out_size);
+
+    assert(!set_nonblocking(fd));
+
+    read_hello = connected = false;
+    for (;;) {
+       if (!read_hello) {
+           struct ofp_header hello;
+           int retval = read(fd, &hello, sizeof hello);
+           if (retval == sizeof hello) {
+               assert(hello.version == OFP_VERSION);
+               assert(hello.type == OFPT_HELLO);
+               assert(hello.length == htons(sizeof hello));
+               read_hello = true;
+           } else {
+               assert(errno == EAGAIN);
+           }
+       }
+
+       if (!connected) {
+           int error = vconn_connect(vconn);
+           if (error == expect_connect_error) {
+               if (!error) {
+                   connected = true;
+               } else {
+                   close(fd);
+                   vconn_close(vconn);
+                   return;
+               }
+           } else {
+               assert(error == EAGAIN);
+           }
+       }
+
+       if (read_hello && connected) {
+           break;
+       }
+
+       if (!connected) {
+           vconn_connect_wait(vconn);
+       }
+       if (!read_hello) {
+           poll_fd_wait(fd, POLLIN);
+       }
+       poll_block();
+    }
+    close(fd);
+    assert(vconn_recv(vconn, &msg) == EOF);
+    vconn_close(vconn);
+}
+
+/* Try connecting and sending a normal hello, which should succeed. */
+static void
+test_send_plain_hello(const char *type)
+{
+    struct ofp_header hello;
+
+    hello.version = OFP_VERSION;
+    hello.type = OFPT_HELLO;
+    hello.length = htons(sizeof hello);
+    hello.xid = htonl(0x12345678);
+    test_send_hello(type, &hello, sizeof hello, 0);
+}
+
+/* Try connecting and sending an extra-long hello, which should succeed (since
+ * the specification says that implementations must accept and ignore extra
+ * data). */
+static void
+test_send_long_hello(const char *type)
+{
+    struct ofp_header hello;
+    char buffer[sizeof hello * 2];
+
+    hello.version = OFP_VERSION;
+    hello.type = OFPT_HELLO;
+    hello.length = htons(sizeof buffer);
+    hello.xid = htonl(0x12345678);
+    memset(buffer, 0, sizeof buffer);
+    memcpy(buffer, &hello, sizeof hello);
+    test_send_hello(type, buffer, sizeof buffer, 0);
+}
+
+/* Try connecting and sending an echo request instead of a hello, which should
+ * fail with EPROTO. */
+static void
+test_send_echo_hello(const char *type)
+{
+    struct ofp_header echo;
+
+    echo.version = OFP_VERSION;
+    echo.type = OFPT_ECHO_REQUEST;
+    echo.length = htons(sizeof echo);
+    echo.xid = htonl(0x89abcdef);
+    test_send_hello(type, &echo, sizeof echo, EPROTO);
+}
+
+/* Try connecting and sending a hello packet that has its length field as 0,
+ * which should fail with EPROTO. */
+static void
+test_send_short_hello(const char *type)
+{
+    struct ofp_header hello;
+
+    memset(&hello, 0, sizeof hello);
+    test_send_hello(type, &hello, sizeof hello, EPROTO);
+}
+
+/* Try connecting and sending a hello packet that has a bad version, which
+ * should fail with EPROTO. */
+static void
+test_send_invalid_version_hello(const char *type)
+{
+    struct ofp_header hello;
+
+    hello.version = OFP_VERSION - 1;
+    hello.type = OFPT_HELLO;
+    hello.length = htons(sizeof hello);
+    hello.xid = htonl(0x12345678);
+    test_send_hello(type, &hello, sizeof hello, EPROTO);
+}
+
+int
+main(int argc UNUSED, char *argv[])
+{
+    set_program_name(argv[0]);
+    time_init();
+    vlog_init();
+    signal(SIGPIPE, SIG_IGN);
+    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_EMER);
+
+    time_alarm(10);
+
+    test_refuse_connection("unix", EPIPE);
+    test_refuse_connection("tcp", ECONNRESET);
+
+    test_accept_then_close("unix", EPIPE);
+    test_accept_then_close("tcp", ECONNRESET);
+
+    test_read_hello("unix", ECONNRESET);
+    test_read_hello("tcp", ECONNRESET);
+
+    test_send_plain_hello("unix");
+    test_send_plain_hello("tcp");
+
+    test_send_long_hello("unix");
+    test_send_long_hello("tcp");
+
+    test_send_echo_hello("unix");
+    test_send_echo_hello("tcp");
+
+    test_send_short_hello("unix");
+    test_send_short_hello("tcp");
+
+    test_send_invalid_version_hello("unix");
+    test_send_invalid_version_hello("tcp");
+
+    return 0;
+}
index 31c7a86..380ddec 100644 (file)
@@ -16,16 +16,22 @@ protocol, causing them to function as L2 MAC-learning switches or hub.
 one or more of the following OpenFlow connection methods:
 
 .TP
-\fBpssl:\fR[\fIport\fR]
+\fBpssl:\fR[\fIport\fR][\fB:\fIip\fR]
 Listens for SSL connections from remote OpenFlow switches on
 \fIport\fR (default: 6633).  The \fB--private-key\fR,
 \fB--certificate\fR, and \fB--ca-cert\fR options are mandatory when
 this form is used.
+By default, \fB\*(PN\fR listens for connections to any local IP
+address, but \fIip\fR may be specified to listen only for connections
+to the given \fIip\fR.
 
 .TP
-\fBptcp:\fR[\fIport\fR]
+\fBptcp:\fR[\fIport\fR][\fB:\fIip\fR]
 Listens for TCP connections from remote OpenFlow switches on
 \fIport\fR (default: 6633).
+By default, \fB\*(PN\fR listens for connections to any local IP
+address, but \fIip\fR may be specified to listen only for connections
+to the given \fIip\fR.
 
 .TP
 \fBpunix:\fIfile\fR
index d38ce9e..eb83a5f 100644 (file)
@@ -28,15 +28,16 @@ itself to the background.
 .SH OPTIONS
 .TP
 \fB--accept-vconn=\fIregex\fR
-By default, \fBovs\-discover\fR accepts any controller location
-advertised over DHCP.  With this option, only controllers whose names
-match POSIX extended regular expression \fIregex\fR will be accepted.
-Specifying \fBssl:.*\fR for \fIregex\fR, for example, would cause only
-SSL controller connections to be accepted.
+With this option, only controllers whose names match POSIX extended
+regular expression \fIregex\fR will be accepted.  Specifying
+\fBssl:.*\fR for \fIregex\fR, for example, would cause only SSL
+controller connections to be accepted.
 
 The \fIregex\fR is implicitly anchored at the beginning of the
 controller location string, as if it begins with \fB^\fR.
 
+When this option is not given, the default \fIregex\fR is
+\fBtcp:.*\fR.
 .TP
 \fB--exit-without-bind\fR
 By default, \fBovs\-discover\fR binds the network device that receives
index 0474105..8c83cac 100644 (file)
@@ -48,7 +48,7 @@ static int n_ifaces;
 
 /* --accept-vconn: Regular expression specifying the class of controller vconns
  * that we will accept during autodiscovery. */
-static const char *accept_controller_re = ".*";
+static const char *accept_controller_re = "tcp:.*";
 static regex_t accept_controller_regex;
 
 /* --exit-without-bind: Exit after discovering the controller, without binding
index 3a9c305..eb98043 100644 (file)
@@ -1,4 +1,4 @@
-.TH ovs\-ofctl 8 "March 2009" "Open vSwitch" "Open vSwitch Manual"
+.TH ovs\-ofctl 8 "June 2009" "Open vSwitch" "Open vSwitch Manual"
 .ds PN ovs\-ofctl
 
 .SH NAME
@@ -224,8 +224,8 @@ Matches physical port \fIport_no\fR.  Switch ports are numbered as
 displayed by \fBovs\-ofctl show\fR.
 
 .IP \fBdl_vlan=\fIvlan\fR
-Matches IEEE 802.1q virtual LAN tag \fIvlan\fR.  Specify \fB0xffff\fR
-as \fIvlan\fR to match packets that are not tagged with a virtual LAN;
+Matches IEEE 802.1q Virtual LAN tag \fIvlan\fR.  Specify \fB0xffff\fR
+as \fIvlan\fR to match packets that are not tagged with a Virtual LAN;
 otherwise, specify a number between 0 and 4095, inclusive, as the
 12-bit VLAN ID to match.
 
index 28e55ba..2585a20 100644 (file)
@@ -1,16 +1,16 @@
-.TH ovs\-vswitchd 8 "March 2009" "Open vSwitch" "OpenVSwitch Manual"
+.TH ovs\-vswitchd 8 "June 2009" "Open vSwitch" "Open vSwitch Manual"
 .ds PN ovs\-vswitchd
 .
 .SH NAME
-ovs\-vswitchd \- virtual switch daemon
+ovs\-vswitchd \- Open vSwitch daemon
 .
 .SH SYNOPSIS
 .B ovs\-vswitchd
 \fIconfig\fR
 .
 .SH DESCRIPTION
-A daemon that manages and controls any number of virtual switches on
-the local machine.
+A daemon that manages and controls any number of Open vSwitch switches 
+on the local machine.
 .PP
 The mandatory \fIconfig\fR argument specifies a configuration file.
 For a description of \fBovs\-vswitchd\fR configuration syntax, see
@@ -22,8 +22,8 @@ operates switching across each bridge described in its configuration
 files.  If a logfile was specified on the command line it will also 
 be opened or reopened.
 .PP
-\fBovs\-vswitchd\fR virtual switches may be configured with any of the
-following features:
+\fBovs\-vswitchd\fR switches may be configured with any of the following 
+features:
 .
 .IP \(bu
 L2 switching with MAC learning.
@@ -46,10 +46,10 @@ Connectivity to an external OpenFlow controller, such as NOX.
 .
 .PP
 Only a single instance of \fBovs\-vswitchd\fR is intended to run at a time.
-A single \fBovs\-vswitchd\fR can manage any number of virtual switches, up
+A single \fBovs\-vswitchd\fR can manage any number of switch instances, up
 to the maximum number of supported Open vSwitch datapaths.
 .PP
-\fBovs\-vswitchd\fR does all the necessary management of OpenVSwitch datapaths
+\fBovs\-vswitchd\fR does all the necessary management of Open vSwitch datapaths
 itself.  Thus, external tools, such \fBovs\-dpctl\fR(8), are not needed for
 managing datapaths in conjunction with \fBovs\-vswitchd\fR, and their use
 to modify datapaths when \fBovs\-vswitchd\fR is running can interfere with
index 8c87fea..e95ee0a 100644 (file)
@@ -230,7 +230,7 @@ parse_options(int argc, char *argv[])
 static void
 usage(void)
 {
-    printf("%s: virtual switch daemon\n"
+    printf("%s: Open vSwitch daemon\n"
            "usage: %s [OPTIONS] CONFIG\n"
            "CONFIG is a configuration file in ovs-vswitchd.conf(5) format.\n",
            program_name, program_name);
index 81e007f..00a0d1e 100644 (file)
 .  RE
 .  PP
 ..
-.TH ovs\-vswitchd.conf 5 "April 2009" "Open vSwitch" "OpenVSwitch Manual"
+.TH ovs\-vswitchd.conf 5 "June 2009" "Open vSwitch" "Open vSwitch Manual"
 .
 .SH NAME
 ovs\-vswitchd.conf \- configuration file for \fBovs\-vswitchd\fR
 .
 .SH DESCRIPTION
 This manual page describes the syntax for the configuration file used 
-by \fBovs\-vswitchd\fR(8), the virtual switch daemon.
+by \fBovs\-vswitchd\fR(8), the Open vSwitch daemon.
 .PP
 The configuration file is based on key-value pairs, which are given
 one per line in the form \fIkey\fB=\fIvalue\fR.  Each \fIkey\fR
@@ -56,8 +56,8 @@ with \fBdp\fR or \fBnl:\fR followed by a digit.)
 The names given on \fBbridge.\fIname\fB.port\fR must be the names of
 existing network devices, except for ``internal ports.''  An internal
 port is a simulated network device that receives traffic only
-through the virtual switch and switches any traffic sent it through
-virtual switch.  An internal port may configured with an IP address,
+through the switch and switches any traffic sent it through the
+switch.  An internal port may configured with an IP address,
 etc. using the usual system tools (e.g. \fBifconfig\fR, \fBip\fR).  To
 designate network device \fInetdev\fR as an internal port, add
 \fBiface.\fInetdev\fB.internal=true\fR to the configuration file.
@@ -322,7 +322,7 @@ This can be overridden with the \fBnetflow.\fIbridge\fB.engine-type\fR and
 \fBnetflow.\fIbridge\fB.engine-id\fR, respectively.  Each takes a value
 between 0 and 255, inclusive. 
 
-Many NetFlow collectors do not expect multiple virtual switches to be
+Many NetFlow collectors do not expect multiple switches to be
 sending messages from the same host, and they do not store the engine
 information which could be used to disambiguate the traffic.  To prevent
 flows from multiple switches appearing as if they came on the interface,
@@ -410,8 +410,8 @@ the regular expression will be accepted.
 .IP
 The default regular expression is \fBssl:.*\fR, meaning that only SSL
 controller connections will be accepted, when SSL is configured (see
-\fBSSL Configuration\fR), and \fB.*\fR otherwise, meaning that any
-controller will be accepted.
+\fBSSL Configuration\fR), and \fBtcp:.*\fR otherwise, meaning that only
+TCP controller connections will be accepted.
 .IP
 The regular expression is implicitly anchored at the beginning of the
 controller location string, as if it begins with \fB^\fR.
@@ -473,7 +473,7 @@ This optional setting may be set to \fIsecs\fR, a number of seconds.
 The minimum value of \fIsecs\fR is 5 seconds.  The default is taken
 from \fBmgmt.inactivity-probe\fR (see above).
 .IP
-When the virtual switch is connected to the controller, it waits for a
+When the switch is connected to the controller, it waits for a
 message to be received from the controller for \fIsecs\fR seconds
 before it sends a inactivity probe to the controller.  After sending
 the inactivity probe, if no response is received for an additional
@@ -485,7 +485,7 @@ before entering standalone mode (see below).
 .IP "\fBbridge.\fIname\fB.controller.fail-mode=\fBstandalone\fR|\fBsecure\fR"
 .IQ "\fBmgmt.fail-mode=standalone\fR|\fBsecure\fR"
 When a controller is configured, it is, ordinarily, responsible for
-setting up all flows on the virtual switch.  Thus, if the connection to
+setting up all flows on the switch.  Thus, if the connection to
 the controller fails, no new network connections can be set up.  If
 the connection to the controller stays down long enough, no packets
 can pass through the switch at all.
@@ -510,7 +510,7 @@ connection attempts starts at 1 second and doubles on each failing
 attempt until it reaches the maximum.  The default maximum backoff
 time is taken from \fBmgmt.max-backoff\fR.
 .ST "Controller Rate-Limiting"
-These settings configure how the virtual switch applies a ``token
+These settings configure how the switch applies a ``token
 bucket'' to limit the rate at which packets in unknown flows are
 forwarded to the OpenFlow controller for flow-setup processing.  This
 feature prevents a single bridge from overwhelming a controller.
@@ -563,24 +563,23 @@ When \fBovs\-vswitchd\fR is configured to connect over SSL for management or
 for controller connectivity, the following settings are required:
 .TP
 \fBssl.private-key=\fIprivkey.pem\fR
-Specifies a PEM file containing the private key used as the virtual
+Specifies a PEM file containing the private key used as the 
 switch's identity for SSL connections to the controller.
 .TP
 \fBssl.certificate=\fIcert.pem\fR
 Specifies a PEM file containing a certificate, signed by the
 certificate authority (CA) used by the controller and manager, that
-certifies the virtual switch's private key, identifying a trustworthy
+certifies the switch's private key, identifying a trustworthy
 switch.
 .TP
 \fBssl.ca-cert=\fIcacert.pem\fR
 Specifies a PEM file containing the CA certificate used to verify that
-the virtual switch is connected to a trustworthy controller.
+the switch is connected to a trustworthy controller.
 .PP
 These files are read only once, at \fBovs\-vswitchd\fR startup time.  If
 their contents change, \fBovs\-vswitchd\fR must be killed and restarted.
 .PP
-These SSL settings apply to all SSL connections made by the virtual
-switch.
+These SSL settings apply to all SSL connections made by the switch.
 .ST "CA Certificate Bootstrap"
 Ordinarily, all of the files named in the SSL configuration must exist
 when \fBovs\-vswitchd\fR starts.  However, if \fBssl.bootstrap-ca-cert\fR
@@ -618,8 +617,11 @@ Listens for connections on the Unix domain server socket named \fIfile\fR.
 Listens for SSL connections on \fIport\fR (default: 6633).  SSL must
 be configured when this form is used (see \fBSSL Configuration\fR,
 above).
-.IP "\fBptcp:\fR[\fIport\fR]"
+.IP "\fBptcp:\fR[\fIport\fR][\fB:\fIip\fR]"
 Listens for TCP connections on \fIport\fR (default: 6633).
+By default, \fB\ovs\-vswitchd\fR listens for connections to any local
+IP address, but \fIip\fR may be specified to limit connections to the
+specified local \fIip\fR.
 .RE
 To entirely disable listening for management connections, set
 \fBbridge.\fIname\fB.openflow.listeners\fR to the single value
index d95d616..e660027 100644 (file)
@@ -84,6 +84,7 @@ rm -rf \
     $RPM_BUILD_ROOT/root/vswitch/bin/ovs-switchui \
     $RPM_BUILD_ROOT/root/vswitch/bin/ovs-wdt \
     $RPM_BUILD_ROOT/root/vswitch/bin/secchan \
+    $RPM_BUILD_ROOT/root/vswitch/kernel_modules/veth_mod.ko \
     $RPM_BUILD_ROOT/root/vswitch/sbin/ovs-monitor \
     $RPM_BUILD_ROOT/root/vswitch/share/man/man8/ovs-controller.8 \
     $RPM_BUILD_ROOT/root/vswitch/share/man/man8/ovs-discover.8 \
@@ -287,7 +288,6 @@ fi
 /etc/profile.d/vswitch.sh
 /root/vswitch/kernel_modules/brcompat_mod.ko
 /root/vswitch/kernel_modules/openvswitch_mod.ko
-/root/vswitch/kernel_modules/veth_mod.ko
 /root/vswitch/scripts/dump-vif-details
 /root/vswitch/scripts/interface-reconfigure
 /root/vswitch/scripts/vif