/base/Applications/Network/UdpBlast/UdpBlast.cs
C# | 261 lines | 202 code | 45 blank | 14 comment | 14 complexity | bf6817cb001ae01e1d8fe8776300cdfc MD5 | raw file
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Microsoft Research Singularity
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // Note: Simple Singularity test program.
- //
- using System;
- using System.Diagnostics;
- using System.Net.IP;
- using System.Threading;
-
- using Microsoft.Singularity;
- using Microsoft.SingSharp;
- using Microsoft.Singularity.Channels;
- using Microsoft.Singularity.Directory;
- using NetStack.Contracts;
- using NetStack.Channels.Public;
-
- using Microsoft.Contracts;
- using Microsoft.SingSharp.Reflection;
- using Microsoft.Singularity.Applications;
- using Microsoft.Singularity.Io;
- using Microsoft.Singularity.Configuration;
- [assembly: Transform(typeof(ApplicationResourceTransform))]
-
- namespace Microsoft.Singularity.Applications.Network
- {
- [ConsoleCategory(HelpMessage="Send UDP data to and ipAddress and port",
- DefaultAction=true)]
- internal class Parameters {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [Endpoint]
- public readonly TRef<UdpContract.Imp:Start> udpRef;
-
- [LongParameter("p", Mandatory=false, HelpMessage="Packet size (bytes)", Default = 1500)]
- internal long packetBytes;
-
- [LongParameter("r", Mandatory=false, HelpMessage="Transmission rate in bits per second", Default = 64000)]
- internal long bitsPerSecond;
-
- [LongParameter("t", Mandatory=false, HelpMessage="Seconds to send packets for", Default = 30)]
- internal long seconds;
-
- [BoolParameter("v", Mandatory=false, HelpMessage="Verbose output", Default = true)]
- internal bool verbose;
-
- [StringParameter("Address", Mandatory=true, Position=0, HelpMessage="Destination IP Address")]
- internal string address;
-
- [LongParameter("port", Mandatory=true, Position=1, HelpMessage="Destination UDP port")]
- internal long port;
-
- reflective internal Parameters();
-
- internal int AppMain() {
- return UdpBlast.AppMain(this);
- }
- }
-
- public class UdpBlast
- {
- private const uint FixedHeaderBytes = 42; // Ether + IP + UDP
-
- private static bool verbose;
-
- public static void VerboseWriteLine(string format,
- params Object [] args)
- {
- string msg = String.Format(format, args);
- DebugStub.WriteLine(msg);
- if (verbose) {
- Console.WriteLine(format, args);
- }
- }
-
- private static void
- SendPackets(
- UdpConnectionContract.Imp:ReadyState! udpConn,
- long bitsPerSecond,
- uint bytesPerPacket,
- long durationSeconds
- )
- {
- DateTime startTime = DateTime.Now;
- DateTime endTime = (startTime +
- TimeSpan.FromSeconds(durationSeconds));
-
- DateTime secondStart = startTime;
- DateTime secondEnd = startTime + TimeSpan.FromSeconds(1);
-
- DateTime now = startTime;
-
- uint second = 0;
- long bitsThisSecond = 0;
- long totalBits = 0;
- int totalPackets = 0;
-
- VerboseWriteLine("UdpBlast: {0} bytesPerPacket, Limiting transfer to {1} bitsPerSecond, for {2} seconds",
- bytesPerPacket, bitsPerSecond, durationSeconds);
-
- while (now < endTime) {
- int pps = 0;
-
- while (now < secondEnd && bitsThisSecond < bitsPerSecond) {
- // XXX: Just bursting packets out for
- // now rather than pacing them,
- // interested mainly in saturation case.
- byte[] in ExHeap pkt;
- uint pktSize;
- if ((long)bytesPerPacket * 8 < bitsPerSecond - bitsThisSecond) {
- pktSize = bytesPerPacket;
- }
- else {
- // Send a final runt packet for this cycle to keep us under
- // the agreed total bits per second rate.
- pktSize = (uint)((bitsPerSecond - bitsThisSecond) / 8);
- if (pktSize <= FixedHeaderBytes) {
- pktSize = FixedHeaderBytes + 1;
- }
- }
- pkt = new [ExHeap] byte [pktSize - FixedHeaderBytes];
- udpConn.SendWrite(pkt);
- udpConn.RecvOK();
- bitsThisSecond += pktSize * 8;
- now = DateTime.Now;
- pps++;
- totalPackets++;
- }
-
- while (now < secondEnd) {
- Thread.Sleep(0);
- now = DateTime.Now;
- }
-
- TimeSpan tau = secondEnd - secondStart;
-
- long bytesPerSecond = (bitsThisSecond / tau.TotalSeconds) / 8;
-
- VerboseWriteLine(
- "Round {0} duration(secs) {1:f2} rate (pps) {2} rate (bps) {3:e3}, bytes/sec {4:e3}",
- second, tau.TotalSeconds,
- pps,
- bitsThisSecond / tau.TotalSeconds,
- bytesPerSecond);
-
- second++;
- totalBits += bitsThisSecond;
- bitsThisSecond = 0;
- secondStart = now;
- secondEnd = now + TimeSpan.FromSeconds(1);
- }
-
- Console.WriteLine(
- "Average rate: packets/sec {0}, bits/sec {1:e3}, bytes/sec {2:e3}",
- totalPackets / (now - startTime).TotalSeconds,
- totalBits / (now - startTime).TotalSeconds,
- (totalBits / (now - startTime).TotalSeconds) / 8
- );
- }
-
- public static int
- Blast(
- [Claims] UdpConnectionContract.Imp:ReadyState! udpConn,
- IPv4 address,
- ushort port,
- long bitsPerSecond,
- long bytesPerPacket,
- long durationSeconds
- )
- {
- Console.WriteLine("UdpBlast({0}, {1})", address, port);
-
- try {
- udpConn.SendConnectWithAnyLocalEndPoint((uint)address, port);
-
- switch receive {
- case udpConn.OK() :
- // success;
- Console.WriteLine("Connected");
- break;
-
- case udpConn.InvalidEndPoint(ip, rejectedPort) :
- throw new Exception("udpConn address and port rejected");
-
- case udpConn.ChannelClosed() :
- throw new Exception("udpConn channel closed");
- }
-
- SendPackets(udpConn,
- bitsPerSecond,
- (uint)bytesPerPacket,
- durationSeconds);
- Console.WriteLine("Closing connection");
-
- udpConn.SendClose();
- }
- catch (Exception e) {
- Console.WriteLine("Unexpected exception: {0}", e);
- }
- finally {
- delete udpConn;
- }
-
- return 0;
- }
-
- internal static int AppMain(Parameters! config)
- {
- IPv4 host;
- try {
- host = IPv4.Parse(config.address);
- }
- catch (FormatException e) {
- Console.WriteLine("{0}: {1}", e, config.address);
- return -1;
- }
-
- if (config.port > 65536 || config.port < 0) {
- Console.WriteLine("Port number out of range: {0}", config.port);
- return -1;
- }
- ushort port = (ushort) config.port;
-
- if ((uint)config.packetBytes < FixedHeaderBytes) {
- Console.WriteLine("Packet size needs to be larger than fixed header size ({0} bytes)", FixedHeaderBytes);
- return -1;
- }
-
- UdpBlast.verbose = config.verbose;
-
- UdpContract.Imp udpConn = ((!)config.udpRef).Acquire();
- if (udpConn == null) {
- Console.WriteLine("Could not initialize TCP endpoint.");
- return 1;
- }
- udpConn.RecvReady();
-
- UdpConnectionContract.Imp! connImp;
- UdpConnectionContract.Exp! connExp;
- UdpConnectionContract.NewChannel(out connImp, out connExp);
-
- udpConn.SendCreateUdpSession(connExp);
- connImp.RecvReady();
- delete udpConn;
-
- return Blast(connImp,
- host, port,
- config.bitsPerSecond,
- config.packetBytes,
- config.seconds
- );
- }
- } // end class UdpBlast
- }