[ovs-dev] [PATCH] ofproto: Detect and handle errors in ofproto_port_add().

Ben Pfaff blp at ovn.org
Wed Feb 3 02:13:32 UTC 2016


The update_port() function called in ofproto_port_add() can encounter
errors that prevent a port from being added, but nothing was checking for
the error and in fact update_port() didn't even pass the error along to
its caller.  This commit fixes the problem.

The scenario that led me to examine this code can be triggered as follows
from the sandbox, as long as you change --enable-dummy=override to
--enable-dummy=system in ovs-sandbox:

ovs-vsctl add-br br0
ovs-vsctl add-port br0 tun0 \
    -- set interface tun0 type=stt options:remote_ip=1.2.3.4
ovs-vsctl add-port br0 tun1 \
    -- set interface tun1 type=stt options:remote_ip=1.2.3.4

The second add-port will fail due to the duplicate tunnel options, but
ofproto_port_add() will not return the error.  Instead, it will report to
the caller that it succeeded and tell it that it has ofp_port OFPP_NONE
(65535), which is invalid and it obviously does not.  The result is that
you get bizarre log messages like this:

    tunnel|WARN|tun1: attempting to add tunnel port with same config as port 'tun0' (::->1.2.3.4, key=0, dp port=7471, pkt mark=0)
    ofproto|WARN|br0: could not add port tun1 (File exists)
    bridge|INFO|bridge br0: added interface tun1 on port 65535
    ofproto|WARN|br0: cannot configure bfd on nonexistent port 65535
    ofproto|WARN|br0: cannot configure LLDP on nonexistent port 65535
    ofproto|WARN|br0: cannot get STP status on nonexistent port 65535
    ofproto|WARN|br0: cannot get RSTP status on nonexistent port 65535
    ofproto|WARN|br0: cannot get STP stats on nonexistent port 65535
    ofproto|WARN|br0: cannot get STP stats on nonexistent port 65535

VMware-BZ: #1598643
Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 ofproto/ofproto.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 3faf42a..bba30ae 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -219,7 +219,7 @@ static void learned_cookies_flush(struct ofproto *, struct ovs_list *dead_cookie
 static void ofport_destroy__(struct ofport *) OVS_EXCLUDED(ofproto_mutex);
 static void ofport_destroy(struct ofport *);
 
-static void update_port(struct ofproto *, const char *devname);
+static int update_port(struct ofproto *, const char *devname);
 static int init_ports(struct ofproto *);
 static void reinit_ports(struct ofproto *);
 
@@ -1962,7 +1962,7 @@ ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
 
         simap_put(&ofproto->ofp_requests, netdev_name,
                   ofp_to_u16(ofp_port));
-        update_port(ofproto, netdev_name);
+        error = update_port(ofproto, netdev_name);
     }
     if (ofp_portp) {
         *ofp_portp = OFPP_NONE;
@@ -2346,7 +2346,7 @@ ofport_equal(const struct ofputil_phy_port *a,
 /* Adds an ofport to 'p' initialized based on the given 'netdev' and 'opp'.
  * The caller must ensure that 'p' does not have a conflicting ofport (that is,
  * one with the same name or port number). */
-static void
+static int
 ofport_install(struct ofproto *p,
                struct netdev *netdev, const struct ofputil_phy_port *pp)
 {
@@ -2380,7 +2380,7 @@ ofport_install(struct ofproto *p,
         goto error;
     }
     connmgr_send_port_status(p->connmgr, NULL, pp, OFPPR_ADD);
-    return;
+    return 0;
 
 error:
     VLOG_WARN_RL(&rl, "%s: could not add port %s (%s)",
@@ -2390,6 +2390,7 @@ error:
     } else {
         netdev_close(netdev);
     }
+    return error;
 }
 
 /* Removes 'ofport' from 'p' and destroys it. */
@@ -2571,13 +2572,14 @@ ofproto_port_get_stats(const struct ofport *port, struct netdev_stats *stats)
     return error;
 }
 
-static void
+static int
 update_port(struct ofproto *ofproto, const char *name)
 {
     struct ofproto_port ofproto_port;
     struct ofputil_phy_port pp;
     struct netdev *netdev;
     struct ofport *port;
+    int error = 0;
 
     COVERAGE_INC(ofproto_update_port);
 
@@ -2617,13 +2619,15 @@ update_port(struct ofproto *ofproto, const char *name)
                 ofport_remove(port);
             }
             ofport_remove_with_name(ofproto, name);
-            ofport_install(ofproto, netdev, &pp);
+            error = ofport_install(ofproto, netdev, &pp);
         }
     } else {
         /* Any port named 'name' is gone now. */
         ofport_remove_with_name(ofproto, name);
     }
     ofproto_port_destroy(&ofproto_port);
+
+    return error;
 }
 
 static int
-- 
2.1.3




More information about the dev mailing list