From 0c32e8e69844e4535c51609d7a90ff5aa8da14de Mon Sep 17 00:00:00 2001 From: Andrea Bondavalli Date: Sun, 2 Feb 2020 07:12:36 -0800 Subject: [PATCH] Added handling of multicast membership for PTP messages. Limited PTP domain value to the range 0 - 127. --- daemon/config.cpp | 2 ++ daemon/http_server.cpp | 10 +++++----- daemon/json.cpp | 2 +- daemon/scripts/ptp_master_start.sh | 3 +++ daemon/session_manager.cpp | 22 +++++++++++++++++++--- daemon/session_manager.hpp | 7 ++++++- webui/src/PTP.js | 2 +- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/daemon/config.cpp b/daemon/config.cpp index fa06e22..294a0db 100644 --- a/daemon/config.cpp +++ b/daemon/config.cpp @@ -68,6 +68,8 @@ std::shared_ptr Config::parse(const std::string& filename) { if (ip::address_v4::from_string(config.rtp_mcast_base_.c_str()).to_ulong() == INADDR_NONE) config.rtp_mcast_base_ = "239.1.0.1"; + if (config.ptp_domain_ > 127) + config.ptp_domain_ = 0; auto [mac_addr, mac_str] = get_interface_mac(config.interface_name_); if (mac_str.empty()) { diff --git a/daemon/http_server.cpp b/daemon/http_server.cpp index a270ceb..714339c 100644 --- a/daemon/http_server.cpp +++ b/daemon/http_server.cpp @@ -137,6 +137,11 @@ bool HttpServer::start() { svr_.Post("/api/ptp/config", [this](const Request& req, Response& res) { try { PTPConfig ptpConfig = json_to_ptp_config(req.body); + auto ret = session_manager_->set_ptp_config(ptpConfig); + if (ret) { + set_error(ret, "failed to set ptp config", res); + return; + } Config config(*config_); config.set_ptp_domain(ptpConfig.domain); config.set_ptp_dscp(ptpConfig.dscp); @@ -144,11 +149,6 @@ bool HttpServer::start() { set_error(500, "failed to save config", res); return; } - auto ret = session_manager_->set_ptp_config(ptpConfig); - if (ret) { - set_error(ret, "failed to set ptp config", res); - return; - } set_headers(res); } catch (const std::runtime_error& e) { set_error(400, e.what(), res); diff --git a/daemon/json.cpp b/daemon/json.cpp index 5c215fb..218421b 100644 --- a/daemon/json.cpp +++ b/daemon/json.cpp @@ -426,7 +426,7 @@ static void parse_json_sources(boost::property_tree::ptree& pt, v.second.get_child("map")) { source.map.emplace_back(std::stoi(vm.second.data())); } - sources.emplace_back(std::move(source)); + sources.emplace_back(std::move(source)); } } diff --git a/daemon/scripts/ptp_master_start.sh b/daemon/scripts/ptp_master_start.sh index 87a2c79..4c14552 100755 --- a/daemon/scripts/ptp_master_start.sh +++ b/daemon/scripts/ptp_master_start.sh @@ -1 +1,4 @@ +# Note: +# currently ptp4l disables IP_MULTICAST_LOOP, so sockets on the same host cannot receive ptp4l traffic. +# Only exception is for lo network interface. sudo ptp4l -i $1 -m -l7 -E -S diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp index 7fdad0a..2c08769 100644 --- a/daemon/session_manager.cpp +++ b/daemon/session_manager.cpp @@ -918,6 +918,11 @@ bool SessionManager::worker() { sap_.set_multicast_interface(config_->get_ip_addr_str()); + // join PTP multicast address for specific domain + uint32_t ptp_addr = ip::address_v4::from_string(ptp_dflt_mcast_addr).to_ulong() + + config_->get_ptp_domain(); + igmp_.join(config_->get_ip_addr_str(), ip::address_v4(ptp_addr).to_string()); + while (running_) { // check if it's time to update the PTP status if (std::chrono::duration_cast (clock_::now() - ptp_timepoint).count() > @@ -944,6 +949,7 @@ bool SessionManager::worker() { // update PTP clock status std::unique_lock ptp_lock(ptp_mutex_); + // update status ptp_status_.gmid = ptp_clock_id; ptp_status_.jitter = ptp_status.i32Jitter; std::string new_ptp_status; @@ -967,9 +973,17 @@ bool SessionManager::worker() { (void)driver_->set_sample_rate(driver_->get_current_sample_rate()); } } - // update config - ptp_config_.domain = ptp_config.ui8Domain; - ptp_config_.dscp = ptp_config.ui8DSCP; + + // update PTP multicast join + uint32_t new_ptp_addr = ip::address_v4::from_string(ptp_dflt_mcast_addr).to_ulong() + + ptp_config.ui8Domain; + if (new_ptp_addr != ptp_addr) { + // leave old PTP multicast address for specific domain + igmp_.leave(config_->get_ip_addr_str(), ip::address_v4(ptp_addr).to_string()); + ptp_addr = new_ptp_addr; + // join new PTP multicast address for specific domain + igmp_.join(config_->get_ip_addr_str(), ip::address_v4(ptp_addr).to_string()); + } } ptp_interval = 10; } @@ -1010,6 +1024,8 @@ bool SessionManager::worker() { // send deletion for this source sap_.deletion(static_cast(msg_id_hash), addr, sdp); } + // leave PTP primary multicast + igmp_.leave(config_->get_ip_addr_str(), ip::address_v4(ptp_addr).to_string()); return true; } diff --git a/daemon/session_manager.hpp b/daemon/session_manager.hpp index dccaa8d..98d8e04 100644 --- a/daemon/session_manager.hpp +++ b/daemon/session_manager.hpp @@ -147,6 +147,8 @@ class SessionManager { size_t process_sap(); protected: + constexpr static const char ptp_dflt_mcast_addr[] = "224.0.1.129"; + std::string get_removed_source_sdp_(uint32_t id, uint32_t src_addr) const; std::string get_source_sdp_(uint32_t id, const StreamInfo& info) const; StreamSource get_source_(uint8_t id, const StreamInfo& info) const; @@ -157,7 +159,10 @@ class SessionManager { // singleton, use create() to build SessionManager(std::shared_ptr driver, std::shared_ptr config) - : driver_(driver), config_(config){}; + : driver_(driver), config_(config){ + ptp_config_.domain = config->get_ptp_domain(); + ptp_config_.dscp = config->get_ptp_dscp(); + }; std::shared_ptr driver_; std::shared_ptr config_; diff --git a/webui/src/PTP.js b/webui/src/PTP.js index b49f4f0..252848f 100644 --- a/webui/src/PTP.js +++ b/webui/src/PTP.js @@ -95,7 +95,7 @@ class PTP extends Component { - this.setState({domain: e.target.value, domainErr: !e.currentTarget.checkValidity()})} required/> + this.setState({domain: e.target.value, domainErr: !e.currentTarget.checkValidity()})} required/>