Skip to content

Commit 16b2274

Browse files
authored
Support shared headroom pool on top of dynamic buffer calculation (sonic-net#1348)
**- What I did** Support shared headroom pool on top of dynamic buffer calculation. Signed-off-by: Stephen Sun <[email protected]> **- How I did it** 1. Introduce new commands for shared headroom pool configuration. - config buffer shared-headroom-pool over-subscribe-ratio - config buffer shared-headroom-pool size Shared headroom pool can be enabled by configuring either over-subscribe-ratio or size. In case both configured, the size will take effect. The following existing commands has been updated accordingly: - config buffer profile 2. Update db_migrator: - Port version 1.0.5 from 201911 branch - Port the main logic of Mellanox buffer migrator from 201911 - Add unit test infra for Mellanox buffer migrator 3. Command "config qos clear/reload" has been updated with tables for dynamic buffer calculation cleared as well **- How to verify it** Run unit test and regression test.
1 parent 2ad1168 commit 16b2274

File tree

186 files changed

+182252
-417
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

186 files changed

+182252
-417
lines changed

config/main.py

+122-27
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,9 @@ def _clear_qos():
658658
'BUFFER_POOL',
659659
'BUFFER_PROFILE',
660660
'BUFFER_PG',
661-
'BUFFER_QUEUE']
661+
'BUFFER_QUEUE',
662+
'DEFAULT_LOSSLESS_BUFFER_PARAMETER',
663+
'LOSSLESS_TRAFFIC_PATTERN']
662664

663665
namespace_list = [DEFAULT_NAMESPACE]
664666
if multi_asic.get_num_asics() > 1:
@@ -3679,11 +3681,28 @@ def set_profile(db, profile, xon, xoff, size, dynamic_th, pool):
36793681
update_profile(ctx, config_db, profile, xon, xoff, size, dynamic_th, pool, profile_entry)
36803682

36813683

3684+
def _is_shared_headroom_pool_enabled(ctx, config_db):
3685+
ingress_lossless_pool = config_db.get_entry('BUFFER_POOL', 'ingress_lossless_pool')
3686+
if 'xoff' in ingress_lossless_pool:
3687+
return True
3688+
3689+
default_lossless_param_table = config_db.get_table('DEFAULT_LOSSLESS_BUFFER_PARAMETER')
3690+
if not default_lossless_param_table:
3691+
ctx.fail("Dynamic buffer calculation is enabled while no entry found in DEFAULT_LOSSLESS_BUFFER_PARAMETER table")
3692+
default_lossless_param = list(default_lossless_param_table.values())[0]
3693+
over_subscribe_ratio = default_lossless_param.get('over_subscribe_ratio')
3694+
if over_subscribe_ratio and over_subscribe_ratio != '0':
3695+
return True
3696+
3697+
return False
3698+
3699+
36823700
def update_profile(ctx, config_db, profile_name, xon, xoff, size, dynamic_th, pool, profile_entry = None):
36833701
params = {}
36843702
if profile_entry:
36853703
params = profile_entry
3686-
dynamic_calculate = True
3704+
3705+
shp_enabled = _is_shared_headroom_pool_enabled(ctx, config_db)
36873706

