13#include "ns3/q2ns-teleportation-app.h"
14#include "ns3/q2ns-analysis.h"
15#include "ns3/q2ns-netcontroller.h"
16#include "ns3/q2ns-qgate.h"
17#include "ns3/q2ns-qnode.h"
18#include "ns3/q2ns-qstate-ket.h"
19#include "ns3/q2ns-qubit.h"
22#include "ns3/boolean.h"
23#include "ns3/bulk-send-helper.h"
24#include "ns3/data-rate.h"
25#include "ns3/double.h"
26#include "ns3/inet-socket-address.h"
27#include "ns3/internet-module.h"
32#include "ns3/on-off-helper.h"
33#include "ns3/packet-sink-helper.h"
34#include "ns3/packet-sink.h"
35#include "ns3/packet.h"
36#include "ns3/pointer.h"
37#include "ns3/simulator.h"
38#include "ns3/string.h"
39#include "ns3/uinteger.h"
49NS_LOG_COMPONENT_DEFINE(
"TeleportationApp");
50NS_OBJECT_ENSURE_REGISTERED(TeleportationApp);
53 static ns3::TypeId tid =
54 ns3::TypeId(
"q2ns::TeleportationApp")
55 .SetParent<ns3::Application>()
58 .AddAttribute(
"Role",
"Session role for this app: 'source' (Alice) or 'sink' (Bob).",
59 ns3::StringValue(
"source"),
61 ns3::MakeStringChecker())
63 .AddAttribute(
"PeerQNode",
"Quantum peer (destination) as a direct object pointer.",
66 ns3::MakePointerChecker<q2ns::QNode>())
69 "Classical control-plane peer address (destination for ctrl packets, used "
71 ns3::Ipv4AddressValue(ns3::Ipv4Address(
"0.0.0.0")),
73 ns3::MakeIpv4AddressChecker())
76 "CtrlPort",
"UDP/TCP port used for teleportation control packets (per-session).",
78 ns3::MakeUintegerChecker<uint16_t>())
80 .AddAttribute(
"ClassicalProtocol",
"Control-plane transport protocol: 'udp' or 'tcp'.",
81 ns3::StringValue(
"udp"),
83 ns3::MakeStringChecker())
86 "Backend",
"Quantum state backend to use (e.g., 'ket').", ns3::StringValue(
"ket"),
89 .AddAttribute(
"SessionId",
"Unique identifier for the logical teleportation session.",
90 ns3::UintegerValue(0),
92 ns3::MakeUintegerChecker<uint64_t>())
94 .AddAttribute(
"TargetQubitTag",
95 "Label used to fetch Bob's target qubit from the NetController.",
96 ns3::StringValue(
"teleport_target_s"),
98 ns3::MakeStringChecker())
100 .AddAttribute(
"SessionStartTime",
"Simulation time at which this app begins its session.",
101 ns3::TimeValue(ns3::Seconds(0.0)),
103 ns3::MakeTimeChecker())
105 .AddTraceSource(
"SourceStart",
"Alice session start (sid,time)",
107 "ns3::TracedCallback::Uint64Time")
109 .AddTraceSource(
"SourceBellDone",
"Alice Bell measurement done (sid,time)",
111 "ns3::TracedCallback::Uint64Time")
113 .AddTraceSource(
"SourceCtrlSent",
"Alice sent ctrl bits (sid,time)",
115 "ns3::TracedCallback::Uint64Time")
117 .AddTraceSource(
"SinkStart",
"Bob session start (sid,time)",
119 "ns3::TracedCallback::Uint64Time")
121 .AddTraceSource(
"SinkQArrive",
"Bob received his qubit (sid,time)",
123 "ns3::TracedCallback::Uint64Time")
125 .AddTraceSource(
"SinkCtrlArrive",
"Bob received ctrl bits (sid,time)",
127 "ns3::TracedCallback::Uint64Time")
129 .AddTraceSource(
"SinkCorrection",
"Bob applied correction (sid,time)",
131 "ns3::TracedCallback::Uint64Time");
151 const std::string suffix =
"_s" + std::to_string(
m_sessionId);
160 const auto now = ns3::Simulator::Now().GetSeconds();
161 NS_LOG_INFO(
"[" << now <<
"s] " << ns3::Names::FindName(GetNode()) <<
" TeleportationApp("
165 }
else if (
m_role ==
"sink") {
168 NS_LOG_ERROR(
"TeleportationApp role must be 'source' or 'sink', got: " <<
m_role);
186 auto qnode = ns3::DynamicCast<q2ns::QNode>(GetNode());
188 NS_LOG_WARN(
"TeleportationApp(source): no QNode bound to this ns-3 node.");
194 "TeleportationApp(source): no source QState to be teleported provided. Aborting session.");
200 auto [aHalf, bHalf] = qnode->CreateBellPair();
201 aHalf->SetLabel(
"epr_A_s" + std::to_string(
m_sessionId));
208 NS_LOG_INFO(
"[" << ns3::Simulator::Now() <<
"s] " << ns3::Names::FindName(GetNode())
209 <<
" TeleportationApp(source): no PeerQNode set; qubit cannot be sent.\n");
213 NS_LOG_WARN(
"TeleportationApp(source): failed to send EPR half to Bob; proceeding anyway");
216 auto [
m1,
m2] = qnode->MeasureBell(psi, aHalf);
226 auto qnode = ns3::DynamicCast<q2ns::QNode>(GetNode());
231 Address bindAddr = InetSocketAddress(Ipv4Address::GetAny(),
m_ctrlPort);
233 PacketSinkHelper sinkHelper(
"ns3::UdpSocketFactory", bindAddr);
234 auto apps = sinkHelper.Install(GetNode());
235 m_ctrlSink = DynamicCast<PacketSink>(apps.Get(0));
237 PacketSinkHelper sinkHelper(
"ns3::TcpSocketFactory", bindAddr);
238 auto apps = sinkHelper.Install(GetNode());
239 m_ctrlSink = DynamicCast<PacketSink>(apps.Get(0));
246 NS_LOG_ERROR(
"Failed to install PacketSink for ctrl on port " <<
m_ctrlPort);
259 NS_LOG_WARN(
"TeleportationApp(source): TCP connect failed\n");
269 NS_LOG_INFO(
"[" << ns3::Simulator::Now() <<
"s] " << ns3::Names::FindName(GetNode())
270 <<
" TeleportationApp(source): Sending classical packet.");
272 uint8_t buf[2] = {
m1,
m2};
273 Ptr<Packet> pkt = Create<Packet>(buf, 2);
276 Ptr<Socket> sock = Socket::CreateSocket(GetNode(), UdpSocketFactory::GetTypeId());
278 if (sock->Connect(dst) == 0) {
281 NS_LOG_WARN(
"TeleportationApp(source): UDP connect failed to " <<
m_peer <<
":" <<
m_ctrlPort
288 Ptr<Socket> sock = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
297 int rc = sock->Connect(dst);
299 NS_LOG_WARN(
"TeleportationApp(source): TCP connect() immediate failure to "
309 NS_LOG_INFO(
"[" << ns3::Simulator::Now() <<
"s] " << ns3::Names::FindName(GetNode())
310 <<
" TeleportationApp(sink): Received qubit " + q->GetLabel() +
".");
320 NS_LOG_INFO(
"[" << ns3::Simulator::Now() <<
"s] " << ns3::Names::FindName(GetNode())
321 <<
" TeleportationApp(sink): Received classical packet.");
323 uint8_t bits[2] = {0, 0};
324 if (!pkt || pkt->GetSize() < 2) {
325 NS_LOG_WARN(
"TeleportationApp(sink): control packet too small (" << (pkt ? pkt->GetSize() : 0)
329 pkt->CopyData(bits, 2);
342 if (
auto qnode = ns3::DynamicCast<q2ns::QNode>(GetNode())) {
Main user-facing facade for creating and configuring a quantum network.
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSourceBellDone
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSourceCtrlSent
void OnTcpConnectSuccess(ns3::Ptr< ns3::Socket > s)
ns3::Ptr< ns3::Application > m_ctrlSender
ns3::Ptr< ns3::PacketSink > m_ctrlSink
void SetTeleportState(const std::shared_ptr< QState > &state)
q2ns::NetController * m_nc
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSinkCorrection
void QubitArrivalHandler(std::shared_ptr< Qubit > q)
std::string m_targetQubitTag
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSourceStart
void StopApplication() override
void OnTcpConnectFail(ns3::Ptr< ns3::Socket > s)
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSinkStart
ns3::Ptr< ns3::Packet > m_pendingCtrlPkt
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSinkQArrive
void StartApplication() override
static ns3::TypeId GetTypeId()
void SetNetController(NetController *nc)
void OnCtrlRx(ns3::Ptr< const ns3::Packet > pkt, const ns3::Address &from)
std::shared_ptr< QState > m_teleportState
ns3::Ptr< q2ns::QNode > m_peerQNode
void TryApplyCorrection()
ns3::TracedCallback< uint64_t, ns3::Time > m_traceSinkCtrlArrive
void SendCtrlBits(uint8_t m1, uint8_t m2)
QGate X(ns3::Time d=ns3::Seconds(0))
Return the Pauli-X gate descriptor.
QGate Z(ns3::Time d=ns3::Seconds(0))
Return the Pauli-Z gate descriptor.