Skip to content

Commit 81fe2bd

Browse files
[debug][undebug] Rework of CLI for BGP (sonic-net#583)
* Changed debug command for FRR * Update undebug * Add ipv6 support to generate_dump
1 parent e40d02d commit 81fe2bd

File tree

5 files changed

+543
-226
lines changed

5 files changed

+543
-226
lines changed

debug/aliases.ini

-5
This file was deleted.

debug/main.py

+265-106
Original file line numberDiff line numberDiff line change
@@ -5,128 +5,287 @@
55
import os
66
import subprocess
77
from click_default_group import DefaultGroup
8-
9-
try:
10-
import ConfigParser as configparser
11-
except ImportError:
12-
import configparser
13-
14-
15-
# This is from the aliases example:
16-
# https://github.com/pallets/click/blob/57c6f09611fc47ca80db0bd010f05998b3c0aa95/examples/aliases/aliases.py
17-
class Config(object):
18-
"""Object to hold CLI config"""
19-
20-
def __init__(self):
21-
self.path = os.getcwd()
22-
self.aliases = {}
23-
24-
def read_config(self, filename):
25-
parser = configparser.RawConfigParser()
26-
parser.read([filename])
27-
try:
28-
self.aliases.update(parser.items('aliases'))
29-
except configparser.NoSectionError:
30-
pass
31-
32-
33-
# Global Config object
34-
_config = None
35-
36-
37-
# This aliased group has been modified from click examples to inherit from DefaultGroup instead of click.Group.
38-
# DefaultFroup is a superclass of click.Group which calls a default subcommand instead of showing
39-
# a help message if no subcommand is passed
40-
class AliasedGroup(DefaultGroup):
41-
"""This subclass of a DefaultGroup supports looking up aliases in a config
42-
file and with a bit of magic.
43-
"""
44-
45-
def get_command(self, ctx, cmd_name):
46-
global _config
47-
48-
# If we haven't instantiated our global config, do it now and load current config
49-
if _config is None:
50-
_config = Config()
51-
52-
# Load our config file
53-
cfg_file = os.path.join(os.path.dirname(__file__), 'aliases.ini')
54-
_config.read_config(cfg_file)
55-
56-
# Try to get builtin commands as normal
57-
rv = click.Group.get_command(self, ctx, cmd_name)
58-
if rv is not None:
59-
return rv
60-
61-
# No builtin found. Look up an explicit command alias in the config
62-
if cmd_name in _config.aliases:
63-
actual_cmd = _config.aliases[cmd_name]
64-
return click.Group.get_command(self, ctx, actual_cmd)
65-
66-
# Alternative option: if we did not find an explicit alias we
67-
# allow automatic abbreviation of the command. "status" for
68-
# instance will match "st". We only allow that however if
69-
# there is only one command.
70-
matches = [x for x in self.list_commands(ctx)
71-
if x.lower().startswith(cmd_name.lower())]
72-
if not matches:
73-
# No command name matched. Issue Default command.
74-
ctx.arg0 = cmd_name
75-
cmd_name = self.default_cmd_name
76-
return DefaultGroup.get_command(self, ctx, cmd_name)
77-
elif len(matches) == 1:
78-
return DefaultGroup.get_command(self, ctx, matches[0])
79-
ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))
80-
8+
from pprint import pprint
819

8210
def run_command(command, pager=False):
83-
if pager is True:
84-
click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green'))
85-
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
86-
click.echo_via_pager(p.stdout.read())
11+
click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green'))
12+
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
13+
output = p.stdout.read()
14+
if pager:
15+
click.echo_via_pager(output)
8716
else:
88-
click.echo(click.style("Command: ", fg='cyan') + click.style(command, fg='green'))
89-
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
90-
click.echo(p.stdout.read())
17+
click.echo(output)
9118

9219

9320
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help', '-?'])
94-
95-
9621
#
9722
# 'cli' group (root group) ###
9823
#
9924

100-
@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS)
25+
@click.group(cls=click.Group, context_settings=CONTEXT_SETTINGS, invoke_without_command=True)
10126
def cli():
10227
"""SONiC command line - 'debug' command"""
10328
pass
10429

105-
#
106-
# 'bgp' group ###
107-
#
10830

