Skip to content

Commit

Permalink
[fdbshow] Adding more options for fdbshow and show mac (sonic-net#1982)
Browse files Browse the repository at this point in the history
#### What I did
 Added more options to filter output in show mac and fdbshow command.
Introduced options for filter by address and filter by type.
Added one more option to display only count.
Introduced show command to display fdb aging time in the switch.

#### How I did it
Modifying fdbshow and show scripts to include the above-mentioned options

#### How to verify it
Added UT for all the newly introduced options and commands

#### Previous command output (if the output of a command-line utility has changed)
```
show mac -h
Usage: show mac [OPTIONS]

  Show MAC (FDB) entries

Options:
  -v, --vlan TEXT
  -p, --port TEXT
  --verbose        Enable verbose output
  -h, -?, --help   Show this message and exit.
```
#### New command output (if the output of a command-line utility has changed)
```
show mac -h
Usage: show mac [OPTIONS] COMMAND [ARGS]...

  Show MAC (FDB) entries

Options:
  -v, --vlan TEXT
  -p, --port TEXT
  -a, --address TEXT
  -t, --type TEXT
  -c, --count
  --verbose           Enable verbose output
  -h, -?, --help      Show this message and exit.

Commands:
  aging-time

show mac
  No.    Vlan  MacAddress         Port         Type
-----  ------  -----------------  -----------  -------
    1      10  98:03:9B:82:BB:5B  Ethernet60   Dynamic
    2      10  EC:0D:9A:CD:91:72  Ethernet64   Dynamic
    3      10  EC:0D:9A:CD:91:73  Ethernet124  Dynamic
Total number of entries 3

show mac --address EC:0D:9A:CD:91:72
  No.    Vlan  MacAddress         Port        Type
-----  ------  -----------------  ----------  -------
    1      10  EC:0D:9A:CD:91:72  Ethernet64  Dynamic

show mac --count
Total number of entries 3

show mac --type Dynamic
  No.    Vlan  MacAddress         Port         Type
-----  ------  -----------------  -----------  -------
    1      10  98:03:9B:82:BB:5B  Ethernet60   Dynamic
    2      10  EC:0D:9A:CD:91:72  Ethernet64   Dynamic
    3      10  EC:0D:9A:CD:91:73  Ethernet124  Dynamic
Total number of entries 3

show mac aging-time
Aging time for switch is 600 seconds
```
  • Loading branch information
dgsudharsan committed Jan 18, 2022
1 parent 902e14f commit d9f3afe
Show file tree
Hide file tree
Showing 9 changed files with 675 additions and 108 deletions.
156 changes: 94 additions & 62 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -8920,90 +8920,122 @@ This command displays the MAC (FDB) entries either in full or partial as given b
1) show mac - displays the full table
2) show mac -v <vlanid> - displays the MACs learnt on the particular VLAN ID.
3) show mac -p <port> - displays the MACs learnt on the particular port.
4) show mac -a <mac-address> - display the MACs that match a specific mac-address
5) show mac -t <type> - display the MACs that match a specific type (static/dynamic)
6) show mac -c - display the count of MAC addresses
To show the default MAC address aging time on the switch.
- Usage:
```
show mac [-v <vlan_id>] [-p <port_name>]
show mac [-v <vlan_id>] [-p <port_name>] [-a <mac_address>] [-t <type>] [-c]
```
- Example:
```
admin@sonic:~$ show mac
No. Vlan MacAddress Port
----- ------ ----------------- -----------
1 1000 E2:8C:56:85:4A:CD Ethernet192
2 1000 A0:1B:5E:47:C9:76 Ethernet192
3 1000 AA:54:EF:2C:EE:30 Ethernet192
4 1000 A4:3F:F2:17:A3:FC Ethernet192
5 1000 0C:FC:01:72:29:91 Ethernet192
6 1000 48:6D:01:7E:C9:FD Ethernet192
7 1000 1C:6B:7E:34:5F:A6 Ethernet192
8 1000 EE:81:D9:7B:93:A9 Ethernet192
9 1000 CC:F8:8D:BB:85:E2 Ethernet192
10 1000 0A:52:B3:9C:FB:6C Ethernet192
11 1000 C6:E2:72:02:D1:23 Ethernet192
12 1000 8A:C9:5C:25:E9:28 Ethernet192
13 1000 5E:CD:34:E4:94:18 Ethernet192
14 1000 7E:49:1F:B5:91:B5 Ethernet192
15 1000 AE:DD:67:F3:09:5A Ethernet192
16 1000 DC:2F:D1:08:4B:DE Ethernet192
17 1000 50:96:23:AD:F1:65 Ethernet192
18 1000 C6:C9:5E:AE:24:42 Ethernet192
No. Vlan MacAddress Port Type
----- ------ ----------------- ----------- -------
1 1000 E2:8C:56:85:4A:CD Ethernet192 Dynamic
2 1000 A0:1B:5E:47:C9:76 Ethernet192 Dynamic
3 1000 AA:54:EF:2C:EE:30 Ethernet192 Dynamic
4 1000 A4:3F:F2:17:A3:FC Ethernet192 Dynamic
5 1000 0C:FC:01:72:29:91 Ethernet192 Dynamic
6 1000 48:6D:01:7E:C9:FD Ethernet192 Dynamic
7 1000 1C:6B:7E:34:5F:A6 Ethernet192 Dynamic
8 1000 EE:81:D9:7B:93:A9 Ethernet192 Dynamic
9 1000 CC:F8:8D:BB:85:E2 Ethernet192 Dynamic
10 1000 0A:52:B3:9C:FB:6C Ethernet192 Dynamic
11 1000 C6:E2:72:02:D1:23 Ethernet192 Dynamic
12 1000 8A:C9:5C:25:E9:28 Ethernet192 Dynamic
13 1000 5E:CD:34:E4:94:18 Ethernet192 Dynamic
14 1000 7E:49:1F:B5:91:B5 Ethernet192 Dynamic
15 1000 AE:DD:67:F3:09:5A Ethernet192 Dynamic
16 1000 DC:2F:D1:08:4B:DE Ethernet192 Dynamic
17 1000 50:96:23:AD:F1:65 Ethernet192 Static
18 1000 C6:C9:5E:AE:24:42 Ethernet192 Static
Total number of entries 18
```
Optionally, you can specify a VLAN ID or interface name in order to display only that particular entries
Optionally, you can specify a VLAN ID or interface name or type or mac-address in order to display only that particular entries
- Examples:
```
admin@sonic:~$ show mac -v 1000
No. Vlan MacAddress Port
----- ------ ----------------- -----------
1 1000 E2:8C:56:85:4A:CD Ethernet192
2 1000 A0:1B:5E:47:C9:76 Ethernet192
3 1000 AA:54:EF:2C:EE:30 Ethernet192
4 1000 A4:3F:F2:17:A3:FC Ethernet192
5 1000 0C:FC:01:72:29:91 Ethernet192
6 1000 48:6D:01:7E:C9:FD Ethernet192
7 1000 1C:6B:7E:34:5F:A6 Ethernet192
8 1000 EE:81:D9:7B:93:A9 Ethernet192
9 1000 CC:F8:8D:BB:85:E2 Ethernet192
10 1000 0A:52:B3:9C:FB:6C Ethernet192
11 1000 C6:E2:72:02:D1:23 Ethernet192
12 1000 8A:C9:5C:25:E9:28 Ethernet192
13 1000 5E:CD:34:E4:94:18 Ethernet192
14 1000 7E:49:1F:B5:91:B5 Ethernet192
15 1000 AE:DD:67:F3:09:5A Ethernet192
16 1000 DC:2F:D1:08:4B:DE Ethernet192
17 1000 50:96:23:AD:F1:65 Ethernet192
18 1000 C6:C9:5E:AE:24:42 Ethernet192
No. Vlan MacAddress Port Type
----- ------ ----------------- ----------- -------
1 1000 E2:8C:56:85:4A:CD Ethernet192 Dynamic
2 1000 A0:1B:5E:47:C9:76 Ethernet192 Dynamic
3 1000 AA:54:EF:2C:EE:30 Ethernet192 Dynamic
4 1000 A4:3F:F2:17:A3:FC Ethernet192 Dynamic
5 1000 0C:FC:01:72:29:91 Ethernet192 Dynamic
6 1000 48:6D:01:7E:C9:FD Ethernet192 Dynamic
7 1000 1C:6B:7E:34:5F:A6 Ethernet192 Dynamic
8 1000 EE:81:D9:7B:93:A9 Ethernet192 Dynamic
9 1000 CC:F8:8D:BB:85:E2 Ethernet192 Dynamic
10 1000 0A:52:B3:9C:FB:6C Ethernet192 Dynamic
11 1000 C6:E2:72:02:D1:23 Ethernet192 Dynamic
12 1000 8A:C9:5C:25:E9:28 Ethernet192 Dynamic
13 1000 5E:CD:34:E4:94:18 Ethernet192 Dynamic
14 1000 7E:49:1F:B5:91:B5 Ethernet192 Dynamic
15 1000 AE:DD:67:F3:09:5A Ethernet192 Dynamic
16 1000 DC:2F:D1:08:4B:DE Ethernet192 Dynamic
17 1000 50:96:23:AD:F1:65 Ethernet192 Static
18 1000 C6:C9:5E:AE:24:42 Ethernet192 Static
Total number of entries 18
```
```
admin@sonic:~$ show mac -p Ethernet192
No. Vlan MacAddress Port
----- ------ ----------------- -----------
1 1000 E2:8C:56:85:4A:CD Ethernet192
2 1000 A0:1B:5E:47:C9:76 Ethernet192
3 1000 AA:54:EF:2C:EE:30 Ethernet192
4 1000 A4:3F:F2:17:A3:FC Ethernet192
5 1000 0C:FC:01:72:29:91 Ethernet192
6 1000 48:6D:01:7E:C9:FD Ethernet192
7 1000 1C:6B:7E:34:5F:A6 Ethernet192
8 1000 EE:81:D9:7B:93:A9 Ethernet192
9 1000 CC:F8:8D:BB:85:E2 Ethernet192
10 1000 0A:52:B3:9C:FB:6C Ethernet192
11 1000 C6:E2:72:02:D1:23 Ethernet192
12 1000 8A:C9:5C:25:E9:28 Ethernet192
13 1000 5E:CD:34:E4:94:18 Ethernet192
14 1000 7E:49:1F:B5:91:B5 Ethernet192
15 1000 AE:DD:67:F3:09:5A Ethernet192
16 1000 DC:2F:D1:08:4B:DE Ethernet192
17 1000 50:96:23:AD:F1:65 Ethernet192
18 1000 C6:C9:5E:AE:24:42 Ethernet192
No. Vlan MacAddress Port Type
----- ------ ----------------- ----------- -------
1 1000 E2:8C:56:85:4A:CD Ethernet192 Dynamic
2 1000 A0:1B:5E:47:C9:76 Ethernet192 Dynamic
3 1000 AA:54:EF:2C:EE:30 Ethernet192 Dynamic
4 1000 A4:3F:F2:17:A3:FC Ethernet192 Dynamic
5 1000 0C:FC:01:72:29:91 Ethernet192 Dynamic
6 1000 48:6D:01:7E:C9:FD Ethernet192 Dynamic
7 1000 1C:6B:7E:34:5F:A6 Ethernet192 Dynamic
8 1000 EE:81:D9:7B:93:A9 Ethernet192 Dynamic
9 1000 CC:F8:8D:BB:85:E2 Ethernet192 Dynamic
10 1000 0A:52:B3:9C:FB:6C Ethernet192 Dynamic
11 1000 C6:E2:72:02:D1:23 Ethernet192 Dynamic
12 1000 8A:C9:5C:25:E9:28 Ethernet192 Dynamic
13 1000 5E:CD:34:E4:94:18 Ethernet192 Dynamic
14 1000 7E:49:1F:B5:91:B5 Ethernet192 Dynamic
15 1000 AE:DD:67:F3:09:5A Ethernet192 Dynamic
16 1000 DC:2F:D1:08:4B:DE Ethernet192 Dynamic
17 1000 50:96:23:AD:F1:65 Ethernet192 Static
18 1000 C6:C9:5E:AE:24:42 Ethernet192 Static
Total number of entries 18
```
```
admin@sonic:~$ show mac -a E2:8C:56:85:4A:CD
No. Vlan MacAddress Port Type
----- ------ ----------------- ----------- -------
1 1000 E2:8C:56:85:4A:CD Ethernet192 Dynamic
Total number of entries 1
```
```
admin@sonic:~$ show mac -t Static
No. Vlan MacAddress Port Type
----- ------ ----------------- ----------- -------
2 1000 50:96:23:AD:F1:65 Ethernet192 Static
2 1000 C6:C9:5E:AE:24:42 Ethernet192 Static
Total number of entries 2
```
```
admin@sonic:~$ show mac -c
Total number of entries 18
```
**show mac aging-time**
This command displays the default mac aging time on the switch
```
admin@sonic:~$ show mac aging-time
Aging time for switch is 600 seconds
```
**sonic-clear fdb all**
Expand Down
87 changes: 58 additions & 29 deletions scripts/fdbshow
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import argparse
import json
import sys
import os
import re

