View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2006-2008 Vlad Skarzhevskyy
4    * 
5    *  Licensed to the Apache Software Foundation (ASF) under one
6    *  or more contributor license agreements.  See the NOTICE file
7    *  distributed with this work for additional information
8    *  regarding copyright ownership.  The ASF licenses this file
9    *  to you under the Apache License, Version 2.0 (the
10   *  "License"); you may not use this file except in compliance
11   *  with the License.  You may obtain a copy of the License at
12   *
13   *    http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing,
16   *  software distributed under the License is distributed on an
17   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   *  KIND, either express or implied.  See the License for the
19   *  specific language governing permissions and limitations
20   *  under the License.
21   *
22   *  @author vlads
23   *  @version $Id: L2TrafficGenerator.java 2607 2008-12-17 23:51:33Z skarzhevskyy $
24   */
25  package net.sf.bluecove.tests;
26  
27  import java.io.IOException;
28  
29  import org.bluecove.tester.log.Logger;
30  import org.bluecove.tester.util.IOUtils;
31  import org.bluecove.tester.util.RuntimeDetect;
32  import org.bluecove.tester.util.TimeUtils;
33  
34  import net.sf.bluecove.CommunicationTesterL2CAP;
35  import net.sf.bluecove.Configuration;
36  import net.sf.bluecove.ConnectionHolderL2CAP;
37  import net.sf.bluecove.TestStatus;
38  import net.sf.bluecove.util.TimeStatistic;
39  
40  /**
41   *
42   * 
43   */
44  public class L2TrafficGenerator {
45  
46  	static final int sequenceSizeMin = 16;
47  
48  	private static class Config {
49  
50  		int sequenceSleep = 0;
51  
52  		int sequenceSize = 0;
53  
54  		int durationMSec = 0;
55  
56  		boolean init(byte[] initialData, boolean server, String messagePrefix) throws IOException {
57  			if (server) {
58  				if (initialData != null) {
59  					if (initialData.length >= 1) {
60  						sequenceSleep = IOUtils.byteToUnsignedInt(initialData[0]);
61  					}
62  					if (initialData.length >= 2) {
63  						sequenceSize = IOUtils.byteToUnsignedInt(initialData[1]);
64  					}
65  					if (initialData.length >= 3) {
66  						durationMSec = IOUtils.byteToUnsignedInt(initialData[2]);
67  					}
68  				}
69  			} else {
70  				sequenceSize = Configuration.tgSize & 0xFF;
71  				sequenceSleep = Configuration.tgSleep & 0xFF;
72  				durationMSec = Configuration.tgDurationMin;
73  			}
74  
75  			sequenceSleep = sequenceSleep * 10;
76  			if (sequenceSize < sequenceSizeMin) {
77  				sequenceSize = sequenceSizeMin;
78  			}
79  			switch (sequenceSize) {
80  			case 251:
81  				// 1K
82  				sequenceSize = 0x400;
83  				break;
84  			case 252:
85  				// 2K
86  				sequenceSize = 0x800;
87  				break;
88  			case 253:
89  				// 3K
90  				sequenceSize = 0xC00;
91  				break;
92  			case 254:
93  				// 4K
94  				sequenceSize = 0x1000;
95  				break;
96  			case 255:
97  				// 5K
98  				sequenceSize = 0x1400;
99  				break;
100 			}
101 			Logger.debug(messagePrefix + " size selected " + sequenceSize + " byte");
102 			Logger.debug(messagePrefix + " duration " + durationMSec + " minutes");
103 			durationMSec *= 60000;
104 			return true;
105 		}
106 	}
107 
108 	public static void trafficGeneratorClientInit(ConnectionHolderL2CAP c, int testType) throws IOException {
109 		byte sequenceSleep = (byte) (Configuration.tgSleep & 0xFF);
110 		byte sequenceSize = (byte) (Configuration.tgSize & 0xFF);
111 		byte durationMin = (byte) (Configuration.tgDurationMin & 0xFF);
112 		c.channel.send(CommunicationTesterL2CAP.startPrefix(testType, new byte[] { sequenceSleep, sequenceSize,
113 				durationMin }));
114 	}
115 
116 	public static void trafficGeneratorWrite(ConnectionHolderL2CAP c, byte[] initialData, boolean server,
117 			final TestStatus testStatus) throws IOException {
118 		Config cf = new Config();
119 		if (!cf.init(initialData, server, "L2 write")) {
120 			return;
121 		}
122 		if (cf.sequenceSleep > 0) {
123 			Logger.debug("write sleep selected " + cf.sequenceSleep + " msec");
124 		} else {
125 			Logger.debug("write no sleep");
126 		}
127 
128 		int transmitMTU = c.channel.getTransmitMTU();
129 		if (transmitMTU < cf.sequenceSize) {
130 			Logger.warn("L2 write size " + cf.sequenceSize + " is greater then MTU " + transmitMTU);
131 			cf.sequenceSize = transmitMTU;
132 		}
133 
134 		long sequenceSentCount = 0;
135 		int reportedSize = 0;
136 
137 		// Create test data
138 		byte[] data = new byte[cf.sequenceSize];
139 		for (int i = 1; i < cf.sequenceSize; i++) {
140 			data[i] = (byte) i;
141 		}
142 		long start = System.currentTimeMillis();
143 		long reported = start;
144 		try {
145 			mainLoop: do {
146 				IOUtils.long2Bytes(sequenceSentCount, 8, data, 0);
147 				long sendTime = System.currentTimeMillis();
148 				IOUtils.long2Bytes(sendTime, 8, data, 8);
149 				c.channel.send(data);
150 				sequenceSentCount++;
151 				reportedSize += cf.sequenceSize;
152 				c.active();
153 				long now = System.currentTimeMillis();
154 				if (now - reported > 5 * 1000) {
155 					Logger
156 							.debug("L2 Sent " + sequenceSentCount + " packet(s) "
157 									+ TimeUtils.bps(reportedSize, reported));
158 					reported = now;
159 					reportedSize = 0;
160 				}
161 				if ((cf.durationMSec != 0) && (now > start + cf.durationMSec)) {
162 					break;
163 				}
164 				if (cf.sequenceSleep > 0) {
165 					try {
166 						Thread.sleep(cf.sequenceSleep);
167 					} catch (InterruptedException e) {
168 						break mainLoop;
169 					}
170 					c.active();
171 				}
172 			} while (c.isConnectionOpen() && (!testStatus.isRunCompleate()));
173 		} finally {
174 			testStatus.setRunCompleate();
175 			Logger.debug("L2 Total " + sequenceSentCount + " packet(s)");
176 			Logger.debug("L2 Total write speed " + TimeUtils.bps(sequenceSentCount * cf.sequenceSize, start));
177 		}
178 	}
179 
180 	public static void trafficGeneratorStatusReadStart(final ConnectionHolderL2CAP c, final TestStatus testStatus) {
181 		Runnable r = new Runnable() {
182 			public void run() {
183 				try {
184 					trafficGeneratorStatusRead(c, testStatus);
185 				} catch (IOException e) {
186 					Logger.error("reader", e);
187 				}
188 			}
189 		};
190 		Thread t = RuntimeDetect.cldcStub.createNamedThread(r, "L2tgStatusReciver");
191 		t.start();
192 	}
193 
194 	public static void trafficGeneratorStatusRead(ConnectionHolderL2CAP c, final TestStatus testStatus)
195 			throws IOException {
196 		try {
197 			int receiveMTU = c.channel.getReceiveMTU();
198 			byte[] dataReceived = new byte[receiveMTU];
199 			mainLoop: do {
200 				if (!c.channel.ready()) {
201 					try {
202 						Thread.sleep(100);
203 					} catch (InterruptedException e) {
204 						break mainLoop;
205 					}
206 				} else {
207 					c.channel.receive(dataReceived);
208 					c.active();
209 				}
210 			} while (c.isConnectionOpen() && (!testStatus.isRunCompleate()));
211 		} finally {
212 			testStatus.setRunCompleate();
213 		}
214 	}
215 
216 	public static void trafficGeneratorReadStart(final ConnectionHolderL2CAP c, final byte[] initialData,
217 			final TestStatus testStatus) {
218 		Runnable r = new Runnable() {
219 			public void run() {
220 				try {
221 					trafficGeneratorRead(c, initialData, testStatus);
222 				} catch (IOException e) {
223 					Logger.error("reader", e);
224 				}
225 			}
226 		};
227 		Thread t = RuntimeDetect.cldcStub.createNamedThread(r, "L2tgReciver");
228 		t.start();
229 	}
230 
231 	public static void trafficGeneratorRead(ConnectionHolderL2CAP c, byte[] initialData, final TestStatus testStatus)
232 			throws IOException {
233 		long sequenceRecivedCount = 0;
234 		long sequenceRecivedNumberLast = -1;
235 		long sequenceOutOfOrderCount = 0;
236 		TimeStatistic delay = new TimeStatistic();
237 		long start = System.currentTimeMillis();
238 		long reported = start;
239 		long receiveTimeLast = 0;
240 		long reportedSize = 0;
241 		long totalSize = 0;
242 		try {
243 			int receiveMTU = c.channel.getReceiveMTU();
244 			mainLoop: do {
245 				if (!c.channel.ready()) {
246 					try {
247 						Thread.sleep(100);
248 					} catch (InterruptedException e) {
249 						break mainLoop;
250 					}
251 					continue;
252 				}
253 				byte[] dataReceived = new byte[receiveMTU];
254 				int lengthdataReceived = c.channel.receive(dataReceived);
255 				c.active();
256 				long receiveTime = System.currentTimeMillis();
257 				sequenceRecivedCount++;
258 				long sendTime = 0;
259 				reportedSize += lengthdataReceived;
260 				totalSize += lengthdataReceived;
261 
262 				if (lengthdataReceived > 8) {
263 					long sequenceRecivedNumber = IOUtils.bytes2Long(dataReceived, 0, 8);
264 					if (sequenceRecivedNumberLast + 1 != sequenceRecivedNumber) {
265 						sequenceOutOfOrderCount++;
266 					} else if (lengthdataReceived > 18) {
267 						sendTime = IOUtils.bytes2Long(dataReceived, 8, 8);
268 					}
269 					sequenceRecivedNumberLast = sequenceRecivedNumber;
270 				} else {
271 					sequenceOutOfOrderCount++;
272 				}
273 
274 				if (receiveTimeLast != 0) {
275 					delay.add(receiveTimeLast - receiveTime);
276 					receiveTimeLast = receiveTime;
277 				}
278 
279 				long now = receiveTime;
280 				if (now - reported > 5 * 1000) {
281 					Logger.debug("L2 Received " + sequenceRecivedCount + "/" + sequenceOutOfOrderCount
282 							+ "(er) packet(s) " + delay.avg() + " msec");
283 					Logger.debug("L2 Received " + TimeUtils.bps(reportedSize, reported));
284 					reported = now;
285 					reportedSize = 0;
286 				}
287 
288 			} while (c.isConnectionOpen() && (!testStatus.isRunCompleate()));
289 		} finally {
290 			testStatus.setRunCompleate();
291 			Logger.debug("L2 Total Received  " + sequenceRecivedCount + " packet(s)");
292 			Logger.debug("L2 Total Misplaced " + sequenceOutOfOrderCount + " packet(s)");
293 			Logger.debug("L2  avg interval " + delay.avg() + " msec");
294 			Logger.debug("L2 Total read speed " + TimeUtils.bps(totalSize, start));
295 		}
296 	}
297 }