Skip to content

Commit

Permalink
[202012][dhcp_relay] Add show/clear/counter cli for dhcp_relay (#2719)
Browse files Browse the repository at this point in the history
What I did
Add support for dhcp_relay show cli, consistent with sonic-net/sonic-buildimage#13614

How I did it
Add support for dhcp_relay show cli

How to verify it
1. UT
2. build wheel and install in device

Signed-off-by: Yaqiang Zhu <yaqiangzhu@microsoft.com>
  • Loading branch information
yaqiangz authored Mar 9, 2023
1 parent 48fd842 commit f0a9f4f
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 190 deletions.
25 changes: 25 additions & 0 deletions clear/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,5 +455,30 @@ def translations():
cmd = "natclear -t"
run_command(cmd)


@cli.group(name="dhcp_relay", cls=AliasedGroup)
def dhcp_relay():
"""Clear dhcp_relay """
pass


@dhcp_relay.group(name="ipv6")
def dhcp_relay_ipv6():
pass


@dhcp_relay_ipv6.command(name="counters")
@click.argument("interface", required=False)
def dhcp_relay_ipv6_counters(interface):
""" Clear dhcp_relay_ipv6 message counts """

if interface:
cmd = "show dhcp6relay_counters clear -i " + interface
else:
cmd = "show dhcp6relay_counters clear"

run_command(cmd)


if __name__ == '__main__':
cli()
95 changes: 0 additions & 95 deletions show/dhcp6relay_counters.py

This file was deleted.

201 changes: 201 additions & 0 deletions show/dhcp_relay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import click
from tabulate import tabulate
from swsscommon.swsscommon import ConfigDBConnector, SonicV2Connector


import utilities_common.cli as clicommon

DHCP_RELAY = 'DHCP_RELAY'
VLAN = "VLAN"
DHCPV6_SERVERS = "dhcpv6_servers"
DHCPV4_SERVERS = "dhcp_servers"
# STATE_DB Table
DHCPv6_COUNTER_TABLE = 'DHCPv6_COUNTER_TABLE'

# DHCPv6 Counter Messages
messages = ["Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", "Decline", "Relay-Forward", "Relay-Reply"]
config_db = ConfigDBConnector()


@click.group(cls=clicommon.AliasedGroup, name="dhcprelay_helper")
def dhcp_relay_helper():
"""Show DHCP_Relay helper information"""
pass


@dhcp_relay_helper.command('ipv6')
def get_dhcpv6_helper_address():
"""Parse through DHCP_RELAY table for each interface in config_db.json and print dhcpv6 helpers in table format"""
if config_db is not None:
config_db.connect()
table_data = config_db.get_table(DHCP_RELAY)
if table_data is not None:
vlans = config_db.get_keys(DHCP_RELAY)
for vlan in vlans:
output = get_data(table_data, vlan)
print(output)


def get_data(table_data, vlan):
vlan_data = table_data.get(vlan, {})
helpers_data = vlan_data.get(DHCPV6_SERVERS)
addr = {vlan: []}
output = ''
if helpers_data is not None:
for ip in helpers_data:
addr[vlan].append(ip)
output = tabulate({'Interface': [vlan], vlan: addr.get(vlan)}, tablefmt='simple', stralign='right') + '\n'
return output


def get_dhcp_relay_data_with_header(table_data, entry_name):
vlan_relay = {}
vlans = table_data.keys()
for vlan in vlans:
vlan_data = table_data.get(vlan)
dhcp_relay_data = vlan_data.get(entry_name)
if dhcp_relay_data is None or len(dhcp_relay_data) == 0:
continue

vlan_relay[vlan] = []
for address in dhcp_relay_data:
vlan_relay[vlan].append(address)

dhcp_relay_vlan_keys = vlan_relay.keys()
relay_address_list = ["\n".join(vlan_relay[key]) for key in dhcp_relay_vlan_keys]
data = {"Interface": dhcp_relay_vlan_keys, "DHCP Relay Address": relay_address_list}
return tabulate(data, tablefmt='grid', stralign='right', headers='keys') + '\n'


def get_dhcp_relay(table_name, entry_name, with_header):
if config_db is None:
return

config_db.connect()
table_data = config_db.get_table(table_name)
if table_data is None:
return

if with_header:
output = get_dhcp_relay_data_with_header(table_data, entry_name)
print(output)
else:
vlans = config_db.get_keys(table_name)
for vlan in vlans:
output = get_data(table_data, vlan)
print(output)


@click.group(cls=clicommon.AliasedGroup, name="dhcp_relay")
def dhcp_relay():
"""show DHCP_Relay information"""
pass


@dhcp_relay.group(cls=clicommon.AliasedGroup, name="ipv6")
def dhcp_relay_ipv6():
pass


@dhcp_relay.group(cls=clicommon.AliasedGroup, name="ipv4")
def dhcp_relay_ipv4():
pass


@dhcp_relay_ipv4.command("helper")
def dhcp_relay_ipv4_destination():
get_dhcp_relay(VLAN, DHCPV4_SERVERS, with_header=True)


@dhcp_relay_ipv6.command("destination")
def dhcp_relay_ipv6_destination():
get_dhcp_relay(DHCP_RELAY, DHCPV6_SERVERS, with_header=True)


class DHCPv6_Counter(object):
def __init__(self):
self.db = SonicV2Connector(use_unix_socket_path=False)
self.db.connect(self.db.STATE_DB)
self.table_name = DHCPv6_COUNTER_TABLE + self.db.get_db_separator(self.db.STATE_DB)

def get_interface(self):
""" Get all names of all interfaces in DHCPv6_COUNTER_TABLE """
vlans = []
for key in self.db.keys(self.db.STATE_DB):
if DHCPv6_COUNTER_TABLE in key:
vlans.append(key[21:])
return vlans

def get_dhcp6relay_msg_count(self, interface, msg):
""" Get count of a dhcp6relay message """
count = self.db.get(self.db.STATE_DB, self.table_name + str(interface), str(msg))
data = [str(msg), count]
return data

def clear_table(self, interface):
""" Reset all message counts to 0 """
for msg in messages:
self.db.set(self.db.STATE_DB, self.table_name + str(interface), str(msg), '0')


def print_count(counter, intf):
"""Print count of each message"""
data = []
for i in messages:
data.append(counter.get_dhcp6relay_msg_count(intf, i))
print(tabulate(data, headers=["Message Type", intf], tablefmt='simple', stralign='right') + "\n")


#
# 'dhcp6relay_counters' group ###
#


@click.group(cls=clicommon.AliasedGroup, name="dhcp6relay_counters")
def dhcp6relay_counters():
"""Show DHCPv6 counter"""
pass


# 'counts' subcommand ("show dhcp6relay_counters counts")
@dhcp6relay_counters.command('counts')
@click.option('-i', '--interface', required=False)
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def counts(interface, verbose):
"""Show dhcp6relay message counts"""
ipv6_counters(interface)


def ipv6_counters(interface):
counter = DHCPv6_Counter()
counter_intf = counter.get_interface()

if interface:
print_count(counter, interface)
else:
for intf in counter_intf:
print_count(counter, intf)


# 'clear' subcommand ("clear dhcp6relay_counters counts")
@dhcp6relay_counters.command('clear')
@click.option('-i', '--interface', required=False)
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def clear(interface, verbose):
"""Clear dhcp6relay message counts"""
counter = DHCPv6_Counter()
counter_intf = counter.get_interface()

if interface:
counter.clear_table(interface)
print("Cleared DHCPv6 Relay Counter " + interface)
else:
for intf in counter_intf:
counter.clear_table(intf)
print("Cleared DHCPv6 Relay Counters")


@dhcp_relay_ipv6.command("counters")
@click.option('-i', '--interface', required=False)
def dhcp_relay_ip6counters(interface):
ipv6_counters(interface)
37 changes: 0 additions & 37 deletions show/dhcp_relay_helper.py

This file was deleted.

8 changes: 4 additions & 4 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
from . import acl
from . import bgp_common
from . import chassis_modules
from . import dhcp6relay_counters
from . import dhcp_relay_helper
from . import dhcp_relay
from . import dropcounters
from . import feature
from . import fgnhg
Expand Down Expand Up @@ -162,8 +161,9 @@ def cli(ctx):
# Add groups from other modules
cli.add_command(acl.acl)
cli.add_command(chassis_modules.chassis_modules)
cli.add_command(dhcp_relay_helper.dhcp_relay_helper)
cli.add_command(dhcp6relay_counters.dhcp6relay_counters)
cli.add_command(dhcp_relay.dhcp_relay_helper)
cli.add_command(dhcp_relay.dhcp_relay)
cli.add_command(dhcp_relay.dhcp6relay_counters)
cli.add_command(dropcounters.dropcounters)
cli.add_command(feature.feature)
cli.add_command(fgnhg.fgnhg)
Expand Down
1 change: 1 addition & 0 deletions tests/config_dhcp_relay_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ def test_config_add_dhcp_relay_ipv6_with_non_entry(self):
db = Db()
table = IP_VER_TEST_PARAM_MAP[ip_version]["table"]
db.cfgdb.set_entry(table, "Vlan1000", None)
db.cfgdb.set_entry(table, "Vlan2000", None)
assert db.cfgdb.get_entry(table, "Vlan1000") == {}
assert len(db.cfgdb.get_keys(table)) == 0

Expand Down
Loading

0 comments on commit f0a9f4f

Please sign in to comment.