# mock the redis for unit test purposes #
try: # pragma: no cover
Expand All @@ -43,7 +44,9 @@ try: # pragma: no cover
"2": 'asic_db_def_vlan',
"3": 'asic_db_no_fdb',
"4": 'asic_db_no_bridge',
"5": 'asic_db_fetch_except'}
"5": 'asic_db_fetch_except',
"6": 'asic_db_no_static',
"7": 'asic_db_mac_case'}
mock_db_path = os.path.join(test_path, "fdbshow_input")
file_name = mock_variants[os.environ["FDBSHOW_MOCK"]]
jsonfile_asic = os.path.join(mock_db_path, file_name)
Expand All @@ -53,15 +56,13 @@ try: # pragma: no cover
except KeyError: # pragma: no cover
pass

from natsort import natsorted
from swsssdk import port_util
from swsscommon.swsscommon import SonicV2Connector
from tabulate import tabulate

class FdbShow(object):

HEADER = ['No.', 'Vlan', 'MacAddress', 'Port', 'Type']
FDB_COUNT = 0

def __init__(self):
super(FdbShow,self).__init__()
Expand Down Expand Up @@ -135,53 +136,81 @@ class FdbShow(object):
return


def get_iter_index(self, key_value, pos=0):
"""
Get the starting index of matched entry
"""
if pos != 0:
self.bridge_mac_list = natsorted(self.bridge_mac_list, key = lambda x: x[pos])

