Skip to content

Commit

Permalink
Merge branch 'Azure:master' into storm_control
Browse files Browse the repository at this point in the history
  • Loading branch information
mohan-selvaraj authored May 11, 2022
2 parents afe1122 + 288c2d8 commit f2c32ca
Show file tree
Hide file tree
Showing 16 changed files with 668 additions and 117 deletions.
63 changes: 37 additions & 26 deletions config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,18 +902,36 @@ def interface_is_in_portchannel(portchannel_member_table, interface_name):

return False

def interface_has_mirror_config(mirror_table, interface_name):
""" Check if port is already configured with mirror config """
for _, v in mirror_table.items():
if 'src_port' in v and v['src_port'] == interface_name:
def check_mirror_direction_config(v, direction):
""" Check if port is already configured for mirror in same direction """
if direction:
direction=direction.upper()
if ('direction' in v and v['direction'] == 'BOTH') or (direction == 'BOTH'):
return True
if 'dst_port' in v and v['dst_port'] == interface_name:
if 'direction' in v and v['direction'] == direction:
return True
else:
return True

def interface_has_mirror_config(ctx, mirror_table, dst_port, src_port, direction):
""" Check if dst/src port is already configured with mirroring in same direction """
for _, v in mirror_table.items():
if src_port:
for port in src_port.split(","):
if 'dst_port' in v and v['dst_port'] == port:
ctx.fail("Error: Source Interface {} already has mirror config".format(port))
if 'src_port' in v and re.search(port,v['src_port']):
if check_mirror_direction_config(v, direction):
ctx.fail("Error: Source Interface {} already has mirror config in same direction".format(port))
if dst_port:
if ('dst_port' in v and v['dst_port'] == dst_port) or ('src_port' in v and re.search(dst_port,v['src_port'])):
ctx.fail("Error: Destination Interface {} already has mirror config".format(dst_port))

return False

