diff --git a/scripts/portstat b/scripts/portstat index 20f10fb67..85f611fe5 100755 --- a/scripts/portstat +++ b/scripts/portstat @@ -51,12 +51,14 @@ NStats = namedtuple("NStats", "rx_ok, rx_err, rx_drop, rx_ovr, tx_ok,\ rx_uca, rx_mca, rx_bca, rx_all,\ tx_64, tx_65_127, tx_128_255, tx_256_511, tx_512_1023, tx_1024_1518, tx_1519_2047, tx_2048_4095, tx_4096_9216, tx_9217_16383,\ tx_uca, tx_mca, tx_bca, tx_all,\ - rx_jbr, rx_frag, rx_usize, rx_ovrrun") + rx_jbr, rx_frag, rx_usize, rx_ovrrun,\ + fec_corr, fec_uncorr, fec_symbol_err") header_all = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR', 'TX_OK', 'TX_BPS', 'TX_PPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR'] header_std = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_UTIL', 'RX_ERR', 'RX_DRP', 'RX_OVR', 'TX_OK', 'TX_BPS', 'TX_UTIL', 'TX_ERR', 'TX_DRP', 'TX_OVR'] header_errors_only = ['IFACE', 'STATE', 'RX_ERR', 'RX_DRP', 'RX_OVR', 'TX_ERR', 'TX_DRP', 'TX_OVR'] +header_fec_only = ['IFACE', 'STATE', 'FEC_CORR', 'FEC_UNCORR', 'FEC_SYMBOL_ERR'] header_rates_only = ['IFACE', 'STATE', 'RX_OK', 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'TX_OK', 'TX_BPS', 'TX_PPS', 'TX_UTIL'] rates_key_list = [ 'RX_BPS', 'RX_PPS', 'RX_UTIL', 'TX_BPS', 'TX_PPS', 'TX_UTIL' ] @@ -67,7 +69,7 @@ RateStats = namedtuple("RateStats", ratestat_fields) The order and count of statistics mentioned below needs to be in sync with the values in portstat script So, any fields added/deleted in here should be reflected in portstat script also """ -BUCKET_NUM = 42 +BUCKET_NUM = 45 counter_bucket_dict = { 0:['SAI_PORT_STAT_IF_IN_UCAST_PKTS', 'SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS'], 1:['SAI_PORT_STAT_IF_IN_ERRORS'], @@ -110,7 +112,10 @@ counter_bucket_dict = { 38:['SAI_PORT_STAT_ETHER_STATS_JABBERS'], 39:['SAI_PORT_STAT_ETHER_STATS_FRAGMENTS'], 40:['SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS'], - 41:['SAI_PORT_STAT_IP_IN_RECEIVES'] + 41:['SAI_PORT_STAT_IP_IN_RECEIVES'], + 42:['SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES'], + 43:['SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES'], + 44:['SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS'] } STATUS_NA = 'N/A' @@ -249,7 +254,7 @@ class Portstat(object): return STATUS_NA - def cnstat_print(self, cnstat_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, rates_only, detail=False): + def cnstat_print(self, cnstat_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, fec_stats_only, rates_only, detail=False): """ Print the cnstat. """ @@ -294,6 +299,12 @@ class Portstat(object): format_number_with_comma(data.tx_err), format_number_with_comma(data.tx_drop), format_number_with_comma(data.tx_ovr))) + elif fec_stats_only: + header = header_fec_only + table.append((key, self.get_port_state(key), + format_number_with_comma(data.fec_corr), + format_number_with_comma(data.fec_uncorr), + format_number_with_comma(data.fec_symbol_err))) elif rates_only: header = header_rates_only table.append((key, self.get_port_state(key), @@ -389,7 +400,10 @@ class Portstat(object): print("Time Since Counters Last Cleared............... " + str(cnstat_old_dict.get('time'))) - def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, rates_only, detail=False): + def cnstat_diff_print(self, cnstat_new_dict, cnstat_old_dict, + ratestat_dict, intf_list, use_json, + print_all, errors_only, fec_stats_only, + rates_only, detail=False): """ Print the difference between two cnstat results. """ @@ -466,6 +480,19 @@ class Portstat(object): format_number_with_comma(cntr.tx_err), format_number_with_comma(cntr.tx_drop), format_number_with_comma(cntr.tx_ovr))) + elif fec_stats_only: + header = header_fec_only + if old_cntr is not None: + table.append((key, self.get_port_state(key), + ns_diff(cntr.fec_corr, old_cntr.fec_corr), + ns_diff(cntr.fec_uncorr, old_cntr.fec_uncorr), + ns_diff(cntr.fec_symbol_err, old_cntr.fec_symbol_err))) + else: + table.append((key, self.get_port_state(key), + format_number_with_comma(cntr.fec_corr), + format_number_with_comma(cntr.fec_uncorr), + format_number_with_comma(cntr.fec_symbol_err))) + elif rates_only: header = header_rates_only if old_cntr is not None: @@ -553,6 +580,7 @@ Examples: parser.add_argument('-d', '--delete', action='store_true', help='Delete saved stats, either the uid or the specified tag') parser.add_argument('-D', '--delete-all', action='store_true', help='Delete all saved stats') parser.add_argument('-e', '--errors', action='store_true', help='Display interface errors') + parser.add_argument('-f', '--fec-stats', action='store_true', help='Display FEC related statistics') parser.add_argument('-j', '--json', action='store_true', help='Display in JSON format') parser.add_argument('-r', '--raw', action='store_true', help='Raw stats (unmodified output of netstat)') parser.add_argument('-R', '--rate', action='store_true', help='Display interface rates') @@ -569,6 +597,7 @@ Examples: delete_saved_stats = args.delete delete_all_stats = args.delete_all errors_only = args.errors + fec_stats_only = args.fec_stats rates_only = args.rate use_json = args.json raw_stats = args.raw @@ -605,7 +634,7 @@ Examples: # Now decide what information to display if raw_stats: - portstat.cnstat_print(cnstat_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, rates_only) + portstat.cnstat_print(cnstat_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, fec_stats_only, rates_only) sys.exit(0) if save_fresh_stats: @@ -624,7 +653,7 @@ Examples: cnstat_cached_dict = pickle.load(open(cnstat_fqn_file, 'rb')) if not detail: print("Last cached time was " + str(cnstat_cached_dict.get('time'))) - portstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, rates_only, detail) + portstat.cnstat_diff_print(cnstat_dict, cnstat_cached_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, fec_stats_only, rates_only, detail) except IOError as e: print(e.errno, e) else: @@ -632,13 +661,13 @@ Examples: print("\nFile '%s' does not exist" % cnstat_fqn_file) print("Did you run 'portstat -c -t %s' to record the counters via tag %s?\n" % (tag_name, tag_name)) else: - portstat.cnstat_print(cnstat_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, rates_only, detail) + portstat.cnstat_print(cnstat_dict, ratestat_dict, intf_list, use_json, print_all, errors_only, fec_stats_only, rates_only, detail) else: #wait for the specified time and then gather the new stats and output the difference. time.sleep(wait_time_in_seconds) print("The rates are calculated within %s seconds period" % wait_time_in_seconds) cnstat_new_dict, ratestat_new_dict = portstat.get_cnstat_dict() - portstat.cnstat_diff_print(cnstat_new_dict, cnstat_dict, ratestat_new_dict, intf_list, use_json, print_all, errors_only, rates_only, detail) + portstat.cnstat_diff_print(cnstat_new_dict, cnstat_dict, ratestat_new_dict, intf_list, use_json, print_all, errors_only, fec_stats_only, rates_only, detail) if __name__ == "__main__": main() diff --git a/scripts/route_check.py b/scripts/route_check.py index f3a31f2c2..3b8c39ee6 100755 --- a/scripts/route_check.py +++ b/scripts/route_check.py @@ -495,8 +495,12 @@ def get_soc_ips(config_db): mux_table = config_db.get_table('MUX_CABLE') soc_ips = [] for _, mux_entry in mux_table.items(): - if mux_entry.get("cable_type", "") == "active-active" and "soc_ipv4" in mux_entry: - soc_ips.append(mux_entry["soc_ipv4"]) + if mux_entry.get("cable_type", "") == "active-active": + if "soc_ipv4" in mux_entry and mux_entry["soc_ipv4"]: + soc_ips.append(mux_entry["soc_ipv4"]) + + if "soc_ipv6" in mux_entry and mux_entry["soc_ipv6"]: + soc_ips.append(mux_entry["soc_ipv6"]) return soc_ips @@ -530,6 +534,51 @@ def filter_out_soc_ip_routes(routes): return updated_routes +def get_vlan_neighbors(): + """Return a list of VLAN neighbors.""" + db = swsscommon.DBConnector(APPL_DB_NAME, 0) + print_message(syslog.LOG_DEBUG, "APPL DB connected for neighbors") + tbl = swsscommon.Table(db, 'NEIGH_TABLE') + neigh_entries = tbl.getKeys() + + valid_neighs = [] + for neigh_entry in neigh_entries: + if ':' in neigh_entry: + device, prefix = neigh_entry.split(':', 1) + if device.startswith("Vlan"): + valid_neighs.append(add_prefix_ifnot(prefix.lower())) + + print_message(syslog.LOG_DEBUG, "Vlan neighbors:", json.dumps(valid_neighs, indent=4)) + return valid_neighs + + +def filter_out_vlan_neigh_route_miss(rt_appl_miss, rt_asic_miss): + """Ignore any route miss for vlan neighbor IPs.""" + + def _filter_out_neigh_route(routes, neighs): + updated_routes = [] + ignored_routes = [] + for route in routes: + if route in neighs: + ignored_routes.append(route) + else: + updated_routes.append(route) + return updated_routes, ignored_routes + + config_db = swsscommon.ConfigDBConnector() + config_db.connect() + + print_message(syslog.LOG_DEBUG, "Ignore vlan neighbor route miss") + if is_dualtor(config_db): + vlan_neighs = set(get_vlan_neighbors()) + rt_appl_miss, ignored_rt_appl_miss = _filter_out_neigh_route(rt_appl_miss, vlan_neighs) + print_message(syslog.LOG_DEBUG, "Ignored appl route miss:", json.dumps(ignored_rt_appl_miss, indent=4)) + rt_asic_miss, ignored_rt_asic_miss = _filter_out_neigh_route(rt_asic_miss, vlan_neighs) + print_message(syslog.LOG_DEBUG, "Ignored asic route miss:", json.dumps(ignored_rt_asic_miss, indent=4)) + + return rt_appl_miss, rt_asic_miss + + def check_routes(): """ The heart of this script which runs the checks. @@ -578,6 +627,11 @@ def check_routes(): if rt_appl_miss: rt_appl_miss = filter_out_voq_neigh_routes(rt_appl_miss) + # NOTE: On dualtor environment, ignore any route miss for the + # neighbors learned from the vlan subnet. + if rt_appl_miss or rt_asic_miss: + rt_appl_miss, rt_asic_miss = filter_out_vlan_neigh_route_miss(rt_appl_miss, rt_asic_miss) + if rt_appl_miss or rt_asic_miss: # Look for subscribe updates for a second adds, deletes = get_subscribe_updates(selector, subs) diff --git a/show/interfaces/__init__.py b/show/interfaces/__init__.py index a5e07b217..a7a562446 100644 --- a/show/interfaces/__init__.py +++ b/show/interfaces/__init__.py @@ -338,7 +338,7 @@ def expected(db, interfacename): @click.pass_context def mpls(ctx, interfacename, namespace, display): """Show Interface MPLS status""" - + #Edge case: Force show frontend interfaces on single asic if not (multi_asic.is_multi_asic()): if (display == 'frontend' or display == 'all' or display is None): @@ -346,7 +346,7 @@ def mpls(ctx, interfacename, namespace, display): else: print("Error: Invalid display option command for single asic") return - + display = "all" if interfacename else display masic = multi_asic_util.MultiAsic(display_option=display, namespace_option=namespace) ns_list = masic.get_ns_list_based_on_options() @@ -372,13 +372,13 @@ def mpls(ctx, interfacename, namespace, display): if (interfacename is not None): if (interfacename != ifname): continue - + intf_found = True - + if (display != "all"): if ("Loopback" in ifname): continue - + if ifname.startswith("Ethernet") and multi_asic.is_port_internal(ifname, ns): continue @@ -391,11 +391,11 @@ def mpls(ctx, interfacename, namespace, display): if 'mpls' not in mpls_intf or mpls_intf['mpls'] == 'disable': intfs_data.update({ifname: 'disable'}) else: - intfs_data.update({ifname: mpls_intf['mpls']}) - + intfs_data.update({ifname: mpls_intf['mpls']}) + # Check if interface is valid if (interfacename is not None and not intf_found): - ctx.fail('interface {} doesn`t exist'.format(interfacename)) + ctx.fail('interface {} doesn`t exist'.format(interfacename)) header = ['Interface', 'MPLS State'] body = [] @@ -603,6 +603,23 @@ def errors(verbose, period, namespace, display): clicommon.run_command(cmd, display_cmd=verbose) +# 'fec-stats' subcommand ("show interfaces counters errors") +@counters.command('fec-stats') +@click.option('-p', '--period') +@multi_asic_util.multi_asic_click_options +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def fec_stats(verbose, period, namespace, display): + """Show interface counters fec-stats""" + cmd = "portstat -f" + if period is not None: + cmd += " -p {}".format(period) + + cmd += " -s {}".format(display) + if namespace is not None: + cmd += " -n {}".format(namespace) + + clicommon.run_command(cmd, display_cmd=verbose) + # 'rates' subcommand ("show interfaces counters rates") @counters.command() @click.option('-p', '--period') diff --git a/show/muxcable.py b/show/muxcable.py index d62760c84..8b72bd8c1 100644 --- a/show/muxcable.py +++ b/show/muxcable.py @@ -592,7 +592,7 @@ def get_tunnel_route_per_port(db, port_tunnel_route, per_npu_configdb, per_npu_a mux_cfg_dict = per_npu_configdb[asic_id].get_all( per_npu_configdb[asic_id].CONFIG_DB, 'MUX_CABLE|{}'.format(port)) - dest_names = ["server_ipv4", "server_ipv6", "soc_ipv4"] + dest_names = ["server_ipv4", "server_ipv6", "soc_ipv4", "soc_ipv6"] for name in dest_names: dest_address = mux_cfg_dict.get(name, None) diff --git a/tests/mock_tables/asic_db.json b/tests/mock_tables/asic_db.json index e16fc315a..f95b835fe 100644 --- a/tests/mock_tables/asic_db.json +++ b/tests/mock_tables/asic_db.json @@ -23,5 +23,9 @@ "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"10.2.1.1\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x300000000007c\"}": { "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION": "SAI_PACKET_ACTION_FORWARD", "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x40000000015d8" - } + }, + "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{\"dest\":\"e801::47\",\"switch_id\":\"oid:0x21000000000000\",\"vr\":\"oid:0x300000000007c\"}": { + "SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION": "SAI_PACKET_ACTION_FORWARD", + "SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID": "oid:0x40000000015d8" + } } diff --git a/tests/mock_tables/config_db.json b/tests/mock_tables/config_db.json index 88ae64ecd..fc16850ce 100644 --- a/tests/mock_tables/config_db.json +++ b/tests/mock_tables/config_db.json @@ -1808,7 +1808,8 @@ "MUX_CABLE|Ethernet4": { "state": "auto", "server_ipv4": "10.3.1.1", - "server_ipv6": "e801::46" + "server_ipv6": "e801::46", + "soc_ipv6": "e801::47" }, "MUX_CABLE|Ethernet8": { "state": "active", diff --git a/tests/mock_tables/counters_db.json b/tests/mock_tables/counters_db.json index d82301dc6..f2caba244 100644 --- a/tests/mock_tables/counters_db.json +++ b/tests/mock_tables/counters_db.json @@ -855,7 +855,10 @@ "SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS": "0", "SAI_PORT_STAT_ETHER_STATS_FRAGMENTS": "0", "SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS": "0", - "SAI_PORT_STAT_ETHER_STATS_JABBERS": "0" + "SAI_PORT_STAT_ETHER_STATS_JABBERS": "0", + "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "130402", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "3", + "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "4" }, "COUNTERS:oid:0x1000000000013": { "SAI_PORT_STAT_IF_IN_UCAST_PKTS": "4", @@ -912,7 +915,10 @@ "SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS": "0", "SAI_PORT_STAT_ETHER_STATS_FRAGMENTS": "0", "SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS": "0", - "SAI_PORT_STAT_ETHER_STATS_JABBERS": "0" + "SAI_PORT_STAT_ETHER_STATS_JABBERS": "0", + "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "110412", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "1", + "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "0" }, "COUNTERS:oid:0x1000000000014": { "SAI_PORT_STAT_IF_IN_UCAST_PKTS": "6", @@ -969,7 +975,10 @@ "SAI_PORT_STAT_ETHER_OUT_PKTS_9217_TO_16383_OCTETS": "0", "SAI_PORT_STAT_ETHER_STATS_FRAGMENTS": "0", "SAI_PORT_STAT_ETHER_STATS_UNDERSIZE_PKTS": "0", - "SAI_PORT_STAT_ETHER_STATS_JABBERS": "0" + "SAI_PORT_STAT_ETHER_STATS_JABBERS": "0", + "SAI_PORT_STAT_IF_IN_FEC_CORRECTABLE_FRAMES": "100317", + "SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES": "0", + "SAI_PORT_STAT_IF_IN_FEC_SYMBOL_ERRORS": "0" }, "COUNTERS:oid:0x21000000000000": { "SAI_SWITCH_STAT_OUT_DROP_REASON_RANGE_BASE": "1000", diff --git a/tests/muxcable_test.py b/tests/muxcable_test.py index 0405b27d8..0b0f8b373 100644 --- a/tests/muxcable_test.py +++ b/tests/muxcable_test.py @@ -580,6 +580,11 @@ "DEST": "10.3.1.1", "kernel": 1, "asic": false + }, + "soc_ipv6": { + "DEST": "e801::47", + "kernel": false, + "asic": 1 } } } @@ -591,6 +596,7 @@ --------- ----------- -------------- -------- ------ Ethernet0 server_ipv4 10.2.1.1 added added Ethernet4 server_ipv4 10.3.1.1 added - +Ethernet4 soc_ipv6 e801::47 - added """ show_muxcable_tunnel_route_expected_output_port_json="""\ diff --git a/tests/portstat_test.py b/tests/portstat_test.py index f431747c6..d418a16fe 100644 --- a/tests/portstat_test.py +++ b/tests/portstat_test.py @@ -34,6 +34,23 @@ Ethernet8 N/A 6 1350.00 KB/s 9000.00/s N/A 100 10 N/A 60 13.37 MB/s 9000.00/s N/A N/A N/A N/A """ +intf_fec_counters = """\ + IFACE STATE FEC_CORR FEC_UNCORR FEC_SYMBOL_ERR +--------- ------- ---------- ------------ ---------------- +Ethernet0 D 130,402 3 4 +Ethernet4 N/A 110,412 1 0 +Ethernet8 N/A 100,317 0 0 +""" + +intf_fec_counters_period = """\ +The rates are calculated within 3 seconds period + IFACE STATE FEC_CORR FEC_UNCORR FEC_SYMBOL_ERR +--------- ------- ---------- ------------ ---------------- +Ethernet0 D 0 0 0 +Ethernet4 N/A 0 0 0 +Ethernet8 N/A 0 0 0 +""" + intf_counters_period = """\ The rates are calculated within 3 seconds period IFACE STATE RX_OK RX_BPS RX_UTIL RX_ERR RX_DRP RX_OVR TX_OK TX_BPS TX_UTIL TX_ERR TX_DRP TX_OVR @@ -289,6 +306,39 @@ def test_show_intf_counters_all(self): assert return_code == 0 assert result == intf_counters_all + def test_show_intf_fec_counters(self): + runner = CliRunner() + result = runner.invoke( + show.cli.commands["interfaces"].commands["counters"].commands["fec-stats"], []) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + assert result.output == intf_fec_counters + + return_code, result = get_result_and_return_code('portstat -f') + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == intf_fec_counters + + def test_show_intf_fec_counters_period(self): + runner = CliRunner() + result = runner.invoke(show.cli.commands["interfaces"].commands["counters"].commands["fec-stats"], + ["-p {}".format(TEST_PERIOD)]) + print(result.exit_code) + print(result.output) + assert result.exit_code == 0 + assert result.output == intf_fec_counters_period + + return_code, result = get_result_and_return_code( + 'portstat -f -p {}'.format(TEST_PERIOD)) + print("return_code: {}".format(return_code)) + print("result = {}".format(result)) + assert return_code == 0 + assert result == intf_fec_counters_period + + + def test_show_intf_counters_period(self): runner = CliRunner() result = runner.invoke(show.cli.commands["interfaces"].commands["counters"], [ diff --git a/tests/route_check_test_data.py b/tests/route_check_test_data.py index 6ada0abc8..b03ec5892 100644 --- a/tests/route_check_test_data.py +++ b/tests/route_check_test_data.py @@ -314,6 +314,7 @@ "server_ipv4": "192.168.0.2/32", "server_ipv6": "fc02:1000::2/128", "soc_ipv4": "192.168.0.3/32", + "soc_ipv6": "fc02:1000::3/128", "state": "auto" }, } @@ -328,7 +329,8 @@ RT_ENTRY_TABLE: { RT_ENTRY_KEY_PREFIX + "192.168.0.2/32" + RT_ENTRY_KEY_SUFFIX: {}, RT_ENTRY_KEY_PREFIX + "fc02:1000::2/128" + RT_ENTRY_KEY_SUFFIX: {}, - RT_ENTRY_KEY_PREFIX + "192.168.0.3/32" + RT_ENTRY_KEY_SUFFIX: {} + RT_ENTRY_KEY_PREFIX + "192.168.0.3/32" + RT_ENTRY_KEY_SUFFIX: {}, + RT_ENTRY_KEY_PREFIX + "fc02:1000::3/128" + RT_ENTRY_KEY_SUFFIX: {} } } } @@ -351,4 +353,58 @@ } } }, + "11": { + DESCR: "dualtor ignore vlan neighbor route miss case", + ARGS: "route_check -i 15", + RET: -1, + PRE: { + CONFIG_DB: { + DEVICE_METADATA: { + LOCALHOST: {"subtype": "DualToR"} + } + }, + APPL_DB: { + ROUTE_TABLE: { + "10.10.196.12/31" : { "ifname": "portchannel0" }, + "10.10.196.20/31" : { "ifname": "portchannel0" }, + "192.168.0.101/32": { "ifname": "tun0" }, + "192.168.0.103/32": { "ifname": "tun0" }, + }, + INTF_TABLE: { + "PortChannel1013:90.10.196.24/31": {}, + "PortChannel1023:9603:10b0:503:df4::5d/126": {}, + }, + NEIGH_TABLE: { + "Vlan1000:192.168.0.100": {}, + "Vlan1000:192.168.0.101": {}, + "Vlan1000:192.168.0.102": {}, + "Vlan1000:192.168.0.103": {}, + } + }, + ASIC_DB: { + RT_ENTRY_TABLE: { + RT_ENTRY_KEY_PREFIX + "20.10.196.12/31" + RT_ENTRY_KEY_SUFFIX: {}, + RT_ENTRY_KEY_PREFIX + "20.10.196.20/31" + RT_ENTRY_KEY_SUFFIX: {}, + RT_ENTRY_KEY_PREFIX + "20.10.196.24/32" + RT_ENTRY_KEY_SUFFIX: {}, + RT_ENTRY_KEY_PREFIX + "192.168.0.101/32" + RT_ENTRY_KEY_SUFFIX: {}, + RT_ENTRY_KEY_PREFIX + "192.168.0.102/32" + RT_ENTRY_KEY_SUFFIX: {}, + } + } + }, + RESULT: { + "missed_ROUTE_TABLE_routes": [ + "10.10.196.12/31", + "10.10.196.20/31" + ], + "missed_INTF_TABLE_entries": [ + "90.10.196.24/32", + "9603:10b0:503:df4::5d/128" + ], + "Unaccounted_ROUTE_ENTRY_TABLE_entries": [ + "20.10.196.12/31", + "20.10.196.20/31", + "20.10.196.24/32", + ] + } + }, }