keys = [r[pos] for r in self.bridge_mac_list]
return keys.index(key_value)


def display(self, vlan, port):
def display(self, vlan, port, address, entry_type, count):
"""
Display the FDB entries for specified vlan/port.
@todo: - PortChannel support
"""
output = []

if vlan is not None:
vlan = int(vlan)
s_index = self.get_iter_index(vlan)
self.bridge_mac_list = [fdb for fdb in self.bridge_mac_list[s_index:]
if fdb[0] == vlan]
if port is not None:
s_index = self.get_iter_index(port, 2)
self.bridge_mac_list = [fdb for fdb in self.bridge_mac_list[s_index:]
if fdb[2] == port]
vlan_val = int(vlan)

if address is not None:
address = address.upper()

for fdb in self.bridge_mac_list:
self.FDB_COUNT += 1
output.append([self.FDB_COUNT, fdb[0], fdb[1], fdb[2], fdb[3]])
if entry_type is not None:
entry_type = entry_type.capitalize()

print(tabulate(output, self.HEADER))
print("Total number of entries {0}".format(self.FDB_COUNT))
self.bridge_mac_list = [fdb for fdb in self.bridge_mac_list
if (vlan is None or fdb[0] == vlan_val) and
(port is None or fdb[2] == port) and
(address is None or fdb[1] == address) and
(entry_type is None or fdb[3] == entry_type)]