36883707
if not pool:
36893708
pool = 'ingress_lossless_pool'
@@ -3693,48 +3712,62 @@ def update_profile(ctx, config_db, profile_name, xon, xoff, size, dynamic_th, po
36933712

36943713
if xon:
36953714
params['xon'] = xon
3696-
dynamic_calculate = False
36973715
else:
36983716
xon = params.get('xon')
36993717

37003718
if xoff:
37013719
params['xoff'] = xoff
3702-
dynamic_calculate = False
37033720
else:
37043721
xoff = params.get('xoff')
37053722

37063723
if size:
37073724
params['size'] = size
3708-
dynamic_calculate = False
3709-
if xon and not xoff:
3710-
xoff = int(size) - int (xon)
3711-
params['xoff'] = xoff
3712-
elif not dynamic_calculate:
3713-
if xon and xoff:
3714-
size = int(xon) + int(xoff)
3715-
params['size'] = size
3716-
else:
3717-
ctx.fail("Either both xon and xoff or size should be provided")
3725+
else:
3726+
size = params.get('size')
3727+
3728+
dynamic_calculate = False if (xon or xoff or size) else True
37183729

37193730
if dynamic_calculate:
37203731
params['headroom_type'] = 'dynamic'
37213732
if not dynamic_th:
37223733
ctx.fail("Either size information (xon, xoff, size) or dynamic_th needs to be provided")
3723-
3724-
if dynamic_th:
37253734
params['dynamic_th'] = dynamic_th
37263735
else:
3727-
# Fetch all the keys of default_lossless_buffer_parameter table
3728-
# and then get the default_dynamic_th from that entry (should be only one)
3729-
keys = config_db.get_keys('DEFAULT_LOSSLESS_BUFFER_PARAMETER')
3730-
if len(keys) > 1 or len(keys) == 0:
3731-
ctx.fail("Multiple or no entry in DEFAULT_LOSSLESS_BUFFER_PARAMETER found while no dynamic_th specified")
3732-
3733-
default_lossless_param = config_db.get_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', keys[0])
3734-
if 'default_dynamic_th' in default_lossless_param.keys():
3735-
params['dynamic_th'] = default_lossless_param['default_dynamic_th']
3736-
else:
3737-
ctx.fail("No dynamic_th defined in DEFAULT_LOSSLESS_BUFFER_PARAMETER")
3736+
if not xon:
3737+
ctx.fail("Xon is mandatory for non-dynamic profile")
3738+
3739+
if not xoff:
3740+
if shp_enabled:
3741+
ctx.fail("Shared headroom pool is enabled, xoff is mandatory for non-dynamic profile")
3742+
elif not size:
3743+
ctx.fail("Neither xoff nor size is provided")
3744+
else:
3745+
xoff_number = int(size) - int(xon)
3746+
if xoff_number <= 0:
3747+
ctx.fail("The xoff must be greater than 0 while we got {} (calculated by: size {} - xon {})".format(xoff_number, size, xon))
3748+
params['xoff'] = str(xoff_number)
3749+
3750+
if not size:
3751+
if shp_enabled:
3752+
size = int(xon)
3753+
else:
3754+
size = int(xon) + int(xoff)
3755+
params['size'] = size
3756+
3757+
if dynamic_th:
3758+
params['dynamic_th'] = dynamic_th
3759+
elif not params.get('dynamic_th'):
3760+
# Fetch all the keys of default_lossless_buffer_parameter table
3761+
# and then get the default_dynamic_th from that entry (should be only one)
3762+
keys = config_db.get_keys('DEFAULT_LOSSLESS_BUFFER_PARAMETER')
3763+
if len(keys) != 1:
3764+
ctx.fail("Multiple entries are found in DEFAULT_LOSSLESS_BUFFER_PARAMETER while no dynamic_th specified")
3765+
3766+
default_lossless_param = config_db.get_entry('DEFAULT_LOSSLESS_BUFFER_PARAMETER', keys[0])
3767+
if 'default_dynamic_th' in default_lossless_param:
3768+
params['dynamic_th'] = default_lossless_param['default_dynamic_th']
3769+
else:
3770+
ctx.fail("No dynamic_th defined in DEFAULT_LOSSLESS_BUFFER_PARAMETER")
37383771

37393772
config_db.set_entry("BUFFER_PROFILE", (profile_name), params)
37403773

@@ -3760,6 +3793,68 @@ def remove_profile(db, profile):
37603793
else:
37613794
ctx.fail("Profile {} doesn't exist".format(profile))
37623795

3796+
@buffer.group(cls=clicommon.AbbreviationGroup)
3797+
@click.pass_context
3798+
def shared_headroom_pool(ctx):
3799+
"""Configure buffer shared headroom pool"""
3800+
pass
3801+
3802+
3803+
@shared_headroom_pool.command()
3804+
@click.argument('ratio', metavar='<ratio>', type=int, required=True)
3805+
@clicommon.pass_db
3806+
def over_subscribe_ratio(db, ratio):
3807+
"""Configure over subscribe ratio"""
3808+
config_db = db.cfgdb
3809+
ctx = click.get_current_context()
3810+
3811+
port_number = len(config_db.get_table('PORT'))
3812+
if ratio < 0 or ratio > port_number:
3813+
ctx.fail("Invalid over-subscribe-ratio value {}. It should be in range [0, {}]".format(ratio, port_number))
3814+
3815+
default_lossless_param = config_db.get_table("DEFAULT_LOSSLESS_BUFFER_PARAMETER")
3816+
first_item = True
3817+
for k, v in default_lossless_param.items():
3818+
if not first_item:
3819+
ctx.fail("More than one item in DEFAULT_LOSSLESS_BUFFER_PARAMETER table. Only the first one is updated")
3820+
first_item = False
3821+
3822+
if ratio == 0:
3823+
if "over_subscribe_ratio" in v.keys():
3824+
v.pop("over_subscribe_ratio")
3825+
else:
3826+
v["over_subscribe_ratio"] = ratio
3827+
3828+
config_db.set_entry("DEFAULT_LOSSLESS_BUFFER_PARAMETER", k, v)
3829+
3830+
3831+
@shared_headroom_pool.command()
3832+
@click.argument('size', metavar='<size>', type=int, required=True)
3833+
@clicommon.pass_db
3834+
def size(db, size):
3835+
"""Configure shared headroom pool size"""
3836+
config_db = db.cfgdb
3837+
state_db = db.db
3838+
ctx = click.get_current_context()
3839+
3840+
_hash = 'BUFFER_MAX_PARAM_TABLE|global'
3841+
buffer_max_params = state_db.get_all(state_db.STATE_DB, _hash)
3842+
if buffer_max_params:
3843+
mmu_size = buffer_max_params.get('mmu_size')
3844+
if mmu_size and int(mmu_size) < size:
3845+
ctx.fail("Shared headroom pool must be less than mmu size ({})".format(mmu_size))
3846+
3847+
ingress_lossless_pool = config_db.get_entry("BUFFER_POOL", "ingress_lossless_pool")
3848+
3849+
if size == 0:
3850+
if "xoff" in ingress_lossless_pool:
3851+
ingress_lossless_pool.pop("xoff")
3852+
else:
3853+
ingress_lossless_pool["xoff"] = size
3854+
3855+
config_db.set_entry("BUFFER_POOL", "ingress_lossless_pool", ingress_lossless_pool)
3856+
3857+
37633858
#
37643859
# 'platform' group ('config platform ...')
37653860
#

doc/Command-Reference.md

+42-8
Original file line numberDiff line numberDiff line change
@@ -2363,25 +2363,53 @@ Dynamic buffer management is responsible for calculating buffer size according t
23632363
23642364
### Configuration commands
23652365
2366+
**configure shared headroom pool**
2367+
2368+
This command is used to configure the shared headroom pool. The shared headroom pool can be enabled in the following ways:
2369+
2370+
- Configure the over subscribe ratio. In this case, the size of shared headroom pool is calculated as the accumulative xoff of all of the lossless PG divided by the over subscribe ratio.
2371+
- Configure the size.
2372+
2373+
In case both of the above parameters have been configured, the `size` will take effect. To disable shared headroom pool, configure both parameters to zero.
2374+
2375+
- Usage:
2376+
2377+
```
2378+
config buffer shared-headroom-pool over-subscribe-ratio <over-subscribe-ratio>
2379+
config buffer shared-headroom-pool size <size>
2380+
```
2381+
2382+
The range of over-subscribe-ratio is from 1 to number of ports inclusive.
2383+
2384+
- Example:
2385+
2386+
```
2387+
admin@sonic:~$ sudo config shared-headroom-pool over-subscribe-ratio 2
2388+
admin@sonic:~$ sudo config shared-headroom-pool size 1024000
2389+
```
2390+
23662391
**configure a lossless buffer profile**
23672392
23682393
This command is used to configure a lossless buffer profile.
23692394
23702395
- Usage:
23712396
23722397
```
2373-
config buffer_profile add <profile_name> -xon <xon_threshold> -xoff <xoff_threshold> [-size <size>] [-dynamic_th <dynamic_th_value>] [-pool <ingress_lossless_pool_name>]
2374-
config buffer_profile set <profile_name> -xon <xon_threshold> -xoff <xoff_threshold> [-size <size>] [-dynamic_th <dynamic_th_value>] [-pool <ingress_lossless_pool_name>]
2375-
config buffer_profile remove <profile_name>
2398+
config buffer profile add <profile_name> --xon <xon_threshold> --xoff <xoff_threshold> [-size <size>] [-dynamic_th <dynamic_th_value>] [-pool <ingress_lossless_pool_name>]
2399+
config buffer profile set <profile_name> --xon <xon_threshold> --xoff <xoff_threshold> [-size <size>] [-dynamic_th <dynamic_th_value>] [-pool <ingress_lossless_pool_name>]
2400+
config buffer profile remove <profile_name>
23762401
```
23772402
23782403
All the parameters are devided to two groups, one for headroom and one for dynamic_th. For any command at lease one group of parameters should be provided.
23792404
For headroom parameters:
23802405
2381-
- At lease one of `xoff` and `size` should be provided and the other will be optional and conducted via the formula `xon + xoff = size`.
2382-
All other parameters are optional.
23832406
- `xon` is madantory.
2384-
- `xon` + `xoff` <= `size`; For Mellanox platform xon + xoff == size
2407+
- If shared headroom pool is disabled:
2408+
- At lease one of `xoff` and `size` should be provided and the other will be optional and conducted via the formula `xon + xoff = size`.
2409+
- `xon` + `xoff` <= `size`; For Mellanox platform xon + xoff == size
2410+
- If shared headroom pool is enabled:
2411+
- `xoff` should be provided.
2412+
- `size` = `xoff` if it is not provided.
23852413
23862414
If only headroom parameters are provided, the `dynamic_th` will be taken from `CONFIG_DB.DEFAULT_LOSSLESS_BUFFER_PARAMETER.default_dynamic_th`.
23872415
@@ -2397,8 +2425,8 @@ This command is used to configure a lossless buffer profile.
23972425
- Example:
23982426
23992427
```
2400-
admin@sonic:~$ sudo config buffer_profile add profile1 -xon 18432 -xoff 18432
2401-
admin@sonic:~$ sudo config buffer_profile remove profile1
2428+
admin@sonic:~$ sudo config buffer profile add profile1 --xon 18432 --xoff 18432
2429+
admin@sonic:~$ sudo config buffer profile remove profile1
24022430
```
24032431
24042432
**config interface cable_length**
@@ -2597,6 +2625,12 @@ This command is used to display the status of buffer pools and profiles currentl
25972625
25982626
```
25992627
admin@sonic:~$ show buffer configuration
2628+
Lossless traffic pattern:
2629+
-------------------- -
2630+
default_dynamic_th 0
2631+
over_subscribe_ratio 0
2632+
-------------------- -
2633+
26002634
Pool: ingress_lossless_pool
26012635
---- --------
26022636
type ingress

0 commit comments

Comments
 (0)