From 01c77073147d934a85b23bba11794d3ae9f5b989 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 2 Feb 2016 17:57:46 -0800 Subject: [PATCH] ofproto: Detect and handle errors in ofproto_port_add(). 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 Acked-by: Justin Pettit --- ofproto/ofproto.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 3faf42ac8..bba30ae16 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.20.1