Skip to content
Open
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
90 changes: 90 additions & 0 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4909,6 +4909,96 @@ def interface(ctx, namespace):
config_db = ConfigDBConnector(use_unix_socket_path=True, namespace=str(namespace))
config_db.connect()
ctx.obj = {'config_db': config_db, 'namespace': str(namespace)}


@config.group(cls=clicommon.AliasedGroup, name='switch-fast-linkup', context_settings=CONTEXT_SETTINGS)
@click.pass_context
def switch_fast_linkup_group(ctx):
"""Configure fast link-up global configuration parameters"""
pass


# 'global' subcommand
@switch_fast_linkup_group.command(name='global')
@click.option('--polling-time', type=int, required=False, help='Polling time (sec)')
@click.option('--guard-time', type=int, required=False, help='Guard time (sec)')
@click.option('--ber', '--ber-threshold', type=int, required=False, help='BER threshold exponent (e.g., 12 for 1e-12)')
@clicommon.pass_db
def switch_fast_linkup_global_cmd(db, polling_time, guard_time, ber):
"""Configure global fast link-up feature parameters"""
if polling_time is None and guard_time is None and ber is None:
raise click.UsageError('Failed to configure fast link-up global: no options are provided')
# Read capability and ranges from STATE_DB for validation
state_db = db.db.STATE_DB
cap_tbl = db.db.get_all(state_db, 'SWITCH_CAPABILITY|switch') or {}
if cap_tbl.get('FAST_LINKUP_CAPABLE', 'false') != 'true':
raise click.ClickException('Fast link-up is not supported on this platform')

poll_range_str = cap_tbl.get('FAST_LINKUP_POLLING_TIMER_RANGE')
guard_range_str = cap_tbl.get('FAST_LINKUP_GUARD_TIMER_RANGE')
if not poll_range_str or not guard_range_str:
raise click.ClickException('Fast link-up capability ranges are not defined on this platform')

poll_range = poll_range_str.split(',')
guard_range = guard_range_str.split(',')

data = {}
if polling_time is not None:
if not (int(poll_range[0]) <= int(polling_time) <= int(poll_range[1])):
raise click.ClickException('polling_time {} out of supported range [{}, {}]'.format(
polling_time, poll_range[0], poll_range[1]))
data['polling_time'] = str(polling_time)
if guard_time is not None:
if not (int(guard_range[0]) <= int(guard_time) <= int(guard_range[1])):
raise click.ClickException('guard_time {} out of supported range [{}, {}]'.format(
guard_time, guard_range[0], guard_range[1]))
data['guard_time'] = str(guard_time)
if ber is not None:
if int(ber) < 1 or int(ber) > 255:
raise click.ClickException('ber_threshold {} out of supported range [1, 255]'.format(ber))
data['ber_threshold'] = str(ber)
try:
db.cfgdb.mod_entry('SWITCH_FAST_LINKUP', 'GLOBAL', data)

log.log_notice('Configured fast link-up global: {}'.format(data))
except Exception as e:
log.log_error('Failed to configure fast link-up global: {}'.format(str(e)))
raise SystemExit(1)


# 'fast-linkup' subcommand
@interface.command('fast-linkup')
@click.argument('interface_name', metavar='<interface_name>', required=True)
@click.argument('mode', metavar='<enabled|disabled>', required=True, type=click.Choice(['enabled', 'disabled']))
@click.option('-v', '--verbose', is_flag=True, help='Enable verbose output')
@click.pass_context
def fast_linkup(ctx, interface_name, mode, verbose):
"""Enable/disable fast link-up on an interface"""
config_db = ctx.obj['config_db']
namespace = ctx.obj.get('namespace', DEFAULT_NAMESPACE)

if clicommon.get_interface_naming_mode() == 'alias':
interface_name = interface_alias_to_name(config_db, interface_name)
if interface_name is None:
raise click.ClickException("'interface_name' is None!")
if not interface_name_is_valid(config_db, interface_name):
raise click.ClickException('Interface name is invalid. Please enter a valid interface name')

# Read capability from STATE_DB for validation
db = Db()
state_db = db.db_clients.get(namespace, db.db)
cap_tbl = state_db.get_all(state_db.STATE_DB, 'SWITCH_CAPABILITY|switch') or {}
if cap_tbl.get('FAST_LINKUP_CAPABLE', 'false') != 'true':
raise click.ClickException('Fast link-up is not supported on this platform')

