From 440753e8b08d48cb5620c5463c9602f13db7c035 Mon Sep 17 00:00:00 2001 From: Baorong Liu Date: Mon, 10 Jul 2023 10:14:11 -0700 Subject: [PATCH] [staticroutebfd] fix ipv6 letter case issue (#15765) *use lower case for IPv6 address as internal key and bfd session key. fixes #15764 Why I did it *staticroutebfd uses the IPv6 address string as a key to create bfd session and cache the bfd sessions using it as a key. When the IPv6 address string has uppercase letter in the static route nexthop list, the string with uppercase letter key is stored in the cache, but the BFD STATE_DB uses lowercase for IPv6 address, so when the staticroutebfd get the bfd state event, it cannot find the bfd session in its local cache because of the letter case. --- src/sonic-bgpcfgd/staticroutebfd/main.py | 8 ++ src/sonic-bgpcfgd/tests/test_static_rt_bfd.py | 76 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/src/sonic-bgpcfgd/staticroutebfd/main.py b/src/sonic-bgpcfgd/staticroutebfd/main.py index 2d7006420eb9..89f10f2dca5a 100644 --- a/src/sonic-bgpcfgd/staticroutebfd/main.py +++ b/src/sonic-bgpcfgd/staticroutebfd/main.py @@ -66,6 +66,9 @@ def static_route_split_key(key): :param key: key to split :return: valid, vrf name extracted from the key, ip prefix extracted from the key """ + if key is None or len(key) == 0: + return False, "", "" + l = tuple(key.split('|')) if len(l) == 1: @@ -376,6 +379,11 @@ def static_route_set_handler(self, key, data): log_err("invalid ip prefix for static route: '%s'"%(key)) return True + #use lower case if there is letter in IPv6 address string + if 'nexthop' in data: + nh = data['nexthop'] + data['nexthop'] = nh.lower() + arg_list = lambda v: [x.strip() for x in v.split(',')] if len(v.strip()) != 0 else None bfd_field = arg_list(data['bfd']) if 'bfd' in data else ["false"] diff --git a/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py b/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py index 24f88bade1c6..107b994c6bc8 100644 --- a/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py +++ b/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py @@ -94,6 +94,82 @@ def intf_setup(dut): {}, {} ) + set_del_test(dut, "intf", + "SET", + ("if1|2603:10E2:400:1::1/64",{} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if2|2603:10E2:400:2::1/64",{} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if3|2603:10E2:400:3::1/64",{} + ), + {}, + {} + ) + +def test_set_del_ipv6(): + dut = constructor() + intf_setup(dut) + + set_del_test(dut, "srt", + "SET", + ("2603:10e2:400::4/128", { + "bfd": "true", + "ifname": "if1, if2, if3", + "nexthop": "2603:10E2:400:1::2,2603:10E2:400:2::2,2603:10e2:400:3::2" + }), + { + "set_default:default:2603:10e2:400:1::2" : {'multihop': 'true', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '2603:10E2:400:1::1'}, + "set_default:default:2603:10e2:400:2::2" : {'multihop': 'true', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '2603:10E2:400:2::1'}, + "set_default:default:2603:10e2:400:3::2" : {'multihop': 'true', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '2603:10E2:400:3::1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("2603:10e2:400:1::2", { + "state": "Up" + }), + {}, + {'set_default:2603:10e2:400::4/128': {'nexthop': '2603:10e2:400:1::2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("2603:10e2:400:2::2", { + "state": "Up" + }), + {}, + {'set_default:2603:10e2:400::4/128': {'nexthop': '2603:10e2:400:1::2,2603:10e2:400:2::2', 'ifname': 'if1,if2', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("2603:10e2:400:3::2", { + "state": "Up" + }), + {}, + {'set_default:2603:10e2:400::4/128': {'nexthop': '2603:10e2:400:1::2,2603:10e2:400:2::2,2603:10e2:400:3::2', 'ifname': 'if1,if2,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "DEL", + ("2603:10e2:400::4/128", { }), + { + "del_default:default:2603:10e2:400:1::2" : {}, + "del_default:default:2603:10e2:400:2::2" : {}, + "del_default:default:2603:10e2:400:3::2" : {} + }, + {'del_default:2603:10e2:400::4/128': { }} + ) @patch('staticroutebfd.main.log_err') def test_invalid_key(mocked_log_err):