def validate_mirror_session_config(config_db, session_name, dst_port, src_port, direction):
""" Check if SPAN mirror-session config is valid """
ctx = click.get_current_context()
if len(config_db.get_entry('MIRROR_SESSION', session_name)) != 0:
click.echo("Error: {} already exists".format(session_name))
return False
Expand All @@ -924,41 +942,34 @@ def validate_mirror_session_config(config_db, session_name, dst_port, src_port,

if dst_port:
if not interface_name_is_valid(config_db, dst_port):
click.echo("Error: Destination Interface {} is invalid".format(dst_port))
return False
ctx.fail("Error: Destination Interface {} is invalid".format(dst_port))

if is_portchannel_present_in_db(config_db, dst_port):
ctx.fail("Error: Destination Interface {} is not supported".format(dst_port))

if interface_is_in_vlan(vlan_member_table, dst_port):
click.echo("Error: Destination Interface {} has vlan config".format(dst_port))
return False
ctx.fail("Error: Destination Interface {} has vlan config".format(dst_port))

if interface_has_mirror_config(mirror_table, dst_port):
click.echo("Error: Destination Interface {} already has mirror config".format(dst_port))
return False

if interface_is_in_portchannel(portchannel_member_table, dst_port):
click.echo("Error: Destination Interface {} has portchannel config".format(dst_port))
return False
ctx.fail("Error: Destination Interface {} has portchannel config".format(dst_port))

if clicommon.is_port_router_interface(config_db, dst_port):
click.echo("Error: Destination Interface {} is a L3 interface".format(dst_port))
return False
ctx.fail("Error: Destination Interface {} is a L3 interface".format(dst_port))

if src_port:
for port in src_port.split(","):
if not interface_name_is_valid(config_db, port):
click.echo("Error: Source Interface {} is invalid".format(port))
return False
ctx.fail("Error: Source Interface {} is invalid".format(port))
if dst_port and dst_port == port:
click.echo("Error: Destination Interface cant be same as Source Interface")
return False
if interface_has_mirror_config(mirror_table, port):
click.echo("Error: Source Interface {} already has mirror config".format(port))
return False
ctx.fail("Error: Destination Interface cant be same as Source Interface")

if interface_has_mirror_config(ctx, mirror_table, dst_port, src_port, direction):
return False

if direction:
if direction not in ['rx', 'tx', 'both']:
click.echo("Error: Direction {} is invalid".format(direction))
return False
ctx.fail("Error: Direction {} is invalid".format(direction))

return True

Expand Down Expand Up @@ -2159,7 +2170,7 @@ def add_span(session_name, dst_port, src_port, direction, queue, policer):
dst_port = interface_alias_to_name(None, dst_port)
if dst_port is None:
click.echo("Error: Destination Interface {} is invalid".format(dst_port))
return
return False

session_info = {
"type" : "SPAN",
Expand Down
3 changes: 3 additions & 0 deletions doc/Command-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5281,8 +5281,11 @@ If vrf-name is also provided as part of the command, if the vrf is created it wi
default Vlan20
Vrf-red Vlan100
Loopback11
Eth0.100
Vrf-blue Loopback100
Loopback102
Ethernet0.10
PortChannel101
````
### VRF config commands
Expand Down
20 changes: 20 additions & 0 deletions scripts/fast-reboot
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,26 @@ for service in ${SERVICES_TO_STOP}; do
fi
done
# Kill other containers to make the reboot faster
# We call `docker kill ...` to ensure the container stops as quickly as possible,
# then immediately call `systemctl stop ...` to prevent the service from
# restarting the container automatically.
debug "Stopping all remaining containers ..."
if test -f /usr/local/bin/ctrmgr_tools.py
then
/usr/local/bin/ctrmgr_tools.py kill-all
else
for CONTAINER_NAME in $(docker ps --format '{{.Names}}'); do
CONTAINER_STOP_RC=0
docker kill $CONTAINER_NAME &> /dev/null || CONTAINER_STOP_RC=$?
systemctl stop $CONTAINER_NAME || debug "Ignore stopping $CONTAINER_NAME error $?"
if [[ CONTAINER_STOP_RC -ne 0 ]]; then
debug "Failed killing container $CONTAINER_NAME RC $CONTAINER_STOP_RC ."
fi
done
fi
debug "Stopped all remaining containers ..."
# Stop the docker container engine. Otherwise we will have a broken docker storage
systemctl stop docker.service || debug "Ignore stopping docker service error $?"
Expand Down
27 changes: 25 additions & 2 deletions scripts/intfutil
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ PORT_OPTICS_TYPE = "type"
PORT_PFC_ASYM_STATUS = "pfc_asym"
PORT_AUTONEG = 'autoneg'
PORT_ADV_SPEEDS = 'adv_speeds'
PORT_RMT_ADV_SPEEDS = 'rmt_adv_speeds'
PORT_INTERFACE_TYPE = 'interface_type'
PORT_ADV_INTERFACE_TYPES = 'adv_interface_types'
PORT_TPID = "tpid"
Expand Down Expand Up @@ -140,8 +141,12 @@ def port_speed_parse(in_speed, optics_type):
speed = int(in_speed)
if optics_type == OPTICS_TYPE_RJ45 and speed <= 1000:
out_speed = '{}M'.format(speed)
elif speed < 1000:
out_speed = '{}M'.format(speed)
elif speed % 1000 >= 100:
out_speed = '{:.1f}G'.format(speed / 1000)
else:
out_speed = '{}G'.format(int(speed/1000))
out_speed = '{:.0f}G'.format(speed / 1000)

return out_speed

Expand All @@ -165,6 +170,23 @@ def appl_db_port_status_get(appl_db, intf_name, status_type):
status = ','.join(new_speed_list)
return status

def state_db_port_status_get(db, intf_name, field):
"""
Get the port status
"""
full_table_id = PORT_STATE_TABLE_PREFIX + intf_name
status = db.get(db.STATE_DB, full_table_id, field)
if not status:
return "N/A"
if field in [PORT_RMT_ADV_SPEEDS] and status not in ["N/A", "all"]:
optics_type = state_db_port_optics_get(db, intf_name, PORT_OPTICS_TYPE)
speed_list = status.split(',')
new_speed_list = []
for s in natsorted(speed_list):
new_speed_list.append(port_speed_parse(s, optics_type))
status = ','.join(new_speed_list)
return status

def port_oper_speed_get(db, intf_name):
"""
Get port oper speed
Expand Down Expand Up @@ -566,7 +588,7 @@ class IntfDescription(object):


# ========================== interface-autoneg logic ==========================
header_autoneg = ['Interface', 'Auto-Neg Mode', 'Speed', 'Adv Speeds', 'Type', 'Adv Types', 'Oper', 'Admin']
header_autoneg = ['Interface', 'Auto-Neg Mode', 'Speed', 'Adv Speeds', 'Rmt Adv Speeds', 'Type', 'Adv Types', 'Oper', 'Admin']


class IntfAutoNegStatus(object):
Expand Down Expand Up @@ -616,6 +638,7 @@ class IntfAutoNegStatus(object):
autoneg_mode,
port_oper_speed_get(self.db, key),
appl_db_port_status_get(self.db, key, PORT_ADV_SPEEDS),
state_db_port_status_get(self.db, key, PORT_RMT_ADV_SPEEDS),
appl_db_port_status_get(self.db, key, PORT_INTERFACE_TYPE),
appl_db_port_status_get(self.db, key, PORT_ADV_INTERFACE_TYPES),
appl_db_port_status_get(self.db, key, PORT_OPER_STATUS),
Expand Down
125 changes: 102 additions & 23 deletions sfputil/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,48 @@
'application_advertisement': 'Application Advertisement'
}

QSFP_DD_DATA_MAP = {
'model': 'Vendor PN',
'vendor_oui': 'Vendor OUI',
'vendor_date': 'Vendor Date Code(YYYY-MM-DD Lot)',
'manufacturer': 'Vendor Name',
'vendor_rev': 'Vendor Rev',
'serial': 'Vendor SN',
'type': 'Identifier',
'ext_identifier': 'Extended Identifier',
'ext_rateselect_compliance': 'Extended RateSelect Compliance',
'cable_length': 'cable_length',
'cable_type': 'Length',
'nominal_bit_rate': 'Nominal Bit Rate(100Mbs)',
'specification_compliance': 'Specification compliance',
'encoding': 'Encoding',
'connector': 'Connector',
'application_advertisement': 'Application Advertisement',
'active_firmware': 'Active Firmware Version',
'inactive_firmware': 'Inactive Firmware Version',
'hardware_rev': 'Hardware Revision',
'media_interface_code': 'Media Interface Code',
'host_electrical_interface': 'Host Electrical Interface',
'host_lane_count': 'Host Lane Count',
'media_lane_count': 'Media Lane Count',
'host_lane_assignment_option': 'Host Lane Assignment Options',
'media_lane_assignment_option': 'Media Lane Assignment Options',
'active_apsel_hostlane1': 'Active App Selection Host Lane 1',
'active_apsel_hostlane2': 'Active App Selection Host Lane 2',
'active_apsel_hostlane3': 'Active App Selection Host Lane 3',
'active_apsel_hostlane4': 'Active App Selection Host Lane 4',
'active_apsel_hostlane5': 'Active App Selection Host Lane 5',
'active_apsel_hostlane6': 'Active App Selection Host Lane 6',
'active_apsel_hostlane7': 'Active App Selection Host Lane 7',
'active_apsel_hostlane8': 'Active App Selection Host Lane 8',
'media_interface_technology': 'Media Interface Technology',
'cmis_rev': 'CMIS Revision',
'supported_max_tx_power': 'Supported Max TX Power',
'supported_min_tx_power': 'Supported Min TX Power',
'supported_max_laser_freq': 'Supported Max Laser Frequency',
'supported_min_laser_freq': 'Supported Min Laser Frequency'
}

SFP_DOM_CHANNEL_MONITOR_MAP = {
'rx1power': 'RXPower',
'tx1bias': 'TXBias',
Expand Down Expand Up @@ -273,31 +315,68 @@ def format_dict_value_to_string(sorted_key_table,
def convert_sfp_info_to_output_string(sfp_info_dict):
indent = ' ' * 8
output = ''

sorted_qsfp_data_map_keys = sorted(QSFP_DATA_MAP, key=QSFP_DATA_MAP.get)
for key in sorted_qsfp_data_map_keys:
if key == 'cable_type':
output += '{}{}: {}\n'.format(indent, sfp_info_dict['cable_type'], sfp_info_dict['cable_length'])
elif key == 'cable_length':
pass
elif key == 'specification_compliance':
if sfp_info_dict['type'] == "QSFP-DD Double Density 8X Pluggable Transceiver" or \
sfp_info_dict['type'] == "OSFP 8X Pluggable Transceiver" or \
sfp_info_dict['type'] == "QSFP+ or later with CMIS":
output += '{}{}: {}\n'.format(indent, QSFP_DATA_MAP[key], sfp_info_dict[key])
sfp_type = sfp_info_dict['type']
# CMIS supported module types include QSFP-DD and OSFP
if sfp_type.startswith('QSFP-DD') or sfp_type.startswith('OSFP'):
sorted_qsfp_data_map_keys = sorted(QSFP_DD_DATA_MAP, key=QSFP_DD_DATA_MAP.get)
for key in sorted_qsfp_data_map_keys:
if key == 'cable_type':
output += '{}{}: {}\n'.format(indent, sfp_info_dict['cable_type'], sfp_info_dict['cable_length'])
elif key == 'cable_length':
pass
elif key == 'specification_compliance':
if sfp_info_dict['type'] == "QSFP-DD Double Density 8X Pluggable Transceiver" or \
sfp_info_dict['type'] == "OSFP 8X Pluggable Transceiver" or \
sfp_info_dict['type'] == "QSFP+ or later with CMIS":
output += '{}{}: {}\n'.format(indent, QSFP_DD_DATA_MAP[key], sfp_info_dict[key])
else:
output += '{}{}:\n'.format(indent, QSFP_DD_DATA_MAP['specification_compliance'])

spec_compliance_dict = {}
try:
spec_compliance_dict = ast.literal_eval(sfp_info_dict['specification_compliance'])
sorted_compliance_key_table = natsorted(spec_compliance_dict)
for compliance_key in sorted_compliance_key_table:
output += '{}{}: {}\n'.format((indent * 2), compliance_key, spec_compliance_dict[compliance_key])
except ValueError as e:
output += '{}N/A\n'.format((indent * 2))
elif key == 'application_advertisement':
pass
elif key == 'supported_max_tx_power' or key == 'supported_min_tx_power':
output += '{}{}: {}dBm\n'.format(indent, QSFP_DD_DATA_MAP[key], sfp_info_dict[key])
elif key == 'supported_max_laser_freq' or key == 'supported_min_laser_freq':
output += '{}{}: {}GHz\n'.format(indent, QSFP_DD_DATA_MAP[key], sfp_info_dict[key])
else:
output += '{}{}:\n'.format(indent, QSFP_DATA_MAP['specification_compliance'])

spec_compliance_dict = {}
try:
spec_compliance_dict = ast.literal_eval(sfp_info_dict['specification_compliance'])
sorted_compliance_key_table = natsorted(spec_compliance_dict)
for compliance_key in sorted_compliance_key_table:
output += '{}{}: {}\n'.format((indent * 2), compliance_key, spec_compliance_dict[compliance_key])
except ValueError as e:
output += '{}N/A\n'.format((indent * 2))
else:
output += '{}{}: {}\n'.format(indent, QSFP_DATA_MAP[key], sfp_info_dict[key])
output += '{}{}: {}\n'.format(indent, QSFP_DD_DATA_MAP[key], sfp_info_dict[key])
except (KeyError, ValueError) as e:
output += '{}{}: N/A\n'.format(indent, QSFP_DD_DATA_MAP[key])

else:
sorted_qsfp_data_map_keys = sorted(QSFP_DATA_MAP, key=QSFP_DATA_MAP.get)
for key in sorted_qsfp_data_map_keys:
if key == 'cable_type':
output += '{}{}: {}\n'.format(indent, sfp_info_dict['cable_type'], sfp_info_dict['cable_length'])
elif key == 'cable_length':
pass
elif key == 'specification_compliance':
if sfp_info_dict['type'] == "QSFP-DD Double Density 8X Pluggable Transceiver" or \
sfp_info_dict['type'] == "OSFP 8X Pluggable Transceiver" or \
sfp_info_dict['type'] == "QSFP+ or later with CMIS":
output += '{}{}: {}\n'.format(indent, QSFP_DATA_MAP[key], sfp_info_dict[key])
else:
output += '{}{}:\n'.format(indent, QSFP_DATA_MAP['specification_compliance'])

spec_compliance_dict = {}
try:
spec_compliance_dict = ast.literal_eval(sfp_info_dict['specification_compliance'])
sorted_compliance_key_table = natsorted(spec_compliance_dict)
for compliance_key in sorted_compliance_key_table:
output += '{}{}: {}\n'.format((indent * 2), compliance_key, spec_compliance_dict[compliance_key])
except ValueError as e:
output += '{}N/A\n'.format((indent * 2))
else:
output += '{}{}: {}\n'.format(indent, QSFP_DATA_MAP[key], sfp_info_dict[key])

return output

Expand Down
2 changes: 1 addition & 1 deletion show/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def cli(ctx):
def get_interface_bind_to_vrf(config_db, vrf_name):
"""Get interfaces belong to vrf
"""
tables = ['INTERFACE', 'PORTCHANNEL_INTERFACE', 'VLAN_INTERFACE', 'LOOPBACK_INTERFACE']
tables = ['INTERFACE', 'PORTCHANNEL_INTERFACE', 'VLAN_INTERFACE', 'LOOPBACK_INTERFACE', 'VLAN_SUB_INTERFACE']
data = []
for table_name in tables:
interface_dict = config_db.get_table(table_name)
Expand Down
Loading

0 comments on commit f2c32ca

Please sign in to comment.