22 #include <ns3/tcp-socket-factory.h>
23 #include <ns3/uinteger.h>
35 : m_serverSocket(nullptr)
39 m_xid = rand() & 0xffffffff;
51 TypeId(
"ns3::OFSwitch13Controller")
53 .SetGroupName(
"OFSwitch13")
55 "Port number to listen for incoming packets.",
58 MakeUintegerChecker<uint16_t>());
86 NS_LOG_DEBUG(
"Schedulling command for an unregistered switch.");
92 std::pair<uint64_t, Ptr<PendingCommands>> entry(dpId, pendCmds);
94 if (ret.second ==
false)
96 NS_LOG_ERROR(
"Error when creating pending commands object.");
102 it->second->m_queue.push(textCmd);
108 wordexp(textCmd.c_str(), &
cmd, 0);
109 char** argv =
cmd.we_wordv;
110 size_t argc =
cmd.we_wordc;
113 int ret = dpctl_exec_ns3_command((
void*)
PeekPointer(swtch), argc, argv);
120 struct ofl_msg_header* msg)
125 swtch->m_ctrlApp->SendToSwitch(swtch, msg, 0);
201 struct ofl_msg_header* msg,
206 char* msgStr = ofl_msg_to_string(msg,
nullptr);
207 NS_LOG_DEBUG(
"TX to switch " << swtch->GetIpv4() <<
" [dp "
208 << swtch->GetDpId() <<
"]: " << msgStr);
218 return swtch->m_handler->SendMessage(
PacketFromMsg(msg, xid));
228 struct ofl_msg_echo msg;
229 msg.header.type = OFPT_ECHO_REQUEST;
230 msg.data_length = payloadSize;
236 msg.data = (uint8_t*)xmalloc(payloadSize);
237 random_bytes(msg.data, payloadSize);
242 std::pair<uint32_t, EchoInfo> entry(xid,
EchoInfo(swtch));
244 if (ret.second ==
false)
246 NS_LOG_ERROR(
"Error requesting echo to switch " << swtch);
265 struct ofl_msg_header msg;
266 msg.type = OFPT_BARRIER_REQUEST;
270 std::pair<uint32_t, BarrierInfo> entry(xid,
BarrierInfo(swtch));
272 if (ret.second ==
false)
274 NS_LOG_ERROR(
"Error requesting barrier to switch " << swtch);
290 struct ofl_msg_echo reply;
291 reply.header.type = OFPT_ECHO_REPLY;
292 reply.data_length = msg->data_length;
293 reply.data = msg->data;
294 SendToSwitch(swtch, (
struct ofl_msg_header*)&reply, xid);
295 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
309 NS_LOG_WARN(
"Echo response for unknonw echo request.");
313 it->second.m_waiting =
false;
315 NS_LOG_INFO(
"Echo reply from " << it->second.m_swtch->GetIpv4()
317 << it->second.GetRtt().As(
Time::MS));
321 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
335 NS_LOG_WARN(
"Barrier response for unknonw barrier request.");
339 NS_LOG_INFO(
"Barrier reply from " << it->second.m_swtch->GetIpv4());
343 ofl_msg_free(msg,
nullptr);
356 ofl_msg_free(msg,
nullptr);
358 struct ofl_msg_header features;
359 features.type = OFPT_FEATURES_REQUEST;
375 swtch->
m_dpId = msg->datapath_id;
380 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
382 std::pair<uint64_t, Ptr<RemoteSwitch>> entry(swtch->
m_dpId, swtch);
384 if (ret.second ==
false)
386 NS_LOG_ERROR(
"This switch is already registered with this controller.");
394 while (!pendCommands->
m_queue.empty())
414 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
425 char* msgStr = ofl_msg_to_string((
struct ofl_msg_header*)msg,
nullptr);
429 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
440 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
451 ofl_msg_free_flow_removed(msg,
true,
nullptr);
462 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
473 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
479 struct ofl_msg_multipart_reply_header* msg,
485 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
496 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
502 struct ofl_msg_queue_get_config_reply* msg,
508 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
528 case OFPT_BARRIER_REPLY:
532 return HandlePacketIn((
struct ofl_msg_packet_in*)msg, swtch, xid);
534 case OFPT_ECHO_REQUEST:
537 case OFPT_ECHO_REPLY:
541 return HandleError((
struct ofl_msg_error*)msg, swtch, xid);
543 case OFPT_FEATURES_REPLY:
548 case OFPT_GET_CONFIG_REPLY:
553 case OFPT_FLOW_REMOVED:
556 case OFPT_PORT_STATUS:
559 case OFPT_GET_ASYNC_REPLY:
562 case OFPT_MULTIPART_REPLY:
567 case OFPT_ROLE_REPLY:
570 case OFPT_QUEUE_GET_CONFIG_REPLY:
572 (
struct ofl_msg_queue_get_config_reply*)msg,
576 case OFPT_EXPERIMENTER:
578 return ofl_error(OFPET_BAD_REQUEST, OFPGMFC_BAD_TYPE);
588 struct ofl_msg_header* msg;
593 error = ofl_msg_unpack((uint8_t*)buffer->data,
602 char* msgStr = ofl_msg_to_string(msg,
nullptr);
604 << swtch->
GetDpId() <<
"]: " << msgStr);
614 ofl_msg_free(msg,
nullptr);
619 NS_LOG_ERROR(
"Error processing OpenFlow message from switch.");
621 ofpbuf_delete(buffer);
634 NS_ABORT_MSG(
"Couldn't find the remote switch for this address.");
643 "Invalid address type (only IPv4 supported by now).");
646 NS_LOG_INFO(
"Switch request connection from " << ipAddr <<
":" <<
port);
658 NS_LOG_INFO(
"Switch connection accepted from " << ipAddr <<
":" <<
port);
670 swtch->
m_handler = CreateObject<OFSwitch13SocketHandler>(socket);
674 std::pair<Address, Ptr<RemoteSwitch>> entry(swtch->
m_address, swtch);
676 if (ret.second ==
false)
678 NS_LOG_ERROR(
"This switch is already registered with this controller.");
683 struct ofl_msg_header hello;
684 hello.type = OFPT_HELLO;
709 : m_handler(nullptr),
712 m_role(OFPCR_ROLE_EQUAL)
751 return m_recv - m_send;
a polymophic address class
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
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.
static Ipv4Address GetAny()
PendingCommands()
Default (empty) constructor.
std::queue< std::string > m_queue
Queue of pending dpctl commands.
Inner class to save information of a remote active OpenFlow switch connected to this controller.
uint32_t m_capabilities
Bitmap of support ofp_capabilities.
RemoteSwitch()
Default (empty) constructor.
Ipv4Address GetIpv4() const
Get the IP from socket connection address.
Ptr< OFSwitch13Controller > m_ctrlApp
Controller application.
uint8_t m_auxiliaryId
Identify auxiliary connections.
Address m_address
Switch connection address.
Ptr< OFSwitch13SocketHandler > m_handler
Socket handler.
uint16_t GetPort() const
Get the port from socket connection address.
uint32_t m_nBuffers
Switch features informed to the controller during handshake procedure.
uint64_t GetDpId() const
Get the datapath ID.
uint64_t m_dpId
OpenFlow datapath ID.
uint8_t m_nTables
Number of tables supported by datapath.
void StopApplication() override
Application specific shutdown code.
OFSwitch13Controller()
Default constructor.
ofl_err HandleEchoRequest(struct ofl_msg_echo *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
ofl_err HandleEchoReply(struct ofl_msg_echo *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
virtual ofl_err HandlePortStatus(struct ofl_msg_port_status *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
virtual void HandshakeSuccessful(Ptr< const RemoteSwitch > swtch)
Function invoked after a successfully handshake procedure between this controller and a remote switch...
virtual ofl_err HandlePacketIn(struct ofl_msg_packet_in *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
void SocketPeerError(Ptr< Socket > socket)
TCP connection error.
AddrSwMap_t m_addrSwMap
Registered switches by address.
void SocketAccept(Ptr< Socket > socket, const Address &from)
TCP handshake succeeded.
virtual ofl_err HandleGetConfigReply(struct ofl_msg_get_config_reply *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
virtual ofl_err HandleMultipartReply(struct ofl_msg_multipart_reply_header *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
void StartApplication() override
Application specific startup code.
static void DpctlSendAndPrint(struct vconn *vconn, struct ofl_msg_header *msg)
Overriding BOFUSS dpctl_send_and_print and dpctl_transact_and_print weak functions from utilities/dpc...
void SocketPeerClose(Ptr< Socket > socket)
TCP connection closed.
uint32_t m_xid
Global transaction idx.
~OFSwitch13Controller() override
Dummy destructor, see DoDispose.
void ReceiveFromSwitch(Ptr< Packet > packet, Address from)
Receive an OpenFlow packet from switch.
void SendEchoRequest(Ptr< const RemoteSwitch > swtch, size_t payloadSize=0)
Send an echo request message to switch, and wait for a non-blocking reply.
virtual ofl_err HandleFlowRemoved(struct ofl_msg_flow_removed *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
ofl_err HandleHello(struct ofl_msg_header *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
Ptr< Socket > m_serverSocket
Listening server socket.
ofl_err HandleBarrierReply(struct ofl_msg_header *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
bool SocketRequest(Ptr< Socket > socket, const Address &from)
TCP request from switch.
uint16_t m_port
Local controller tcp port.
virtual ofl_err HandleQueueGetConfigReply(struct ofl_msg_queue_get_config_reply *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
ofl_err HandleSwitchMsg(struct ofl_msg_header *msg, Ptr< RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
ofl_err HandleFeaturesReply(struct ofl_msg_features_reply *msg, Ptr< RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
static TypeId GetTypeId()
Register this type.
int SendToSwitch(Ptr< const RemoteSwitch > swtch, struct ofl_msg_header *msg, uint32_t xid=0)
Send a OFLib message to a registered switch.
void SendBarrierRequest(Ptr< const RemoteSwitch > swtch)
Send a barrier request message to switch, and wait for a non-blocking reply.
EchoMsgMap_t m_echoMap
Metadata for echo requests.
virtual ofl_err HandleError(struct ofl_msg_error *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
Ptr< const RemoteSwitch > GetRemoteSwitch(uint64_t dpId) const
Get the remote switch for this OpenFlow datapath ID.
BarrierMsgMap_t m_barrierMap
Metadata for barrier requests.
DpIdCmdMap_t m_commandsMap
Commands scheduled for execution.
virtual ofl_err HandleAsyncReply(struct ofl_msg_async_config *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
virtual ofl_err HandleRoleReply(struct ofl_msg_role_request *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Called when an OpenFlow message is received from a switch.
int DpctlExecute(uint64_t dpId, const std::string textCmd)
Execute a dpctl command to interact with the remote switch.
void DoDispose() override
Destructor implementation.
DpIdSwMap_t m_dpIdSwMap
Registered switches by datapath id.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
A base class which provides memory management and object aggregation.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Smart pointer class similar to boost::intrusive_ptr.
Control the scheduling of simulation events.
static Time Now()
Return the current simulation virtual time.
void SetCloseCallbacks(Callback< void, Ptr< Socket >> normalClose, Callback< void, Ptr< Socket >> errorClose)
Detect socket recv() events such as graceful shutdown or error.
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
virtual int ShutdownRecv()=0
virtual int ShutdownSend()=0
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...
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int Listen()=0
Listen for incoming connections.
Simulation virtual time values and global simulation resolution.
a unique identifier for an interface.
static TypeId LookupByName(std::string name)
Get a TypeId by name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Callback< R, Args... > MakeNullCallback()
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< Packet > PacketFromMsg(struct ofl_msg_header *msg, uint32_t xid)
Create a new ns3::Packet from internal OFLib message.
struct ofpbuf * BufferFromPacket(Ptr< const Packet > packet, size_t bodyRoom, size_t headRoom)
Create an internal BOFUSS buffer from ns3::Packet.
Time Now()
create an ns3::Time instance which contains the current simulation time.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
U * PeekPointer(const Ptr< U > &p)
Structure to save barrier metadata used by the controller interface.
BarrierInfo(Ptr< const RemoteSwitch > swtch)
Complete constructor, with remote switch.
Structure to save echo request metadata used by the controller interface.
Time GetRtt() const
Compute the echo RTT time.
EchoInfo(Ptr< const RemoteSwitch > swtch)
Complete constructor, with remote switch.