A Discrete-Event Network Simulator
API
qkd-sdn-controller.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 DOTFEESA www.tk.etf.unsa.ba
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Emir Dervisevic <emir.dervisevic@etf.unsa.ba>
19  * Miralem Mehic <miralem.mehic@ieee.org>
20  */
21 
22 #include "ns3/log.h"
23 #include "ns3/address.h"
24 #include "ns3/node.h"
25 #include "ns3/nstime.h"
26 #include "ns3/socket.h"
27 #include "ns3/simulator.h"
28 #include "ns3/tcp-socket-factory.h"
29 #include "ns3/packet.h"
30 #include "ns3/uinteger.h"
31 #include "ns3/trace-source-accessor.h"
32 #include "ns3/qkd-control.h"
33 #include "ns3/http.h"
34 #include "ns3/json.h"
35 
36 #include <iostream>
37 #include <fstream>
38 #include <string>
39 
40 #include "qkd-sdn-controller.h"
41 
42 namespace ns3 {
43 
44 NS_LOG_COMPONENT_DEFINE ("QKDSDNController");
45 
46 NS_OBJECT_ENSURE_REGISTERED (QKDSDNController);
47 
48 TypeId
50 {
51  static TypeId tid = TypeId ("ns3::QKDSDNController")
53  .SetGroupName("Applications")
54  .AddConstructor<QKDSDNController> ()
55  //send params
56  .AddAttribute ("Protocol", "The type of protocol to use.",
60  .AddAttribute ("LocalAddress", "The ipv4 address of the application",
64  .AddAttribute ("MaximalKeysPerRequest",
65  "The maximal number of keys per request (ESTI QKD 014)",
66  UintegerValue (20),
68  MakeUintegerChecker<uint32_t> ())
69  .AddAttribute ("MinimalKeySize",
70  "The minimal size of key QKDApp can request",
71  UintegerValue (32), //in bits
73  MakeUintegerChecker<uint32_t> ())
74  .AddAttribute ("MaximalKeySize",
75  "The maximal size of key QKDApp can request",
76  UintegerValue (10240), //in bits
78  MakeUintegerChecker<uint32_t> ())
79  .AddAttribute ("DefaultKeySize",
80  "The default size of the key",
81  UintegerValue (512), //in bits
83  MakeUintegerChecker<uint32_t> ())
84  .AddAttribute ("MaliciousRequestBlocking",
85  "Does SDN detects and blocks malicious get_key_004 request?",
86  UintegerValue (1), //default: YES/TRUE
88  MakeUintegerChecker<uint32_t> ())
89  .AddAttribute ("QKDLinkUpdateInterval",
90  "Default value of QKD link status update interval (in seconds)",
91  DoubleValue (5.0),
93  MakeDoubleChecker<double> ())
94 
95 
96  .AddTraceSource ("Tx", "A new packet is created and is sent to the APP",
98  "ns3::QKDSDNController::Tx")
99  .AddTraceSource ("Rx", "A packet from the APP has been received",
101  "ns3::QKDSDNController::Rx")
102  .AddTraceSource ("TxSDNs", "A new packet is created and is sent to the SDN",
104  "ns3::QKDSDNController::TxSDNs")
105  .AddTraceSource ("RxSDNs", "A packet from the APP has been received",
107  "ns3::QKDSDNController::RxSDNs")
108  //**********************************************************************
109  .AddTraceSource ("NewKeyGeneratedEmir", "The trace to monitor key material received from QL",
111  "ns3::QKDSDNController::NewKeyGeneratedEmir")
112  .AddTraceSource ("KeyServedEmir", "The trace to monitor key material served to QKD Apps",
114  "ns3:QKDSDNController::KeyServedEmir")
115  //**********************************************************************
116  .AddTraceSource ("NewKeyGenerated", "The trace to monitor key material received from QL",
118  "ns3::QKDSDNController::NewKeyGenerated")
119 
120  .AddTraceSource ("KeyServedEtsi014", "The threce to monitor key usage by etsi 014",
122  "ns3::QKDSDNController::KeyServedEtsi014")
123 
124  .AddTraceSource ("KeyServedEtsi004", "The threce to monitor key usage by etsi 004",
126  "ns3::QKDSDNController::KeyServedEtsi004")
127 
128  .AddTraceSource ("DropKMSRequest", "Drop a request from the queue disc",
130  "ns3::QKDSDNController::TracedCallback")
131  ;
132  return tid;
133 }
134 
136 {
137  NS_LOG_FUNCTION (this);
138  m_totalRx = 0;
139 
140 }
141 
143 {
144  NS_LOG_FUNCTION (this);
145 }
146 
147 uint32_t
149  return m_kms_id;
150 }
151 
152 uint32_t
154 {
155  NS_LOG_FUNCTION (this);
156  return m_totalRx;
157 }
158 
159 std::map<Ptr<Socket>, Ptr<Socket> >
161 {
162  NS_LOG_FUNCTION (this);
163  return m_socketPairs;
164 }
165 
166 
167 
178 {
179  NS_LOG_FUNCTION (this);
180  return m_sinkSocket;
181 }
182 
183 void
184 QKDSDNController::SetSocket (std::string type, Ptr<Socket> socket)
185 {
186  NS_LOG_FUNCTION (this << type << socket);
187  m_sinkSocket = socket;
188 }
189 
190 void
192 {
193  NS_LOG_FUNCTION (this);
194  m_sinkSocket = 0;
195  m_socketPairs.clear ();
197 }
198 
199 void
201 {
202  NS_LOG_FUNCTION (this << s << from << InetSocketAddress::ConvertFrom(from).GetIpv4 ());
204 
205  std::map<Ptr<Socket>, Ptr<Socket> >::iterator i = m_socketPairs.find ( s );
206  if (i == m_socketPairs.end ()){
207 
208  Ptr<Socket> sendSocket;
209 
210  if (s->GetSocketType () != Socket::NS3_SOCK_STREAM &&
212  {
213  NS_LOG_FUNCTION("Create UDP socket!");
215  }else{
216  NS_LOG_FUNCTION("Create TCP socket!");
218  }
219  sendSocket->ShutdownRecv ();
220  sendSocket->SetConnectCallback (
224 
225  InetSocketAddress receiveAddress = InetSocketAddress (
226  InetSocketAddress::ConvertFrom(from).GetIpv4 (),
227  3060//InetSocketAddress::ConvertFrom(from).GetPort ()
228  );
229  sendSocket->Bind ();
230  sendSocket->Connect ( receiveAddress );
231 
232  m_socketPairs.insert( std::make_pair( s , sendSocket) );
233 
234  NS_LOG_FUNCTION(this
235  << "Create the response socket " << sendSocket
236  << " from SDN to KMS on IP: " << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
237  << " and port 3060" //<< InetSocketAddress::ConvertFrom(from).GetPort ()
238  );
239  }
240 }
241 
242 void
244 {
245  NS_LOG_FUNCTION (this << socket);
246  NS_LOG_FUNCTION (this << "QKDSDNController Connection succeeded");
247 
248  std::map<Ptr<Socket>, Ptr<Packet> >::iterator j;
249  for (j = m_packetQueues.begin (); !(j == m_packetQueues.end ()); j++){
250  if(j->first == socket){
251  uint32_t response = j->first->Send(j->second);
252  response = j->first->Send(j->second);
253  m_txTrace (j->second);
254  m_packetQueues.erase (j);
255  NS_LOG_FUNCTION(this << j->first << "Sending packet from the queue!" << response );
256  }
257  }
258 }
259 
260 void
262 {
263  NS_LOG_FUNCTION (this << socket);
264  NS_LOG_FUNCTION (this << "QKDSDNController, Connection Failed");
265 }
266 
267 void
269 {
270  NS_LOG_FUNCTION (this);
271 }
272 
273 void
275 {
276  NS_LOG_FUNCTION (this << socket);
277 }
278 
279 void
281 {
282  NS_LOG_FUNCTION (this << socket);
283 }
284 
285 void
287 {
288  NS_LOG_FUNCTION( this << socket);
289 
290  std::map<Ptr<Socket>, Ptr<Socket> >::iterator socketPair = m_socketPairs.find ( socket );
291  if (socketPair != m_socketPairs.end ()){
292 
293  Ptr<Socket> sendingSocket = socketPair->second;
294  //check if socket is connected
295  //https://www.nsnam.org/doxygen/classns3_1_1_socket.html#a78a3c37a539d2e70869bb82cc60fbb09
296  Address connectedAddress;
297 
298  //send the packet only if connected!
299  if(sendingSocket->GetPeerName(connectedAddress) == 0){
300  sendingSocket->Send(packet);
301  m_txTrace (packet);
302  NS_LOG_FUNCTION(this << packet->GetUid() << "sent via socket " << sendingSocket);
303 
304  //otherwise wait in the queue
305  }else{
306  m_packetQueues.insert( std::make_pair( sendingSocket , packet) );
307  NS_LOG_FUNCTION(this << packet->GetUid() << "enqued for socket " << sendingSocket);
308  }
309  }
310 }
311 
312 void
314 {
315 
316  NS_LOG_FUNCTION (this << socket);
317 
318  Ptr<Packet> packet;
319  Address from;
320  while ((packet = socket->RecvFrom (from)))
321  {
322  if (packet->GetSize () == 0)
323  { //EOF
324  break;
325  }
326 
327  m_totalRx += packet->GetSize ();
328  NS_LOG_FUNCTION (this << packet << "PACKETID: " << packet->GetUid() << " of size: " << packet->GetSize() );
329 
331  {
332  NS_LOG_FUNCTION(this << "At time " << Simulator::Now ().GetSeconds ()
333  << "s SDN received packet ID: "
334  << packet->GetUid () << " of "
335  << packet->GetSize () << " bytes from "
337  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
338  << " total Rx " << m_totalRx << " bytes");
339  }
340 
341  m_rxTrace (packet, from);
342  PacketReceived (packet, from, socket);
343  }
344 }
345 
346 void
348 {
349  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
350  std::string receivedStatus = p->ToString();
351  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
352 
353  Ptr<Packet> buffer;
354  if (receivedStatus.find("Fragment") != std::string::npos) {
355  auto itBuffer = m_buffer.find (from);
356  if (itBuffer == m_buffer.end ()){
357  itBuffer = m_buffer.insert (
358  std::make_pair (from, Create<Packet> (0))
359  ).first;
360  }
361  buffer = itBuffer->second;
362  buffer->AddAtEnd (p);
363  }else{
364  NS_LOG_FUNCTION(this << "Full packet received!");
365  buffer = p;
366  }
367 
368  HTTPMessageParser parser;
369  HTTPMessage request;
370 
371  //copy buffer payload to string
372  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
373  buffer->CopyData(b1, buffer->GetSize ());
374  std::string requestString = std::string((char*)b1);
375  delete[] b1;
376 
377  //parse HTTP message
378  parser.Parse(&request, requestString);
379  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
380  {
381  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
382  }else{
383  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString());
384  }
385 
386  while (buffer->GetSize () >= request.GetSize())
387  {
388  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize () << " from buffer of size " << buffer->GetSize ());
389  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
390 
391  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
392  completePacket->CopyData(b2, completePacket->GetSize ());
393  std::string s2 = std::string((char*)b2);
394 
395  HTTPMessage request2;
396  parser.Parse(&request2, s2);
397  delete[] b2;
398 
399  if(request2.IsFragmented() == false){
400  buffer->RemoveAtStart (static_cast<uint32_t> (request2.GetSize () ));
401  ProcessRequest(request2, completePacket, socket);
402  }
403  NS_LOG_FUNCTION(this << "Croped HTTP message: " << request2.ToString());
404  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
405  break;
406  }
407 }
408 
417 void
418 QKDSDNController::StartApplication (void) // Called at time specified by Start
419 {
420  NS_LOG_FUNCTION(this);
422 }
423 
424 void
425 QKDSDNController::PrepareSinkSocket (void) // Called at time specified by Start
426 {
427 
428  NS_LOG_FUNCTION (this);
429 
430  // Create the sink socket if not already
431  if (!m_sinkSocket){
433  NS_LOG_FUNCTION (this << "Create the sink SDN socket!" << m_sinkSocket);
434  }
435 
436  NS_LOG_FUNCTION (this << "Sink SDN socket listens on " << m_local << " and port " << m_port << " for APP requests" );
438 
439  if (m_sinkSocket->Bind (sinkAddress) == -1)
440  NS_FATAL_ERROR ("Failed to bind socket");
441 
442  m_sinkSocket->Listen ();
446  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
448  );
452  );
453 
454 }
455 
456 void
457 QKDSDNController::StopApplication (void) // Called at time specified by Stop
458 {
459  NS_LOG_FUNCTION (this);
460 
461  std::map<Ptr<Socket>, Ptr<Socket> >::iterator j;
462  for (
463  j = m_socketPairs.begin ();
464  !(j == m_socketPairs.end ());
465  j++
466  ){
467  if(j->first != 0) {
468  j->first->Close();
469  j->first->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
470  }
471  if(j->second != 0) j->second->Close();
472  }
473 
474  if (m_sinkSocket != 0)
475  {
476  m_sinkSocket->Close ();
478  }
479 }
480 
489 void
491 {
492  NS_LOG_FUNCTION (this);
493  uint32_t slave_SAE_ID = 0;
494  std::string ksid;
495  QKDSDNController::RequestType requestType = NONE;
496 
497  std::string s = headerIn.GetUri();
498  std::string delimiter = "/";
499 
500  size_t pos = 0;
501  std::string token;
502  std::vector<std::string> uriParams;
503  while ((pos = s.find(delimiter)) != std::string::npos) {
504  token = s.substr(0, pos);
505  if(token.length() > 0){
506  uriParams.push_back(token);
507  }
508  s.erase(0, pos + delimiter.length());
509  }
510  if(s.length() > 0){
511  uriParams.push_back(s);
512  }
513 
514  if(
515  uriParams.size() > 3 &&
516  uriParams[1] == "api" &&
517  uriParams[2] == "v1" &&
518  uriParams[3] == "keys"
519  ){
520  std::string receivedAddressStr (uriParams[0]);
521  Ipv4Address receivedAddress = Ipv4Address(receivedAddressStr.c_str()); //string to IPv4Address
522  NS_LOG_FUNCTION(this << "received address" << receivedAddressStr << receivedAddress);
523 
524  /*
525  Due to static routing in the first versions of scripts, IP addresses of SDN controller can differ.
526  Therefore, we do not check the address of the SDN controller since we know there is ONLY one SDN controller in the network
527  if(receivedAddress != GetAddress())
528  NS_FATAL_ERROR ( this << "The request is not for me!\t" << receivedAddress << "\t" << GetAddress() << "\t" << headerIn.GetUri());
529  */
530 
531  std::stringstream tempString (uriParams[4]);
532  tempString >> slave_SAE_ID;
533 
534  ksid = uriParams[4];
535  requestType = FetchRequestType(uriParams[5]);
536  }
537  NS_LOG_FUNCTION(this << "uri:" << headerIn.GetUri());
538  NS_LOG_FUNCTION (this << "slave_SAE_ID: " << slave_SAE_ID << "requestType: " << requestType );
539 
540 
541  if(requestType == REGISTER_QKD_LINK){ //Process status request
542 
543  uint32_t srcSaeId = 0;
544  uint32_t dstSaeId = 0;
545  Ipv4Address kmsSrcAddress;
546  Ipv4Address kmsDstAddress;
547  std::string keyAssociationIdString;
548 
549  if(headerIn.GetMethod() == HTTPMessage::HttpMethod::POST){
550  std::string payload = headerIn.GetMessageBodyString(); //Read payload
551  try{
552 
553  //Try parse JSON
554  nlohmann::json jrequest; //JSON request structure
555  jrequest = nlohmann::json::parse(payload);
556  if (jrequest.contains("master_SAE_ID")) srcSaeId = jrequest["master_SAE_ID"];
557  if (jrequest.contains("slave_SAE_ID")) dstSaeId = jrequest["slave_SAE_ID"];
558  if (jrequest.contains("key_association_id")) keyAssociationIdString = jrequest["key_association_id"];
559 
560  std::string kmsSrcAddressStr;
561  if (jrequest.contains("master_kms_address")) kmsSrcAddressStr = jrequest["master_kms_address"];
562  kmsSrcAddress = Ipv4Address(kmsSrcAddressStr.c_str()); //string to IPv4Address
563 
564  std::string kmsDstAddressStr;
565  if (jrequest.contains("slave_kms_address")) kmsDstAddressStr = jrequest["slave_kms_address"];
566  kmsDstAddress = Ipv4Address(kmsDstAddressStr.c_str()); //string to IPv4Address
567 
568  }catch(...){
569  NS_FATAL_ERROR( this << "JSON parse error of the received payload: " << payload << "\t" << payload.length() );
570  }
571 
572  }else
573  NS_FATAL_ERROR(this << "Invalid HTTP request method" << headerIn.GetMethod()); //@toDo: include HTTP response?
574 
576  NS_ASSERT (lr != 0);
577 
579  srcSaeId,
580  dstSaeId,
581  dstSaeId,//nextHop
582  1,//dirrect p2p connection (number of hops)
583  0,// 0-QKD generation link; 1-etsi014; 2-etsi004
584  kmsSrcAddress,
585  kmsDstAddress,
586  0
587  );
588  newEntry.SetId( UUID{keyAssociationIdString} );
590  lr->AddKeyAssociationEntry(newEntry);
591 
592  NS_LOG_FUNCTION (this << "NEW QKD LINK REGISTERED AT SDN CONTROLLER!");
593  NS_LOG_FUNCTION (this << "SET STATUS UPDATE TIME TO: " << m_qkdLinkDefaultUpdateInterval);
594 
595  nlohmann::json j;
596  j["accepted"] = 1; //true
597  j["qkd_link_update_interval"] = m_qkdLinkDefaultUpdateInterval;
598  j["key_association_id"] = keyAssociationIdString;
599  NS_LOG_FUNCTION( this << "json_response:" << j.dump() );
600 
601  std::string msg = j.dump();
602 
603  //create packet
604  HTTPMessage httpMessage;
605  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok, msg, {
606  {"Content-Type", "application/json; charset=utf-8"},
607  {"Request URI", headerIn.GetUri() }
608  });
609  std::string hMessage = httpMessage.ToString();
610  Ptr<Packet> packet = Create<Packet> (
611  (uint8_t*) (hMessage).c_str(),
612  hMessage.size()
613  );
614  NS_ASSERT (packet != 0);
615 
616 
617  NS_LOG_FUNCTION (this
618  << "Sending Response to REGISTER_QKD_LINK\n PacketID: "
619  << packet->GetUid()
620  << " of size: "
621  << packet->GetSize()
622  );
623  SendToSocketPair(socket, packet);
624 
625 
626 
627  }else if(requestType == KEY_ASSOCIATION_STATUS){ //Process status request
628 
629  double skr = 0;
630  double expectedConsumption = 0;
631  double effectiveSkr = 0;
632  std::string keyAssociationIdString;
633 
634  if(headerIn.GetMethod() == HTTPMessage::HttpMethod::POST){
635  std::string payload = headerIn.GetMessageBodyString(); //Read payload
636  try{
637 
638  //Try parse JSON
639  nlohmann::json jrequest; //JSON request structure
640  jrequest = nlohmann::json::parse(payload);
641  if (jrequest.contains("key_association_id")) keyAssociationIdString = jrequest["key_association_id"];
642  if (jrequest.contains("qkdl_performance_skr")) skr = jrequest["qkdl_performance_skr"];
643  if (jrequest.contains("qkdl_performance_expected_consumption")) expectedConsumption = jrequest["qkdl_performance_expected_consumption"];
644  if (jrequest.contains("qkdl_performance_eskr")) effectiveSkr = jrequest["qkdl_performance_eskr"];
645 
646  }catch(...){
647  NS_FATAL_ERROR( this << "JSON parse error of the received payload: " << payload << "\t" << payload.length() );
648  }
649 
650  }else
651  NS_FATAL_ERROR(this << "Invalid HTTP request method" << headerIn.GetMethod()); //@toDo: include HTTP response?
652 
654  NS_ASSERT (lr != 0);
655 
657  lr->LookupKeyAssociationById(UUID{keyAssociationIdString}, conn);
658 
659  //Secret key rate generation (in bits per second) of the key association link.
660  conn.SetSKR(skr);
661  //Sum of all the application's bandwidth (in bits per second) on this particular key association link.
662  conn.SetExpectedConsumption(expectedConsumption);
663  //Effective secret key rate (in bits per second) generation of the key association link available after internal consumption
664  conn.SetEffectiveSKR(effectiveSkr);
665 
666  lr->SaveKeyAssociation(conn);
667 
668  NS_LOG_FUNCTION (this << "NEW QKD LINK STATS (id: " << keyAssociationIdString << "; eskr:" << effectiveSkr << ") UPDATE RECEIVED AT SDN CONTROLLER!");
669 
670  }else if(requestType == REGISTER_SAE_LINK){
671 
672  std::string srcSaeId;
673  std::string dstSaeId;
674  std::string nextHopId;
675  uint32_t hops = 0;
676  uint32_t linkType = 0;
677  Ipv4Address kmsSrcAddress;
678  Ipv4Address kmsDstAddress;
679 
680  if(headerIn.GetMethod() == HTTPMessage::HttpMethod::POST){
681  std::string payload = headerIn.GetMessageBodyString(); //Read payload
682  try{
683 
684  //Try parse JSON
685  nlohmann::json jrequest; //JSON request structure
686  jrequest = nlohmann::json::parse(payload);
687  if (jrequest.contains("master_SAE_ID")) srcSaeId = jrequest["master_SAE_ID"];
688  if (jrequest.contains("slave_SAE_ID")) dstSaeId = jrequest["slave_SAE_ID"];
689  if (jrequest.contains("hops")) hops = jrequest["hops"];
690  if (jrequest.contains("linkType")) linkType = jrequest["linkType"];
691  if (jrequest.contains("next_hop_id")) nextHopId = jrequest["next_hop_id"];
692 
693  std::string kmsSrcAddressStr;
694  if (jrequest.contains("master_kms_address")) kmsSrcAddressStr = jrequest["master_kms_address"];
695  kmsSrcAddress = Ipv4Address(kmsSrcAddressStr.c_str()); //string to IPv4Address
696 
697  std::string kmsDstAddressStr;
698  if (jrequest.contains("slave_kms_address")) kmsDstAddressStr = jrequest["slave_kms_address"];
699  kmsDstAddress = Ipv4Address(kmsDstAddressStr.c_str()); //string to IPv4Address
700 
701  }catch(...){
702  NS_FATAL_ERROR( this << "JSON parse error of the received payload: " << payload << "\t" << payload.length() );
703  }
704 
705  }else
706  NS_FATAL_ERROR(this << "Invalid HTTP request method" << headerIn.GetMethod()); //@toDo: include HTTP response?
707 
709  NS_ASSERT (lr != 0);
710 
711  NS_LOG_FUNCTION(this << srcSaeId << dstSaeId << nextHopId << hops << linkType);
712 
713  /*
714  QKDLocationRegisterEntry newEntry(
715  srcSaeId,
716  dstSaeId,
717  nextHopId, //nextHop
718  hops, //number of hops
719  linkType,// 0-QKD generation link; 1-etsi014; 2-etsi004
720  kmsSrcAddress,
721  kmsDstAddress,
722  0
723  );
724  lr->AddApplicationEntry(newEntry);
725  */
726 
727  NS_LOG_FUNCTION (this << "NEW SAE LINK REGISTERED AT SDN CONTROLLER!");
728 
729  }
730 
731 }
732 
733 
734 uint32_t
736  return m_maxKeyPerRequest;
737 }
738 
741 {
742  NS_LOG_FUNCTION(this << s);
743  RequestType output;
744 
745  if(s == "status"){
746 
748 
749  } else if(s == "enc_keys") {
750 
751  return ETSI_QKD_014_GET_KEY;
752 
753  } else if(s == "dec_keys"){
754 
756 
757  } else if (s == "open_connect"){
758 
760 
761  } else if (s == "get_key") {
762 
763  return ETSI_QKD_004_GET_KEY;
764 
765  } else if (s == "close") {
766 
767  return ETSI_QKD_004_CLOSE;
768 
769  } else if (s == "new_app") {
770 
771  return NEW_APP;
772 
773  } else if (s == "register") {
774 
775  return REGISTER;
776 
777  } else if (s == "fill") {
778 
779  return FILL;
780 
781  } else if (s == "store_pp_key") {
782 
783  return STORE_PP_KEYS;
784 
785  } else if (s == "transform_keys") {
786 
787  return TRANSFORM_KEYS;
788 
789  } else if (s == "close_kms") {
790 
791  return ETSI_QKD_004_KMS_CLOSE;
792 
793  } else if (s == "register_sae_link") {
794 
795  return REGISTER_SAE_LINK;
796 
797  } else if (s == "register_qkd_link") {
798 
799  return REGISTER_QKD_LINK;
800 
801  } else if (s == "key_association_status") {
802 
803  return KEY_ASSOCIATION_STATUS;
804 
805  } else {
806 
807  NS_FATAL_ERROR ("Unknown Type: " << s);
808  }
809 
810  return output;
811 }
812 
813 //function called from QKD Control
814 //by default srcSaeId == srcNodeId where the link is installed
815 void
817  uint32_t srcSaeId,
818  uint32_t dstSaeId,
819  Ipv4Address kmsDstAddress,
820  Ptr<QKDBuffer> srcBuffer
821 ){
822 
823  NS_LOG_FUNCTION( this << srcSaeId << dstSaeId << m_local << kmsDstAddress );
824 
826  NS_ASSERT (lr != 0);
827 
829  srcSaeId,
830  dstSaeId,
831  dstSaeId,//nextHop
832  1,//dirrect p2p connection (number of hops)
833  0,// 0-QKD generation link; 1-etsi014; 2-etsi004
834  m_local,
835  kmsDstAddress,
836  srcBuffer
837  );
838  lr->AddKeyAssociationEntry(newEntry);
839 
840  NS_LOG_FUNCTION (this << "Create sink socket to listen requests exchanged between KMSs!" );
841 
842 }
843 
848 void
850  Ptr<Node> srcNode,
851  Ptr<Node> dstNode,
852  uint32_t srcSaeId,
853  uint32_t dstSaeId,
854  std::string type // 0-QKD generation link; 1-etsi014; 2-etsi004
855 ){
856 
857  NS_LOG_FUNCTION( this << dstNode );
858 
860  NS_ASSERT (lr != 0);
861  /*
862  //By default there should be one LR entry that connects nodes
863  //source_SAE and master_SAE of that connection is the ID of nodes
864  //we use that entry to fetch details about KMS and the local buffer
865  //@toDo: allow much easier way for adding of saes
866  QKDLocationRegisterEntry conn = GetConnectionDetailsByNodeId( dstNode->GetId() );
867 
868  uint32_t linkType;
869  if(type == "etsi014"){
870  linkType = 1;
871  }else if(type == "etsi004"){
872  linkType = 2;
873  }
874 
875  if(conn.GetSourceSaeId() == srcNode->GetId() &&
876  conn.GetDestinationSaeId() == dstNode->GetId()
877  ){
878 
879  QKDLocationRegisterEntry newEntry(
880  srcSaeId,
881  dstSaeId,
882  conn.GetNextHop(),
883  conn.GetHop(),
884  linkType,
885  conn.GetSourceKmsAddress(),
886  conn.GetDestinationKmsAddress(),
887  conn.GetSourceBuffer()
888  );
889  lr->AddEntry(newEntry);
890  }
891  */
892 
893 }
894 
895 void
897  m_node = n;
898 }
899 
900 Ptr<Node>
902  return m_node;
903 }
904 
905 
906 std::string
908 {
909  std::string output;
910  CryptoPP::StringSource(input, true,
911  new CryptoPP::Base64Encoder(
912  new CryptoPP::StringSink(output)
913  ) // Base64Encoder
914  ); // StringSource
915  return output;
916 }
917 
918 std::string
920 {
921  std::string output;
922  CryptoPP::StringSource(input, true,
923  new CryptoPP::Base64Decoder(
924  new CryptoPP::StringSink(output)
925  ) // Base64Dencoder
926  ); // StringSource
927  return output;
928 }
929 
930 
931 } // Namespace ns3
a polymophic address class
Definition: address.h:91
The base class for all ns3 applications.
Definition: application.h:61
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
The basic class to represent both HTTP requests and responses.
Definition: http.h:78
std::string ToString()
Takes the headers added to the message along with the body and outputs it to a std::string for use in...
Definition: http.h:633
uint32_t GetSize()
Definition: http.h:686
std::string GetUri() const
Grab the uri.
Definition: http.h:519
bool IsFragmented()
Definition: http.h:852
std::string GetMessageBodyString()
Definition: http.h:714
void CreateResponse(const HttpStatus status)
Definition: http.h:785
HTTPMessage::HttpMethod GetMethod() const
Definition: http.h:482
std::string GetStatusMessage() const
Get the current status message for this message.
Definition: http.h:623
A basic class to parse a HTTP message, both request and response.
Definition: http.h:941
void Parse(HTTPMessage *httpMessage, const std::string &buffer)
Parse a std::string to a HTTP message.
Definition: http.h:951
an Inet address class
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static Ipv4Address GetAny(void)
AttributeValue implementation for Ipv4Address.
Definition: ipv4-address.h:341
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
std::string ToString(void) const
Return a string representation of the packet.
Definition: packet.cc:426
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
QKDConnectionRegister is a class used to keep details about distant QKD links and applications.
Introspection did not find any typical Config paths.
void SetId(UUID id)
void SetExpectedConsumption(double value)
void SetUpdateStatusInterval(double statusInterval)
void SetSKR(double value)
void SetEffectiveSKR(double value)
TracedCallback< Ptr< const Packet > > m_txTraceSDNs
static TypeId GetTypeId(void)
Get the type ID.
std::map< Ptr< Socket >, Ptr< Packet > > m_packetQueues
Buffering unsend messages due to connection problems.
uint32_t GetMaxKeyPerRequest()
Get maximum number of keys per request (ETSI QKD 014)
uint32_t GetId()
Get key menager system ID.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
Traced Callback: received packets, source address.
uint32_t GetTotalRx() const
Get the total amount of bytes received.
std::map< Ptr< Socket >, Ptr< Socket > > m_socketPairs
the accepted sockets
void HandleRead(Ptr< Socket > socket)
Handle a packet received by the KMS application.
void StopApplication(void)
Stop KMS Application.
TracedCallback< const std::string &, const uint32_t &, const uint32_t &, const uint32_t & > m_keyServedETSI004Trace
TracedCallback< Ptr< const Packet >, const Address & > m_rxTraceSDNs
void StartApplication(void)
Start KMS Application.
std::string Base64Decode(std::string input)
Base64 decoder.
void HandlePeerClose(Ptr< Socket > socket)
Handle an connection close.
void HandlePeerError(Ptr< Socket > socket)
Handle an connection error.
uint32_t m_port
Local port to bind to.
Ipv4Address m_local
Local address to bind to.
TracedCallback< const uint32_t & > m_newKeyGeneratedTraceEmir
uint32_t m_totalRx
Total bytes received
void ConnectionFailed(Ptr< Socket > socket)
TracedCallback< const std::string &, const uint32_t &, Ptr< QKDKey > > m_keyServedETSI014Trace
double m_qkdLinkDefaultUpdateInterval
Default update interval of QKD link status (seconds)
void SetSocket(std::string type, Ptr< Socket > socket)
Set sink socket.
@ ETSI_QKD_014_GET_KEY
Integer equivalent = 1.
@ ETSI_QKD_014_GET_KEY_WITH_KEY_IDS
Integer equivalent = 2.
@ ETSI_QKD_014_GET_STATUS
Integer equivalent = 0.
QKDSDNController::RequestType FetchRequestType(std::string s)
Get request type.
TracedCallback< const uint32_t & > m_keyServedTraceEmir
void PacketReceived(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Assemble byte stream to extract HTTPMessage.
Ptr< Node > GetNode()
Get node.
void SendToSocketPair(Ptr< Socket > socket, Ptr< Packet > packet)
Send packet to the pair socket.
virtual void DoDispose(void)
@toDo
std::string Base64Encode(std::string input)
Base64 encoder.
virtual ~QKDSDNController()
QKDSDNController destructor.
void ConnectionSucceeded(Ptr< Socket > socket)
@toDo:following functions
std::map< Ptr< Socket >, Ptr< Socket > > GetAcceptedSockets(void) const
Get list of all accepted sockets.
void AddNewLink(uint32_t srcSaeId, uint32_t dstSaeId, Ipv4Address kmsDstAddress, Ptr< QKDBuffer > srcBuffer)
Inform KMS about the new QKD connection/link.
TracedCallback< const Ipv4Address &, Ptr< const Packet > > m_dropTrace
Traced callback: fired when a packet is dropped.
void RegisterSaePair(Ptr< Node > srcNode, Ptr< Node > dstNode, uint32_t srcSaeId, uint32_t dstSaeId, std::string type)
Inform KMS about the SAE connection.
void HandleAccept(Ptr< Socket > s, const Address &from)
Handle an incoming connection.
TracedCallback< const uint32_t &, const uint32_t & > m_newKeyGeneratedTrace
void DataSend(Ptr< Socket >, uint32_t)
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer
Buffer for received packets (TCP segmentation)
Ptr< Socket > GetSocket(void) const
Get sink socket.
QKDSDNController()
QKDSDNController constructor.
void ProcessRequest(HTTPMessage header, Ptr< Packet > packet, Ptr< Socket > socket)
QKD key manager system application process the request from QKDApp, and complete certain actions to r...
TracedCallback< Ptr< const Packet > > m_txTrace
void SetNode(Ptr< Node > n)
Set node.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetConnectCallback(Callback< void, Ptr< Socket > > connectionSucceeded, Callback< void, Ptr< Socket > > connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:84
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
Definition: socket.cc:104
virtual int ShutdownRecv(void)=0
@ NS3_SOCK_STREAM
Definition: socket.h:105
@ NS3_SOCK_SEQPACKET
Definition: socket.h:106
virtual int Listen(void)=0
Listen for incoming connections.
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call)
Definition: socket.cc:114
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int ShutdownSend(void)=0
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual int Close(void)=0
Close a socket.
void SetCloseCallbacks(Callback< void, Ptr< Socket > > normalClose, Callback< void, Ptr< Socket > > errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition: socket.cc:94
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual enum Socket::SocketType GetSocketType(void) const =0
static TypeId GetTypeId(void)
Get the type ID.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
AttributeValue implementation for TypeId.
Definition: type-id.h:595
Universally unique identifier (UUID)
Definition: uuid.h:35
static TypeId GetTypeId(void)
Get the type ID.
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: double.h:42
Ptr< const AttributeChecker > MakeIpv4AddressChecker(void)
Ptr< const AttributeAccessor > MakeIpv4AddressAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: ipv4-address.h:341
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: type-id.h:595
Ptr< const AttributeChecker > MakeTypeIdChecker(void)
Definition: type-id.cc:1226
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
Callback< R, Ts... > MakeNullCallback(void)
Definition: callback.h:1688
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
basic_json<> json
default JSON class
Definition: json.h:3000
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648