Skip to content

Commit 425f699

Browse files
simonartxavierdceara
authored andcommitted
controller: fixed potential segfault when changing tunnel_key and deleting ls.
When a tunnel_key for a datapath was changed, the local_datapaths hmap was not properly updated as the old/initial entry was not removed. - If the datapath was not deleted at the same time, a new entry (for the same dp) was created in the local_datapaths as the previous entry was not found (wrong hash). - If the datapath was deleted at the same time, the former entry also remained (as, again, the hash was wrong). So, we kept a deleted (dp) entry in the hmap, and might crash when we used it later. When tunnel_key is updated for an existing datapath, we now clean the local_datapaths, removing bad entries (i.e entries for which the hash is not the tunnel_key). This issue was identified by flaky failures of test "ovn-ic -- route deletion upon TS deletion". Backtrace: 0 0x0000000000504a9a in hmap_first_with_hash (hmap=0x20f4d90, hmap@entry=0x5d5634, hmap=0x20f4d90, hmap@entry=0x5d5634, hash=1956414673) at ./include/openvswitch/hmap.h:360 1 smap_find__ (smap=smap@entry=0x20f4d90, key=key@entry=0x5d5634 "snat-ct-zone", key_len=key_len@entry=12, hash=1956414673) at lib/smap.c:421 2 0x0000000000505073 in smap_get_node (key=0x5d5634 "snat-ct-zone", smap=0x20f4d90) at lib/smap.c:217 3 smap_get_def (def=0x0, key=0x5d5634 "snat-ct-zone", smap=0x20f4d90) at lib/smap.c:208 4 smap_get (smap=0x20f4d90, key=key@entry=0x5d5634 "snat-ct-zone") at lib/smap.c:200 5 0x0000000000419898 in get_common_nat_zone (ldp=0x20a8c40, ldp=0x20a8c40) at controller/lflow.c:831 6 add_matches_to_flow_table (lflow=lflow@entry=0x21ddf90, ldp=ldp@entry=0x20a8c40, matches=matches@entry=0x211bb50, ptable=ptable@entry=10 '\n', output_ptable=output_ptable@entry=37 '%', ovnacts=ovnacts@entry=0x7ffd19b99de0, ingress=true, l_ctx_in=0x7ffd19b9a300, l_ctx_out=0x7ffd19b9a2c0) at controller/lflow.c:892 7 0x000000000041a29b in consider_logical_flow__ (lflow=lflow@entry=0x21ddf90, dp=0x20eb720, l_ctx_in=l_ctx_in@entry=0x7ffd19b9a300, l_ctx_out=l_ctx_out@entry=0x7ffd19b9a2c0) at controller/lflow.c:1207 8 0x000000000041a587 in consider_logical_flow (lflow=lflow@entry=0x21ddf90, is_recompute=is_recompute@entry=false, l_ctx_in=l_ctx_in@entry=0x7ffd19b9a300, l_ctx_out=l_ctx_out@entry=0x7ffd19b9a2c0) at controller/lflow.c:1276 9 0x000000000041e30f in lflow_handle_changed_flows (l_ctx_in=l_ctx_in@entry=0x7ffd19b9a300, l_ctx_out=l_ctx_out@entry=0x7ffd19b9a2c0) at controller/lflow.c:271 10 0x0000000000439fc7 in lflow_output_sb_logical_flow_handler (node=0x7ffd19ba5b70, data=<optimized out>) at controller/ovn-controller.c:4045 11 0x00000000004682fe in engine_compute (recompute_allowed=<optimized out>, node=<optimized out>) at lib/inc-proc-eng.c:441 12 engine_run_node (recompute_allowed=true, node=0x7ffd19ba5b70) at lib/inc-proc-eng.c:503 13 engine_run (recompute_allowed=recompute_allowed@entry=true) at lib/inc-proc-eng.c:528 14 0x000000000040ade2 in main (argc=<optimized out>, argv=<optimized out>) at controller/ovn-controller.c:5709 Signed-off-by: Xavier Simonart <xsimonar@redhat.com> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
1 parent e3b798b commit 425f699

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

controller/local_data.c

+14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@ static bool datapath_is_transit_switch(const struct sbrec_datapath_binding *);
5656

5757
static uint64_t local_datapath_usage;
5858

