From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pb0-f43.google.com (mail-pb0-f43.google.com [209.85.160.43]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (verified OK)) by huchra.bufferbloat.net (Postfix) with ESMTPS id A577B201B46 for ; Sun, 6 May 2012 20:31:40 -0700 (PDT) Received: by pbcwz7 with SMTP id wz7so10487854pbc.16 for ; Sun, 06 May 2012 20:31:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-type:subject:date:message-id:cc:to:mime-version :x-mailer; bh=/LxWFGQ5BDj8On/3g51T5iKiq77yWophba8J24Ff7/Y=; b=mu1TGXOqMhHJgDpjLiLx1o90HGQIPpjcoldv5rTaUxESfEpMSeijBnfcb4gzRbrdM3 BmksI+q4uE8D0UFNKy9xdECsRGD0cKZtfW3fFU8jxbdyv1LCT9bzaLvnq/0PehLDk5tE DKOA82nktPQ7nM22wEoO35Qgs4alfM4D6bhx6EfmHSeP4cJtkMmYF7Uqs4jTwCx3+BcE 8e4deMxW8WP6laiufZ19OHZTcjRma17BCMdCWDZ411xU2LQyJ5oGpLJP99aCuWbTX5bz va0uVUoSSa6TNEyMn0lEP949DKq70zVBpazpCiPVOWtk4dt+PcJW+llgdxdhhZvfO54J WgZQ== Received: by 10.68.72.70 with SMTP id b6mr33225683pbv.58.1336361499508; Sun, 06 May 2012 20:31:39 -0700 (PDT) Received: from andrewm-lo.ws.atlnz.lc ([202.49.72.37]) by mx.google.com with ESMTPS id rs3sm16826883pbc.47.2012.05.06.20.31.35 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 06 May 2012 20:31:38 -0700 (PDT) From: Andrew McGregor Content-Type: multipart/signed; boundary="Apple-Mail=_497B6151-3B09-4044-A074-2BBD5EE90E2C"; protocol="application/pkcs7-signature"; micalg=sha1 Date: Mon, 7 May 2012 15:31:32 +1200 Message-Id: <1B606228-D699-4A38-9CBC-B7436AEE1E3E@gmail.com> To: codel@lists.bufferbloat.net Mime-Version: 1.0 (Apple Message framework v1257) X-Mailer: Apple Mail (2.1257) Subject: [Codel] CoDel for ns3 X-BeenThere: codel@lists.bufferbloat.net X-Mailman-Version: 2.1.13 Precedence: list List-Id: CoDel AQM discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 May 2012 03:31:41 -0000 --Apple-Mail=_497B6151-3B09-4044-A074-2BBD5EE90E2C Content-Type: multipart/mixed; boundary="Apple-Mail=_841ED7E1-4200-4479-96E5-91CABE078CCB" --Apple-Mail=_841ED7E1-4200-4479-96E5-91CABE078CCB Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Based on Eric and Dave's kernel code, here's a patch that adds CoDel to = ns3. This uses the same approximations as v8 of the kernel code, so it = should behave very similarly in terms of which packets get dropped. It = may have some issues with headers if you haven't built ns3 before = applying the patch, I will try to address that next. The patch doesn't do anything with CoDel, but you can replace droptail = on any point-to-point in any of the examples by doing something like = this: bottleneckchannel.SetQueue ("ns3::CoDelQueue", "Interval", StringValue("100ms"), "Target", StringValue("5ms"), "MinBytes", UintegerValue(1500) ); Andrew McGregor --Apple-Mail=_841ED7E1-4200-4479-96E5-91CABE078CCB Content-Disposition: attachment; filename=ns3-codel.patch Content-Type: application/octet-stream; name="ns3-codel.patch" Content-Transfer-Encoding: quoted-printable diff=20-r=202a669a0c452e=20-r=204cc58164a9c9=20= src/internet/model/tcp-socket-base.cc=0A---=20= a/src/internet/model/tcp-socket-base.cc=09Sun=20Apr=2008=2023:03:34=20= 2012=20-0700=0A+++=20b/src/internet/model/tcp-socket-base.cc=09Mon=20May=20= 07=2015:23:05=202012=20+1200=0A@@=20-22,6=20+22,7=20@@=0A=20#define=20= NS_LOG_APPEND_CONTEXT=20\=0A=20=20=20if=20(m_node)=20{=20std::clog=20<<=20= Simulator::Now=20().GetSeconds=20()=20<<=20"=20[node=20"=20<<=20= m_node->GetId=20()=20<<=20"]=20";=20}=0A=20=0A+#include=20=0A=20= #include=20"ns3/abort.h"=0A=20#include=20"ns3/node.h"=0A=20#include=20= "ns3/inet-socket-address.h"=0Adiff=20-r=202a669a0c452e=20-r=20= 4cc58164a9c9=20src/network/utils/codel-queue.cc=0A---=20/dev/null=09Thu=20= Jan=2001=2000:00:00=201970=20+0000=0A+++=20= b/src/network/utils/codel-queue.cc=09Mon=20May=2007=2015:23:05=202012=20= +1200=0A@@=20-0,0=20+1,461=20@@=0A+/*=20-*-=20Mode:C++;=20= c-file-style:"gnu";=20indent-tabs-mode:nil;=20-*-=20*/=0A+/*=0A+=20*=20= Copyright=20(c)=202012=20Andrew=20McGregor=0A+=20*=0A+=20*=20This=20= program=20is=20free=20software;=20you=20can=20redistribute=20it=20and/or=20= modify=0A+=20*=20it=20under=20the=20terms=20of=20the=20GNU=20General=20= Public=20License=20version=202=20as=0A+=20*=20published=20by=20the=20= Free=20Software=20Foundation;=0A+=20*=0A+=20*=20This=20program=20is=20= distributed=20in=20the=20hope=20that=20it=20will=20be=20useful,=0A+=20*=20= but=20WITHOUT=20ANY=20WARRANTY;=20without=20even=20the=20implied=20= warranty=20of=0A+=20*=20MERCHANTABILITY=20or=20FITNESS=20FOR=20A=20= PARTICULAR=20PURPOSE.=20=20See=20the=0A+=20*=20GNU=20General=20Public=20= License=20for=20more=20details.=0A+=20*=0A+=20*=20You=20should=20have=20= received=20a=20copy=20of=20the=20GNU=20General=20Public=20License=0A+=20= *=20along=20with=20this=20program;=20if=20not,=20write=20to=20the=20Free=20= Software=0A+=20*=20Foundation,=20Inc.,=2059=20Temple=20Place,=20Suite=20= 330,=20Boston,=20MA=20=2002111-1307=20=20USA=0A+=20*=20=0A+=20*=20Codel,=20= the=20COntrolled=20DELay=20Queueing=20discipline=0A+=20*=20Based=20on=20= ns2=20simulation=20code=20presented=20by=20Kathie=20Nichols=0A+=20*=0A+=20= *=20This=20port=20based=20on=20linux=20kernel=20code=20by=0A+=20*=20= Authors:=09Dave=20T=C3=A4ht=20=0A+=20*=09=09Eric=20Dumazet=20= =0A+=20*=0A+=20*=20Ported=20to=20ns-3=20by:=20= Andrew=20McGregor=20=0A+*/=0A+=0A+#include=20= "ns3/log.h"=0A+#include=20"ns3/enum.h"=0A+#include=20"ns3/uinteger.h"=0A= +#include=20"codel-queue.h"=0A+=0A+NS_LOG_COMPONENT_DEFINE=20= ("CoDelQueue");=0A+=0A+namespace=20ns3=20{=0A+=0A+#define=20= BITS_PER_LONG=20(8=20*=20sizeof=20(unsigned=20long))=0A+/*=20borrowed=20= from=20the=20linux=20kernel=20*/=0A+/**=0A+=20*=20int_sqrt=20-=20rough=20= approximation=20to=20sqrt=0A+=20*=20@x:=20integer=20of=20which=20to=20= calculate=20the=20sqrt=0A+=20*=0A+=20*=20A=20very=20rough=20= approximation=20to=20the=20sqrt()=20function.=0A+=20*/=0A+static=20= unsigned=20long=20int_sqrt(unsigned=20long=20x)=0A+{=0A+=09unsigned=20= long=20op,=20res,=20one;=0A+=0A+=09op=20=3D=20x;=0A+=09res=20=3D=200;=0A= +=0A+=09one=20=3D=201UL=20<<=20(BITS_PER_LONG=20-=202);=0A+=09while=20= (one=20>=20op)=0A+=09=09one=20>>=3D=202;=0A+=0A+=09while=20(one=20!=3D=20= 0)=20{=0A+=09=09if=20(op=20>=3D=20res=20+=20one)=20{=0A+=09=09=09op=20=3D=20= op=20-=20(res=20+=20one);=0A+=09=09=09res=20=3D=20res=20+=20=202=20*=20= one;=0A+=09=09}=0A+=09=09res=20/=3D=202;=0A+=09=09one=20/=3D=204;=0A+=09= }=0A+=09return=20res;=0A+}=0A+=0A+#define=20do_div(n,base)=09=09=09=09=09= =09\=0A+({=09=09=09=09=09=09=09=09\=0A+=09int=20__res;=09=09=09=09=09=09= \=0A+=09__res=20=3D=20((unsigned=20long)n)=20%=20(unsigned=20int)base;=09= \=0A+=09n=20=3D=20((unsigned=20long)n)=20/=20(unsigned=20int)base;=09=09= \=0A+=09__res;=09=09=09=09=09=09=09\=0A+})=0A+=0A+static=20codel_time_t=20= codel_get_time(void)=0A+{=0A+=20=20Time=20time=20=3D=20Simulator::Now=20= ();=0A+=20=20uint64_t=20ns=20=3D=20time.GetNanoSeconds=20();=0A+=0A+=20=20= return=20ns=20>>=20CODEL_SHIFT;=0A+}=0A+=0A+#define=20= codel_time_after(a,=20b)=09=20((int)(a)=20-=20(int)(b)=20>=200)=0A= +#define=20codel_time_after_eq(a,=20b)=20((int)(a)=20-=20(int)(b)=20>=3D=20= 0)=0A+#define=20codel_time_before(a,=20b)=09=20((int)(a)=20-=20(int)(b)=20= <=200)=0A+#define=20codel_time_before_eq(a,=20b)=20((int)(a)=20-=20= (int)(b)=20>=3D=200)=0A+=0A+#define=20NSEC_PER_MSEC=201000000=0A+#define=20= NSEC_PER_USEC=201000=0A+#define=20MS2TIME(a)=20((a=20*=20NSEC_PER_MSEC)=20= >>=20CODEL_SHIFT)=0A+#define=20US2TIME(a)=20((a=20*=20NSEC_PER_USEC)=20= >>=20CODEL_SHIFT)=0A+#define=20NS2TIME(a)=20((a)=20>>=20CODEL_SHIFT)=0A= +#define=20TIME2CODEL(a)=20NS2TIME(a.GetNanoSeconds())=0A+=0A+#define=20= DEFAULT_CODEL_LIMIT=201000=0A+=0A+/*=20=0A+=20*=20return=20= interval/sqrt(x)=20with=20good=20precision=0A+=20*/=0A+static=20uint32_t=20= calc(uint32_t=20_interval,=20uint32_t=20_x)=0A+{=0A+=09uint64_t=20= interval=20=3D=20_interval;=0A+=09unsigned=20long=20x=20=3D=20_x;=0A+=0A= +=09/*=20scale=20operands=20for=20max=20precision=0A+=09=20*=20On=20= 64bit=20arches,=20we=20can=20prescale=20x=20by=2032bits=0A+=09=20*/=0A+=09= if=20(BITS_PER_LONG=20=3D=3D=2064)=20{=0A+=09=09x=20<<=3D=2032;=0A+=09=09= interval=20<<=3D=2016;=0A+=09}=0A+=09while=20(x=20<=20(1UL=20<<=20= (BITS_PER_LONG=20-=202)))=20{=0A+=09=09x=20<<=3D=202;=0A+=09=09interval=20= <<=3D=201;=0A+=09}=0A+=09do_div(interval,=20int_sqrt(x));=0A+=09return=20= (uint32_t)interval;=0A+}=0A+=0A+=0A+class=20CoDelTimestampTag=20:=20= public=20Tag=0A+{=0A+public:=0A+=20=20CoDelTimestampTag=20();=0A+=20=20= static=20TypeId=20GetTypeId=20(void);=0A+=20=20virtual=20TypeId=20= GetInstanceTypeId=20(void)=20const;=0A+=0A+=20=20virtual=20uint32_t=20= GetSerializedSize=20(void)=20const;=0A+=20=20virtual=20void=20Serialize=20= (TagBuffer=20i)=20const;=0A+=20=20virtual=20void=20Deserialize=20= (TagBuffer=20i);=0A+=20=20virtual=20void=20Print=20(std::ostream=20&os)=20= const;=0A+=0A+=20=20Time=20GetTxTime=20(void)=20const;=0A+private:=0A+=20= =20uint64_t=20m_creationTime;=0A+};=0A+=0A= +CoDelTimestampTag::CoDelTimestampTag=20()=0A+=20=20:=20m_creationTime=20= (Simulator::Now=20().GetTimeStep=20())=0A+{=0A+}=0A+=0A+TypeId=0A= +CoDelTimestampTag::GetTypeId=20(void)=0A+{=0A+=20=20static=20TypeId=20= tid=20=3D=20TypeId=20("anon::CoDelTimestampTag")=0A+=20=20=20=20= .SetParent=20()=0A+=20=20=20=20.AddConstructor=20= ()=0A+=20=20=20=20.AddAttribute=20("CreationTime",=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20"The=20time=20at=20which=20the=20= timestamp=20was=20created",=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20StringValue=20("0.0s"),=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20MakeTimeAccessor=20= (&CoDelTimestampTag::GetTxTime),=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20MakeTimeChecker=20())=0A+=20=20;=0A+=20=20return=20= tid;=0A+}=0A+TypeId=0A+CoDelTimestampTag::GetInstanceTypeId=20(void)=20= const=0A+{=0A+=20=20return=20GetTypeId=20();=0A+}=0A+=0A+uint32_t=0A= +CoDelTimestampTag::GetSerializedSize=20(void)=20const=0A+{=0A+=20=20= return=208;=0A+}=0A+void=0A+CoDelTimestampTag::Serialize=20(TagBuffer=20= i)=20const=0A+{=0A+=20=20i.WriteU64=20(m_creationTime);=0A+}=0A+void=0A= +CoDelTimestampTag::Deserialize=20(TagBuffer=20i)=0A+{=0A+=20=20= m_creationTime=20=3D=20i.ReadU64=20();=0A+}=0A+void=0A= +CoDelTimestampTag::Print=20(std::ostream=20&os)=20const=0A+{=0A+=20=20= os=20<<=20"CreationTime=3D"=20<<=20m_creationTime;=0A+}=0A+Time=0A= +CoDelTimestampTag::GetTxTime=20(void)=20const=0A+{=0A+=20=20return=20= TimeStep=20(m_creationTime);=0A+}=0A+=0A+NS_OBJECT_ENSURE_REGISTERED=20= (CoDelQueue);=0A+=0A+TypeId=20CoDelQueue::GetTypeId=20(void)=20=0A+{=0A+=20= =20static=20TypeId=20tid=20=3D=20TypeId=20("ns3::CoDelQueue")=0A+=20=20=20= =20.SetParent=20()=0A+=20=20=20=20.AddConstructor=20= ()=0A+=20=20=20=20.AddAttribute=20("Mode",=20=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20"Whether=20to=20use=20Bytes=20(see=20= MaxBytes)=20or=20Packets=20(see=20MaxPackets)=20as=20the=20maximum=20= queue=20size=20metric.",=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20EnumValue=20(PACKETS),=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20MakeEnumAccessor=20(&CoDelQueue::SetMode),=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20MakeEnumChecker=20= (BYTES,=20"Bytes",=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20PACKETS,=20= "Packets"))=0A+=20=20=20=20.AddAttribute=20("MaxPackets",=20=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"The=20maximum=20number=20= of=20packets=20accepted=20by=20this=20CoDelQueue.",=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20UintegerValue=20= (DEFAULT_CODEL_LIMIT),=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20MakeUintegerAccessor=20(&CoDelQueue::m_maxPackets),=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= MakeUintegerChecker=20())=0A+=20=20=20=20.AddAttribute=20= ("MaxBytes",=20=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20"The=20maximum=20number=20of=20bytes=20accepted=20by=20this=20= CoDelQueue.",=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= UintegerValue=20(1500*DEFAULT_CODEL_LIMIT),=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20MakeUintegerAccessor=20= (&CoDelQueue::m_maxBytes),=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20MakeUintegerChecker=20())=0A+=20=20=20=20= .AddAttribute=20("MinBytes",=20=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20"The=20CoDel=20algorithm=20minbytes=20parameter.",=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20UintegerValue=20= (1500),=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= MakeUintegerAccessor=20(&CoDelQueue::m_minbytes),=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20MakeUintegerChecker=20())=0A= +=20=20=20=20.AddAttribute=20("Interval",=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"The=20CoDel=20algorithm=20interval",=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20StringValue=20= ("100ms"),=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= MakeTimeAccessor=20(&CoDelQueue::m_Interval),=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20MakeTimeChecker=20())=0A+=20=20=20=20= .AddAttribute=20("Target",=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20"The=20CoDel=20algorithm=20target=20queue=20delay",=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20StringValue=20= ("5ms"),=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= MakeTimeAccessor=20(&CoDelQueue::m_Target),=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20MakeTimeChecker=20())=0A+=20=20;=0A+=0A+=20= =20return=20tid;=0A+}=0A+=0A+CoDelQueue::CoDelQueue=20()=20:=0A+=20=20= Queue=20(),=0A+=20=20m_packets=20(),=0A+=20=20m_maxBytes(),=0A+=20=20= m_bytesInQueue(0),=0A+=20=20m_count(0),=0A+=20=20m_drop_count(0),=0A+=20=20= m_dropping(false),=0A+=20=20m_first_above_time(0),=0A+=20=20= m_drop_next(0),=0A+=20=20m_state1(0),=0A+=20=20m_state2(0),=0A+=20=20= m_state3(0),=0A+=20=20m_states(0),=0A+=20=20m_drop_overlimit(0)=20=20=0A= +{=0A+=20=20NS_LOG_FUNCTION_NOARGS=20();=0A+}=0A+=0A= +CoDelQueue::~CoDelQueue=20()=0A+{=0A+=20=20NS_LOG_FUNCTION_NOARGS=20();=0A= +}=0A+=0A+codel_time_t=20=0A+CoDelQueue::ControlLaw(codel_time_t=20t)=0A= +{=0A+=09return=20t=20+=20calc(TIME2CODEL(m_Interval),=20m_count);=0A+}=0A= +=0A+void=0A+CoDelQueue::SetMode=20(enum=20Mode=20mode)=0A+{=0A+=20=20= NS_LOG_FUNCTION=20(mode);=0A+=20=20m_mode=20=3D=20mode;=0A+}=0A+=0A= +CoDelQueue::Mode=0A+CoDelQueue::GetMode=20(void)=0A+{=0A+=20=20= NS_LOG_FUNCTION_NOARGS=20();=0A+=20=20return=20m_mode;=0A+}=0A+=0A+bool=20= =0A+CoDelQueue::DoEnqueue=20(Ptr=20p)=0A+{=0A+=20=20= NS_LOG_FUNCTION=20(this=20<<=20p);=0A+=0A+=20=20if=20(m_mode=20=3D=3D=20= PACKETS=20&&=20(m_packets.size=20()=20>=3D=20m_maxPackets))=0A+=20=20=20=20= {=0A+=20=20=20=20=20=20NS_LOG_LOGIC=20("Queue=20full=20(at=20max=20= packets)=20--=20droppping=20pkt");=0A+=20=20=20=20=20=20Drop=20(p);=0A+=20= =20=20=20=20=20++m_drop_overlimit;=0A+=20=20=20=20=20=20return=20false;=0A= +=20=20=20=20}=0A+=0A+=20=20if=20(m_mode=20=3D=3D=20BYTES=20&&=20= (m_bytesInQueue=20+=20p->GetSize=20()=20>=3D=20m_maxBytes))=0A+=20=20=20=20= {=0A+=20=20=20=20=20=20NS_LOG_LOGIC=20("Queue=20full=20(packet=20would=20= exceed=20max=20bytes)=20--=20droppping=20pkt");=0A+=20=20=20=20=20=20= Drop=20(p);=0A+=20=20=20=20=20=20++m_drop_overlimit;=0A+=20=20=20=20=20=20= return=20false;=0A+=20=20=20=20}=0A+=0A+=20=20CoDelTimestampTag=20tag;=0A= +=20=20p->AddByteTag=20(tag);=0A+=20=20m_bytesInQueue=20+=3D=20= p->GetSize=20();=0A+=20=20m_packets.push=20(p);=0A+=0A+=20=20= NS_LOG_LOGIC=20("Number=20packets=20"=20<<=20m_packets.size=20());=0A+=20= =20NS_LOG_LOGIC=20("Number=20bytes=20"=20<<=20m_bytesInQueue);=0A+=0A+=20= =20return=20true;=0A+}=0A+=0A+bool=0A+CoDelQueue::ShouldDrop(Ptr=20= p,=20codel_time_t=20now)=0A+{=0A+=20=20CoDelTimestampTag=20tag;=0A+=20=20= bool=20found;=0A+=20=20bool=20drop;=0A+=20=20found=20=3D=20= p->FindFirstMatchingByteTag=20(tag);=0A+=20=20Time=20delta=20=3D=20= Simulator::Now=20()=20-=20tag.GetTxTime=20();=0A+=20=20codel_time_t=20= sojourn_time=20=3D=20NS2TIME(delta.GetNanoSeconds=20());=0A+=20=20=0A+=20= =20if=20(codel_time_before(sojourn_time,=20TIME2CODEL(m_Target))=20||=20=0A= +=20=20=20=20=20=20m_bytesInQueue=20<=20m_minbytes)=0A+=20=20=20=20{=0A+=20= =20=20=20=20=20/*=20went=20below=20so=20we'll=20stay=20below=20for=20at=20= least=20q->interval=20*/=0A+=20=20=20=20=20=20m_first_above_time=20=3D=20= 0;=0A+=20=20=20=20=20=20return=20false;=0A+=20=20=20=20}=0A+=20=20drop=20= =3D=20false;=0A+=20=20if=20(m_first_above_time=20=3D=3D=200)=20=0A+=20=20= =20=20{=0A+=20=20=20=20=20=20/*=20just=20went=20above=20from=20below.=20= If=20we=20stay=20above=0A+=20=20=20=20=20=20=20*=20for=20at=20least=20= q->interval=20we'll=20say=20it's=20ok=20to=20drop=0A+=20=20=20=20=20=20=20= */=0A+=20=20=20=20=20=20m_first_above_time=20=3D=20now=20+=20= TIME2CODEL(m_Interval);=0A+=20=20=20=20}=20=0A+=20=20else=20=0A+=20=20=20= =20if=20(codel_time_after(now,=20m_first_above_time))=20=0A+=20=20=20=20=20= =20{=0A+=20=20=20=20=20=20=20=20drop=20=3D=20true;=0A+=20=20=20=20=20=20=20= =20++m_state1;=0A+=20=20=20=20=20=20}=0A+=20=20return=20drop;=0A+}=0A+=0A= +Ptr=0A+CoDelQueue::DoDequeue=20(void)=0A+{=0A+=20=20= NS_LOG_FUNCTION=20(this);=0A+=0A+=20=20if=20(m_packets.empty=20())=0A+=20= =20=20=20{=0A+=20=20=20=20=20=20m_dropping=20=3D=20false;=0A+=20=20=20=20= =20=20NS_LOG_LOGIC=20("Queue=20empty");=0A+=20=20=20=20=20=20return=200;=0A= +=20=20=20=20}=0A+=20=20codel_time_t=20now=20=3D=20codel_get_time();=0A+=20= =20Ptr=20p=20=3D=20m_packets.front=20();=0A+=20=20m_packets.pop=20= ();=0A+=20=20m_bytesInQueue=20-=3D=20p->GetSize=20();=0A+=0A+=20=20= NS_LOG_LOGIC=20("Popped=20"=20<<=20p);=0A+=20=20NS_LOG_LOGIC=20("Number=20= packets=20"=20<<=20m_packets.size=20());=0A+=20=20NS_LOG_LOGIC=20= ("Number=20bytes=20"=20<<=20m_bytesInQueue);=0A+=0A+=20=20bool=20drop=20= =3D=20ShouldDrop(p,=20now);=0A+=20=20if=20(m_dropping)=0A+=20=20=20=20{=0A= +=20=20=20=20=20=20if=20(!drop)=0A+=20=20=20=20=20=20=20=20{=0A+=20=20=20= =20=20=20=20=20=20=20/*=20sojourn=20time=20below=20target=20-=20leave=20= dropping=20state=20*/=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20= m_dropping=20=3D=20false;=0A+=20=20=20=20=20=20=20=20}=0A+=20=20=20=20=20= =20else=0A+=20=20=20=20=20=20=20=20if=20(codel_time_after_eq(now,=20= m_drop_next))=0A+=20=20=20=20=20=20=20=20=20=20{=0A+=20=20=20=20=20=20=20= =20=20=20=20=20m_state2++;=0A+=20=20=20=20=20=20=20=20=20=20=20=20/*=20= It's=20time=20for=20the=20next=20drop.=20Drop=20the=20current=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20*=20packet=20and=20dequeue=20the=20next.=20= The=20dequeue=20might=20=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20*=20= take=20us=20out=20of=20dropping=20state.=20=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20*=20If=20not,=20schedule=20the=20next=20drop.=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20*=20A=20large=20backlog=20might=20result=20in=20= drop=20rates=20so=20high=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20*=20= that=20the=20next=20drop=20should=20happen=20now,=20=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20*=20hence=20the=20while=20loop.=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20*/=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20=20= while=20(m_dropping=20&&=20=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20codel_time_after_eq(now,=20m_drop_next))=20{=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20Drop(p);=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20++m_drop_count;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ++m_count;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20p=20=3D=20= m_packets.front=20();=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= m_packets.pop=20();=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= m_bytesInQueue=20-=3D=20p->GetSize=20();=0A+=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20NS_LOG_LOGIC=20("Popped=20"=20<<=20p);=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20NS_LOG_LOGIC=20("Number=20packets=20"=20<<=20= m_packets.size=20());=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= NS_LOG_LOGIC=20("Number=20bytes=20"=20<<=20m_bytesInQueue);=0A+=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20if=20(!ShouldDrop(p,=20now))=20=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20{=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20/*=20leave=20dropping=20state=20*/=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20m_dropping=20=3D=20= false;=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20}=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20else=20=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20{=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= /*=20and=20schedule=20the=20next=20drop=20*/=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20m_drop_next=20=3D=20ControlLaw(m_drop_next);=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20}=0A+=20=20=20=20=20=20=20= =20=20=20=20=20}=0A+=20=20=20=20=20=20=20=20=20=20}=0A+=20=20=20=20}=20=0A= +=20=20else=20=0A+=20=20=20=20if=20(drop=20&&=0A+=20=20=20=20=20=20=20=20= (codel_time_before(now=20-=20m_drop_next,=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2016=20*=20= TIME2CODEL(m_Interval))=20||=0A+=20=20=20=20=20=20=20=20=20= codel_time_after_eq(now=20-=20m_first_above_time,=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=202=20*=20= TIME2CODEL(m_Interval))))=20=0A+=20=20=20=20=20=20{=0A+=20=20=20=20=20=20= =20=20Drop(p);=0A+=20=20=20=20=20=20=20=20++m_drop_count;=0A+=20=20=20=20= =20=20=20=20drop=20=3D=20ShouldDrop(p,=20now);=0A+=20=20=20=20=20=20=20=20= m_dropping=20=3D=20true;=0A+=20=20=20=20=20=20=20=20++m_state3;=0A+=20=20= =20=20=20=20=20=20/*=20=0A+=20=20=20=20=20=20=20=20=20*=20if=20min=20= went=20above=20target=20close=20to=20when=20we=20last=20went=20below=20= it=0A+=20=20=20=20=20=20=20=20=20*=20assume=20that=20the=20drop=20rate=20= that=20controlled=20the=20queue=20on=20the=0A+=20=20=20=20=20=20=20=20=20= *=20last=20cycle=20is=20a=20good=20starting=20point=20to=20control=20it=20= now.=0A+=20=20=20=20=20=20=20=20=20*/=0A+=20=20=20=20=20=20=20=20if=20= (codel_time_after(now=20-=20m_drop_next,=2016=20*=20= TIME2CODEL(m_Interval)))=20=0A+=20=20=20=20=20=20=20=20=20=20{=0A+=20=20=20= =20=20=20=20=20=20=20=20=20//uint32_t=20c=20=3D=20min(m_count=20-=201,=20= m_count=20-=20(m_count=20>>=204));=0A+=20=20=20=20=20=20=20=20=20=20=20=20= uint32_t=20c=20=3D=20m_count=20-=201;=0A+=20=20=20=20=20=20=20=20=20=20=20= =20m_count=20=3D=20std::max(1U,=20c);=0A+=20=20=20=20=20=20=20=20=20=20}=20= =0A+=20=20=20=20=20=20=20=20else=0A+=20=20=20=20=20=20=20=20=20=20{=0A+=20= =20=20=20=20=20=20=20=20=20=20=20m_count=20=3D=201;=0A+=20=20=20=20=20=20= =20=20=20=20}=0A+=20=20=20=20=20=20=20=20m_drop_next=20=3D=20= ControlLaw(now);=0A+=20=20=20=20=20=20}=0A+=20=20++m_states;=0A+=20=20= return=20p;=0A+}=0A+=0A+Ptr=0A+CoDelQueue::DoPeek=20= (void)=20const=0A+{=0A+=20=20NS_LOG_FUNCTION=20(this);=0A+=0A+=20=20if=20= (m_packets.empty=20())=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= NS_LOG_LOGIC=20("Queue=20empty");=0A+=20=20=20=20=20=20return=200;=0A+=20= =20=20=20}=0A+=0A+=20=20Ptr=20p=20=3D=20m_packets.front=20();=0A= +=0A+=20=20NS_LOG_LOGIC=20("Number=20packets=20"=20<<=20m_packets.size=20= ());=0A+=20=20NS_LOG_LOGIC=20("Number=20bytes=20"=20<<=20= m_bytesInQueue);=0A+=0A+=20=20return=20p;=0A+}=0A+=0A+}=20//=20namespace=20= ns3=0A+=0Adiff=20-r=202a669a0c452e=20-r=204cc58164a9c9=20= src/network/utils/codel-queue.h=0A---=20/dev/null=09Thu=20Jan=2001=20= 00:00:00=201970=20+0000=0A+++=20b/src/network/utils/codel-queue.h=09Mon=20= May=2007=2015:23:05=202012=20+1200=0A@@=20-0,0=20+1,117=20@@=0A+/*=20-*-=20= Mode:C++;=20c-file-style:"gnu";=20indent-tabs-mode:nil;=20-*-=20*/=0A+/*=0A= +=20*=20Copyright=20(c)=202012=20Andrew=20McGregor=0A+=20*=0A+=20*=20= This=20program=20is=20free=20software;=20you=20can=20redistribute=20it=20= and/or=20modify=0A+=20*=20it=20under=20the=20terms=20of=20the=20GNU=20= General=20Public=20License=20version=202=20as=0A+=20*=20published=20by=20= the=20Free=20Software=20Foundation;=0A+=20*=0A+=20*=20This=20program=20= is=20distributed=20in=20the=20hope=20that=20it=20will=20be=20useful,=0A+=20= *=20but=20WITHOUT=20ANY=20WARRANTY;=20without=20even=20the=20implied=20= warranty=20of=0A+=20*=20MERCHANTABILITY=20or=20FITNESS=20FOR=20A=20= PARTICULAR=20PURPOSE.=20=20See=20the=0A+=20*=20GNU=20General=20Public=20= License=20for=20more=20details.=0A+=20*=0A+=20*=20You=20should=20have=20= received=20a=20copy=20of=20the=20GNU=20General=20Public=20License=0A+=20= *=20along=20with=20this=20program;=20if=20not,=20write=20to=20the=20Free=20= Software=0A+=20*=20Foundation,=20Inc.,=2059=20Temple=20Place,=20Suite=20= 330,=20Boston,=20MA=20=2002111-1307=20=20USA=0A+=20*=20=0A+=20*=20Codel,=20= the=20COntrolled=20DELay=20Queueing=20discipline=0A+=20*=20Based=20on=20= ns2=20simulation=20code=20presented=20by=20Kathie=20Nichols=0A+=20*=0A+=20= *=20This=20port=20based=20on=20linux=20kernel=20code=20by=0A+=20*=20= Authors:=09Dave=20T=C3=A4ht=20=0A+=20*=09=09Eric=20Dumazet=20= =0A+=20*=0A+=20*=20Ported=20to=20ns-3=20by:=20= Andrew=20McGregor=20=0A+=20*/=0A+=0A+#ifndef=20= CODEL_H=0A+#define=20CODEL_H=0A+=0A+#include=20=0A+#include=20= "ns3/core-module.h"=0A+#include=20"ns3/packet.h"=0A+#include=20= "ns3/queue.h"=0A+#include=20"ns3/nstime.h"=0A+=0A+=0A+namespace=20ns3=20= {=0A+=0A+typedef=20uint32_t=20codel_time_t;=0A+=0A+#define=20CODEL_SHIFT=20= 10=0A+=0A+class=20TraceContainer;=0A+=0A+/**=0A+=20*=20\ingroup=20queue=0A= +=20*=0A+=20*=20\brief=20A=20FIFO=20packet=20queue=20that=20drops=20= tail-end=20packets=20on=20overflow=0A+=20*/=0A+class=20CoDelQueue=20:=20= public=20Queue=20{=0A+public:=0A+=20=20static=20TypeId=20GetTypeId=20= (void);=0A+=20=20/**=0A+=20=20=20*=20\brief=20CoDelQueue=20Constructor=0A= +=20=20=20*=0A+=20=20=20*=20Creates=20a=20codel=20queue=20with=20a=20= maximum=20size=20of=20100=20packets=20by=20default=0A+=20=20=20*/=0A+=20=20= CoDelQueue=20();=0A+=0A+=20=20virtual=20~CoDelQueue();=0A+=0A+=20=20/**=0A= +=20=20=20*=20Enumeration=20of=20the=20modes=20supported=20in=20the=20= class.=0A+=20=20=20*=0A+=20=20=20*/=0A+=20=20enum=20Mode=20{=0A+=20=20=20= =20ILLEGAL,=20=20=20=20=20/**<=20Mode=20not=20set=20*/=0A+=20=20=20=20= PACKETS,=20=20=20=20=20/**<=20Use=20number=20of=20packets=20for=20= maximum=20queue=20size=20*/=0A+=20=20=20=20BYTES,=20=20=20=20=20=20=20= /**<=20Use=20number=20of=20bytes=20for=20maximum=20queue=20size=20*/=0A+=20= =20};=0A+=0A+=20=20/**=0A+=20=20=20*=20Set=20the=20operating=20mode=20of=20= this=20device.=0A+=20=20=20*=0A+=20=20=20*=20\param=20mode=20The=20= operating=20mode=20of=20this=20device.=0A+=20=20=20*=0A+=20=20=20*/=0A+=20= =20void=20SetMode=20(CoDelQueue::Mode=20mode);=0A+=0A+=20=20/**=0A+=20=20= =20*=20Get=20the=20encapsulation=20mode=20of=20this=20device.=0A+=20=20=20= *=0A+=20=20=20*=20\returns=20The=20encapsulation=20mode=20of=20this=20= device.=0A+=20=20=20*/=0A+=20=20CoDelQueue::Mode=20=20GetMode=20(void);=0A= +=0A+private:=0A+=20=20virtual=20bool=20DoEnqueue=20(Ptr=20p);=0A= +=20=20virtual=20Ptr=20DoDequeue=20(void);=0A+=20=20virtual=20= Ptr=20DoPeek=20(void)=20const;=0A+=20=20codel_time_t=20= ControlLaw(codel_time_t=20t);=0A+=20=20bool=20ShouldDrop(Ptr=20= p,=20codel_time_t=20now);=0A+=0A+=20=20std::queue=20>=20= m_packets;=0A+=20=20uint32_t=20m_maxPackets;=0A+=20=20uint32_t=20= m_maxBytes;=0A+=20=20uint32_t=20m_bytesInQueue;=0A+=20=20uint32_t=20= m_minbytes;=0A+=20=20Time=20m_Interval;=0A+=20=20Time=20m_Target;=0A+=20=20= uint32_t=20m_count;=0A+=20=20uint32_t=20m_drop_count;=0A+=20=20bool=20= m_dropping;=0A+=20=20codel_time_t=20m_first_above_time;=0A+=20=20= codel_time_t=20m_drop_next;=0A+=20=20uint32_t=20m_state1;=0A+=20=20= uint32_t=20m_state2;=0A+=20=20uint32_t=20m_state3;=0A+=20=20uint32_t=20= m_states;=0A+=20=20uint32_t=20m_drop_overlimit;=0A+=20=20Mode=20=20=20=20= =20m_mode;=0A+};=0A+=0A+}=20//=20namespace=20ns3=0A+=0A+#endif=20/*=20= CODEL_H=20*/=0Adiff=20-r=202a669a0c452e=20-r=204cc58164a9c9=20= src/network/wscript=0A---=20a/src/network/wscript=09Sun=20Apr=2008=20= 23:03:34=202012=20-0700=0A+++=20b/src/network/wscript=09Mon=20May=2007=20= 15:23:05=202012=20+1200=0A@@=20-24,6=20+24,7=20@@=0A=20=20=20=20=20=20=20= =20=20'model/tag-buffer.cc',=0A=20=20=20=20=20=20=20=20=20= 'model/trailer.cc',=0A=20=09'utils/address-utils.cc',=0A+=20=20=20=20=20=20= =20=20'utils/codel-queue.cc',=0A=20=20=20=20=20=20=20=20=20= 'utils/data-rate.cc',=0A=20=20=20=20=20=20=20=20=20= 'utils/drop-tail-queue.cc',=0A=20=20=20=20=20=20=20=20=20= 'utils/error-model.cc',=0A@@=20-93,6=20+94,7=20@@=0A=20=20=20=20=20=20=20= =20=20'model/tag-buffer.h',=0A=20=20=20=20=20=20=20=20=20= 'model/trailer.h',=0A=20=20=20=20=20=20=20=09'utils/address-utils.h',=0A= +=20=20=20=20=20=20=20=20'utils/codel-queue.h',=0A=20=20=20=20=20=20=20=20= =20'utils/data-rate.h',=0A=20=20=20=20=20=20=20=20=20= 'utils/drop-tail-queue.h',=0A=20=20=20=20=20=20=20=20=20= 'utils/error-model.h',=0A= --Apple-Mail=_841ED7E1-4200-4479-96E5-91CABE078CCB-- --Apple-Mail=_497B6151-3B09-4044-A074-2BBD5EE90E2C Content-Disposition: attachment; filename=smime.p7s Content-Type: application/pkcs7-signature; name=smime.p7s Content-Transfer-Encoding: base64 MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIFLjCCBSow ggQSoAMCAQICEQDMQ2ZKvgsUYA5oQg5SjWfVMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYDVQQGEwJH QjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQK ExFDT01PRE8gQ0EgTGltaXRlZDE5MDcGA1UEAxMwQ09NT0RPIENsaWVudCBBdXRoZW50aWNhdGlv biBhbmQgU2VjdXJlIEVtYWlsIENBMB4XDTExMTAwMTAwMDAwMFoXDTEyMDkzMDIzNTk1OVowJTEj MCEGCSqGSIb3DQEJARYUYW5kcmV3bWNnckBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQC+buTRxzSXTQmMyUqaokLJit3xU5WVudxHijhKbGRSTgJ867L/v8+rNhSoFwCV MdKIu/M7apWgGkkA+MT/LjDFj63jLT+4nTTLIojXZdoezbpp/rQ2ViSbi54AjhZBQ5X+yH2xcXmG KpDhZjeZC1bvKNvBtdOHCAcrx1Ys1BNj+AhwridEX/KD0cq5xSsJhjDggF6XSUOsaiqBHR6fiQMi 7gH8EuFBh83oklb/pdreg1fQ7gKJk/Me/atIbE1gtbIR88oaCtXoHfZxgkFwagwMtBHdkxN+wcZy 9xx78el9Lxrjx2nMq50hRlj/bqg/m4rSox7//DKfx7bfKNZAiSMDAgMBAAGjggHkMIIB4DAfBgNV HSMEGDAWgBR6E04AdFvGeGNkJ8Ev4qBbvHnFezAdBgNVHQ4EFgQUXOXqNkq6sNbrD8B41dPko8Gs JucwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwIAYDVR0lBBkwFwYIKwYBBQUHAwQGCysG AQQBsjEBAwUCMBEGCWCGSAGG+EIBAQQEAwIFIDBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgEBATAr MCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8ubmV0L0NQUzBXBgNVHR8EUDBOMEyg SqBIhkZodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DbGllbnRBdXRoZW50aWNhdGlvbmFu ZFNlY3VyZUVtYWlsQ0EuY3JsMIGIBggrBgEFBQcBAQR8MHowUgYIKwYBBQUHMAKGRmh0dHA6Ly9j cnQuY29tb2RvY2EuY29tL0NPTU9ET0NsaWVudEF1dGhlbnRpY2F0aW9uYW5kU2VjdXJlRW1haWxD QS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAfBgNVHREEGDAWgRRh bmRyZXdtY2dyQGdtYWlsLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAgmf81vnsAnbcmIAyyqvEKxAK jRHerfreN10DK1ISkUJ//U4uffQV8sAGDtyIErzVFsW6NYRmFCMSE20M1ffbFpWUmXCtm/YTlkf1 5STVjTMNshDzMDhpjx99Z2J5RBJPZpXjwmpQnfKwB7zft9TcUSIb9FvZm33EKdF/XlS12U4Q9fsj 2shZf88RituX2+fCWfHoTWiFEhFUkLRtWf1YpgHpEXr82nqROxs/aWNlqtLnwTTu2ULr/WpUaRDs kom8gFZkMgw5kRfLpSXRrCFSORsZzkH2ooRxaJY7wMwZaCUS1am9DuwVy7gehoc3ZsjsDkMObZeu kx7Cg7GxIkgo+zGCA64wggOqAgEBMIGpMIGTMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRl ciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRl ZDE5MDcGA1UEAxMwQ09NT0RPIENsaWVudCBBdXRoZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWls IENBAhEAzENmSr4LFGAOaEIOUo1n1TAJBgUrDgMCGgUAoIIB2TAYBgkqhkiG9w0BCQMxCwYJKoZI hvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xMjA1MDcwMzMxMzJaMCMGCSqGSIb3DQEJBDEWBBRjp89z gQ+UL5YX94aEXZYJLXNjxjCBugYJKwYBBAGCNxAEMYGsMIGpMIGTMQswCQYDVQQGEwJHQjEbMBkG A1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P RE8gQ0EgTGltaXRlZDE5MDcGA1UEAxMwQ09NT0RPIENsaWVudCBBdXRoZW50aWNhdGlvbiBhbmQg U2VjdXJlIEVtYWlsIENBAhEAzENmSr4LFGAOaEIOUo1n1TCBvAYLKoZIhvcNAQkQAgsxgayggakw gZMxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1Nh bGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTkwNwYDVQQDEzBDT01PRE8gQ2xpZW50 IEF1dGhlbnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0ECEQDMQ2ZKvgsUYA5oQg5SjWfVMA0G CSqGSIb3DQEBAQUABIIBAF3+l+iOAmaZnq78V2qLGb/plXf65yMl90nbxtKnGkQFWrgl9AXcM6VF KbuJYCSD7/rDgfbmjOsmMcpw+uYUUso7yyTl+55U2YFbdEhTRZYO0DXTmwGJ/jpLuWF+/l4V65Ru 6r0vqJGpr6Op6XUSasLoeF38xf5/4wAXdd4IRuxvfxMG+y6HDm5U8BVeu/EgZ8JEnnLJXVt8I5ES 2Zr46fvN9n8pc2DFcOY4qbeN0kecb4jer5rOLwRE2fYY/Fy3baRse3gDatytWU/Ujzf5zHm/w0/X 6XbT3OIC0BUAei1wuZ/vAVz2jTN6xWFy6+bUJnQJG4GhJGaWtvLOh8l64GMAAAAAAAA= --Apple-Mail=_497B6151-3B09-4044-A074-2BBD5EE90E2C--