Skip to content
Merged
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
3 changes: 2 additions & 1 deletion files/build_templates/init_cfg.json.j2
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"polling_interval": "300",
{%- for crm_res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor",
"ipv6_neighbor", "nexthop_group_member", "nexthop_group", "acl_table",
"acl_group", "acl_entry", "acl_counter", "fdb_entry", "snat_entry", "dnat_entry", "ipmc_entry"] %}
"acl_group", "acl_entry", "acl_counter", "fdb_entry", "snat_entry", "dnat_entry",
"ipmc_entry", "mpls_inseg", "mpls_nexthop"] %}
"{{crm_res}}_threshold_type": "percentage",
"{{crm_res}}_low_threshold": "70",
"{{crm_res}}_high_threshold": "85"{% if not loop.last %},{% endif -%}
Expand Down
7 changes: 4 additions & 3 deletions files/image_config/pcie-check/pcie-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ VERBOSE="no"
RESULTS="PCIe Device Checking All Test"
EXPECTED="PCIe Device Checking All Test ----------->>> PASSED"
MAX_WAIT_SECONDS=15
PCIE_STATUS_TABLE="PCIE_DEVICES|status"

function debug()
{
Expand All @@ -19,7 +20,7 @@ function check_and_rescan_pcie_devices()
PCIE_CHK_CMD='sudo pcieutil check | grep "$RESULTS"'
PLATFORM=$(sonic-cfggen -H -v DEVICE_METADATA.localhost.platform)

if [ ! -f /usr/share/sonic/device/$PLATFORM/pcie.yaml ]; then
if [ ! -f /usr/share/sonic/device/$PLATFORM/pcie*.yaml ]; then
debug "pcie.yaml does not exist! Can't check PCIe status!"
exit
fi
Expand All @@ -37,7 +38,7 @@ function check_and_rescan_pcie_devices()
fi

if [ "$(eval $PCIE_CHK_CMD)" = "$EXPECTED" ]; then
redis-cli -n 6 HSET "PCIE_DEVICES" "status" "PASSED"
redis-cli -n 6 HSET $PCIE_STATUS_TABLE "status" "PASSED"
debug "PCIe check passed"
exit
else
Expand All @@ -53,7 +54,7 @@ function check_and_rescan_pcie_devices()

done
debug "PCIe check failed"
redis-cli -n 6 HSET "PCIE_DEVICES" "status" "FAILED"
redis-cli -n 6 HSET $PCIE_STATUS_TABLE "status" "FAILED"
}

check_and_rescan_pcie_devices
64 changes: 63 additions & 1 deletion platform/mellanox/mlnx-platform-api/sonic_platform/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
else:
import ConfigParser as configparser

from sonic_platform_base.component_base import ComponentBase
from sonic_platform_base.component_base import ComponentBase, \
FW_AUTO_INSTALLED, \
FW_AUTO_ERR_BOOT_TYPE, \
FW_AUTO_ERR_IMAGE, \
FW_AUTO_ERR_UKNOWN
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

Expand Down Expand Up @@ -332,6 +336,30 @@ def get_name(self):
def get_description(self):
return self.description

def auto_update_firmware(self, image_path, boot_action):
"""
Default handling of attempted automatic update for a component of a Mellanox switch.
Will skip the installation if the boot_action is 'warm' or 'fast' and will call update_firmware()
if boot_action is fast.
"""

default_supported_boot = ['cold']

# Verify image path exists
if not os.path.exists(image_path):
# Invalid image path
return FW_AUTO_ERR_IMAGE

if boot_action in default_supported_boot:
if self.install_firmware(image_path):
# Successful update
return FW_AUTO_INSTALLED
# Failed update (unknown reason)
return FW_AUTO_ERR_UKNOWN

# boot_type did not match (skip)
return FW_AUTO_ERR_BOOT_TYPE

