Skip to content

Commit 29d4e88

Browse files
Add multi ASIC support for syslog rate limit feature (#3235)
* Add multi ASIC support for syslog rate limit feature * Update command ref
1 parent f81317c commit 29d4e88

File tree

9 files changed

+586
-31
lines changed

9 files changed

+586
-31
lines changed

config/syslog.py

+103-15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import subprocess
66

77
import utilities_common.cli as clicommon
8+
import utilities_common.multi_asic as multi_asic_util
89
from sonic_py_common import logger
10+
from sonic_py_common import multi_asic
911
from syslog_util import common as syslog_common
1012

1113

@@ -457,20 +459,46 @@ def delete(db, server_ip_address):
457459
def rate_limit_host(db, interval, burst):
458460
""" Configure syslog rate limit for host """
459461
syslog_common.rate_limit_validator(interval, burst)
460-
syslog_common.save_rate_limit_to_db(db, None, interval, burst, log)
462+
syslog_common.save_rate_limit_to_db(db.cfgdb, None, interval, burst, log)
461463

462464

463465
@syslog.command("rate-limit-container")
464466
@click.argument("service_name", required=True)
465467
@click.option("-i", "--interval", help="Configures syslog rate limit interval in seconds for specified containers", type=click.IntRange(0, 2147483647))
466468
@click.option("-b", "--burst", help="Configures syslog rate limit burst in number of messages for specified containers", type=click.IntRange(0, 2147483647))
469+
@click.option('--namespace', '-n', 'namespace', default=None,
470+
type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']),
471+
show_default=True, help='Namespace name or all')
467472
@clicommon.pass_db
468-
def rate_limit_container(db, service_name, interval, burst):
473+
def rate_limit_container(db, service_name, interval, burst, namespace):
469474
""" Configure syslog rate limit for containers """
470475
syslog_common.rate_limit_validator(interval, burst)
471-
feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
476+
features = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
477+
syslog_common.service_validator(features, service_name)
478+
479+
global_feature_data, per_ns_feature_data = syslog_common.extract_feature_data(features)
480+
if not namespace:
481+
# for all namespaces
482+
for namespace, cfg_db in db.cfgdb_clients.items():
483+
if namespace == multi_asic.DEFAULT_NAMESPACE:
484+
feature_data = global_feature_data
485+
else:
486+
feature_data = per_ns_feature_data
487+
if service_name and service_name not in feature_data:
488+
continue
489+
syslog_common.service_validator(feature_data, service_name)
490+
syslog_common.save_rate_limit_to_db(cfg_db, service_name, interval, burst, log)
491+
return
492+
elif namespace == 'default':
493+
# for default/global namespace only
494+
namespace = multi_asic.DEFAULT_NAMESPACE
495+
feature_data = global_feature_data
496+
else:
497+
# for a specific namespace
498+
feature_data = per_ns_feature_data
499+
472500
syslog_common.service_validator(feature_data, service_name)
473-
syslog_common.save_rate_limit_to_db(db, service_name, interval, burst, log)
501+
syslog_common.save_rate_limit_to_db(db.cfgdb_clients[namespace], service_name, interval, burst, log)
474502

475503

476504
@syslog.group(
@@ -482,14 +510,70 @@ def rate_limit_feature():
482510
pass
483511

484512

513+
def get_feature_names_to_proceed(db, service_name, namespace):
514+
"""Get feature name list to be proceed by "config syslog rate-limit-feature enable" and
515+
"config syslog rate-limit-feature disable" CLIs
516+
517+
Args:
518+
db (object): Db object
519+
service_name (str): Nullable service name to be enable/disable
520+
namespace (str): Namespace provided by user
521+
522+
Returns:
523+
list: A list of feature name
524+
"""
525+
features = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
526+
if service_name:
527+
syslog_common.service_validator(features, service_name)
528+
529+
global_feature_data, per_ns_feature_data = syslog_common.extract_feature_data(features)
530+
if not namespace:
531+
if not service_name:
532+
feature_list = [feature_name for feature_name in global_feature_data.keys()]
533+
if multi_asic.is_multi_asic():
534+
asic_count = multi_asic.get_num_asics()
535+
for i in range(asic_count):
536+
feature_list.extend([f'{feature_name}{i}' for feature_name in per_ns_feature_data.keys()])
537+
else:
538+
feature_config = features[service_name]
539+
feature_list = []
540+
if feature_config[syslog_common.FEATURE_HAS_GLOBAL_SCOPE].lower() == 'true':
541+
feature_list.append(service_name)
542+
543+
if multi_asic.is_multi_asic():
544+
if feature_config[syslog_common.FEATURE_HAS_PER_ASIC_SCOPE].lower() == 'true':
545+
asic_count = multi_asic.get_num_asics()
546+
for i in range(asic_count):
547+
feature_list.append(multi_asic.get_container_name_from_asic_id(service_name, i))
548+
elif namespace == 'default':
549+
if not service_name:
550+
feature_list = [feature_name for feature_name in global_feature_data.keys()]
551+
else:
552+
syslog_common.service_validator(global_feature_data, service_name)
553+
feature_list = [service_name]
554+
else:
555+
asic_num = multi_asic.get_asic_id_from_name(namespace)
556+
if not service_name:
557+
feature_list = [multi_asic.get_container_name_from_asic_id(feature_name, asic_num) for feature_name in per_ns_feature_data.keys()]
558+
else:
559+
syslog_common.service_validator(per_ns_feature_data, service_name)
560+
feature_list = [multi_asic.get_container_name_from_asic_id(service_name, asic_num)]
561+
return feature_list
562+
563+
485564
@rate_limit_feature.command("enable")
565+
@click.argument("service_name", required=False)
566+
@click.option('--namespace', '-n', 'namespace', default=None,
567+
type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']),
568+
show_default=True, help='Namespace name or all')
486569
@clicommon.pass_db
487-
def enable_rate_limit_feature(db):
570+
def enable_rate_limit_feature(db, service_name, namespace):
488571
""" Enable syslog rate limit feature """
489-
feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
490-
for feature_name in feature_data.keys():
572+
feature_list = get_feature_names_to_proceed(db, service_name, namespace)
573+
for feature_name in feature_list:
491574
click.echo(f'Enabling syslog rate limit feature for {feature_name}')
492-
output, _ = clicommon.run_command(['docker', 'ps', '-q', '-f', 'status=running', '-f', f'name={feature_name}'], return_cmd=True)
575+
shell_cmd = f'docker ps -f status=running --format "{{{{.Names}}}}" | grep -E "^{feature_name}$"'
576+
output, _ = clicommon.run_command(shell_cmd, return_cmd=True, shell=True)
493577
if not output:
494578
click.echo(f'{feature_name} is not running, ignoring...')
495579
continue
@@ -517,16 +601,21 @@ def enable_rate_limit_feature(db):
517601

518602
if not failed:
519603
click.echo(f'Enabled syslog rate limit feature for {feature_name}')
520-
521-
604+
605+
522606
@rate_limit_feature.command("disable")
607+
@click.argument("service_name", required=False)
608+
@click.option('--namespace', '-n', 'namespace', default=None,
609+
type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']),
610+
show_default=True, help='Namespace name or all')
523611
@clicommon.pass_db
524-
def disable_rate_limit_feature(db):
612+
def disable_rate_limit_feature(db, service_name, namespace):
525613
""" Disable syslog rate limit feature """
526-
feature_data = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
527-
for feature_name in feature_data.keys():
614+
feature_list = get_feature_names_to_proceed(db, service_name, namespace)
615+
for feature_name in feature_list:
528616
click.echo(f'Disabling syslog rate limit feature for {feature_name}')
529-
output, _ = clicommon.run_command(['docker', 'ps', '-q', '-f', 'status=running', '-f', f'name={feature_name}'], return_cmd=True)
617+
shell_cmd = f'docker ps -f status=running --format "{{{{.Names}}}}" | grep -E "^{feature_name}$"'
618+
output, _ = clicommon.run_command(shell_cmd, return_cmd=True, shell=True)
530619
if not output:
531620
click.echo(f'{feature_name} is not running, ignoring...')
532621
continue
@@ -553,4 +642,3 @@ def disable_rate_limit_feature(db):
553642

554643
if not failed:
555644
click.echo(f'Disabled syslog rate limit feature for {feature_name}')
556-

doc/Command-Reference.md

+75-3
Original file line numberDiff line numberDiff line change
@@ -10149,7 +10149,7 @@ This command displays rate limit configuration for containers.
1014910149
1015010150
- Usage
1015110151
```
10152-
show syslog rate-limit-container [<service_name>]
10152+
show syslog rate-limit-container [<service_name>] -n [<namespace>]
1015310153
```
1015410154
1015510155
- Example:
@@ -10173,6 +10173,37 @@ This command displays rate limit configuration for containers.
1017310173
SERVICE INTERVAL BURST
1017410174
-------------- ---------- -------
1017510175
bgp 0 0
10176+
10177+
# Multi ASIC
10178+
show syslog rate-limit-container
10179+
SERVICE INTERVAL BURST
10180+
-------- ---------- --------
10181+
bgp 500 N/A
10182+
snmp 300 20000
10183+
swss 2000 12000
10184+
Namespace asic0:
10185+
SERVICE INTERVAL BURST
10186+
-------- ---------- --------
10187+
bgp 500 N/A
10188+
snmp 300 20000
10189+
swss 2000 12000
10190+
10191+
# Multi ASIC
10192+
show syslog rate-limit-container bgp
10193+
SERVICE INTERVAL BURST
10194+
-------- ---------- --------
10195+
bgp 500 5000
10196+
Namespace asic0:
10197+
SERVICE INTERVAL BURST
10198+
-------- ---------- --------
10199+
bgp 500 5000
10200+
10201+
# Multi ASIC
10202+
show syslog rate-limit-container bgp -n asic1
10203+
Namespace asic1:
10204+
SERVICE INTERVAL BURST
10205+
-------- ---------- --------
10206+
bgp 500 5000
1017610207
```
1017710208
1017810209
### Syslog Config Commands
@@ -10251,10 +10282,19 @@ This command is used to configure syslog rate limit for containers.
1025110282
- Parameters:
1025210283
- _interval_: determines the amount of time that is being measured for rate limiting.
1025310284
- _burst_: defines the amount of messages, that have to occur in the time limit of interval, to trigger rate limiting
10285+
- _namespace_: namespace name or all. Value "default" indicates global namespace.
1025410286
1025510287
- Example:
1025610288
```
10289+
# Config bgp for all namespaces. For multi ASIC platforms, bgp service in all namespaces will be affected.
10290+
# For single ASIC platforms, bgp service in global namespace will be affected.
1025710291
admin@sonic:~$ sudo config syslog rate-limit-container bgp --interval 300 --burst 20000
10292+
10293+
# Config bgp for global namespace only.
10294+
config syslog rate-limit-container bgp --interval 300 --burst 20000 -n default
10295+
10296+
# Config bgp for asic0 namespace only.
10297+
config syslog rate-limit-container bgp --interval 300 --burst 20000 -n asic0
1025810298
```
1025910299
1026010300
**config syslog rate-limit-feature enable**
@@ -10263,12 +10303,28 @@ This command is used to enable syslog rate limit feature.
1026310303
1026410304
- Usage:
1026510305
```
10266-
config syslog rate-limit-feature enable
10306+
config syslog rate-limit-feature enable [<service_name>] -n [<namespace>]
1026710307
```
1026810308
1026910309
- Example:
1027010310
```
10311+
# Enable syslog rate limit for all services in all namespaces
1027110312
admin@sonic:~$ sudo config syslog rate-limit-feature enable
10313+
10314+
# Enable syslog rate limit for all services in global namespace
10315+
config syslog rate-limit-feature enable -n default
10316+
10317+
# Enable syslog rate limit for all services in asic0 namespace
10318+
config syslog rate-limit-feature enable -n asic0
10319+
10320+
# Enable syslog rate limit for database in all namespaces
10321+
config syslog rate-limit-feature enable database
10322+
10323+
# Enable syslog rate limit for database in default namespace
10324+
config syslog rate-limit-feature enable database -n default
10325+
10326+
# Enable syslog rate limit for database in asci0 namespace
10327+
config syslog rate-limit-feature enable database -n asci0
1027210328
```
1027310329
1027410330
**config syslog rate-limit-feature disable**
@@ -10277,12 +10333,28 @@ This command is used to disable syslog rate limit feature.
1027710333
1027810334
- Usage:
1027910335
```
10280-
config syslog rate-limit-feature disable
10336+
config syslog rate-limit-feature disable [<service_name>] -n [<namespace>]
1028110337
```
1028210338
1028310339
- Example:
1028410340
```
10341+
# Disable syslog rate limit for all services in all namespaces
1028510342
admin@sonic:~$ sudo config syslog rate-limit-feature disable
10343+
10344+
# Disable syslog rate limit for all services in global namespace
10345+
config syslog rate-limit-feature disable -n default
10346+
10347+
# Disable syslog rate limit for all services in asic0 namespace
10348+
config syslog rate-limit-feature disable -n asic0
10349+
10350+
# Disable syslog rate limit for database in all namespaces
10351+
config syslog rate-limit-feature disable database
10352+
10353+
# Disable syslog rate limit for database in default namespace
10354+
config syslog rate-limit-feature disable database -n default
10355+
10356+
# Disable syslog rate limit for database in asci0 namespace
10357+
config syslog rate-limit-feature disable database -n asci0
1028610358
```
1028710359
1028810360
Go Back To [Beginning of the document](#) or [Beginning of this section](#syslog)

show/syslog.py

+61-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
from unicodedata import name
12
import click
23

34
import tabulate
45
from natsort import natsorted
56

67
import utilities_common.cli as clicommon
8+
import utilities_common.multi_asic as multi_asic_util
9+
from sonic_py_common import multi_asic
710
from syslog_util import common as syslog_common
811

912

@@ -83,25 +86,69 @@ def rate_limit_host(db):
8386
name='rate-limit-container'
8487
)
8588
@click.argument('service_name', metavar='<service_name>', required=False)
89+
@click.option('--namespace', '-n', 'namespace', default=None,
90+
type=click.Choice(multi_asic_util.multi_asic_ns_choices() + ['default']),
91+
show_default=True, help='Namespace name or all')
8692
@clicommon.pass_db
87-
def rate_limit_container(db, service_name):
93+
def rate_limit_container(db, service_name, namespace):
8894
""" Show syslog rate limit configuration for containers """
8995

9096
header = [
9197
"SERVICE",
9298
"INTERVAL",
9399
"BURST",
94100
]
95-
body = []
101+
102+
# Feature configuration in global DB
96103
features = db.cfgdb.get_table(syslog_common.FEATURE_TABLE)
97-
104+
if service_name:
105+
syslog_common.service_validator(features, service_name)
106+
107+
global_feature_data, per_ns_feature_data = syslog_common.extract_feature_data(features)
108+
if not namespace:
109+
# for all namespaces
110+
is_first = True
111+
for namespace, cfg_db in natsorted(db.cfgdb_clients.items()):
112+
if is_first:
113+
is_first = False
114+
else:
115+
# add a new blank line between each namespace
116+
click.echo('\n')
117+
118+
if namespace == multi_asic.DEFAULT_NAMESPACE:
119+
if service_name and service_name not in global_feature_data:
120+
continue
121+
echo_rate_limit_config(header, cfg_db, service_name, global_feature_data)
122+
else:
123+
if service_name and service_name not in per_ns_feature_data:
124+
continue
125+
echo_rate_limit_config(header, cfg_db, service_name, per_ns_feature_data, namespace)
126+
elif namespace == 'default':
127+
# for default/global namespace only
128+
echo_rate_limit_config(header, db.cfgdb, service_name, global_feature_data)
129+
else:
130+
# for a specific namespace
131+
echo_rate_limit_config(header, db.cfgdb_clients[namespace], service_name, per_ns_feature_data, namespace)
132+
133+
134+
def echo_rate_limit_config(header, db, service_name, features, namespace=None):
135+
"""Echo rate limit configuration
136+
137+
Args:
138+
header (list): CLI headers
139+
db (object): Db object
140+
service_name (str): Nullable service name to be printed.
141+
features (dict): Feature data got from CONFIG DB
142+
namespace (str, optional): Namespace provided by user. Defaults to None.
143+
"""
144+
body = []
98145
if service_name:
99146
syslog_common.service_validator(features, service_name)
100147
service_list = [service_name]
101148
else:
102-
service_list = [name for name, service_config in features.items() if service_config.get(syslog_common.SUPPORT_RATE_LIMIT, '').lower() == 'true']
103-
104-
syslog_configs = db.cfgdb.get_table(syslog_common.SYSLOG_CONFIG_FEATURE_TABLE)
149+
service_list = features.keys()
150+
151+
syslog_configs = db.get_table(syslog_common.SYSLOG_CONFIG_FEATURE_TABLE)
105152
for service in natsorted(service_list):
106153
if service in syslog_configs:
107154
entry = syslog_configs[service]
@@ -110,5 +157,11 @@ def rate_limit_container(db, service_name):
110157
entry.get(syslog_common.SYSLOG_RATE_LIMIT_BURST, 'N/A')])
111158
else:
112159
body.append([service, 'N/A', 'N/A'])
113-
114-
click.echo(format(header, body))
160+
161+
if namespace:
162+
click.echo(f'Namespace {namespace}:')
163+
164+
if body:
165+
click.echo(format(header, body))
166+
else:
167+
click.echo('N/A')

0 commit comments

Comments
 (0)