Mike J. Chen | 6c92951 | 2011-08-15 11:59:47 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #ifndef ANDROID_COMMON_TIME_SERVER_H |
| 18 | #define ANDROID_COMMON_TIME_SERVER_H |
| 19 | |
| 20 | #include <arpa/inet.h> |
| 21 | #include <stdint.h> |
Elliott Hughes | 778c859 | 2012-09-11 18:50:25 -0700 | [diff] [blame] | 22 | #include <sys/socket.h> |
Mike J. Chen | 6c92951 | 2011-08-15 11:59:47 -0700 | [diff] [blame] | 23 | |
| 24 | #include <common_time/ICommonClock.h> |
| 25 | #include <common_time/local_clock.h> |
| 26 | #include <utils/String8.h> |
| 27 | |
| 28 | #include "clock_recovery.h" |
| 29 | #include "common_clock.h" |
| 30 | #include "common_time_server_packets.h" |
John Grossman | c7f57c6 | 2012-06-26 12:50:28 -0700 | [diff] [blame] | 31 | #include "utils.h" |
Mike J. Chen | 6c92951 | 2011-08-15 11:59:47 -0700 | [diff] [blame] | 32 | |
| 33 | #define RTT_LOG_SIZE 30 |
| 34 | |
| 35 | namespace android { |
| 36 | |
| 37 | class CommonClockService; |
| 38 | class CommonTimeConfigService; |
| 39 | |
| 40 | /***** time service implementation *****/ |
| 41 | |
| 42 | class CommonTimeServer : public Thread { |
| 43 | public: |
| 44 | CommonTimeServer(); |
| 45 | ~CommonTimeServer(); |
| 46 | |
| 47 | bool startServices(); |
| 48 | |
| 49 | // Common Clock API methods |
| 50 | CommonClock& getCommonClock() { return mCommonClock; } |
| 51 | LocalClock& getLocalClock() { return mLocalClock; } |
| 52 | uint64_t getTimelineID(); |
| 53 | int32_t getEstimatedError(); |
| 54 | ICommonClock::State getState(); |
| 55 | status_t getMasterAddr(struct sockaddr_storage* addr); |
| 56 | status_t isCommonTimeValid(bool* valid, uint32_t* timelineID); |
| 57 | |
| 58 | // Config API methods |
| 59 | status_t getMasterElectionPriority(uint8_t *priority); |
| 60 | status_t setMasterElectionPriority(uint8_t priority); |
| 61 | status_t getMasterElectionEndpoint(struct sockaddr_storage *addr); |
| 62 | status_t setMasterElectionEndpoint(const struct sockaddr_storage *addr); |
| 63 | status_t getMasterElectionGroupId(uint64_t *id); |
| 64 | status_t setMasterElectionGroupId(uint64_t id); |
| 65 | status_t getInterfaceBinding(String8& ifaceName); |
| 66 | status_t setInterfaceBinding(const String8& ifaceName); |
| 67 | status_t getMasterAnnounceInterval(int *interval); |
| 68 | status_t setMasterAnnounceInterval(int interval); |
| 69 | status_t getClientSyncInterval(int *interval); |
| 70 | status_t setClientSyncInterval(int interval); |
| 71 | status_t getPanicThreshold(int *threshold); |
| 72 | status_t setPanicThreshold(int threshold); |
| 73 | status_t getAutoDisable(bool *autoDisable); |
| 74 | status_t setAutoDisable(bool autoDisable); |
| 75 | status_t forceNetworklessMasterMode(); |
| 76 | |
| 77 | // Method used by the CommonClockService to notify the core service about |
| 78 | // changes in the number of active common clock clients. |
| 79 | void reevaluateAutoDisableState(bool commonClockHasClients); |
| 80 | |
| 81 | status_t dumpClockInterface(int fd, const Vector<String16>& args, |
| 82 | size_t activeClients); |
| 83 | status_t dumpConfigInterface(int fd, const Vector<String16>& args); |
| 84 | |
| 85 | private: |
| 86 | class PacketRTTLog { |
| 87 | public: |
| 88 | PacketRTTLog() { |
| 89 | resetLog(); |
| 90 | } |
| 91 | |
| 92 | void resetLog() { |
| 93 | wrPtr = 0; |
| 94 | logFull = 0; |
| 95 | } |
| 96 | |
| 97 | void logTX(int64_t txTime); |
| 98 | void logRX(int64_t txTime, int64_t rxTime); |
| 99 | void dumpLog(int fd, const CommonClock& cclk); |
| 100 | |
| 101 | private: |
| 102 | uint32_t wrPtr; |
| 103 | bool logFull; |
| 104 | int64_t txTimes[RTT_LOG_SIZE]; |
| 105 | int64_t rxTimes[RTT_LOG_SIZE]; |
| 106 | }; |
| 107 | |
Mike J. Chen | 6c92951 | 2011-08-15 11:59:47 -0700 | [diff] [blame] | 108 | bool threadLoop(); |
| 109 | |
| 110 | bool runStateMachine_l(); |
| 111 | bool setupSocket_l(); |
| 112 | |
| 113 | void assignTimelineID(); |
| 114 | bool assignDeviceID(); |
| 115 | |
| 116 | static bool arbitrateMaster(uint64_t deviceID1, uint8_t devicePrio1, |
| 117 | uint64_t deviceID2, uint8_t devicePrio2); |
| 118 | |
| 119 | bool handlePacket(); |
| 120 | bool handleWhoIsMasterRequest (const WhoIsMasterRequestPacket* request, |
| 121 | const sockaddr_storage& srcAddr); |
| 122 | bool handleWhoIsMasterResponse(const WhoIsMasterResponsePacket* response, |
| 123 | const sockaddr_storage& srcAddr); |
| 124 | bool handleSyncRequest (const SyncRequestPacket* request, |
| 125 | const sockaddr_storage& srcAddr); |
| 126 | bool handleSyncResponse (const SyncResponsePacket* response, |
| 127 | const sockaddr_storage& srcAddr); |
| 128 | bool handleMasterAnnouncement (const MasterAnnouncementPacket* packet, |
| 129 | const sockaddr_storage& srcAddr); |
| 130 | |
| 131 | bool handleTimeout(); |
| 132 | bool handleTimeoutInitial(); |
| 133 | bool handleTimeoutClient(); |
| 134 | bool handleTimeoutMaster(); |
| 135 | bool handleTimeoutRonin(); |
| 136 | bool handleTimeoutWaitForElection(); |
| 137 | |
| 138 | bool sendWhoIsMasterRequest(); |
| 139 | bool sendSyncRequest(); |
| 140 | bool sendMasterAnnouncement(); |
| 141 | |
| 142 | bool becomeClient(const sockaddr_storage& masterAddr, |
| 143 | uint64_t masterDeviceID, |
| 144 | uint8_t masterDevicePriority, |
| 145 | uint64_t timelineID, |
| 146 | const char* cause); |
| 147 | bool becomeMaster(const char* cause); |
| 148 | bool becomeRonin(const char* cause); |
| 149 | bool becomeWaitForElection(const char* cause); |
| 150 | bool becomeInitial(const char* cause); |
| 151 | |
| 152 | void notifyClockSync(); |
| 153 | void notifyClockSyncLoss(); |
| 154 | |
| 155 | ICommonClock::State mState; |
| 156 | void setState(ICommonClock::State s); |
| 157 | |
| 158 | void clearPendingWakeupEvents_l(); |
| 159 | void wakeupThread_l(); |
| 160 | void cleanupSocket_l(); |
| 161 | void shutdownThread(); |
| 162 | |
| 163 | inline uint8_t effectivePriority() const { |
| 164 | return (mMasterPriority & 0x7F) | |
| 165 | (mForceLowPriority ? 0x00 : 0x80); |
| 166 | } |
| 167 | |
| 168 | inline bool shouldAutoDisable() const { |
| 169 | return (mAutoDisable && !mCommonClockHasClients); |
| 170 | } |
| 171 | |
| 172 | inline void resetSyncStats() { |
| 173 | mClient_SyncRequestPending = false; |
| 174 | mClient_SyncRequestTimeouts = 0; |
| 175 | mClient_SyncsSentToCurMaster = 0; |
| 176 | mClient_SyncRespsRXedFromCurMaster = 0; |
| 177 | mClient_ExpiredSyncRespsRXedFromCurMaster = 0; |
| 178 | mClient_FirstSyncTX = 0; |
| 179 | mClient_LastGoodSyncRX = 0; |
| 180 | mClient_PacketRTTLog.resetLog(); |
| 181 | } |
| 182 | |
| 183 | bool shouldPanicNotGettingGoodData(); |
| 184 | |
| 185 | // Helper to keep track of the state machine's current timeout |
John Grossman | c7f57c6 | 2012-06-26 12:50:28 -0700 | [diff] [blame] | 186 | Timeout mCurTimeout; |
Mike J. Chen | 6c92951 | 2011-08-15 11:59:47 -0700 | [diff] [blame] | 187 | |
| 188 | // common clock, local clock abstraction, and clock recovery loop |
| 189 | CommonClock mCommonClock; |
| 190 | LocalClock mLocalClock; |
| 191 | ClockRecoveryLoop mClockRecovery; |
| 192 | |
| 193 | // implementation of ICommonClock |
| 194 | sp<CommonClockService> mICommonClock; |
| 195 | |
| 196 | // implementation of ICommonTimeConfig |
| 197 | sp<CommonTimeConfigService> mICommonTimeConfig; |
| 198 | |
| 199 | // UDP socket for the time sync protocol |
| 200 | int mSocket; |
| 201 | |
| 202 | // eventfd used to wakeup the work thread in response to configuration |
| 203 | // changes. |
| 204 | int mWakeupThreadFD; |
| 205 | |
| 206 | // timestamp captured when a packet is received |
| 207 | int64_t mLastPacketRxLocalTime; |
| 208 | |
| 209 | // ID of the timeline that this device is following |
| 210 | uint64_t mTimelineID; |
| 211 | |
| 212 | // flag for whether the clock has been synced to a timeline |
| 213 | bool mClockSynced; |
| 214 | |
| 215 | // flag used to indicate that clients should be considered to be lower |
| 216 | // priority than all of their peers during elections. This flag is set and |
| 217 | // cleared by the state machine. It is set when the client joins a new |
| 218 | // network. If the client had been a master in the old network (or an |
| 219 | // isolated master with no network connectivity) it should defer to any |
| 220 | // masters which may already be on the network. It will be cleared whenever |
| 221 | // the state machine transitions to the master state. |
| 222 | bool mForceLowPriority; |
| 223 | inline void setForceLowPriority(bool val) { |
| 224 | mForceLowPriority = val; |
| 225 | if (mState == ICommonClock::STATE_MASTER) |
| 226 | mClient_MasterDevicePriority = effectivePriority(); |
| 227 | } |
| 228 | |
| 229 | // Lock to synchronize access to internal state and configuration. |
| 230 | Mutex mLock; |
| 231 | |
| 232 | // Flag updated by the common clock service to indicate that it does or does |
| 233 | // not currently have registered clients. When the the auto disable flag is |
| 234 | // cleared on the common time service, the service will participate in |
| 235 | // network synchronization whenever it has a valid network interface to bind |
| 236 | // to. When the auto disable flag is set on the common time service, it |
| 237 | // will only participate in network synchronization when it has both a valid |
| 238 | // interface AND currently active common clock clients. |
| 239 | bool mCommonClockHasClients; |
| 240 | |
John Grossman | 79489c4 | 2012-07-20 10:17:26 -0700 | [diff] [blame] | 241 | // Internal logs used for dumpsys. |
| 242 | LogRing mStateChangeLog; |
| 243 | LogRing mElectionLog; |
| 244 | LogRing mBadPktLog; |
| 245 | |
Mike J. Chen | 6c92951 | 2011-08-15 11:59:47 -0700 | [diff] [blame] | 246 | // Configuration info |
| 247 | struct sockaddr_storage mMasterElectionEP; // Endpoint over which we conduct master election |
| 248 | String8 mBindIface; // Endpoint for the service to bind to. |
| 249 | bool mBindIfaceValid; // whether or not the bind Iface is valid. |
| 250 | bool mBindIfaceDirty; // whether or not the bind Iface is valid. |
| 251 | struct sockaddr_storage mMasterEP; // Endpoint of our current master (if any) |
| 252 | bool mMasterEPValid; |
| 253 | uint64_t mDeviceID; // unique ID of this device |
| 254 | uint64_t mSyncGroupID; // synchronization group ID of this device. |
| 255 | uint8_t mMasterPriority; // Priority of this device in master election. |
| 256 | uint32_t mMasterAnnounceIntervalMs; |
| 257 | uint32_t mSyncRequestIntervalMs; |
| 258 | uint32_t mPanicThresholdUsec; |
| 259 | bool mAutoDisable; |
| 260 | |
| 261 | // Config defaults. |
| 262 | static const char* kDefaultMasterElectionAddr; |
| 263 | static const uint16_t kDefaultMasterElectionPort; |
| 264 | static const uint64_t kDefaultSyncGroupID; |
| 265 | static const uint8_t kDefaultMasterPriority; |
| 266 | static const uint32_t kDefaultMasterAnnounceIntervalMs; |
| 267 | static const uint32_t kDefaultSyncRequestIntervalMs; |
| 268 | static const uint32_t kDefaultPanicThresholdUsec; |
| 269 | static const bool kDefaultAutoDisable; |
| 270 | |
| 271 | // Priority mask and shift fields. |
| 272 | static const uint64_t kDeviceIDMask; |
| 273 | static const uint8_t kDevicePriorityMask; |
| 274 | static const uint8_t kDevicePriorityHiLowBit; |
| 275 | static const uint32_t kDevicePriorityShift; |
| 276 | |
| 277 | // Unconfgurable constants |
| 278 | static const int kSetupRetryTimeoutMs; |
| 279 | static const int64_t kNoGoodDataPanicThresholdUsec; |
| 280 | static const uint32_t kRTTDiscardPanicThreshMultiplier; |
| 281 | |
| 282 | /*** status while in the Initial state ***/ |
| 283 | int mInitial_WhoIsMasterRequestTimeouts; |
| 284 | static const int kInitial_NumWhoIsMasterRetries; |
| 285 | static const int kInitial_WhoIsMasterTimeoutMs; |
| 286 | |
| 287 | /*** status while in the Client state ***/ |
| 288 | uint64_t mClient_MasterDeviceID; |
| 289 | uint8_t mClient_MasterDevicePriority; |
| 290 | bool mClient_SyncRequestPending; |
| 291 | int mClient_SyncRequestTimeouts; |
| 292 | uint32_t mClient_SyncsSentToCurMaster; |
| 293 | uint32_t mClient_SyncRespsRXedFromCurMaster; |
| 294 | uint32_t mClient_ExpiredSyncRespsRXedFromCurMaster; |
| 295 | int64_t mClient_FirstSyncTX; |
| 296 | int64_t mClient_LastGoodSyncRX; |
| 297 | PacketRTTLog mClient_PacketRTTLog; |
| 298 | static const int kClient_NumSyncRequestRetries; |
| 299 | |
| 300 | |
| 301 | /*** status while in the Master state ***/ |
| 302 | static const uint32_t kDefaultMaster_AnnouncementIntervalMs; |
| 303 | |
| 304 | /*** status while in the Ronin state ***/ |
| 305 | int mRonin_WhoIsMasterRequestTimeouts; |
| 306 | static const int kRonin_NumWhoIsMasterRetries; |
| 307 | static const int kRonin_WhoIsMasterTimeoutMs; |
| 308 | |
| 309 | /*** status while in the WaitForElection state ***/ |
| 310 | static const int kWaitForElection_TimeoutMs; |
| 311 | |
| 312 | static const int kInfiniteTimeout; |
| 313 | |
| 314 | static const char* stateToString(ICommonClock::State s); |
| 315 | static void sockaddrToString(const sockaddr_storage& addr, bool addrValid, |
| 316 | char* buf, size_t bufLen); |
| 317 | static bool sockaddrMatch(const sockaddr_storage& a1, |
| 318 | const sockaddr_storage& a2, |
| 319 | bool matchAddressOnly); |
| 320 | }; |
| 321 | |
| 322 | } // namespace android |
| 323 | |
| 324 | #endif // ANDROID_COMMON_TIME_SERVER_H |