summaryrefslogtreecommitdiff
path: root/lib/netdev.c
diff options
context:
space:
mode:
authorAshish Varma <ashishvarma.ovs@gmail.com>2017-11-06 12:17:45 -0800
committerBen Pfaff <blp@ovn.org>2017-11-13 11:05:31 -0800
commit97459c2f011341d6f8376b84af52dd34fed629ba (patch)
tree1595c02c653b027a659d163c11c1a38d7f6e2085 /lib/netdev.c
parentb4027b17e890915472d568619ea9f3ae675d4ac8 (diff)
downloadopenvswitch-97459c2f011341d6f8376b84af52dd34fed629ba.tar.gz
netdev, dpif: fix the crash/assert on port delete
a crash is seen in "netdev_ports_remove" when an interface is deleted and added back in the system and when the interface is part of a bridge configuration. e.g. steps: create a tap0 interface using "ip tuntap add.." add the tap0 interface to br0 using "ovs-vsctl add-port.." delete the tap0 interface from system using "ip tuntap del.." add the tap0 interface back in system using "ip tuntap add.." (this changes the ifindex of the interface) delete tap0 from br0 using "ovs-vsctl del-port.." In the function "netdev_ports_insert", two hmap entries were created for mapping "portnum -> netdev" and "ifindex -> portnum". When the interface is deleted from the system, the "netdev_ports_remove" function is not getting called and the old ifindex entry is not getting cleaned up from the "ifindex_to_port" hmap. As part of the fix, added function "dpif_port_remove" which will call "netdev_ports_remove" in the path where the interface deletion from the system is detected. Also, in "netdev_ports_remove", added the code where the "ifindex_to_port_data" (ifindex -> portnum map node) is getting freed when the ifindex is not available any more. (as the interface is already deleted.) VMware-BZ: #1975788 Signed-off-by: Ashish Varma <ashishvarma.ovs@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib/netdev.c')
-rw-r--r--lib/netdev.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/lib/netdev.c b/lib/netdev.c
index 3c6fbfa34..0c1545a83 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -2176,6 +2176,7 @@ struct ifindex_to_port_data {
struct hmap_node node;
int ifindex;
odp_port_t port;
+ const struct dpif_class *dpif_class;
};
#define NETDEV_PORTS_HASH_INT(port, dpif) \
@@ -2225,6 +2226,7 @@ netdev_ports_insert(struct netdev *netdev, const struct dpif_class *dpif_class,
ifidx = xzalloc(sizeof *ifidx);
ifidx->ifindex = ifindex;
ifidx->port = dpif_port->port_no;
+ ifidx->dpif_class = dpif_class;
hmap_insert(&port_to_netdev, &data->node, hash);
hmap_insert(&ifindex_to_port, &ifidx->node, ifidx->ifindex);
@@ -2263,10 +2265,9 @@ netdev_ports_remove(odp_port_t port_no, const struct dpif_class *dpif_class)
if (data) {
int ifindex = netdev_get_ifindex(data->netdev);
+ struct ifindex_to_port_data *ifidx = NULL;
if (ifindex > 0) {
- struct ifindex_to_port_data *ifidx = NULL;
-
HMAP_FOR_EACH_WITH_HASH (ifidx, node, ifindex, &ifindex_to_port) {
if (ifidx->port == port_no) {
hmap_remove(&ifindex_to_port, &ifidx->node);
@@ -2276,11 +2277,18 @@ netdev_ports_remove(odp_port_t port_no, const struct dpif_class *dpif_class)
}
ovs_assert(ifidx);
} else {
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
-
- VLOG_WARN_RL(&rl, "netdev ports map has dpif port %"PRIu32
- " but netdev has no ifindex: %s", port_no,
- ovs_strerror(ifindex));
+ /* case where the interface is already deleted form the datapath
+ * (e.g. tunctl -d or ip tuntap del), then the ifindex is not
+ * valid anymore. Traverse the HMAP for the port number. */
+ HMAP_FOR_EACH (ifidx, node, &ifindex_to_port) {
+ if (ifidx->port == port_no &&
+ ifidx->dpif_class == dpif_class) {
+ hmap_remove(&ifindex_to_port, &ifidx->node);
+ free(ifidx);
+ break;
+ }
+ }
+ ovs_assert(ifidx);
}
dpif_port_destroy(&data->dpif_port);