summaryrefslogtreecommitdiffstats
path: root/services/common_time/common_time_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/common_time/common_time_server.cpp')
-rw-r--r--services/common_time/common_time_server.cpp259
1 files changed, 188 insertions, 71 deletions
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index 7a4986b..21e706f 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -53,9 +53,9 @@
namespace android {
-const char* CommonTimeServer::kDefaultMasterElectionAddr = "239.195.128.88";
-const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8887;
-const uint64_t CommonTimeServer::kDefaultSyncGroupID = 0;
+const char* CommonTimeServer::kDefaultMasterElectionAddr = "255.255.255.255";
+const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8886;
+const uint64_t CommonTimeServer::kDefaultSyncGroupID = 1;
const uint8_t CommonTimeServer::kDefaultMasterPriority = 1;
const uint32_t CommonTimeServer::kDefaultMasterAnnounceIntervalMs = 10000;
const uint32_t CommonTimeServer::kDefaultSyncRequestIntervalMs = 1000;
@@ -107,6 +107,9 @@ CommonTimeServer::CommonTimeServer()
, mTimelineID(ICommonClock::kInvalidTimelineID)
, mClockSynced(false)
, mCommonClockHasClients(false)
+ , mStateChangeLog("Recent State Change Events", 30)
+ , mElectionLog("Recent Master Election Traffic", 30)
+ , mBadPktLog("Recent Bad Packet RX Info", 8)
, mInitial_WhoIsMasterRequestTimeouts(0)
, mClient_MasterDeviceID(0)
, mClient_MasterDevicePriority(0)
@@ -202,9 +205,11 @@ bool CommonTimeServer::runStateMachine_l() {
// run the state machine
while (!exitPending()) {
struct pollfd pfds[2];
- int rc;
+ int rc, timeout;
int eventCnt = 0;
int64_t wakeupTime;
+ uint32_t t1, t2;
+ bool needHandleTimeout = false;
// We are always interested in our wakeup FD.
pfds[eventCnt].fd = mWakeupThreadFD;
@@ -221,10 +226,14 @@ bool CommonTimeServer::runStateMachine_l() {
eventCnt++;
}
+ t1 = static_cast<uint32_t>(mCurTimeout.msecTillTimeout());
+ t2 = static_cast<uint32_t>(mClockRecovery.applyRateLimitedSlew());
+ timeout = static_cast<int>(t1 < t2 ? t1 : t2);
+
// Note, we were holding mLock when this function was called. We
// release it only while we are blocking and hold it at all other times.
mLock.unlock();
- rc = poll(pfds, eventCnt, mCurTimeout.msecTillTimeout());
+ rc = poll(pfds, eventCnt, timeout);
wakeupTime = mLocalClock.getLocalTime();
mLock.lock();
@@ -238,8 +247,11 @@ bool CommonTimeServer::runStateMachine_l() {
return false;
}
- if (rc == 0)
- mCurTimeout.setTimeout(kInfiniteTimeout);
+ if (rc == 0) {
+ needHandleTimeout = !mCurTimeout.msecTillTimeout();
+ if (needHandleTimeout)
+ mCurTimeout.setTimeout(kInfiniteTimeout);
+ }
// Were we woken up on purpose? If so, clear the eventfd with a read.
if (pfds[0].revents)
@@ -321,10 +333,11 @@ bool CommonTimeServer::runStateMachine_l() {
// we are in any other state (CLIENT, RONIN or WAIT_FOR_ELECTION),
// then transition to either INITIAL or MASTER depending on whether
// or not our timeline is valid.
- ALOGI("Entering networkless mode interface is %s, "
- "shouldAutoDisable = %s",
- mBindIfaceValid ? "valid" : "invalid",
- shouldAutoDisable() ? "true" : "false");
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "Entering networkless mode interface is %s, "
+ "shouldAutoDisable = %s",
+ mBindIfaceValid ? "valid" : "invalid",
+ shouldAutoDisable() ? "true" : "false");
if ((mState != ICommonClock::STATE_INITIAL) &&
(mState != ICommonClock::STATE_MASTER)) {
if (mTimelineID == ICommonClock::kInvalidTimelineID)
@@ -336,9 +349,8 @@ bool CommonTimeServer::runStateMachine_l() {
continue;
}
- // Did we wakeup with no signalled events across all of our FDs? If so,
- // we must have hit our timeout.
- if (rc == 0) {
+ // Time to handle the timeouts?
+ if (needHandleTimeout) {
if (!handleTimeout())
ALOGE("handleTimeout failed");
continue;
@@ -407,20 +419,23 @@ bool CommonTimeServer::setupSocket_l() {
sockaddrToString(mMasterElectionEP, true, masterElectionEPStr,
sizeof(masterElectionEPStr));
- ALOGI("Building socket :: bind = %s master election = %s",
- mBindIface.string(), masterElectionEPStr);
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "Building socket :: bind = %s master election = %s",
+ mBindIface.string(), masterElectionEPStr);
// TODO: add proper support for IPv6. Right now, we block IPv6 addresses at
// the configuration interface level.
if (AF_INET != mMasterElectionEP.ss_family) {
- ALOGW("TODO: add proper IPv6 support");
+ mStateChangeLog.log(ANDROID_LOG_WARN, LOG_TAG,
+ "TODO: add proper IPv6 support");
goto bailout;
}
// open a UDP socket for the timeline serivce
mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (mSocket < 0) {
- ALOGE("Failed to create socket (errno = %d)", errno);
+ mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Failed to create socket (errno = %d)", errno);
goto bailout;
}
@@ -432,8 +447,9 @@ bool CommonTimeServer::setupSocket_l() {
rc = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE,
(void *)&ifr, sizeof(ifr));
if (rc) {
- ALOGE("Failed to bind socket at to interface %s (errno = %d)",
- ifr.ifr_name, errno);
+ mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Failed to bind socket at to interface %s "
+ "(errno = %d)", ifr.ifr_name, errno);
goto bailout;
}
@@ -451,8 +467,9 @@ bool CommonTimeServer::setupSocket_l() {
reinterpret_cast<const sockaddr *>(&bindAddr),
sizeof(bindAddr));
if (rc) {
- ALOGE("Failed to bind socket to port %hu (errno = %d)",
- ntohs(bindAddr.sin_port), errno);
+ mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Failed to bind socket to port %hu (errno = %d)",
+ ntohs(bindAddr.sin_port), errno);
goto bailout;
}
@@ -475,11 +492,23 @@ bool CommonTimeServer::setupSocket_l() {
rc = setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
&zero, sizeof(zero));
if (rc == -1) {
- ALOGE("Failed to disable multicast loopback (errno = %d)", errno);
+ mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Failed to disable multicast loopback "
+ "(errno = %d)", errno);
goto bailout;
}
} else
- if (ntohl(ipv4_addr->sin_addr.s_addr) != 0xFFFFFFFF) {
+ if (ntohl(ipv4_addr->sin_addr.s_addr) == 0xFFFFFFFF) {
+ // If the master election address is the broadcast address, then enable
+ // the broadcast socket option
+ rc = setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
+ if (rc == -1) {
+ mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Failed to enable broadcast (errno = %d)",
+ errno);
+ goto bailout;
+ }
+ } else {
// If the master election address is neither broadcast, nor multicast,
// then we are misconfigured. The config API layer should prevent this
// from ever happening.
@@ -490,7 +519,8 @@ bool CommonTimeServer::setupSocket_l() {
// the local subnet)
rc = setsockopt(mSocket, IPPROTO_IP, IP_TTL, &one, sizeof(one));
if (rc == -1) {
- ALOGE("Failed to set TTL to %d (errno = %d)", one, errno);
+ mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Failed to set TTL to %d (errno = %d)", one, errno);
goto bailout;
}
@@ -552,6 +582,31 @@ bool CommonTimeServer::arbitrateMaster(
((devicePrio1 == devicePrio2) && (deviceID1 > deviceID2)));
}
+static void hexDumpToString(const uint8_t* src, size_t src_len,
+ char* dst, size_t dst_len) {
+ size_t offset = 0;
+ size_t i;
+
+ for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
+ int res;
+ if (0 == (i % 16)) {
+ res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+ if (res < 0)
+ break;
+ offset += res;
+ if (offset >= dst_len)
+ break;
+ }
+
+ res = snprintf(dst + offset, dst_len - offset, " %02x", src[i]);
+ if (res < 0)
+ break;
+ offset += res;
+ }
+
+ dst[dst_len - 1] = 0;
+}
+
bool CommonTimeServer::handlePacket() {
uint8_t buf[256];
struct sockaddr_storage srcAddr;
@@ -562,14 +617,24 @@ bool CommonTimeServer::handlePacket() {
reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen);
if (recvBytes < 0) {
- ALOGE("%s:%d recvfrom failed", __PRETTY_FUNCTION__, __LINE__);
+ mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG,
+ "recvfrom failed (res %d, errno %d)",
+ recvBytes, errno);
return false;
}
UniversalTimeServicePacket pkt;
- recvBytes = pkt.deserializePacket(buf, recvBytes, mSyncGroupID);
- if (recvBytes < 0)
+ if (pkt.deserializePacket(buf, recvBytes, mSyncGroupID) < 0) {
+ char hex[256];
+ char srcEPStr[64];
+
+ hexDumpToString(buf, static_cast<size_t>(recvBytes), hex, sizeof(hex));
+ sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+
+ mBadPktLog.log("Failed to parse %d byte packet from %s.%s",
+ recvBytes, srcEPStr, hex);
return false;
+ }
bool result;
switch (pkt.packetType) {
@@ -597,8 +662,13 @@ bool CommonTimeServer::handlePacket() {
break;
default: {
- ALOGD("%s:%d unknown packet type(%d)",
- __PRETTY_FUNCTION__, __LINE__, pkt.packetType);
+ char srcEPStr[64];
+ sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+
+ mBadPktLog.log(ANDROID_LOG_WARN, LOG_TAG,
+ "unknown packet type (%d) from %s",
+ pkt.packetType, srcEPStr);
+
result = false;
} break;
}
@@ -682,6 +752,17 @@ bool CommonTimeServer::handleTimeoutWaitForElection() {
bool CommonTimeServer::handleWhoIsMasterRequest(
const WhoIsMasterRequestPacket* request,
const sockaddr_storage& srcAddr) {
+ // Skip our own messages which come back via broadcast loopback.
+ if (request->senderDeviceID == mDeviceID)
+ return true;
+
+ char srcEPStr[64];
+ sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+ mElectionLog.log("RXed WhoIs master request while in state %s. "
+ "src %s reqTID %016llx ourTID %016llx",
+ stateToString(mState), srcEPStr,
+ request->timelineID, mTimelineID);
+
if (mState == ICommonClock::STATE_MASTER) {
// is this request related to this master's timeline?
if (request->timelineID != ICommonClock::kInvalidTimelineID &&
@@ -693,6 +774,13 @@ bool CommonTimeServer::handleWhoIsMasterRequest(
pkt.deviceID = mDeviceID;
pkt.devicePriority = effectivePriority();
+ mElectionLog.log("TXing WhoIs master resp to %s while in state %s. "
+ "ourTID %016llx ourGID %016llx ourDID %016llx "
+ "ourPrio %u",
+ srcEPStr, stateToString(mState),
+ mTimelineID, mSyncGroupID,
+ pkt.deviceID, pkt.devicePriority);
+
uint8_t buf[256];
ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
if (bufSz < 0)
@@ -744,6 +832,21 @@ bool CommonTimeServer::handleWhoIsMasterRequest(
bool CommonTimeServer::handleWhoIsMasterResponse(
const WhoIsMasterResponsePacket* response,
const sockaddr_storage& srcAddr) {
+ // Skip our own messages which come back via broadcast loopback.
+ if (response->deviceID == mDeviceID)
+ return true;
+
+ char srcEPStr[64];
+ sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+ mElectionLog.log("RXed WhoIs master response while in state %s. "
+ "src %s respTID %016llx respDID %016llx respPrio %u "
+ "ourTID %016llx",
+ stateToString(mState), srcEPStr,
+ response->timelineID,
+ response->deviceID,
+ static_cast<uint32_t>(response->devicePriority),
+ mTimelineID);
+
if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN) {
return becomeClient(srcAddr,
response->deviceID,
@@ -900,6 +1003,18 @@ bool CommonTimeServer::handleMasterAnnouncement(
uint8_t newDevicePrio = packet->devicePriority;
uint64_t newTimelineID = packet->timelineID;
+ // Skip our own messages which come back via broadcast loopback.
+ if (newDeviceID == mDeviceID)
+ return true;
+
+ char srcEPStr[64];
+ sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
+ mElectionLog.log("RXed master announcement while in state %s. "
+ "src %s srcDevID %lld srcPrio %u srcTID %016llx",
+ stateToString(mState), srcEPStr,
+ newDeviceID, static_cast<uint32_t>(newDevicePrio),
+ newTimelineID);
+
if (mState == ICommonClock::STATE_INITIAL ||
mState == ICommonClock::STATE_RONIN ||
mState == ICommonClock::STATE_WAIT_FOR_ELECTION) {
@@ -956,6 +1071,15 @@ bool CommonTimeServer::sendWhoIsMasterRequest() {
uint8_t buf[256];
ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
if (bufSz >= 0) {
+ char dstEPStr[64];
+ sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
+ mElectionLog.log("TXing WhoIs master request to %s while in state %s. "
+ "ourTID %016llx ourGID %016llx ourDID %016llx "
+ "ourPrio %u",
+ dstEPStr, stateToString(mState),
+ mTimelineID, mSyncGroupID,
+ pkt.senderDeviceID, pkt.senderDevicePriority);
+
ssize_t sendBytes = sendto(
mSocket, buf, bufSz, 0,
reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
@@ -1032,6 +1156,15 @@ bool CommonTimeServer::sendMasterAnnouncement() {
uint8_t buf[256];
ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
if (bufSz >= 0) {
+ char dstEPStr[64];
+ sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
+ mElectionLog.log("TXing Master announcement to %s while in state %s. "
+ "ourTID %016llx ourGID %016llx ourDID %016llx "
+ "ourPrio %u",
+ dstEPStr, stateToString(mState),
+ mTimelineID, mSyncGroupID,
+ pkt.deviceID, pkt.devicePriority);
+
ssize_t sendBytes = sendto(
mSocket, buf, bufSz, 0,
reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
@@ -1054,15 +1187,16 @@ bool CommonTimeServer::becomeClient(const sockaddr_storage& masterEP,
sockaddrToString(masterEP, true, newEPStr, sizeof(newEPStr));
sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr));
- ALOGI("%s --> CLIENT (%s) :%s"
- " OldMaster: %02x-%014llx::%016llx::%s"
- " NewMaster: %02x-%014llx::%016llx::%s",
- stateToString(mState), cause,
- (mTimelineID != timelineID) ? " (new timeline)" : "",
- mClient_MasterDevicePriority, mClient_MasterDeviceID,
- mTimelineID, oldEPStr,
- masterDevicePriority, masterDeviceID,
- timelineID, newEPStr);
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "%s --> CLIENT (%s) :%s"
+ " OldMaster: %02x-%014llx::%016llx::%s"
+ " NewMaster: %02x-%014llx::%016llx::%s",
+ stateToString(mState), cause,
+ (mTimelineID != timelineID) ? " (new timeline)" : "",
+ mClient_MasterDevicePriority, mClient_MasterDeviceID,
+ mTimelineID, oldEPStr,
+ masterDevicePriority, masterDeviceID,
+ timelineID, newEPStr);
if (mTimelineID != timelineID) {
// start following a new timeline
@@ -1115,11 +1249,12 @@ bool CommonTimeServer::becomeMaster(const char* cause) {
notifyClockSync();
}
- ALOGI("%s --> MASTER (%s) : %s timeline %016llx",
- stateToString(mState), cause,
- (oldTimelineID == mTimelineID) ? "taking ownership of"
- : "creating new",
- mTimelineID);
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "%s --> MASTER (%s) : %s timeline %016llx",
+ stateToString(mState), cause,
+ (oldTimelineID == mTimelineID) ? "taking ownership of"
+ : "creating new",
+ mTimelineID);
memset(&mMasterEP, 0, sizeof(mMasterEP));
mMasterEPValid = false;
@@ -1148,7 +1283,8 @@ bool CommonTimeServer::becomeRonin(const char* cause) {
mMasterEPValid = false;
if (mCommonClock.isValid()) {
- ALOGI("%s --> RONIN (%s) : lost track of previously valid timeline "
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "%s --> RONIN (%s) : lost track of previously valid timeline "
"%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
stateToString(mState), cause,
mClient_MasterDevicePriority, mClient_MasterDeviceID,
@@ -1161,7 +1297,8 @@ bool CommonTimeServer::becomeRonin(const char* cause) {
setState(ICommonClock::STATE_RONIN);
return sendWhoIsMasterRequest();
} else {
- ALOGI("%s --> INITIAL (%s) : never synced timeline "
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "%s --> INITIAL (%s) : never synced timeline "
"%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
stateToString(mState), cause,
mClient_MasterDevicePriority, mClient_MasterDeviceID,
@@ -1175,7 +1312,8 @@ bool CommonTimeServer::becomeRonin(const char* cause) {
}
bool CommonTimeServer::becomeWaitForElection(const char* cause) {
- ALOGI("%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
" waiting %d mSec for completion.",
stateToString(mState), cause, kWaitForElection_TimeoutMs);
@@ -1185,7 +1323,9 @@ bool CommonTimeServer::becomeWaitForElection(const char* cause) {
}
bool CommonTimeServer::becomeInitial(const char* cause) {
- ALOGI("Entering INITIAL (%s), total reset.", cause);
+ mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
+ "Entering INITIAL (%s), total reset.",
+ cause);
setState(ICommonClock::STATE_INITIAL);
@@ -1326,29 +1466,6 @@ bool CommonTimeServer::sockaddrMatch(const sockaddr_storage& a1,
}
}
-void CommonTimeServer::TimeoutHelper::setTimeout(int msec) {
- mTimeoutValid = (msec >= 0);
- if (mTimeoutValid)
- mEndTime = systemTime() +
- (static_cast<nsecs_t>(msec) * 1000000);
-}
-
-int CommonTimeServer::TimeoutHelper::msecTillTimeout() {
- if (!mTimeoutValid)
- return kInfiniteTimeout;
-
- nsecs_t now = systemTime();
- if (now >= mEndTime)
- return 0;
-
- uint64_t deltaMsec = (((mEndTime - now) + 999999) / 1000000);
-
- if (deltaMsec > static_cast<uint64_t>(MAX_INT))
- return MAX_INT;
-
- return static_cast<int>(deltaMsec);
-}
-
bool CommonTimeServer::shouldPanicNotGettingGoodData() {
if (mClient_FirstSyncTX) {
int64_t now = mLocalClock.getLocalTime();