From 9d0a40120f9f71ed9ddf32d37d1b03b0fd7f4703 Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Tue, 12 Mar 2024 22:04:11 +0800 Subject: [PATCH] ofproto-dpif: Fix tunnel with different name del/add failure. Reproduce: ovs-vsctl add-port br-int p0 \ -- set interface p0 type=vxlan options:remote_ip=10.10.10.1 sleep 2 ovs-vsctl --if-exists del-port p0 \ -- add-port br-int p1 \ -- set interface p1 type=vxlan options:remote_ip=10.10.10.1 ovs-vsctl: Error detected while setting up 'p1': could not add network device p1 to ofproto (File exists). vswitchd log: bridge|INFO|bridge br-int: added interface p0 on port 1106 bridge|INFO|bridge br-int: deleted interface p0 on port 1106 tunnel|WARN|p1: attempting to add tunnel port with same config as port 'p0' (::->10.10.10.1, key=0, legacy_l2, dp port=122) ofproto|WARN|br-int: could not add port p1 (File exists) bridge|WARN|could not add network device p1 to ofproto (File exists) CallTrace: bridge_reconfigure bridge_del_ports port_destroy iface_destroy__ netdev_remove <------ netdev p0 removed bridge_delete_or_reconfigure_ports OFPROTO_PORT_FOR_EACH ofproto_port_dump_next port_dump_next port_query_by_name <------ netdev_shash do not contain p0 ofproto_port_del <------ p0 do not del in ofproto bridge_add_ports bridge_add_ports__ iface_create iface_do_create ofproto_port_add <------ p1 add failed Fixes: fe83f81df977 ("netdev: Remove netdev from global shash when the user is changing interface configuration.") Acked-by: Han Zhou Tested-by: Han Zhou Signed-off-by: Tao Liu Signed-off-by: Ilya Maximets --- ofproto/ofproto-dpif.c | 18 ++++++++++++------ tests/tunnel.at | 12 ++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index f59d69c4d1e..fe034f9717b 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -3904,15 +3904,21 @@ port_query_by_name(const struct ofproto *ofproto_, const char *devname, int error; if (sset_contains(&ofproto->ghost_ports, devname)) { - const char *type = netdev_get_type_from_name(devname); - /* We may be called before ofproto->up.port_by_name is populated with * the appropriate ofport. For this reason, we must get the name and - * type from the netdev layer directly. */ - if (type) { - const struct ofport *ofport; + * type from the netdev layer directly. + * However, when a port deleted, the corresponding netdev is also + * removed from netdev_shash. netdev_get_type_from_name returns NULL + * in such case and we should try to get type from ofport->netdev. */ + const char *type = netdev_get_type_from_name(devname); + const struct ofport *ofport = + shash_find_data(&ofproto->up.port_by_name, devname); - ofport = shash_find_data(&ofproto->up.port_by_name, devname); + if (!type && ofport && ofport->netdev) { + type = netdev_get_type(ofport->netdev); + } + + if (type) { ofproto_port->ofp_port = ofport ? ofport->ofp_port : OFPP_NONE; ofproto_port->name = xstrdup(devname); ofproto_port->type = xstrdup(type); diff --git a/tests/tunnel.at b/tests/tunnel.at index 71e7c2df4ea..9d539ee6f67 100644 --- a/tests/tunnel.at +++ b/tests/tunnel.at @@ -1269,6 +1269,18 @@ OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) OVS_APP_EXIT_AND_WAIT([ovsdb-server])] AT_CLEANUP +AT_SETUP([tunnel - re-create port with different name]) +OVS_VSWITCHD_START( + [add-port br0 p0 -- set int p0 type=vxlan options:remote_ip=10.10.10.1]) + +AT_CHECK([ovs-vsctl --if-exists del-port p0 -- \ + add-port br0 p1 -- \ + set int p1 type=vxlan options:remote_ip=10.10.10.1]) + +OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) +OVS_APP_EXIT_AND_WAIT([ovsdb-server])] +AT_CLEANUP + AT_SETUP([tunnel - SRV6 basic]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy \ ofport_request=1 \