Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dhcp/dhcpv6 per interface counter support #16377

Merged
merged 1 commit into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dockers/docker-dhcp-relay/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ ENV IMAGE_VERSION=$image_version
# Update apt's cache of available packages
RUN apt-get update

RUN apt-get install -y libjsoncpp-dev

{% if docker_dhcp_relay_debs.strip() -%}
# Copy built Debian packages
{{ copy_files("debs/", docker_dhcp_relay_debs.split(' '), "/debs/") }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,21 @@
except KeyError:
pass

expected_counts = """\
Message Type Vlan1000
------------------- -----------
Unknown
Solicit
Advertise
Request
Confirm
Renew
Rebind
Reply
Release
Decline
Reconfigure
Information-Request
Relay-Forward
Relay-Reply
Malformed
expected_counts_v6 = """\
Message Type Vlan1000(RX)
-------------- ---------------
Message Type Vlan1000(TX)
-------------- ---------------
"""

expected_counts_v4 = """\
Message Type Vlan1000(RX)
-------------- ---------------
Message Type Vlan1000(TX)
-------------- ---------------
"""

Expand All @@ -43,5 +40,14 @@ class TestDhcp6RelayCounters(object):
def test_show_counts(self):
runner = CliRunner()
result = runner.invoke(show.dhcp6relay_counters.commands["counts"], ["-i Vlan1000"])
assert result.output == expected_counts
print(result.output)
assert result.output == expected_counts_v6

class TestDhcpRelayCounters(object):

def test_show_counts(self):
runner = CliRunner()
result = runner.invoke(show.dhcp4relay_counters.commands["counts"], ["-i Vlan1000"])
print(result.output)
assert result.output == expected_counts_v4

122 changes: 103 additions & 19 deletions dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import click
import ast
from natsort import natsorted
from tabulate import tabulate
import show.vlan as show_vlan
Expand All @@ -7,13 +8,20 @@
from swsscommon.swsscommon import ConfigDBConnector
from swsscommon.swsscommon import SonicV2Connector


# STATE_DB Table
DHCPv4_COUNTER_TABLE = 'DHCP_COUNTER_TABLE'
DHCPv6_COUNTER_TABLE = 'DHCPv6_COUNTER_TABLE'

# DHCPv4 Counter Messages
dhcpv4_messages = [
"Unknown", "Discover", "Offer", "Request", "Decline", "Ack", "Nack", "Release", "Inform"
]

# DHCPv6 Counter Messages
messages = ["Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", "Decline",
"Reconfigure", "Information-Request", "Relay-Forward", "Relay-Reply", "Malformed"]
dhcpv6_messages = [
"Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release",
"Decline", "Reconfigure", "Information-Request", "Relay-Forward", "Relay-Reply", "Malformed"
]

# DHCP_RELAY Config Table
DHCP_RELAY = 'DHCP_RELAY'
Expand All @@ -37,6 +45,75 @@ def get_dhcp_helper_address(ctx, vlan):

show_vlan.VlanBrief.register_column('DHCP Helper Address', get_dhcp_helper_address)

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

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

def get_dhcp4relay_msg_count(self, interface, dir):
""" Get count of a dhcprelay message """
value = self.db.get(self.db.STATE_DB, self.table_name + str(interface), str(dir))
cnts = ast.literal_eval(str(value))
data = []
if cnts is not None:
for k, v in cnts.items():
data.append([k, v])
return data

def clear_table(self, interface):
""" Reset all message counts to 0 """
v4_cnts = {}
for msg in dhcpv4_messages:
v4_cnts[msg] = '0'
self.db.set(self.db.STATE_DB, self.table_name + str(interface), str("RX"), str(v4_cnts))
self.db.set(self.db.STATE_DB, self.table_name + str(interface), str("TX"), str(v4_cnts))

def print_dhcpv4_count(counter, intf):
"""Print count of each message"""
rx_data = counter.get_dhcp4relay_msg_count(intf, "RX")
print(tabulate(rx_data, headers=["Message Type", intf+"(RX)"], tablefmt='simple', stralign='right') + "\n")
tx_data = counter.get_dhcp4relay_msg_count(intf, "TX")
print(tabulate(tx_data, headers=["Message Type", intf+"(TX)"], tablefmt='simple', stralign='right') + "\n")

#
# 'dhcp4relay_counters' group ###
#


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


def ipv4_counters(interface):
counter = DHCPv4_Counter()
counter_intf = counter.get_interface()

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


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


class DHCPv6_Counter(object):
def __init__(self):
Expand All @@ -46,30 +123,37 @@ def __init__(self):

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

def get_dhcp6relay_msg_count(self, interface, msg):
def get_dhcp6relay_msg_count(self, interface, dir):
""" 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]
value = self.db.get(self.db.STATE_DB, self.table_name + str(interface), str(dir))
cnts = ast.literal_eval(str(value))
data = []
if cnts is not None:
for k, v in cnts.items():
data.append([k, v])
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')
v6_cnts = {}
for msg in dhcpv6_messages:
v6_cnts[msg] = '0'
self.db.set(self.db.STATE_DB, self.table_name + str(interface), str("RX"), str(v6_cnts))
self.db.set(self.db.STATE_DB, self.table_name + str(interface), str("TX"), str(v6_cnts))


def print_count(counter, intf):
def print_dhcpv6_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")
rx_data = counter.get_dhcp6relay_msg_count(intf, "RX")
print(tabulate(rx_data, headers=["Message Type", intf+"(RX)"], tablefmt='simple', stralign='right') + "\n")
tx_data = counter.get_dhcp6relay_msg_count(intf, "TX")
print(tabulate(tx_data, headers=["Message Type", intf+"(TX)"], tablefmt='simple', stralign='right') + "\n")


#
Expand All @@ -88,10 +172,10 @@ def ipv6_counters(interface):
counter_intf = counter.get_interface()

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


# 'counts' subcommand ("show dhcp6relay_counters counts")
Expand All @@ -100,7 +184,6 @@ def ipv6_counters(interface):
@click.option('--verbose', is_flag=True, help="Enable verbose output")
def counts(interface, verbose):
"""Show dhcp6relay message counts"""

ipv6_counters(interface)


Expand Down Expand Up @@ -199,6 +282,7 @@ def dhcp_relay_ip6counters(interface):


def register(cli):
cli.add_command(dhcp4relay_counters)
cli.add_command(dhcp6relay_counters)
cli.add_command(dhcp_relay_helper)
cli.add_command(dhcp_relay)
1 change: 1 addition & 0 deletions sonic-slave-bullseye/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ RUN apt-get update && apt-get install -y \
# For DHCP Monitor tool
libexplain-dev \
libevent-dev \
libjsoncpp-dev \
# For libyang
swig \
# For build dtb
Expand Down