14#include "ns3/q2ns-qchannel.h"
16#include "ns3/q2ns-qmap.h"
17#include "ns3/q2ns-qnet-device.h"
18#include "ns3/q2ns-qubit.h"
20#include "ns3/attribute.h"
22#include "ns3/net-device.h"
23#include "ns3/nstime.h"
24#include "ns3/pointer.h"
25#include "ns3/simulator.h"
29NS_LOG_COMPONENT_DEFINE(
"QChannel");
30NS_OBJECT_ENSURE_REGISTERED(QChannel);
33 static ns3::TypeId tid =
34 ns3::TypeId(
"q2ns::QChannel")
35 .SetParent<ns3::Channel>()
38 .AddAttribute(
"Delay",
"Symmetric propagation delay", ns3::TimeValue(ns3::Seconds(0)),
40 ns3::MakeTimeChecker())
41 .AddAttribute(
"DelayAB",
"One-way propagation delay A->B",
42 ns3::TimeValue(ns3::Seconds(0)),
44 ns3::MakeTimeChecker())
45 .AddAttribute(
"DelayBA",
"One-way propagation delay B->A",
46 ns3::TimeValue(ns3::Seconds(0)),
48 ns3::MakeTimeChecker())
49 .AddAttribute(
"Jitter",
50 "Symmetric jitter. A uniform random jitter in [-jitter, +jitter] is added "
51 "to the propagation delay on each send, with a minimum value of 0.",
52 ns3::TimeValue(ns3::Seconds(0)),
54 ns3::MakeTimeChecker())
57 "One-way jitter A->B. A uniform random jitter in [-jitter, +jitter] is added "
58 "to the propagation delay on each send, with a minimum value of 0.",
59 ns3::TimeValue(ns3::Seconds(0)),
61 ns3::MakeTimeChecker())
64 "One-way jitter B->A. A uniform random jitter in [-jitter, +jitter] is added "
65 "to the propagation delay on each send, with a minimum value of 0.",
66 ns3::TimeValue(ns3::Seconds(0)),
68 ns3::MakeTimeChecker())
70 "QMap",
"Symmetric channel map applied to both directions unless overridden.",
72 ns3::MakePointerChecker<QMap>())
73 .AddAttribute(
"QMapAB",
"One-way channel map for A->B.", ns3::PointerValue(),
75 ns3::MakePointerChecker<QMap>())
76 .AddAttribute(
"QMapBA",
"One-way channel map for B->A.", ns3::PointerValue(),
78 ns3::MakePointerChecker<QMap>());
85 jitterRv_ = ns3::CreateObject<ns3::UniformRandomVariable>();
86 mapRv_ = ns3::CreateObject<ns3::UniformRandomVariable>();
92 if (d < ns3::Seconds(0)) {
93 NS_LOG_WARN(
"SetDelay rejected: negative delay.");
105 NS_LOG_WARN(
"GetDelay returned A->B delay because the channel is asymmetric.");
114 if (j < ns3::Seconds(0)) {
115 NS_LOG_WARN(
"SetJitter rejected: negative jitter.");
127 NS_LOG_WARN(
"GetJitter returned A->B jitter because the channel is asymmetric.");
137 NS_LOG_WARN(
"SetQMap received a null map; transmissions will use the identity map.");
148 NS_LOG_WARN(
"GetQMap returned A->B map because the channel is asymmetric.");
157 if (d < ns3::Seconds(0)) {
158 NS_LOG_WARN(
"SetDelayAB rejected: negative delay.");
174 if (d < ns3::Seconds(0)) {
175 NS_LOG_WARN(
"SetDelayBA rejected: negative delay.");
191 if (j < ns3::Seconds(0)) {
192 NS_LOG_WARN(
"SetJitterAB rejected: negative jitter.");
208 if (j < ns3::Seconds(0)) {
209 NS_LOG_WARN(
"SetJitterBA rejected: negative jitter.");
226 NS_LOG_WARN(
"SetQMapAB received a null map; transmissions will use the identity map.");
242 NS_LOG_WARN(
"SetQMapBA received a null map; transmissions will use the identity map.");
258 NS_LOG_WARN(
"Connect received a null endpoint device.");
261 if (a == b && a !=
nullptr) {
262 NS_LOG_WARN(
"Connect received the same device for both endpoints.");
269 aDev_->AttachChannel(ns3::Ptr<QChannel>(
this));
272 bDev_->AttachChannel(ns3::Ptr<QChannel>(
this));
280 NS_LOG_WARN(
"SendFrom rejected: null source device.");
285 NS_LOG_WARN(
"SendFrom rejected: null qubit.");
289 const auto loc = q->GetLocation();
291 NS_LOG_WARN(
"SendFrom rejected: qubit " << q->GetQubitId() <<
" is lost.");
295 ns3::Ptr<QNetDevice> dst;
300 if (
aDev_ && src == ns3::PeekPointer(
aDev_)) {
305 }
else if (
bDev_ && src == ns3::PeekPointer(
bDev_)) {
311 NS_LOG_WARN(
"SendFrom rejected: source device is not attached to this channel.");
316 NS_LOG_WARN(
"SendFrom rejected: destination device is null.");
321 if (jtr > ns3::Time(0)) {
322 const double j =
jitterRv_->GetValue(-jtr.GetSeconds(), jtr.GetSeconds());
323 dly += ns3::Seconds(j);
324 if (dly < ns3::Time(0)) {
334 mapInstance = qmap->Sample(
mapRv_, ctx);
337 ns3::Simulator::Schedule(
338 dly, [dst, q, mapInstance]()
mutable { dst->ReceiveFromChannel(q, mapInstance); });
360 return ns3::Ptr<ns3::NetDevice>(
aDev_);
363 return ns3::Ptr<ns3::NetDevice>(
bDev_);
377 mapRv_->SetStream(stream + used++);
Duplex quantum channel with configurable delay, jitter, and transit maps.
ns3::Ptr< ns3::NetDevice > GetDevice(std::size_t i) const override
Return an attached device by endpoint index.
void SetJitter(ns3::Time j)
Set the same jitter in both directions.
void SetJitterBA(ns3::Time j)
Set the one-way jitter from B to A.
std::size_t GetNDevices() const override
Return the number of attached devices.
ns3::Time delayAB_
Propagation delay from A to B.
ns3::Time delayBA_
Propagation delay from B to A.
ns3::Ptr< QMap > GetQMap() const
Get the A->B transit QMap.
bool SendFrom(QNetDevice *src, std::shared_ptr< Qubit > q)
Send a qubit from one endpoint to the opposite endpoint.
void SetDelay(ns3::Time d)
Set the same propagation delay in both directions.
void SetQMap(ns3::Ptr< QMap > m)
Set the same transit QMap in both directions.
ns3::Ptr< ns3::UniformRandomVariable > jitterRv_
Jitter sampler.
void SetDelayAB(ns3::Time d)
Set the one-way delay from A to B.
void SetJitterAB(ns3::Time j)
Set the one-way jitter from A to B.
ns3::Ptr< QMap > qmapAB_
Transit QMap from A to B. Null means identity.
ns3::Ptr< QNetDevice > aDev_
Device attached to endpoint A.
ns3::Ptr< QNetDevice > bDev_
Device attached to endpoint B.
void SetQMapAB(ns3::Ptr< QMap > m)
Set the one-way transit QMap from A to B.
int64_t AssignStreams(int64_t stream)
Assign RNG streams used by this channel.
void SetQMapBA(ns3::Ptr< QMap > m)
Set the one-way transit QMap from B to A.
ns3::Time GetJitterAB() const
Get the one-way jitter from A to B.
void SetDelayBA(ns3::Time d)
Set the one-way delay from B to A.
ns3::Ptr< QMap > GetQMapBA() const
Get the one-way transit QMap from B to A.
static ns3::TypeId GetTypeId(void)
Get the ns-3 TypeId.
ns3::Time GetDelay() const
Get the A->B propagation delay.
void Connect(ns3::Ptr< QNetDevice > a, ns3::Ptr< QNetDevice > b)
Connect two QNetDevice endpoints to this channel.
ns3::Time GetDelayAB() const
Get the one-way delay from A to B.
ns3::Time jitterBA_
Jitter magnitude from B to A.
ns3::Ptr< QMap > qmapBA_
Transit QMap from B to A. Null means identity.
ns3::Time GetJitter() const
Get the A->B jitter.
ns3::Time jitterAB_
Jitter magnitude from A to B.
ns3::Time GetJitterBA() const
Get the one-way jitter from B to A.
ns3::Time GetDelayBA() const
Get the one-way delay from B to A.
ns3::Ptr< ns3::UniformRandomVariable > mapRv_
QMap sampler.
QChannel()
Default constructor.
ns3::Ptr< QMap > GetQMapAB() const
Get the one-way transit QMap from A to B.
Minimal quantum net device that bridges a QChannel and a QNetworker.
std::function< void(QNode &, std::shared_ptr< Qubit > &)> QMapInstance
Per-transmission quantum map callable applied to a received qubit.
@ Lost
Qubit was lost and is no longer accessible.
Optional per-sample context passed to QMaps.
ns3::Time elapsedTime
Elapsed time that this map is applied over.