109-
@cli.group(cls=AliasedGroup, default_if_no_args=True)
110-
def bgp():
111-
"""debug bgp on """
112-
pass
31+
p = subprocess.check_output(["sudo vtysh -c 'show version'"], shell=True)
32+
if 'FRRouting' in p:
33+
#
34+
# 'bgp' group for FRR ###
35+
#
36+
@cli.group()
37+
def bgp():
38+
"""debug bgp group """
39+
pass
40+
41+
@bgp.command()
42+
def allow_martians():
43+
"""BGP allow martian next hops"""
44+
command = 'sudo vtysh -c "debug bgp allow-martians"'
45+
run_command(command)
46+
47+
@bgp.command()
48+
@click.argument('additional', type=click.Choice(['segment']), required=False)
49+
def as4(additional):
50+
"""BGP AS4 actions"""
51+
command = 'sudo vtysh -c "debug bgp as4'
52+
if additional is not None:
53+
command += " segment"
54+
command += '"'
55+
run_command(command)
56+
57+
@bgp.command()
58+
@click.argument('prefix', required=True)
59+
def bestpath(prefix):
60+
"""BGP bestpath"""
61+
command = 'sudo vtysh -c "debug bgp bestpath %s"' % prefix
62+
run_command(command)
63+
64+
@bgp.command()
65+
@click.argument('prefix_or_iface', required=False)
66+
def keepalives(prefix_or_iface):
67+
"""BGP Neighbor Keepalives"""
68+
command = 'sudo vtysh -c "debug bgp keepalives'
69+
if prefix_or_iface is not None:
70+
command += " " + prefix_or_iface
71+
command += '"'
72+
run_command(command)
73+
74+
@bgp.command()
75+
@click.argument('prefix_or_iface', required=False)
76+
def neighbor_events(prefix_or_iface):
77+
"""BGP Neighbor Events"""
78+
command = 'sudo vtysh -c "debug bgp neighbor-events'
79+
if prefix_or_iface is not None:
80+
command += " " + prefix_or_iface
81+
command += '"'
82+
run_command(command)
83+
84+
@bgp.command()
85+
def nht():
86+
"""BGP nexthop tracking events"""
87+
command = 'sudo vtysh -c "debug bgp nht"'
88+
run_command(command)
89+
90+
@bgp.command()
91+
@click.argument('additional', type=click.Choice(['error']), required=False)
92+
def pbr(additional):
93+
"""BGP policy based routing"""
94+
command = 'sudo vtysh -c "debug bgp pbr'
95+
if additional is not None:
96+
command += " error"
97+
command += '"'
98+
run_command(command)
99+
100+
@bgp.command()
101+
def update_groups():
102+
"""BGP update-groups"""
103+
command = 'sudo vtysh -c "debug bgp update-groups"'
104+
run_command(command)
105+
106+
@bgp.command()
107+
@click.argument('direction', type=click.Choice(['in', 'out', 'prefix']), required=False)
108+
@click.argument('prefix', required=False)
109+
def updates(direction, prefix):
110+
"""BGP updates"""
111+
command = 'sudo vtysh -c "debug bgp updates'
112+
if direction is not None:
113+
command += " " + direction
114+
if prefix is not None:
115+
command += " " + prefix
116+
command += '"'
117+
run_command(command)
118+
119+
@bgp.command()
120+
@click.argument('prefix', required=False)
121+
def zebra(prefix):
122+
"""BGP Zebra messages"""
123+
command = 'sudo vtysh -c "debug bgp zebra'
124+
if prefix is not None:
125+
command += " prefix " + prefix
126+
command += '"'
127+
run_command(command)
128+
129+
#
130+
# 'zebra' group for FRR ###
131+
#
132+
@cli.group()
133+
def zebra():
134+
"""debug zebra group"""
135+
pass
136+
137+
@zebra.command()
138+
@click.argument('detailed', type=click.Choice(['detailed']), required=False)
139+
def dplane(detailed):
140+
"""Debug zebra dataplane events"""
141+
command = 'sudo vtysh -c "debug zebra dplane'
142+
if detailed is not None:
143+
command += " detailed"
144+
command += '"'
145+
run_command(command)
146+
147+
@zebra.command()
148+
def events():
149+
"""Debug option set for zebra events"""
150+
command = 'sudo vtysh -c "debug zebra events"'
151+
run_command(command)
152+
153+
@zebra.command()
154+
def fpm():
155+
"""Debug zebra FPM events"""
156+
command = 'sudo vtysh -c "debug zebra fpm"'
157+
run_command(command)
158+
159+
@zebra.command()
160+
def kernel():
161+
"""Debug option set for zebra between kernel interface"""
162+
command = 'sudo vtysh -c "debug zebra kernel"'
163+
run_command(command)
164+
165+
@zebra.command()
166+
def nht():
167+
"""Debug option set for zebra next hop tracking"""
168+
command = 'sudo vtysh -c "debug zebra nht"'
169+
run_command(command)
170+
171+
@zebra.command()
172+
def packet():
173+
"""Debug option set for zebra packet"""
174+
command = 'sudo vtysh -c "debug zebra packet"'
175+
run_command(command)
176+
177+
@zebra.command()
178+
@click.argument('detailed', type=click.Choice(['detailed']), required=False)
179+
def rib(detailed):
180+
"""Debug RIB events"""
181+
command = 'sudo vtysh -c "debug zebra rib'
182+
if detailed is not None:
183+
command += " detailed"
184+
command += '"'
185+
run_command(command)
186+
187+
@zebra.command()
188+
def vxlan():
189+
"""Debug option set for zebra VxLAN (EVPN)"""
190+
command = 'sudo vtysh -c "debug zebra vxlan"'
191+
run_command(command)
192+
193+
else:
194+
#
195+
# 'bgp' group for quagga ###
196+
#
197+
@cli.group(cls=DefaultGroup, default_if_no_args=True)
198+
#@cli.group()
199+
def bgp():
200+
"""debug bgp on """
201+
pass
202+
203+
@bgp.command(default=True)
204+
def default():
205+
"""debug bgp"""
206+
command = 'sudo vtysh -c "debug bgp"'
207+
run_command(command)
208+
209+
@bgp.command()
210+
def events():
211+
"""debug bgp events on"""
212+
command = 'sudo vtysh -c "debug bgp events"'
213+
run_command(command)
214+
215+
@bgp.command()
216+
def updates():
217+
"""debug bgp updates on"""
218+
command = 'sudo vtysh -c "debug bgp updates"'
219+
run_command(command)
220+
221+
@bgp.command()
222+
def as4():
223+
"""debug bgp as4 actions on"""
224+
command = 'sudo vtysh -c "debug bgp as4"'
225+
run_command(command)
226+
227+
@bgp.command()
228+
def filters():
229+
"""debug bgp filters on"""
230+
command = 'sudo vtysh -c "debug bgp filters"'
231+
run_command(command)
232+
233+
@bgp.command()
234+
def fsm():
235+
"""debug bgp finite state machine on"""
236+
command = 'sudo vtysh -c "debug bgp fsm"'
237+
run_command(command)
238+
239+
@bgp.command()
240+
def keepalives():
241+
"""debug bgp keepalives on"""
242+
command = 'sudo vtysh -c "debug bgp keepalives"'
243+
run_command(command)
244+
245+
@bgp.command()
246+
def zebra():
247+
"""debug bgp zebra messages on"""
248+
command = 'sudo vtysh -c "debug bgp zebra"'
249+
run_command(command)
250+
251+
#
252+
# 'zebra' group for quagga ###
253+
#
254+
@cli.group()
255+
def zebra():
256+
"""debug zebra group"""
257+
pass
258+
259+
@zebra.command()
260+
def events():
261+
"""debug option set for zebra events"""
262+
command = 'sudo vtysh -c "debug zebra events"'
263+
run_command(command)
264+
265+
@zebra.command()
266+
def fpm():
267+
"""debug zebra FPM events"""
268+
command = 'sudo vtysh -c "debug zebra fpm"'
269+
run_command(command)
270+
271+
@zebra.command()
272+
def kernel():
273+
"""debug option set for zebra between kernel interface"""
274+
command = 'sudo vtysh -c "debug zebra kernel"'
275+
run_command(command)
276+
277+
@zebra.command()
278+
def packet():
279+
"""debug option set for zebra packet"""
280+
command = 'sudo vtysh -c "debug zebra packet"'
281+
run_command(command)
282+
283+
@zebra.command()
284+
def rib():
285+
"""debug RIB events"""
286+
command = 'sudo vtysh -c "debug zebra rib"'
287+
run_command(command)
113288

114-
@bgp.command(default=True)
115-
def default():
116-
command = 'sudo vtysh -c "debug bgp"'
117-
run_command(command)
118-
119-
@bgp.command()
120-
def events():
121-
"""debug bgp events on """
122-
command = 'sudo vtysh -c "debug bgp events"'
123-
run_command(command)
124-
125-
@bgp.command()
126-
def updates():
127-
"""debug bgp events on """
128-
command = 'sudo vtysh -c "debug bgp updates"'
129-
run_command(command)
130289

131290
if __name__ == '__main__':
132291
cli()

0 commit comments

Comments
 (0)