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