A Discrete-Event Network Simulator
API
ofswitch13-socket-handler.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 University of Campinas (Unicamp)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Luciano Jerez Chaves <ljerezchaves@gmail.com>
18  */
19 
21 
22 namespace ns3
23 {
24 
25 NS_LOG_COMPONENT_DEFINE("OFSwitch13SocketHandler");
26 NS_OBJECT_ENSURE_REGISTERED(OFSwitch13SocketHandler);
27 
28 TypeId
30 {
31  static TypeId tid = TypeId("ns3::OFSwitch13SocketHandler")
32  .SetParent<Object>()
33  .SetGroupName("OFSwitch13");
34  return tid;
35 }
36 
38  : m_socket(socket),
39  m_pendingPacket(nullptr),
40  m_pendingBytes(0),
41  m_txQueue()
42 {
43  NS_LOG_FUNCTION(this << socket);
44 
45  // Setup socket callbacks.
48 }
49 
51 {
52  NS_LOG_FUNCTION(this);
53 }
54 
55 void
57 {
58  NS_LOG_FUNCTION(this);
59 
60  m_receivedMsg = cb;
61 }
62 
63 int
65 {
66  NS_LOG_FUNCTION(this << packet);
67 
68  // Insert this message into tx queue and try to forward it to the socket.
69  m_txQueue.push(packet);
71  return 0;
72 }
73 
74 void
76 {
77  NS_LOG_FUNCTION(this);
78 
79  m_socket = nullptr;
80  m_pendingPacket = nullptr;
81 }
82 
83 void
84 OFSwitch13SocketHandler::Send(Ptr<Socket> socket, uint32_t available)
85 {
86  NS_LOG_FUNCTION(this << socket << available);
87 
88  while (!m_txQueue.empty())
89  {
90  // Get a reference for the next packet in the queue and check for
91  // available space in socket tx buffer.
92  Ptr<Packet> packet = m_txQueue.front();
93  if (socket->GetTxAvailable() < packet->GetSize())
94  {
95  NS_LOG_WARN("No space available to send message now.");
96  return;
97  }
98 
99  // Remove the packet from the queue and send it to the socket.
100  m_txQueue.pop();
101  int retval = socket->Send(packet);
102  if (retval == -1)
103  {
104  NS_LOG_ERROR("Error while sending OpenFlow message to socket. "
105  << "Discarding. Socket error: " << socket->GetErrno());
106  }
107  }
108 }
109 
110 void
112 {
113  NS_LOG_FUNCTION(this << socket);
114 
115  static const size_t ofpHeaderSize = sizeof(struct ofp_header);
116  Address from;
117 
118  // Repeat the loop until socket buffer gets empty.
119  while (socket->GetRxAvailable())
120  {
121  // If we don't have pending bytes from an incomplete OpenFlow messages
122  // it means that this is the start of a new message.
123  if (!m_pendingBytes)
124  {
125  // At least 8 bytes from the OpenFlow header must be available.
126  if (socket->GetRxAvailable() < 8)
127  {
128  return; // Wait for more bytes.
129  }
130 
131  // Read the OpenFlow header and get the OpenFlow message size.
132  struct ofp_header header;
133  m_pendingPacket = socket->RecvFrom(ofpHeaderSize, 0, from);
134  m_pendingPacket->CopyData((uint8_t*)&header, ofpHeaderSize);
135  m_pendingBytes = ntohs(header.length) - ofpHeaderSize;
136  }
137 
138  // If we have pending bytes from an incomplete OpenFlow message and we
139  // also have bytes available to read at socket, let's read them now.
140  uint32_t read = std::min(m_pendingBytes, socket->GetRxAvailable());
141  if (read)
142  {
143  m_pendingPacket->AddAtEnd(socket->RecvFrom(read, 0, from));
144  m_pendingBytes -= read;
145  }
146 
147  // If we don't have pending bytes anymore it means that now we have a
148  // complete OpenFlow message.
149  if (!m_pendingBytes)
150  {
151  // Let's send the message to the registered callback.
152  if (!m_receivedMsg.IsNull())
153  {
155  }
156  m_pendingPacket = nullptr;
157  }
158  }
159 }
160 
161 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
a polymophic address class
Definition: address.h:100
bool IsNull() const
Check for null implementation.
Definition: callback.h:572
MessageCallback m_receivedMsg
OpenFlow message callback.
void Send(Ptr< Socket > socket, uint32_t available)
Callback for bytes available in tx buffer.
OFSwitch13SocketHandler(Ptr< Socket > socket)
Complete constructor.
uint32_t m_pendingBytes
Pending bytes for message.
std::queue< Ptr< Packet > > m_txQueue
TX queue.
~OFSwitch13SocketHandler() override
Dummy destructor, see DoDispose.
void Recv(Ptr< Socket > socket)
Callback for bytes available in rx buffer.
static TypeId GetTypeId()
Register this type.
int SendMessage(Ptr< Packet > packet)
Send an OpenFlow message to the TCP socket.
Ptr< Packet > m_pendingPacket
Buffer for receiving bytes.
void DoDispose() override
Destructor implementation.
void SetReceiveCallback(MessageCallback cb)
Set the callback to invoke whenever an OpenFlow message has been received at the associated socket.
A base class which provides memory management and object aggregation.
Definition: object.h:89
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual uint32_t GetRxAvailable() const =0
Return number of bytes which can be returned from one or multiple calls to Recv.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:126
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:119
virtual enum Socket::SocketErrno GetErrno() const =0
Get last error number.
virtual uint32_t GetTxAvailable() const =0
Returns the number of bytes which can be sent in a single call to Send.
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.
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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.
Definition: log.h:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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...
Definition: callback.h:707