@staticmethod
def _read_generic_file(filename, len, ignore_errors=False):
"""
Expand Down Expand Up @@ -467,6 +495,40 @@ def __install_firmware(self, image_path):

return True

def auto_update_firmware(self, image_path, boot_action):
"""
Handling of attempted automatic update for a SSD of a Mellanox switch.
Will first check the image_path to determine if a post-install reboot is required,
then compares it against boot_action to determine whether to proceed with install.
"""

# All devices support cold boot
supported_boot = ['cold']

# Verify image path exists
if not os.path.exists(image_path):
# Invalid image path
return FW_AUTO_ERR_IMAGE

# Check if post_install reboot is required
try:
if self.get_firmware_update_notification(image_path) is None:
# No power cycle required
supported_boot += ['warm', 'fast', 'none', 'any']
except RuntimeError:
# Unknown error from firmware probe
return FW_AUTO_ERR_UKNOWN

if boot_action in supported_boot:
if self.install_firmware(image_path):
# Successful update
return FW_AUTO_INSTALLED
# Failed update (unknown reason)
return FW_AUTO_ERR_UKNOWN

# boot_type did not match (skip)
return FW_AUTO_ERR_BOOT_TYPE

def get_firmware_version(self):
cmd = self.SSD_INFO_COMMAND

Expand Down
82 changes: 82 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_firmware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os
import sys
import pytest
from mock import MagicMock
from .mock_platform import MockFan

test_path = os.path.dirname(os.path.abspath(__file__))
modules_path = os.path.dirname(test_path)
sys.path.insert(0, modules_path)

from sonic_platform.component import Component, ComponentSSD

from sonic_platform_base.component_base import ComponentBase, \
FW_AUTO_INSTALLED, \
FW_AUTO_ERR_BOOT_TYPE, \
FW_AUTO_ERR_IMAGE, \
FW_AUTO_ERR_UKNOWN

def mock_install_firmware_success(image_path):
return True

def mock_install_firmware_fail(image_path):
return False

def mock_update_notification_cold_boot(image_path):
return "Immediate power cycle is required to complete NAME firmware update"

def mock_update_notification_warm_boot(image_path):
return None

def mock_update_notification_error(image_path):
raise RuntimeError("Failed to parse NAME firmware upgrade status")

test_data_default = [
(None, False, None, FW_AUTO_ERR_IMAGE),
(None, True, 'warm', FW_AUTO_ERR_BOOT_TYPE),
(mock_install_firmware_fail, True, 'cold', FW_AUTO_ERR_UKNOWN),
(mock_install_firmware_success, True, 'cold', FW_AUTO_INSTALLED)
]

test_data_ssd = [
(None, None, False, None, FW_AUTO_ERR_IMAGE),
(None, mock_update_notification_error, True, None, FW_AUTO_ERR_UKNOWN),
(mock_install_firmware_fail, mock_update_notification_cold_boot, True, 'cold', FW_AUTO_ERR_UKNOWN),
(mock_install_firmware_success, mock_update_notification_cold_boot, True, 'warm', FW_AUTO_ERR_BOOT_TYPE),
(mock_install_firmware_success, mock_update_notification_cold_boot, True, 'cold', FW_AUTO_INSTALLED),
(mock_install_firmware_success, mock_update_notification_warm_boot, True, 'warm', FW_AUTO_INSTALLED),
(mock_install_firmware_success, mock_update_notification_warm_boot, True, 'cold', FW_AUTO_INSTALLED)
]

@pytest.mark.parametrize('install_func, image_found, boot_type, expect', test_data_default)
def test_auto_update_firmware_default(monkeypatch, install_func, image_found, boot_type, expect):

def mock_path_exists(path):
return image_found

test_component = Component()

monkeypatch.setattr(test_component, 'install_firmware', install_func)
monkeypatch.setattr(os.path, 'exists', mock_path_exists)

result = test_component.auto_update_firmware(None, boot_type)

assert result == expect


@pytest.mark.parametrize('install_func, notify, image_found, boot_type, expect', test_data_ssd)
def test_auto_update_firmware_default(monkeypatch, install_func, notify, image_found, boot_type, expect):

def mock_path_exists(path):
return image_found

test_component_ssd = ComponentSSD()

monkeypatch.setattr(test_component_ssd, 'install_firmware', install_func)
monkeypatch.setattr(test_component_ssd, 'get_firmware_update_notification', notify)
monkeypatch.setattr(os.path, 'exists', mock_path_exists)

result = test_component_ssd.auto_update_firmware(None, boot_type)

assert result == expect

1 change: 1 addition & 0 deletions src/libnl3/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
!debian/
debian/libnl-*/
!Makefile
!patch
4 changes: 4 additions & 0 deletions src/libnl3/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
pushd libnl3-$(LIBNL3_VERSION_BASE)
git checkout tags/libnl$(subst .,_,$(LIBNL3_VERSION_BASE))

git checkout -b sonic
stg init
stg import -s ../patch/series

ln -s ../debian debian
dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR)
popd
Expand Down
77 changes: 77 additions & 0 deletions src/libnl3/patch/0001-mpls-encap-accessors.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
From 701122c539d6da3fbd3367be6e62141328ebeb07 Mon Sep 17 00:00:00 2001
From: Ann Pokora <apokora@juniper.net>
Date: Tue, 25 May 2021 18:07:37 -0700
Subject: [PATCH 1/2] mpls encap accessors

Signed-off-by: Ann Pokora <apokora@juniper.net>
---
include/netlink/route/nexthop.h | 2 ++
lib/route/nh_encap_mpls.c | 28 ++++++++++++++++++++++++++++
libnl-route-3.sym | 2 ++
3 files changed, 32 insertions(+)

diff --git a/include/netlink/route/nexthop.h b/include/netlink/route/nexthop.h
index 5b422dd..a502005 100644
--- a/include/netlink/route/nexthop.h
+++ b/include/netlink/route/nexthop.h
@@ -70,6 +70,8 @@ extern int rtnl_route_nh_str2flags(const char *);
extern int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,
struct nl_addr *addr,
uint8_t ttl);
+extern struct nl_addr * rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *);
+extern uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *);
#ifdef __cplusplus
}
#endif
diff --git a/lib/route/nh_encap_mpls.c b/lib/route/nh_encap_mpls.c
index 081661e..18336ac 100644
--- a/lib/route/nh_encap_mpls.c
+++ b/lib/route/nh_encap_mpls.c
@@ -133,3 +133,31 @@ int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,

return 0;
}
+
+struct nl_addr *rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *nh)
+{
+ struct mpls_iptunnel_encap *mpls_encap;
+
+ if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS)
+ return NULL;
+
+ mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv;
+ if (!mpls_encap)
+ return NULL;
+
+ return mpls_encap->dst;
+}
+
+uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *nh)
+{
+ struct mpls_iptunnel_encap *mpls_encap;
+
+ if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS)
+ return 0;
+
+ mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv;
+ if (!mpls_encap)
+ return 0;
+
+ return mpls_encap->ttl;
+}
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index 4a65503..ce6d714 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -1127,6 +1127,8 @@ global:
rtnl_qdisc_mqprio_set_priomap;
rtnl_qdisc_mqprio_set_queue;
rtnl_qdisc_mqprio_set_shaper;
+ rtnl_route_nh_get_encap_mpls_dst;
+ rtnl_route_nh_get_encap_mpls_ttl;
rtnl_rule_get_dport;
rtnl_rule_get_ipproto;
rtnl_rule_get_protocol;
--
2.7.4

63 changes: 63 additions & 0 deletions src/libnl3/patch/0002-mpls-remove-nl_addr_valid.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
From c89d1a129f71d3d2f76e6cbadb11ef41d8941a73 Mon Sep 17 00:00:00 2001
From: Ann Pokora <apokora@juniper.net>
Date: Tue, 25 May 2021 18:10:04 -0700
Subject: [PATCH 2/2] mpls remove nl_addr_valid

The removed calls to nl_addr_valid() are passing in a pointer to a binary address
and the length of the binary address, which does not match expected arguments for
nl_addr_valid().
nl_addr_valid() expects a pointer to an ASCII string and the address family of
the string format.
The incorrect arguments cause unexpected failures and the expected arguments are
not available in the context.

Signed-off-by: Ann Pokora <apokora@juniper.net>
---
lib/route/nexthop.c | 8 --------
lib/route/nh_encap_mpls.c | 4 ----
2 files changed, 12 deletions(-)

diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c
index 7a9904c..ac0095e 100644
--- a/lib/route/nexthop.c
+++ b/lib/route/nexthop.c
@@ -351,10 +351,6 @@ int rtnl_route_nh_set_newdst(struct rtnl_nexthop *nh, struct nl_addr *addr)
{
struct nl_addr *old = nh->rtnh_newdst;

- if (!nl_addr_valid(nl_addr_get_binary_addr(addr),
- nl_addr_get_len(addr)))
- return -NLE_INVAL;
-
if (addr) {
nh->rtnh_newdst = nl_addr_get(addr);
nh->ce_mask |= NH_ATTR_NEWDST;
@@ -378,10 +374,6 @@ int rtnl_route_nh_set_via(struct rtnl_nexthop *nh, struct nl_addr *addr)
{
struct nl_addr *old = nh->rtnh_via;

- if (!nl_addr_valid(nl_addr_get_binary_addr(addr),
- nl_addr_get_len(addr)))
- return -NLE_INVAL;
-
if (addr) {
nh->rtnh_via = nl_addr_get(addr);
nh->ce_mask |= NH_ATTR_VIA;
diff --git a/lib/route/nh_encap_mpls.c b/lib/route/nh_encap_mpls.c
index 18336ac..6c5a3c7 100644
--- a/lib/route/nh_encap_mpls.c
+++ b/lib/route/nh_encap_mpls.c
@@ -109,10 +109,6 @@ int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,
if (!addr)
return -NLE_INVAL;

- if (!nl_addr_valid(nl_addr_get_binary_addr(addr),
- nl_addr_get_len(addr)))
- return -NLE_INVAL;
-
rtnh_encap = calloc(1, sizeof(*rtnh_encap));
if (!rtnh_encap)
return -NLE_NOMEM;
--
2.7.4

2 changes: 2 additions & 0 deletions src/libnl3/patch/series
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
0001-mpls-encap-accessors.patch
0002-mpls-remove-nl_addr_valid.patch
1 change: 1 addition & 0 deletions src/sonic-host-services/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
'wheel'
],
tests_require = [
'parameterized',
'pytest',
'sonic-py-common'
],
Expand Down