log.log_info("'interface fast-linkup {} {}' executing...".format(interface_name, mode))
if namespace is DEFAULT_NAMESPACE:
command = ['portconfig', '-p', str(interface_name), '-fl', str(mode)]
else:
command = ['portconfig', '-p', str(interface_name), '-fl', str(mode), '-n', str(namespace)]
if verbose:
command += ['-vv']
clicommon.run_command(command, display_cmd=verbose)
#
# 'startup' subcommand
#
Expand Down
86 changes: 86 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5323,6 +5323,92 @@ This command is used to manage switch hash algorithm global configuration.
admin@sonic:~$ config switch-hash global lag-hash-algorithm 'CRC'
```

## Fast Link-Up

This section documents the commands to configure and display the Fast Link-Up feature.

### Fast Link-Up Show Commands

**show switch-fast-linkup global**

Display switch Fast Link-Up global configuration.

- Usage:
```bash
show switch-fast-linkup global [--json]
```

- Examples:
```bash
admin@sonic:~$ show switch-fast-linkup global
Field Value
------------- -----
polling_time 60
guard_time 10
ber_threshold 12
```

**show interfaces fast-linkup status**

Display per-interface Fast Link-Up mode.

- Usage:
```bash
show interfaces fast-linkup status
```

- Example:
```bash
admin@sonic:~$ show interfaces fast-linkup status
Interface fast_linkup
----------- -----------
Ethernet0 true
Ethernet4 false
```

### Fast Link-Up Config Commands

**config switch-fast-linkup global**

Configure the switch Fast Link-Up global parameters.

- Usage:
```bash
config switch-fast-linkup global [--polling-time <sec>] [--guard-time <sec>] [--ber <exp>]
```

- Parameters:
- _polling-time_: time in seconds to attempt fast link-up (uint16).
- _guard-time_: time in seconds link must stay up with low BER to keep fast link-up (uint8).
- _ber_: BER threshold exponent (uint8). Example: 12 means 1e-12.

- Validation:
- Reads `SWITCH_CAPABILITY|switch` from STATE_DB. Fails if `FAST_LINKUP_CAPABLE != true`.
- If ranges are present, rejects out-of-range `polling_time`/`guard_time`.

- Examples:
```bash
admin@sonic:~$ config switch-fast-linkup global --polling-time 60 --guard-time 10 --ber 12
```

**config interface fast-linkup**

Enable/disable Fast Link-Up per interface.

- Usage:
```bash
config interface fast-linkup <interface_name> <enabled|disabled>
```

- Behavior:
- Writes `PORT|<interface_name>:fast_linkup` as `true` (enabled) or `false` (disabled).

- Examples:
```bash
admin@sonic:~$ config interface fast-linkup Ethernet0 enabled
admin@sonic:~$ config interface fast-linkup Ethernet4 disabled
```

## Interfaces

### Interface Show Commands
Expand Down
26 changes: 25 additions & 1 deletion scripts/portconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ portconfig is the utility to show and change ECN configuration
usage: portconfig [-h] [-v] [-s] [-f] [-m] [-tp] [-p PROFILE] [-gmin GREEN_MIN]
[-gmax GREEN_MAX] [-ymin YELLOW_MIN] [-ymax YELLOW_MAX]
[-rmin RED_MIN] [-rmax RED_MAX] [-vv] [-n namespace]
[-fl FAST_LINKUP]

optional arguments:
-h --help show this help message and exit
Expand All @@ -22,6 +23,7 @@ optional arguments:
-t --interface-type port interface type
-T --adv-interface-types port advertised interface types
-lt --link-training port link training mode
-fl --fast-linkup port fast link-up mode (enabled/disabled)
-P --tx-power 400G ZR modulet target Tx output power (dBm)
-F --laser-freq 400G ZR module 75GHz grid frequency (GHz)
"""
Expand Down Expand Up @@ -56,6 +58,7 @@ PORT_ADV_SPEEDS_CONFIG_FIELD_NAME = "adv_speeds"
PORT_INTERFACE_TYPE_CONFIG_FIELD_NAME = "interface_type"
PORT_ADV_INTERFACE_TYPES_CONFIG_FIELD_NAME = "adv_interface_types"
PORT_LINK_TRAINING_CONFIG_FIELD_NAME = "link_training"
PORT_FAST_LINKUP_CONFIG_FIELD_NAME = "fast_linkup"
PORT_XCVR_LASER_FREQ_FIELD_NAME = "laser_freq"
PORT_XCVR_TX_POWER_FIELD_NAME = "tx_power"
PORT_CHANNEL_TABLE_NAME = "PORTCHANNEL"
Expand Down Expand Up @@ -325,6 +328,23 @@ class portconfig(object):
else:
raise Exception("System not ready to accept TPID config. Please try again later.")

def set_fast_linkup(self, port, mode):
if self.is_lag:
raise Exception("Invalid port %s" % (port))
if self.verbose:
print("Setting fast-linkup %s on port %s" % (mode, port))

normalized = str(mode).strip().lower()
if normalized == 'enabled':
value = 'true'
elif normalized == 'disabled':
value = 'false'
else:
print('Invalid fast-linkup mode specified: {}'.format(mode))
print('Valid modes: enabled, disabled')
exit(1)
self.db.mod_entry(PORT_TABLE_NAME, port, {PORT_FAST_LINKUP_CONFIG_FIELD_NAME: value})


def main():
parser = argparse.ArgumentParser(description='Set SONiC port parameters',
Expand All @@ -349,6 +369,8 @@ def main():
help = 'port advertised interface types', default=None)
parser.add_argument('-lt', '--link-training', type = str, required = False,
help = 'port link training mode', default=None)
parser.add_argument('-fl', '--fast-linkup', type=str, required=False,
help='port fast link-up mode (enabled|disabled)', default=None)
parser.add_argument('-P', '--tx-power', type=float, required=False,
help='Tx output power(dBm)', default=None)
parser.add_argument('-F', '--laser-freq', type=int, required=False,
Expand All @@ -363,7 +385,7 @@ def main():
port.list_params(args.port)
elif args.speed or args.fec or args.mtu or args.link_training or args.autoneg or args.adv_speeds or \
args.interface_type or args.adv_interface_types or args.tpid or \
args.tx_power or args.laser_freq:
args.tx_power or args.laser_freq or args.fast_linkup:
if args.speed:
port.set_speed(args.port, args.speed)
if args.fec:
Expand All @@ -374,6 +396,8 @@ def main():
port.set_link_training(args.port, args.link_training)
if args.autoneg:
port.set_autoneg(args.port, args.autoneg)
if args.fast_linkup:
port.set_fast_linkup(args.port, args.fast_linkup)
if args.adv_speeds:
port.set_adv_speeds(args.port, args.adv_speeds)
if args.interface_type:
Expand Down
24 changes: 24 additions & 0 deletions show/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1214,3 +1214,27 @@ def tablelize(keys):

header = ['Interface', 'DHCP Mitigation Rate']
click.echo(tabulate(tablelize(keys), header, tablefmt="simple", stralign='left'))


#
# fast-linkup group (show interfaces fast-linkup ...)
#


@interfaces.group(name='fast-linkup', cls=clicommon.AliasedGroup)
def fast_linkup():
"""Show interface fast-linkup information"""
pass


@fast_linkup.command(name='status')
@clicommon.pass_db
def fast_linkup_status(db):
"""show interfaces fast-linkup status"""
config_db = db.cfgdb
ports = config_db.get_table('PORT') or {}
rows = []
for ifname, entry in natsorted(ports.items()):
fast_linkup = entry.get('fast_linkup', 'false')
rows.append([ifname, fast_linkup])
click.echo(tabulate(rows, headers=['Interface', 'fast_linkup'], tablefmt='outline'))
22 changes: 22 additions & 0 deletions show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2875,6 +2875,28 @@ def banner(db):
click.echo(tabulate(messages, headers=hdrs, tablefmt='simple', missingval=''))


#
# 'switch-fast-linkup' command group ("show switch-fast-linkup ...")
#
@cli.group(cls=clicommon.AliasedGroup, name='switch-fast-linkup', context_settings=CONTEXT_SETTINGS)
@click.pass_context
def switch_fast_linkup_group(ctx):
"""Show fast link-up feature configuration (global)"""
pass


@switch_fast_linkup_group.command(name='global')
@click.option('--json', 'json_output', is_flag=True, default=False, help='JSON output')
@clicommon.pass_db
def show_fast_linkup_global(db, json_output):
data = db.cfgdb.get_entry('SWITCH_FAST_LINKUP', 'GLOBAL') or {}
if json_output:
click.echo(json.dumps(data, indent=2))
return
rows = [[k, v] for k, v in data.items()]
click.echo(tabulate(rows, headers=['Field', 'Value'], tablefmt='grid'))


# Load plugins and register them
helper = util_base.UtilHelper()
helper.load_and_register_plugins(plugins, cli)
Expand Down
9 changes: 9 additions & 0 deletions tests/fast_linkup_input/mock_config/global/config_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"SWITCH_FAST_LINKUP|GLOBAL": {
"polling_time": "60",
"guard_time": "10",
"ber_threshold": "12"
}
}


12 changes: 12 additions & 0 deletions tests/fast_linkup_input/mock_config/ports/config_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"PORT|Ethernet0": {
"admin_status": "up",
"fast_linkup": "true"
},
"PORT|Ethernet4": {
"admin_status": "up",
"fast_linkup": "false"
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"SWITCH_CAPABILITY|switch": {
"FAST_LINKUP_CAPABLE": "true"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"SWITCH_CAPABILITY|switch": {
"FAST_LINKUP_CAPABLE": "false"
}
}


9 changes: 9 additions & 0 deletions tests/fast_linkup_input/mock_state/supported/state_db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"SWITCH_CAPABILITY|switch": {
"FAST_LINKUP_CAPABLE": "true",
"FAST_LINKUP_POLLING_TIMER_RANGE": "5,120",
"FAST_LINKUP_GUARD_TIMER_RANGE": "1,20"
}
}


Loading
Loading