if not count:
fdb_index = 1
for fdb in self.bridge_mac_list:
output.append([fdb_index, fdb[0], fdb[1], fdb[2], fdb[3]])
fdb_index += 1
print(tabulate(output, self.HEADER))

print("Total number of entries {0}".format(len(self.bridge_mac_list)))

def validate_params(self, vlan, port, address, entry_type):
if vlan is not None:
if not vlan.isnumeric():
print("Error: Invalid vlan id {0}".format(vlan))
return False

vlan_val = int(vlan)
if (vlan_val not in range(1,4096)):
print("Error: Invalid vlan id {0}".format(vlan))
return False

if port is not None and port not in self.if_name_map:
print("Error: Invalid port {0}".format(port))
return False

if address is not None:
mac_addr_pattern ="^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$"
if not re.match(mac_addr_pattern, address):
print("Error: Invalid mac address {0}".format(address))
return False

if entry_type is not None and entry_type.capitalize() not in ["Static", "Dynamic"]:
print("Error: Invalid type {0}". format(entry_type))
return False

return True

def main():

parser = argparse.ArgumentParser(description='Display ASIC FDB entries',
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-p', '--port', type=str, help='FDB learned on specific port: Ethernet0', default=None)
parser.add_argument('-v', '--vlan', type=str, help='FDB learned on specific Vlan: 1001', default=None)
parser.add_argument('-a', '--address', type=str, help='FDB display based on specific mac address', default=None)
parser.add_argument('-t', '--type', type=str, help='FDB display of specific type of mac address', default=None)
parser.add_argument('-c', '--count', action='store_true', help='FDB display count of mac address')
args = parser.parse_args()

try:
fdb = FdbShow()
fdb.display(args.vlan, args.port)
if not fdb.validate_params(args.vlan, args.port, args.address, args.type):
sys.exit(1)

fdb.display(args.vlan, args.port, args.address, args.type, args.count)
except Exception as e:
print(str(e))
sys.exit(1)
Expand Down
38 changes: 36 additions & 2 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,13 +722,20 @@ def pwm_headroom_pool():
# 'mac' command ("show mac ...")
#

@cli.command()
@cli.group(cls=clicommon.AliasedGroup, invoke_without_command="true")
@click.pass_context
@click.option('-v', '--vlan')
@click.option('-p', '--port')
@click.option('-a', '--address')
@click.option('-t', '--type')
@click.option('-c', '--count', is_flag=True)
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def mac(vlan, port, verbose):
def mac(ctx, vlan, port, address, type, count, verbose):
"""Show MAC (FDB) entries"""

if ctx.invoked_subcommand is not None:
return

cmd = "fdbshow"

if vlan is not None:
Expand All @@ -737,8 +744,35 @@ def mac(vlan, port, verbose):
if port is not None:
cmd += " -p {}".format(port)

if address is not None:
cmd += " -a {}".format(address)

if type is not None:
cmd += " -t {}".format(type)

if count:
cmd += " -c"

run_command(cmd, display_cmd=verbose)

@mac.command('aging-time')
@click.pass_context
def aging_time(ctx):
app_db = SonicV2Connector()
app_db.connect(app_db.APPL_DB)
table = "SWITCH_TABLE*"
keys = app_db.keys(app_db.APPL_DB, table)

if not keys:
click.echo("Aging time not configured for the switch")
return

for key in keys:
fdb_aging_time = app_db.get(app_db.APPL_DB, key, 'fdb_aging_time')
if fdb_aging_time is not None:
click.echo("Aging time for {} is {} seconds".format(key.split(':')[-1], fdb_aging_time))
else:
click.echo("Aging time not configured for the {}".format(key.split(':')[-1]))
#
# 'show route-map' command ("show route-map")
#
Expand Down
5 changes: 5 additions & 0 deletions tests/fdbshow_input/appl_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"SWITCH_TABLE:switch": {
"fdb_aging_time" : "600"
}
}
5 changes: 5 additions & 0 deletions tests/fdbshow_input/appl_db_no_age.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed" : "600"
}
}
Loading

0 comments on commit d9f3afe

Please sign in to comment.