22 #include <ns3/epc-gtpu-header.h>
45 .SetGroupName(
"OFSwitch13")
55 std::pair<Ipv4Address, Mac48Address> entry(ipAddr, macAddr);
56 std::pair<IpMacMap_t::iterator, bool> ret;
58 if (ret.second ==
true)
60 NS_LOG_INFO(
"New ARP entry: " << ipAddr <<
" - " << macAddr);
72 std::pair<DpPortPair_t, Ipv4Address> entry(key, ipAddr);
73 std::pair<DpPortIpMap_t::iterator, bool> ret;
75 if (ret.second ==
true)
77 NS_LOG_INFO(
"New endpoint entry: " << dpId <<
"/" << portNo <<
" - " << ipAddr);
80 NS_ABORT_MSG(
"This endpoint already exists in tunnel endpoint table.");
99 uint64_t swDpId = swtch->GetDpId();
103 "flow-mod cmd=add,table=0,prio=16 eth_type=0x0806 "
104 "apply:output=ctrl");
107 DpctlExecute(swDpId,
"flow-mod cmd=add,table=0,prio=0 apply:output=ctrl");
118 uint64_t swDpId = swtch->GetDpId();
120 struct ofl_match_tlv* tlv;
121 enum ofp_packet_in_reason reason = msg->reason;
122 if (reason == OFPR_NO_MATCH)
124 char* msgStr = ofl_structs_match_to_string(msg->match,
nullptr);
130 tlv = oxm_match_lookup(OXM_OF_IN_PORT, (
struct ofl_match*)msg->match);
131 memcpy(&inPort, tlv->value, OXM_LENGTH(OXM_OF_IN_PORT));
140 uint64_t tunnelId =
static_cast<uint64_t
>(dstAddr.
Get()) << 32;
142 char tunnelIdStr[20];
143 sprintf(tunnelIdStr,
"0x%016lX", tunnelId);
145 std::ostringstream
cmd;
146 cmd <<
"flow-mod cmd=add,table=0,prio=11,buffer=" << msg->buffer_id
147 <<
" in_port=1,eth_type=0x0800 "
148 <<
"write:set_field=tunn_id:" << tunnelIdStr <<
",output=2";
152 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
155 else if (inPort == 2)
168 std::ostringstream
cmd;
169 cmd <<
"flow-mod cmd=add,table=0,prio=10,buffer=" << msg->buffer_id
170 <<
" in_port=2,eth_type=0x0800,tunn_id=0xFFFF "
171 <<
"write:set_field=eth_dst:" << dstMac <<
",output=1";
175 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
179 NS_LOG_ERROR(
"This packet in was not supposed to be sent here.");
181 else if (reason == OFPR_ACTION)
185 tlv = oxm_match_lookup(OXM_OF_ETH_TYPE, (
struct ofl_match*)msg->match);
186 memcpy(ðType, tlv->value, OXM_LENGTH(OXM_OF_ETH_TYPE));
195 NS_LOG_WARN(
"Ignoring packet sent to controller.");
198 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
207 IpMacMap_t::iterator ret;
211 NS_LOG_INFO(
"Found ARP entry: " << ip <<
" - " << ret->second);
223 DpPortIpMap_t::iterator ret;
227 NS_LOG_INFO(
"Found endpoint entry: " << dpId <<
"/" << portNo <<
" - " << ret->second);
230 NS_ABORT_MSG(
"No tunnel endpoint information for this datapath + port.");
240 struct ofl_match_tlv* tlv;
244 tlv = oxm_match_lookup(OXM_OF_ARP_OP, (
struct ofl_match*)msg->match);
245 memcpy(&arpOp, tlv->value, OXM_LENGTH(OXM_OF_ARP_OP));
249 tlv = oxm_match_lookup(OXM_OF_IN_PORT, (
struct ofl_match*)msg->match);
250 memcpy(&inPort, tlv->value, OXM_LENGTH(OXM_OF_IN_PORT));
260 NS_LOG_INFO(
"Got ARP request for IP " << dstIp <<
", resolved to " << dstMac);
268 tlv = oxm_match_lookup(OXM_OF_ARP_SHA, (
struct ofl_match*)msg->match);
273 uint8_t pktData[pkt->
GetSize()];
277 struct ofl_msg_packet_out reply;
278 reply.header.type = OFPT_PACKET_OUT;
279 reply.buffer_id = OFP_NO_BUFFER;
280 reply.in_port = inPort;
281 reply.data_length = pkt->
GetSize();
282 reply.data = &pktData[0];
285 struct ofl_action_output*
action =
286 (
struct ofl_action_output*)xmalloc(
sizeof(
struct ofl_action_output));
287 action->header.type = OFPAT_OUTPUT;
288 action->port = OFPP_IN_PORT;
291 reply.actions_num = 1;
292 reply.actions = (
struct ofl_action_header**)&
action;
294 int error =
SendToSwitch(swtch, (
struct ofl_msg_header*)&reply, xid);
298 NS_LOG_ERROR(
"Error sending packet out with ARP request.");
303 NS_LOG_WARN(
"Not supposed to get ARP reply. Ignoring...");
307 ofl_msg_free((
struct ofl_msg_header*)msg,
nullptr);
316 case static_cast<uint32_t
>(OXM_OF_ARP_SPA):
317 case static_cast<uint32_t
>(OXM_OF_ARP_TPA):
318 case static_cast<uint32_t
>(OXM_OF_IPV4_DST):
319 case static_cast<uint32_t
>(OXM_OF_IPV4_SRC): {
321 int size = OXM_LENGTH(oxm_of);
322 struct ofl_match_tlv* tlv = oxm_match_lookup(oxm_of, match);
323 memcpy(&ip, tlv->value, size);
343 arp.
SetReply(srcMac, srcIp, dstMac, dstIp);
353 memset(buffer, 0, 46);
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
Packet trailer for Ethernet.
void EnableFcs(bool enable)
Enable or disable FCS checking and calculations.
void CalcFcs(Ptr< const Packet > p)
Updates the Fcs Field to the correct FCS.
Ipv4 addresses are stored in host order in this class.
uint32_t Get() const
Get the host-order 32-bit IP address.
void CopyFrom(const uint8_t buffer[6])
static bool ChecksumEnabled()
OpenFlow 1.3 controller base class that can handle a collection of OpenFlow switches and provides the...
int SendToSwitch(Ptr< const RemoteSwitch > swtch, struct ofl_msg_header *msg, uint32_t xid=0)
Send a OFLib message to a registered 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.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
void AddHeader(const Header &header)
Add header to this packet.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Smart pointer class similar to boost::intrusive_ptr.
This controller is responsible for installing the forwarding rules on the switches.
ofl_err HandleArpPacketIn(struct ofl_msg_packet_in *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid)
Handle packet-in messages sent from switch with ARP message.
TunnelController()
Default constructor.
IpMacMap_t m_arpTable
ARP resolution table.
Ipv4Address ExtractIpv4Address(uint32_t oxm_of, struct ofl_match *match)
Extract an IPv4 address from packet match.
static TypeId GetTypeId()
Register this type.
void SaveTunnelEndpoint(uint64_t dpId, uint32_t portNo, Ipv4Address ipAddr)
Save the pair datapath ID + port no / IP address in tunnel endpoint table.
~TunnelController() override
Dummy destructor, see DoDispose.
void DoDispose() override
Destructor implementation.
Ipv4Address GetTunnelEndpoint(uint64_t dpId, uint32_t portNo)
Perform tunnel endpoint resolution.
Ptr< Packet > CreateArpReply(Mac48Address srcMac, Ipv4Address srcIp, Mac48Address dstMac, Ipv4Address dstIp)
Create a Packet with an ARP reply, encapsulated inside of an Ethernet frame (with header and trailer.
DpPortIpMap_t m_endpointTable
Tunnel endpoint resolution table.
Mac48Address GetArpEntry(Ipv4Address ip)
Perform ARP resolution.
ofl_err HandlePacketIn(struct ofl_msg_packet_in *msg, Ptr< const RemoteSwitch > swtch, uint32_t xid) override
Handle a packet in message sent by the switch to this controller.
std::pair< uint64_t, uint32_t > DpPortPair_t
A pair identifying OpenFlow datapath id and port number.
void SaveArpEntry(Ipv4Address ipAddr, Mac48Address macAddr)
Save the pair IP / MAC address in ARP table.
void HandshakeSuccessful(Ptr< const RemoteSwitch > swtch) override
Function invoked after a successfully handshake procedure between this controller and a remote switch...
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#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_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.
Every class exported by the ns3 library is enclosed in the ns3 namespace.