59+
/* To be used when hmap_node.hash might be wrong e.g. tunnel_key got updated */
60+
struct local_datapath *
61+
get_local_datapath_no_hash(const struct hmap *local_datapaths,
62+
uint32_t tunnel_key)
63+
{
64+
struct local_datapath *ld;
65+
HMAP_FOR_EACH (ld, hmap_node, local_datapaths) {
66+
if (ld->datapath->tunnel_key == tunnel_key) {
67+
return ld;
68+
}
69+
}
70+
return NULL;
71+
}
72+
5973
struct local_datapath *
6074
get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key)
6175
{

controller/local_data.h

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ struct local_datapath *local_datapath_alloc(
6969
const struct sbrec_datapath_binding *);
7070
struct local_datapath *get_local_datapath(const struct hmap *,
7171
uint32_t tunnel_key);
72+
struct local_datapath *get_local_datapath_no_hash(
73+
const struct hmap *local_datapaths,
74+
uint32_t tunnel_key);
75+
7276
bool
7377
need_add_peer_to_local(
7478
struct ovsdb_idl_index *sbrec_port_binding_by_name,

controller/ovn-controller.c

+23
Original file line numberDiff line numberDiff line change
@@ -1893,13 +1893,36 @@ runtime_data_sb_datapath_binding_handler(struct engine_node *node OVS_UNUSED,
18931893
engine_get_input("SB_datapath_binding", node));
18941894
const struct sbrec_datapath_binding *dp;
18951895
struct ed_type_runtime_data *rt_data = data;
1896+
struct local_datapath *ld;
18961897

18971898
SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (dp, dp_table) {
18981899
if (sbrec_datapath_binding_is_deleted(dp)) {
18991900
if (get_local_datapath(&rt_data->local_datapaths,
19001901
dp->tunnel_key)) {
19011902
return false;
19021903
}
1904+
/* If the tunnel key got updated, get_local_datapath will not find
1905+
* the ld. Use get_local_datapath_no_hash which does not
1906+
* rely on the hash.
1907+
*/
1908+
if (sbrec_datapath_binding_is_updated(
1909+
dp, SBREC_DATAPATH_BINDING_COL_TUNNEL_KEY)) {
1910+
if (get_local_datapath_no_hash(&rt_data->local_datapaths,
1911+
dp->tunnel_key)) {
1912+
return false;
1913+
}
1914+
}
1915+
} else if (sbrec_datapath_binding_is_updated(
1916+
dp, SBREC_DATAPATH_BINDING_COL_TUNNEL_KEY)
1917+
&& !sbrec_datapath_binding_is_new(dp)) {
1918+
/* If the tunnel key is updated, remove the entry (with a wrong
1919+
* hash) from the map. It will be (properly) added back later.
1920+
*/
1921+
if ((ld = get_local_datapath_no_hash(&rt_data->local_datapaths,
1922+
dp->tunnel_key))) {
1923+
hmap_remove(&rt_data->local_datapaths, &ld->hmap_node);
1924+
local_datapath_destroy(ld);
1925+
}
19031926
}
19041927
}
19051928

tests/ovn.at

+43
Original file line numberDiff line numberDiff line change
@@ -37607,3 +37607,46 @@ OVN_CLEANUP([hv1])
3760737607

3760837608
AT_CLEANUP
3760937609
])
37610+
37611+
OVN_FOR_EACH_NORTHD([
37612+
AT_SETUP([Changing tunnel_key])
37613+
ovn_start
37614+
37615+
net_add n1
37616+
37617+
sim_add hv1
37618+
as hv1
37619+
check ovs-vsctl add-br br-phys
37620+
ovn_attach n1 br-phys 192.168.0.11
37621+
37622+
check ovn-nbctl --wait=hv ls-add ls \
37623+
-- lsp-add ls lsp1 \
37624+
-- lsp-add ls ls-lr \
37625+
-- lr-add lr \
37626+
-- lrp-add lr lr-ls f0:00:00:00:00:f1 192.168.1.1/24 \
37627+
-- set Logical_Switch_Port ls-lr \
37628+
type=router \
37629+
options:router-port=lr-ls \
37630+
addresses=router \
37631+
-- lrp-set-gateway-chassis lr-ls hv1
37632+
37633+
sleep_controller hv1
37634+
37635+
check ovn-nbctl --wait=sb set Logical_Switch ls other_config:requested-tnl-key=1000
37636+
check ovn-nbctl --wait=sb ls-del ls
37637+
wake_up_controller hv1
37638+
37639+
check ovn-nbctl --wait=hv sync
37640+
37641+
check ovn-nbctl --wait=hv ls-add ls1 \
37642+
-- lsp-add ls1 ls1-lr \
37643+
-- lrp-add lr lr-ls1 f0:00:00:00:00:f2 192.168.2.1/24 \
37644+
-- set Logical_Switch_Port ls1-lr type=router options:router-port=lr-ls1 addresses=router \
37645+
-- lrp-set-gateway-chassis lr-ls1 hv1
37646+
37647+
check ovn-nbctl --wait=hv set Logical_Switch ls1 other_config:requested-tnl-key=1001
37648+
37649+
OVN_CLEANUP([hv1])
37650+
37651+
AT_CLEANUP
37652+
])

0 commit comments

Comments
 (0)