Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
JunhongMao committed Dec 12, 2023
2 parents 86d3efa + 377e581 commit 1ca9676
Show file tree
Hide file tree
Showing 64 changed files with 3,383 additions and 1,047 deletions.
9 changes: 8 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ resources:
name: sonic-net/sonic-swss
endpoint: sonic-net

variables:
- name: BUILD_BRANCH
${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
value: $(System.PullRequest.TargetBranch)
${{ else }}:
value: $(Build.SourceBranchName)

stages:
- stage: Build

Expand All @@ -26,7 +33,7 @@ stages:
vmImage: ubuntu-20.04

container:
image: sonicdev-microsoft.azurecr.io:443/sonic-slave-bullseye:latest
image: sonicdev-microsoft.azurecr.io:443/sonic-slave-bullseye:$(BUILD_BRANCH)

steps:
- script: |
Expand Down
46 changes: 44 additions & 2 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import time
import itertools
import copy
import tempfile

from jsonpatch import JsonPatchConflict
from jsonpointer import JsonPointerException
Expand Down Expand Up @@ -142,6 +143,14 @@ def read_json_file(fileName):
raise Exception(str(e))
return result

# write given JSON file
def write_json_file(json_input, fileName):
try:
with open(fileName, 'w') as f:
json.dump(json_input, f, indent=4)
except Exception as e:
raise Exception(str(e))

def _get_breakout_options(ctx, args, incomplete):
""" Provides dynamic mode option as per user argument i.e. interface name """
all_mode_options = []
Expand Down Expand Up @@ -1525,6 +1534,12 @@ def reload(db, filename, yes, load_sysinfo, no_service_restart, force, file_form
# Get the file from user input, else take the default file /etc/sonic/config_db{NS_id}.json
if cfg_files:
file = cfg_files[inst+1]
# Save to tmpfile in case of stdin input which can only be read once
if file == "/dev/stdin":
file_input = read_json_file(file)
(_, tmpfname) = tempfile.mkstemp(dir="/tmp", suffix="_configReloadStdin")
write_json_file(file_input, tmpfname)
file = tmpfname
else:
if file_format == 'config_db':
if namespace is None:
Expand All @@ -1540,6 +1555,19 @@ def reload(db, filename, yes, load_sysinfo, no_service_restart, force, file_form
click.echo("The config file {} doesn't exist".format(file))
continue

if file_format == 'config_db':
file_input = read_json_file(file)

platform = file_input.get("DEVICE_METADATA", {}).\
get("localhost", {}).get("platform")
mac = file_input.get("DEVICE_METADATA", {}).\
get("localhost", {}).get("mac")

if not platform or not mac:
log.log_warning("Input file does't have platform or mac. platform: {}, mac: {}"
.format(None if platform is None else platform, None if mac is None else mac))
load_sysinfo = True

if load_sysinfo:
try:
command = [SONIC_CFGGEN_PATH, "-j", file, '-v', "DEVICE_METADATA.localhost.hwsku"]
Expand Down Expand Up @@ -1598,6 +1626,13 @@ def reload(db, filename, yes, load_sysinfo, no_service_restart, force, file_form
clicommon.run_command(command, display_cmd=True)
client.set(config_db.INIT_INDICATOR, 1)

if os.path.exists(file) and file.endswith("_configReloadStdin"):
# Remove tmpfile
try:
os.remove(file)
except OSError as e:
click.echo("An error occurred while removing the temporary file: {}".format(str(e)), err=True)

# Migrate DB contents to latest version
db_migrator='/usr/local/bin/db_migrator.py'
if os.path.isfile(db_migrator) and os.access(db_migrator, os.X_OK):
Expand Down Expand Up @@ -2909,7 +2944,12 @@ def _qos_update_ports(ctx, ports, dry_run, json_data):
click.secho("QoS definition template not found at {}".format(qos_template_file), fg="yellow")
ctx.abort()

# Remove multi indexed entries first
# Remove entries first
for table_name in tables_single_index:
for port in portset_to_handle:
if config_db.get_entry(table_name, port):
config_db.set_entry(table_name, port, None)

for table_name in tables_multi_index:
entries = config_db.get_keys(table_name)
for key in entries:
Expand Down Expand Up @@ -6541,7 +6581,9 @@ def add_ntp_server(ctx, ntp_ip_address):
return
else:
try:
db.set_entry('NTP_SERVER', ntp_ip_address, {'NULL': 'NULL'})
db.set_entry('NTP_SERVER', ntp_ip_address,
{'resolve_as': ntp_ip_address,
'association_type': 'server'})
except ValueError as e:
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
click.echo("NTP server {} added to configuration".format(ntp_ip_address))
Expand Down
159 changes: 153 additions & 6 deletions config/plugins/sonic-hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@
CFG_SWITCH_HASH,
STATE_SWITCH_CAPABILITY,
SW_CAP_HASH_FIELD_LIST_KEY,
SW_CAP_ECMP_HASH_KEY,
SW_CAP_LAG_HASH_KEY,
SW_CAP_ECMP_HASH_ALGORITHM_KEY,
SW_CAP_LAG_HASH_ALGORITHM_KEY,
SW_CAP_ECMP_HASH_CAPABLE_KEY,
SW_CAP_LAG_HASH_CAPABLE_KEY,
SW_CAP_ECMP_HASH_ALGORITHM_CAPABLE_KEY,
SW_CAP_LAG_HASH_ALGORITHM_CAPABLE_KEY,
SW_HASH_KEY,
SW_CAP_KEY,
HASH_FIELD_LIST,
HASH_ALGORITHM,
SYSLOG_IDENTIFIER,
get_param,
get_param_hint,
Expand Down Expand Up @@ -47,6 +52,22 @@ def hash_field_validator(ctx, param, value):
return list(value)


def hash_algorithm_validator(ctx, param, value):
"""
Check if hash algorithm argument is valid
Args:
ctx: click context
param: click parameter context
value: value of parameter
Returns:
str: validated parameter
"""

click.Choice(HASH_ALGORITHM).convert(value, param, ctx)

return value


def ecmp_hash_validator(ctx, db, ecmp_hash):
"""
Check if ECMP hash argument is valid
Expand All @@ -66,9 +87,9 @@ def ecmp_hash_validator(ctx, db, ecmp_hash):
entry = db.get_all(db.STATE_DB, "{}|{}".format(STATE_SWITCH_CAPABILITY, SW_CAP_KEY))

entry.setdefault(SW_CAP_HASH_FIELD_LIST_KEY, 'N/A')
entry.setdefault(SW_CAP_ECMP_HASH_KEY, 'false')
entry.setdefault(SW_CAP_ECMP_HASH_CAPABLE_KEY, 'false')

if entry[SW_CAP_ECMP_HASH_KEY] == 'false':
if entry[SW_CAP_ECMP_HASH_CAPABLE_KEY] == 'false':
raise click.UsageError("Failed to configure {}: operation is not supported".format(
get_param_hint(ctx, "ecmp_hash")), ctx
)
Expand Down Expand Up @@ -106,9 +127,9 @@ def lag_hash_validator(ctx, db, lag_hash):
entry = db.get_all(db.STATE_DB, "{}|{}".format(STATE_SWITCH_CAPABILITY, SW_CAP_KEY))

entry.setdefault(SW_CAP_HASH_FIELD_LIST_KEY, 'N/A')
entry.setdefault(SW_CAP_LAG_HASH_KEY, 'false')
entry.setdefault(SW_CAP_LAG_HASH_CAPABLE_KEY, 'false')

if entry[SW_CAP_LAG_HASH_KEY] == 'false':
if entry[SW_CAP_LAG_HASH_CAPABLE_KEY] == 'false':
raise click.UsageError("Failed to configure {}: operation is not supported".format(
get_param_hint(ctx, "lag_hash")), ctx
)
Expand All @@ -126,6 +147,72 @@ def lag_hash_validator(ctx, db, lag_hash):
for hash_field in lag_hash:
click.Choice(cap_list).convert(hash_field, get_param(ctx, "lag_hash"), ctx)


def ecmp_hash_algorithm_validator(ctx, db, ecmp_hash_algorithm):
"""
Check if ECMP hash algorithm argument is valid
Args:
ctx: click context
db: State DB connector object
ecmp_hash_algorithm: ECMP hash algorithm
"""

entry = db.get_all(db.STATE_DB, "{}|{}".format(STATE_SWITCH_CAPABILITY, SW_CAP_KEY))

entry.setdefault(SW_CAP_ECMP_HASH_ALGORITHM_KEY, 'N/A')
entry.setdefault(SW_CAP_ECMP_HASH_ALGORITHM_CAPABLE_KEY, 'false')

if entry[SW_CAP_ECMP_HASH_ALGORITHM_CAPABLE_KEY] == 'false':
raise click.UsageError("Failed to configure {}: operation is not supported".format(
get_param_hint(ctx, "ecmp_hash_algorithm")), ctx
)

if not entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY]:
raise click.UsageError("Failed to configure {}: no hash algorithm capabilities".format(
get_param_hint(ctx, "ecmp_hash_algorithm")), ctx
)

if entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY] == 'N/A':
return

cap_list = entry[SW_CAP_ECMP_HASH_ALGORITHM_KEY].split(',')

click.Choice(cap_list).convert(ecmp_hash_algorithm, get_param(ctx, "ecmp_hash_algorithm"), ctx)


def lag_hash_algorithm_validator(ctx, db, lag_hash_algorithm):
"""
Check if LAG hash algorithm argument is valid
Args:
ctx: click context
db: State DB connector object
lag_hash_algorithm: LAG hash algorithm
"""

entry = db.get_all(db.STATE_DB, "{}|{}".format(STATE_SWITCH_CAPABILITY, SW_CAP_KEY))

entry.setdefault(SW_CAP_LAG_HASH_ALGORITHM_KEY, 'N/A')
entry.setdefault(SW_CAP_LAG_HASH_ALGORITHM_CAPABLE_KEY, 'false')

if entry[SW_CAP_LAG_HASH_ALGORITHM_CAPABLE_KEY] == 'false':
raise click.UsageError("Failed to configure {}: operation is not supported".format(
get_param_hint(ctx, "lag_hash_algorithm")), ctx
)

if not entry[SW_CAP_LAG_HASH_ALGORITHM_KEY]:
raise click.UsageError("Failed to configure {}: no hash algorithm capabilities".format(
get_param_hint(ctx, "lag_hash_algorithm")), ctx
)

if entry[SW_CAP_LAG_HASH_ALGORITHM_KEY] == 'N/A':
return

cap_list = entry[SW_CAP_LAG_HASH_ALGORITHM_KEY].split(',')

click.Choice(cap_list).convert(lag_hash_algorithm, get_param(ctx, "lag_hash_algorithm"), ctx)

#
# Hash DB interface ---------------------------------------------------------------------------------------------------
#
Expand Down Expand Up @@ -258,6 +345,66 @@ def SWITCH_HASH_GLOBAL_lag_hash(ctx, db, lag_hash):
ctx.fail(str(err))


@SWITCH_HASH_GLOBAL.command(
name="ecmp-hash-algorithm"
)
@click.argument(
"ecmp-hash-algorithm",
nargs=1,
required=True,
callback=hash_algorithm_validator,
)
@clicommon.pass_db
@click.pass_context
def SWITCH_HASH_GLOBAL_ecmp_hash_algorithm(ctx, db, ecmp_hash_algorithm):
""" Hash algorithm for hashing packets going through ECMP """

ecmp_hash_algorithm_validator(ctx, db.db, ecmp_hash_algorithm)

table = CFG_SWITCH_HASH
key = SW_HASH_KEY
data = {
"ecmp_hash_algorithm": ecmp_hash_algorithm,
}

try:
update_entry_validated(db.cfgdb, table, key, data, create_if_not_exists=True)
log.log_notice("Configured switch global ECMP hash algorithm: {}".format(ecmp_hash_algorithm))
except Exception as e:
log.log_error("Failed to configure switch global ECMP hash algorithm: {}".format(str(e)))
ctx.fail(str(e))


@SWITCH_HASH_GLOBAL.command(
name="lag-hash-algorithm"
)
@click.argument(
"lag-hash-algorithm",
nargs=1,
required=True,
callback=hash_algorithm_validator,
)
@clicommon.pass_db
@click.pass_context
def SWITCH_HASH_GLOBAL_lag_hash_algorithm(ctx, db, lag_hash_algorithm):
""" Hash algorithm for hashing packets going through LAG """

lag_hash_algorithm_validator(ctx, db.db, lag_hash_algorithm)

table = CFG_SWITCH_HASH
key = SW_HASH_KEY
data = {
"lag_hash_algorithm": lag_hash_algorithm,
}

try:
update_entry_validated(db.cfgdb, table, key, data, create_if_not_exists=True)
log.log_notice("Configured switch global LAG hash algorithm: {}".format(lag_hash_algorithm))
except Exception as e:
log.log_error("Failed to configure switch global LAG hash algorithm: {}".format(str(e)))
ctx.fail(str(e))


def register(cli):
""" Register new CLI nodes in root CLI.
Expand Down
13 changes: 7 additions & 6 deletions config/vlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,10 @@ def is_dhcpv6_relay_config_exist(db, vlan_name):
return True


def delete_state_db_entry(entry_name):
state_db = SonicV2Connector()
state_db.connect(state_db.STATE_DB)
exists = state_db.exists(state_db.STATE_DB, 'DHCPv6_COUNTER_TABLE|{}'.format(entry_name))
def delete_db_entry(entry_name, db_connector, db_name):
exists = db_connector.exists(db_name, entry_name)
if exists:
state_db.delete(state_db.STATE_DB, 'DHCPv6_COUNTER_TABLE|{}'.format(entry_name))
db_connector.delete(db_name, entry_name)


@vlan.command('del')
Expand Down Expand Up @@ -125,7 +123,8 @@ def del_vlan(db, vid, no_restart_dhcp_relay):
# We need to restart dhcp_relay service after dhcpv6_relay config change
if is_dhcp_relay_running():
dhcp_relay_util.handle_restart_dhcp_relay_service()
delete_state_db_entry(vlan)
delete_db_entry("DHCPv6_COUNTER_TABLE|{}".format(vlan), db.db, db.db.STATE_DB)
delete_db_entry("DHCP_COUNTER_TABLE|{}".format(vlan), db.db, db.db.STATE_DB)

vlans = db.cfgdb.get_keys('VLAN')
if not vlans:
Expand Down Expand Up @@ -279,6 +278,8 @@ def del_vlan_member(db, vid, port):

try:
config_db.set_entry('VLAN_MEMBER', (vlan, port), None)
delete_db_entry("DHCPv6_COUNTER_TABLE|{}".format(port), db.db, db.db.STATE_DB)
delete_db_entry("DHCP_COUNTER_TABLE|{}".format(port), db.db, db.db.STATE_DB)
except JsonPatchConflict:
ctx.fail("{} invalid or does not exist, or {} is not a member of {}".format(vlan, port, vlan))

Loading

0 comments on commit 1ca9676

Please sign in to comment.