diff --git a/Development/nmos/node_interfaces.cpp b/Development/nmos/node_interfaces.cpp index 2af5e40d..55a56dda 100644 --- a/Development/nmos/node_interfaces.cpp +++ b/Development/nmos/node_interfaces.cpp @@ -20,13 +20,35 @@ namespace nmos return chassis_id.is_null() ? utility::string_t{} : chassis_id.as_string(); } + bool is_valid_node_interfaces_port_id(const utility::string_t& port_id) + { + if (17 != port_id.size()) return false; + + for (size_t index = 0; index < port_id.size(); ++index) + { + const auto character = port_id[index]; + if (2 == index % 3) + { + if (U('-') != character) return false; + } + else if (!((U('0') <= character && character <= U('9')) || (U('a') <= character && character <= U('f')))) + { + return false; + } + } + + return true; + } + // Port ID must be a MAC address web::json::value make_node_interfaces_port_id(const utility::string_t& port_id) { using web::json::value; - // when no physical address is available, use the common null value of all zeros + // IS-04 port_id requires the six-octet lowercase-hyphen form. Any other representation, + // including uppercase or colon-separated MAC addresses, is not representable in this field + // and uses the existing null-address fallback of all zeros // see https://standards.ieee.org/content/dam/ieee-standards/standards/web/documents/tutorials/eui.pdf - return value::string(!port_id.empty() ? port_id : U("00-00-00-00-00-00")); + return value::string(is_valid_node_interfaces_port_id(port_id) ? port_id : U("00-00-00-00-00-00")); } } diff --git a/Development/nmos/test/node_interfaces_test.cpp b/Development/nmos/test/node_interfaces_test.cpp index 29bbae62..4f540298 100644 --- a/Development/nmos/test/node_interfaces_test.cpp +++ b/Development/nmos/test/node_interfaces_test.cpp @@ -4,6 +4,22 @@ #include "bst/test/test.h" #include "nmos/json_fields.h" +namespace +{ + utility::string_t make_node_interface_port_id(const utility::string_t& port_id) + { + const nmos::node_interface iface{ + U("aa-bb-cc-dd-ee-01"), + port_id, + U("tunl0"), + U(""), + U("") + }; + auto json = nmos::make_node_interface(iface); + return nmos::fields::port_id(json); + } +} + //////////////////////////////////////////////////////////////////////////////////////////// BST_TEST_CASE(testMakeParseNodeInterface) { @@ -45,6 +61,36 @@ BST_TEST_CASE(testMakeParseNodeInterfaceNullChassisId) BST_REQUIRE(iface == nmos::parse_node_interface(json)); } +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testMakeNodeInterfaceValidPortIdUnchanged) +{ + BST_REQUIRE_EQUAL(U("aa-bb-cc-dd-ee-ff"), make_node_interface_port_id(U("aa-bb-cc-dd-ee-ff"))); +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testMakeNodeInterfaceEmptyPortIdFallback) +{ + BST_REQUIRE_EQUAL(U("00-00-00-00-00-00"), make_node_interface_port_id(U(""))); +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testMakeNodeInterfaceInvalidPortIdFallback) +{ + const std::vector invalid_port_ids{ + U("00-00-00-00"), + U("00-00-00-00-00"), + U("00-00-00-00-00-00-00"), + U("gg-00-00-00-00-00"), + U("AA-BB-CC-DD-EE-FF"), + U("00:00:00:00:00:00") + }; + + for (const auto& invalid_port_id : invalid_port_ids) + { + BST_CHECK_EQUAL(U("00-00-00-00-00-00"), make_node_interface_port_id(invalid_port_id)); + } +} + //////////////////////////////////////////////////////////////////////////////////////////// BST_TEST_CASE(testMakeParseNodeInterfaceAttachedNetworkDevice) {