tnl-ports: Fix loss of tunneling upon removal of a single tunnel port.
When OVS had multiple tunnel ports of a single kind, and any one of them
was removed, the remaining ports could no longer receive traffic.  This
fixes the problem.
@@ -51,6 +51,7 @@ static struct ovs_list addr_list;
struct tnl_port {
odp_port_t port;
+ struct ovs_refcount ref_cnt;
ovs_be16 tp_port;
uint8_t nw_proto;
char dev_name[IFNAMSIZ];
@@ -195,6 +196,7 @@ tnl_port_map_insert(odp_port_t port, ovs_be16 tp_port,
ovs_mutex_lock(&mutex);
LIST_FOR_EACH(p, node, &port_list) {
if (tp_port == p->tp_port && p->nw_proto == nw_proto) {
+ ovs_refcount_ref(&p->ref_cnt);
goto out;
}
}
@@ -204,6 +206,7 @@ tnl_port_map_insert(odp_port_t port, ovs_be16 tp_port,
p->tp_port = tp_port;
p->nw_proto = nw_proto;
ovs_strlcpy(p->dev_name, dev_name, sizeof p->dev_name);
+ ovs_refcount_init(&p->ref_cnt);
ovs_list_insert(&port_list, &p->node);
LIST_FOR_EACH(ip_dev, node, &addr_list) {
@@ -256,29 +259,22 @@ tnl_port_map_delete(ovs_be16 tp_port, const char type[])
{
struct tnl_port *p, *next;
struct ip_device *ip_dev;
- bool found = false;
uint8_t nw_proto;
nw_proto = tnl_type_to_nw_proto(type);
ovs_mutex_lock(&mutex);
LIST_FOR_EACH_SAFE(p, next, node, &port_list) {
- if (p->tp_port == tp_port && p->nw_proto == nw_proto) {
+ if (p->tp_port == tp_port && p->nw_proto == nw_proto &&
+ ovs_refcount_unref_relaxed(&p->ref_cnt) == 1) {
ovs_list_remove(&p->node);
- found = true;
- break;
- }
- }
-
- if (!found) {
- goto out;
- }
LIST_FOR_EACH(ip_dev, node, &addr_list) {
ipdev_map_delete(ip_dev, p->tp_port, p->nw_proto);
}
-
free(p);
-out:
+ break;
+ }
+ }
ovs_mutex_unlock(&mutex);
}
