9#include "ns3/tcp-l4-protocol.h"
10#include "ns3/udp-l4-protocol.h"
35 return "The ns-3 team";
47 return "Simulated OpenFlow Switch";
60 TypeId(
"ns3::OpenFlowSwitchNetDevice")
62 .SetGroupName(
"Openflow")
65 "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for "
66 "OpenFlow compatibility.",
70 .AddAttribute(
"FlowTableLookupDelay",
71 "A real switch will have an overhead for looking up in the flow table. "
72 "For the default, we simulate a standard TCAM on an FPGA.",
76 .AddAttribute(
"Flags",
78 "Flags to turn different functionality on/off, such as whether to inform "
79 "the controller when a flow expires, or how to handle fragments.",
84 .AddAttribute(
"FlowTableMissSendLength",
86 "When forwarding a packet the switch didn't match up to the controller, "
87 "it can be more efficient to forward only the first x bytes.",
112 NS_LOG_ERROR(
"Not enough memory to create the flow table.");
165 NS_FATAL_ERROR(
"Device does not support eui 48 addresses: cannot be added to switch.");
169 NS_FATAL_ERROR(
"Device does not support SendFrom: cannot be added to switch.");
335 uint16_t protocolNumber)
344 data.buffer = buffer;
345 data.protocolNumber = protocolNumber;
461 NS_LOG_INFO(
"Creating Openflow buffer from packet.");
504 if (packet->PeekHeader(
ip_hd))
510 ip_h->ip_tot_len = packet->GetSize();
512 ip_h->ip_frag_off =
ip_hd.GetFragmentOffset();
519 packet->RemoveHeader(
ip_hd);
529 if (packet->PeekHeader(
arp_hd))
536 arp_hd.GetDestinationHardwareAddress().CopyTo(
538 arp_hd.GetSourceHardwareAddress().CopyTo(
arp_h->ar_sha);
539 arp_h->ar_tpa =
arp_hd.GetDestinationIpv4Address().Get();
540 arp_h->ar_spa =
arp_hd.GetSourceIpv4Address().Get();
544 packet->RemoveHeader(
arp_hd);
556 if (packet->PeekHeader(
tcp_hd))
562 tcp_h->tcp_seq =
tcp_hd.GetSequenceNumber().GetValue();
569 packet->RemoveHeader(
tcp_hd);
577 if (packet->PeekHeader(
udp_hd))
594 packet->RemoveHeader(
udp_hd);
602 packet->CopyData((uint8_t*)buffer->data, packet->GetSize());
632 NS_LOG_INFO(
"--------------------------------------------");
672 m_ports[
i].rx_bytes += buffer->size;
673 data.buffer = buffer;
676 data.protocolNumber = protocol;
710 std::ostringstream str;
712 for (
int i = 0;
i < 6;
i++)
714 str << (
i != 0 ?
":" :
"") << std::hex << f->key.flow.dl_src[
i] / 16
715 << f->key.flow.dl_src[
i] % 16;
718 for (
int i = 0;
i < 6;
i++)
720 str << (
i != 0 ?
":" :
"") << std::hex << f->key.flow.dl_dst[
i] / 16
721 << f->key.flow.dl_dst[
i] % 16;
878 opi->header.length =
htons(buffer->size);
883 opi->reason = reason;
893 std::ostringstream
nm;
904 desc->advertised = 0;
940 ovtfr->mixed_chaining =
true;
971 ops->reason = status;
988 ofe->reason = reason;
1025 flow->sf_acts->actions,
1026 flow->sf_acts->actions_len,
1129 vpe->port_acts->actions,
1130 vpe->port_acts->actions_len);
1132 if (!
vpe->parent_port_ptr)
1136 if (
vpe->parent_port <=
1151 vpe =
vpe->parent_port_ptr;
1252 NS_LOG_DEBUG(
"message too short for number of actions");
1348 flow->byte_count = 0;
1349 flow->packet_count = 0;
1372 if (
ntohl(
ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
1418 uint16_t priority = key.wildcards ?
ntohs(
ofm->priority) : -1;
1422 if (
ntohl(
ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
1474 priority = key.wildcards ?
ntohs(
ofm->priority) : -1;
1499 err =
cb->s->DoDump(
this,
cb->state, buffer);
1528 cb->s->DoCleanup(
cb->state);
1539 int type =
ntohs(rq->type);
1560 NS_LOG_WARN(
"failed initialization of stats request type " << type <<
": "
1574 "Switch needs to be registered to a controller in order to start the stats reply.");
1597 if (
ntohs(
oh->length) > length)
a polymophic address class
uint32_t CopyTo(uint8_t buffer[MAX_SIZE]) const
Copy the address bytes into a buffer.
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
bool IsNull() const
Check for null implementation.
Ipv4 addresses are stored in host order in this class.
static constexpr uint16_t PROT_NUMBER
Protocol number.
Describes an IPv6 address.
static Mac48Address GetMulticast(Ipv4Address address)
static bool IsMatchingType(const Address &address)
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Network layer to device interface.
PacketType
Packet types are used as they are in Linux.
@ PACKET_HOST
Packet addressed to us.
@ PACKET_OTHERHOST
Packet addressed to someone else.
@ PACKET_BROADCAST
Packet addressed to all.
@ PACKET_MULTICAST
Packet addressed to multicast group.
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
virtual void DoDispose()
Destructor implementation.
A net device that switches multiple LAN segments via an OpenFlow-compatible flow table.
int ReceiveStatsRequest(const void *msg)
void OutputControl(uint32_t packet_uid, int in_port, size_t max_len, int reason)
Sends a copy of the Packet to the controller.
Address GetBroadcast() const override
Mac48Address m_address
Address of this device.
ofi::Port GetSwitchPort(uint32_t n) const
bool IsBroadcast() const override
int ReceiveFeaturesRequest(const void *msg)
Ptr< Node > m_node
Node this device is installed on.
uint64_t m_id
Unique identifier for this switch, needed for OpenFlow.
uint32_t GetNSwitchPorts() const
int ReceiveGetConfigRequest(const void *msg)
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
OpenFlowSwitchNetDevice()
uint32_t GetIfIndex() const override
void * MakeOpenflowReply(size_t openflow_len, uint8_t type, ofpbuf **bufferp)
Generates an OpenFlow reply message based on the type.
Ptr< Channel > GetChannel() const override
void SendFlowExpired(sw_flow *flow, ofp_flow_expired_reason reason)
Send a reply to the controller that a specific flow has expired.
Ptr< BridgeChannel > m_channel
Collection of port channels into the Switch Channel.
void SetNode(Ptr< Node > node) override
int ReceiveVPortMod(const void *msg)
int ReceiveSetConfig(const void *msg)
bool IsLinkUp() const override
void SendPortStatus(ofi::Port p, uint8_t status)
Send a reply about a Port's status to the controller.
Ptr< Node > GetNode() const override
uint16_t m_mtu
Maximum Transmission Unit.
void DoOutput(uint32_t packet_uid, int in_port, size_t max_len, int out_port, bool ignore_no_fwd)
Called from the OpenFlow Interface to output the Packet on either a Port or the Controller.
void RunThroughFlowTable(uint32_t packet_uid, int port, bool send_to_controller=true)
Run the packet through the flow table.
int ReceiveEchoReply(const void *msg)
void ReceiveFromDevice(Ptr< NetDevice > netdev, Ptr< const Packet > packet, uint16_t protocol, const Address &src, const Address &dst, PacketType packetType)
Called when a packet is received on one of the switch's ports.
int ModFlow(const ofp_flow_mod *ofm)
Modify a flow.
static const char * GetManufacturerDescription()
vport_table_t m_vportTable
Virtual Port Table.
bool IsBridge() const override
Return true if the net device is acting as a bridge.
void SendFeaturesReply()
Send a reply about this OpenFlow switch's features to the controller.
void SendVPortTableFeatures()
Send a reply about this OpenFlow switch's virtual port table features to the controller.
Ports_t m_ports
Switch's ports.
Time m_lastExecute
Last time the periodic execution occurred.
int ForwardControlInput(const void *msg, size_t length)
The registered controller calls this method when sending a message to the switch.
bool SetMtu(const uint16_t mtu) override
int UpdatePortStatus(ofi::Port &p)
Update the port status field of the switch port.
uint16_t m_flags
Flags; configurable by the controller.
void SetAddress(Address address) override
Set the address of this interface.
uint16_t GetMtu() const override
void FlowTableLookup(sw_flow_key key, ofpbuf *buffer, uint32_t packet_uid, int port, bool send_to_controller)
Called by RunThroughFlowTable on a scheduled delay to account for the flow table lookup overhead.
int ReceivePacketOut(const void *msg)
void AddLinkChangeCallback(Callback< void > callback) override
uint16_t m_missSendLen
Flow Table Miss Send Length; configurable by the controller.
int ReceivePortMod(const void *msg)
bool NeedsArp() const override
bool SupportsSendFrom() const override
PacketData_t m_packetData
Packet data.
void SetReceiveCallback(NetDevice::ReceiveCallback cb) override
vport_table_t GetVPortTable()
void OutputPort(uint32_t packet_uid, int in_port, int out_port, bool ignore_no_fwd)
Seeks to send out a Packet over the provided output port.
void StatsDone(ofi::StatsDumpCallback *cb_)
Stats callback is done.
void SendErrorMsg(uint16_t type, uint16_t code, const void *data, size_t len)
If an error message happened during the controller's request, send it to the controller.
void OutputPacket(uint32_t packet_uid, int out_port)
Sends a copy of the Packet over the provided output port.
int AddSwitchPort(Ptr< NetDevice > switchPort)
Add a 'port' to a switch device.
Address GetAddress() const override
~OpenFlowSwitchNetDevice() override
int SendOpenflowBuffer(ofpbuf *buffer)
Send a message to the controller.
void SetController(Ptr< ofi::Controller > c)
Set up the Switch's controller connection.
NetDevice::PromiscReceiveCallback m_promiscRxCallback
Promiscuous Rx Callback.
void DoDispose() override
Destructor implementation.
int StatsDump(ofi::StatsDumpCallback *cb_)
Stats callback is ready for a dump.
Time m_lookupDelay
Flow Table Lookup Delay [overhead].
int ReceiveEchoRequest(const void *msg)
int AddFlow(const ofp_flow_mod *ofm)
Add a flow.
int RunThroughVPortTable(uint32_t packet_uid, int port, uint32_t vport)
Run the packet through the vport table.
static TypeId GetTypeId()
Register this type.
NetDevice::ReceiveCallback m_rxCallback
Rx Callback.
void SetIfIndex(const uint32_t index) override
void SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb) override
static const char * GetSoftwareDescription()
int OutputAll(uint32_t packet_uid, int in_port, bool flood)
Send packets out all the ports except the originating one.
int AddVPort(const ofp_vport_mod *ovpm)
Add a virtual port to a switch device.
static const char * GetHardwareDescription()
uint32_t m_ifIndex
Interface Index.
ofpbuf * BufferFromPacket(Ptr< const Packet > packet, Address src, Address dst, int mtu, uint16_t protocol)
Takes a packet and generates an OpenFlow buffer from it, loading the packet data as well as its heade...
Address GetMulticast(Ipv4Address multicastGroup) const override
Make and return a MAC multicast address using the provided multicast group.
Ptr< ofi::Controller > m_controller
Connection to controller.
static const char * GetSerialNumber()
void FillPortDesc(ofi::Port p, ofp_phy_port *desc)
Fill out a description of the switch port.
bool IsMulticast() const override
int ReceiveVPortTableFeaturesRequest(const void *msg)
sw_chain * m_chain
Flow Table; forwarding rules.
bool SendFrom(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber) override
int ReceiveFlow(const void *msg)
bool IsPointToPoint() const override
Return true if the net device is on a point-to-point link.
int GetSwitchPortIndex(ofi::Port p)
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
static constexpr uint8_t PROT_NUMBER
Protocol number (see http://www.iana.org/assignments/protocol-numbers)
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static constexpr uint8_t PROT_NUMBER
Protocol number (see http://www.iana.org/assignments/protocol-numbers)
Hold an unsigned integer type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
void ExecuteVPortActions(Ptr< OpenFlowSwitchNetDevice > swtch, uint64_t packet_uid, ofpbuf *buffer, sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Executes a list of virtual port table entry actions.
void ExecuteActions(Ptr< OpenFlowSwitchNetDevice > swtch, uint64_t packet_uid, ofpbuf *buffer, sw_flow_key *key, const ofp_action_header *actions, size_t actions_len, int ignore_no_fwd)
Executes a list of flow table actions.
uint16_t ValidateActions(const sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Validates a list of flow table actions.
uint16_t ValidateVPortActions(const ofp_action_header *actions, size_t actions_len)
Validates a list of virtual port table entry actions.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
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...
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
static uint64_t GenerateId()
Generate an ID.
void discard_buffer(uint32_t id)
#define OFP_SUPPORTED_CAPABILITIES
uint32_t save_buffer(ofpbuf *)
ofpbuf * retrieve_buffer(uint32_t id)
#define OFP_SUPPORTED_VPORT_TABLE_ACTIONS
#define OFP_SUPPORTED_ACTIONS
Ptr< NetDevice > netdev
NetDevice pointer.
unsigned long long int tx_packets
Counter of Tx packets.
unsigned long long int tx_bytes
Counter of Tx bytes.
uint32_t config
Some subset of OFPPC_* flags.
unsigned long long int tx_dropped
Counter of Tx dropped packets.
uint32_t state
Some subset of OFPPS_* flags.
Callback for a stats dump request.
bool done
Whether we are done requesting stats.