20 #include "ns3/tcp-l4-protocol.h"
21 #include "ns3/udp-l4-protocol.h"
38 uint8_t ea[ETH_ADDR_LEN];
40 return eth_addr_to_uint64(ea);
46 return "The ns-3 team";
58 return "Simulated OpenFlow Switch";
71 TypeId(
"ns3::OpenFlowSwitchNetDevice")
73 .SetGroupName(
"Openflow")
76 "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for "
77 "OpenFlow compatibility.",
80 MakeUintegerChecker<uint64_t>())
81 .AddAttribute(
"FlowTableLookupDelay",
82 "A real switch will have an overhead for looking up in the flow table. "
83 "For the default, we simulate a standard TCAM on an FPGA.",
87 .AddAttribute(
"Flags",
89 "Flags to turn different functionality on/off, such as whether to inform "
90 "the controller when a flow expires, or how to handle fragments.",
94 MakeUintegerChecker<uint16_t>())
95 .AddAttribute(
"FlowTableMissSendLength",
97 "When forwarding a packet the switch didn't match up to the controller, "
98 "it can be more efficient to forward only the first x bytes.",
101 MakeUintegerChecker<uint16_t>());
112 m_channel = CreateObject<BridgeChannel>();
123 NS_LOG_ERROR(
"Not enough memory to create the flow table.");
176 NS_FATAL_ERROR(
"Device does not support eui 48 addresses: cannot be added to switch.");
178 if (!switchPort->SupportsSendFrom())
180 NS_FATAL_ERROR(
"Device does not support SendFrom: cannot be added to switch.");
187 if (
m_ports.size() < DP_MAX_PORTS)
197 NS_LOG_DEBUG(
"RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
203 m_channel->AddChannel(switchPort->GetChannel());
325 if (out_port != OFPP_CONTROLLER)
327 OutputPort(packet_uid, in_port, out_port, ignore_no_fwd);
346 uint16_t protocolNumber)
354 data.packet = packet;
355 data.buffer = buffer;
356 data.protocolNumber = protocolNumber;
419 size_t actions_len = ntohs(ovpm->header.length) -
sizeof *ovpm;
420 unsigned int vport = ntohl(ovpm->vport);
421 unsigned int parent_port = ntohl(ovpm->parent_port);
424 vport_table_entry* vpe = vport_table_lookup(&
m_vportTable, vport);
428 SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
434 if (v_code != ACT_VALIDATION_OK)
436 SendErrorMsg(OFPET_BAD_ACTION, v_code, ovpm, ntohs(ovpm->header.length));
440 vpe = vport_table_entry_alloc(actions_len);
443 vpe->parent_port = parent_port;
444 if (vport < OFPP_VP_START || vport > OFPP_VP_END)
446 NS_LOG_ERROR(
"port " << vport <<
" is not in the virtual port range (" << OFPP_VP_START
447 <<
"-" << OFPP_VP_END <<
")");
448 SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
449 free_vport_table_entry(vpe);
453 vpe->port_acts->actions_len = actions_len;
454 memcpy(vpe->port_acts->actions, ovpm->actions, actions_len);
456 int error = insert_vport_table_entry(&
m_vportTable, vpe);
459 NS_LOG_ERROR(
"could not insert port table entry for port " << vport);
472 NS_LOG_INFO(
"Creating Openflow buffer from packet.");
480 const int headroom = 128 + 2;
481 const int hard_header = VLAN_ETH_HEADER_LEN;
482 ofpbuf* buffer = ofpbuf_new(headroom + hard_header + mtu);
483 buffer->data = (
char*)buffer->data + headroom + hard_header;
490 buffer->l2 =
new eth_header;
491 eth_header* eth_h = (eth_header*)buffer->l2;
492 dst.
CopyTo(eth_h->eth_dst);
493 src.
CopyTo(eth_h->eth_src);
496 eth_h->eth_type = htons(ETH_TYPE_ARP);
500 eth_h->eth_type = htons(ETH_TYPE_IP);
508 l2_length = ETH_HEADER_LEN;
517 buffer->l3 =
new ip_header;
518 ip_header* ip_h = (ip_header*)buffer->l3;
519 ip_h->ip_ihl_ver = IP_IHL_VER(5, IP_VERSION);
520 ip_h->ip_tos = ip_hd.
GetTos();
521 ip_h->ip_tot_len = packet->
GetSize();
524 ip_h->ip_ttl = ip_hd.
GetTtl();
528 ip_h->ip_csum = csum(&ip_h,
sizeof ip_h);
532 l3_length = IP_HEADER_LEN;
542 buffer->l3 =
new arp_eth_header;
543 arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
544 arp_h->ar_hrd = ARP_HRD_ETHERNET;
545 arp_h->ar_pro = ARP_PRO_IP;
546 arp_h->ar_op = arp_hd.
m_type;
552 arp_h->ar_hln =
sizeof arp_h->ar_tha;
553 arp_h->ar_pln =
sizeof arp_h->ar_tpa;
557 l3_length = ARP_ETH_HEADER_LEN;
563 ip_header* ip_h = (ip_header*)buffer->l3;
569 buffer->l4 =
new tcp_header;
570 tcp_header* tcp_h = (tcp_header*)buffer->l4;
575 tcp_h->tcp_ctl = TCP_FLAGS(tcp_hd.
GetFlags());
578 tcp_h->tcp_csum = csum(&tcp_h,
sizeof tcp_h);
582 l4_length = TCP_HEADER_LEN;
590 buffer->l4 =
new udp_header;
591 udp_header* udp_h = (udp_header*)buffer->l4;
594 udp_h->udp_len = htons(UDP_HEADER_LEN + packet->
GetSize());
596 ip_header* ip_h = (ip_header*)buffer->l3;
597 uint32_t udp_csum = csum_add32(0, ip_h->ip_src);
598 udp_csum = csum_add32(udp_csum, ip_h->ip_dst);
599 udp_csum = csum_add16(udp_csum, IP_TYPE_UDP << 8);
600 udp_csum = csum_add16(udp_csum, udp_h->udp_len);
601 udp_csum = csum_continue(udp_csum, udp_h,
sizeof udp_h);
602 udp_h->udp_csum = csum_finish(
603 csum_continue(udp_csum, buffer->data, buffer->size));
607 l4_length = UDP_HEADER_LEN;
617 ofpbuf_push(buffer, buffer->l4, l4_length);
618 delete (tcp_header*)buffer->l4;
622 ofpbuf_push(buffer, buffer->l3, l3_length);
623 delete (ip_header*)buffer->l3;
627 ofpbuf_push(buffer, buffer->l2, l2_length);
628 delete (eth_header*)buffer->l2;
643 NS_LOG_INFO(
"--------------------------------------------");
655 for (
size_t i = 0; i <
m_ports.size(); i++)
657 if (
m_ports[i].netdev == netdev)
683 m_ports[i].rx_bytes += buffer->size;
684 data.buffer = buffer;
687 data.protocolNumber = protocol;
706 for (
size_t i = 0; i <
m_ports.size(); i++)
715 List deleted = LIST_INITIALIZER(&deleted);
718 chain_timeout(
m_chain, &deleted);
719 LIST_FOR_EACH_SAFE(
f, n, sw_flow, node, &deleted)
721 std::ostringstream str;
723 for (
int i = 0; i < 6; i++)
725 str << (i != 0 ?
":" :
"") << std::hex <<
f->key.flow.dl_src[i] / 16
726 <<
f->key.flow.dl_src[i] % 16;
729 for (
int i = 0; i < 6; i++)
731 str << (i != 0 ?
":" :
"") << std::hex <<
f->key.flow.dl_dst[i] / 16
732 <<
f->key.flow.dl_dst[i] % 16;
738 list_remove(&
f->node);
753 for (
size_t i = 0; i <
m_ports.size(); i++)
755 if (i == (
unsigned)in_port)
759 if (flood &&
m_ports[i].config & OFPPC_NO_FLOOD)
765 OutputPort(packet_uid, in_port, prev_port,
false);
771 OutputPort(packet_uid, in_port, prev_port,
false);
780 if (out_port >= 0 && out_port < DP_MAX_PORTS)
786 size_t bufsize =
data.buffer->size;
787 NS_LOG_INFO(
"Sending packet " <<
data.packet->GetUid() <<
" over port " << out_port);
812 if (out_port == OFPP_FLOOD)
816 else if (out_port == OFPP_ALL)
820 else if (out_port == OFPP_CONTROLLER)
824 else if (out_port == OFPP_IN_PORT)
828 else if (out_port == OFPP_TABLE)
832 else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
835 NS_LOG_INFO(
"packet sent to virtual port " << out_port);
836 if (in_port < DP_MAX_PORTS)
845 else if (in_port == out_port)
858 return make_openflow_xid(openflow_len,
type, 0, bufferp);
866 update_openflow_length(buffer);
878 ofpbuf* buffer =
m_packetData.find(packet_uid)->second.buffer;
879 size_t total_len = buffer->size;
881 buffer->size > max_len)
883 buffer->size = max_len;
886 ofp_packet_in* opi = (ofp_packet_in*)ofpbuf_push_uninit(buffer, offsetof(ofp_packet_in,
data));
887 opi->header.version = OFP_VERSION;
888 opi->header.type = OFPT_PACKET_IN;
889 opi->header.length = htons(buffer->size);
890 opi->header.xid = htonl(0);
891 opi->buffer_id = htonl(packet_uid);
892 opi->total_len = htons(total_len);
893 opi->in_port = htons(in_port);
894 opi->reason = reason;
904 std::ostringstream nm;
906 strncpy((
char*)desc->name, nm.str().c_str(),
sizeof desc->name);
908 p.
netdev->GetAddress().CopyTo(desc->hw_addr);
909 desc->config = htonl(p.
config);
910 desc->state = htonl(p.
state);
915 desc->advertised = 0;
923 ofp_switch_features* ofr =
924 (ofp_switch_features*)
MakeOpenflowReply(
sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
925 ofr->datapath_id = htonll(
m_id);
926 ofr->n_tables =
m_chain->n_tables;
931 for (
size_t i = 0; i <
m_ports.size(); i++)
933 ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros(buffer,
sizeof *opp);
944 ofp_vport_table_features* ovtfr =
946 OFPT_VPORT_TABLE_FEATURES_REPLY,
950 ovtfr->max_chain_depth = htons(-1);
951 ovtfr->mixed_chaining =
true;
958 uint32_t orig_config = p.
config;
959 uint32_t orig_state = p.
state;
962 p.
config &= ~OFPPC_PORT_DOWN;
966 p.
state &= ~OFPPS_LINK_DOWN;
970 p.
state |= OFPPS_LINK_DOWN;
973 return ((orig_config != p.
config) || (orig_state != p.
state));
980 ofp_port_status* ops =
982 ops->reason = status;
983 memset(ops->pad, 0,
sizeof ops->pad);
987 ofpbuf_delete(buffer);
994 ofp_flow_expired* ofe =
996 flow_fill_match(&ofe->match, &flow->key);
998 ofe->priority = htons(flow->priority);
999 ofe->reason = reason;
1000 memset(ofe->pad, 0,
sizeof ofe->pad);
1002 ofe->duration = htonl(time_now() - flow->created);
1003 memset(ofe->pad2, 0,
sizeof ofe->pad2);
1004 ofe->packet_count = htonll(flow->packet_count);
1005 ofe->byte_count = htonll(flow->byte_count);
1013 ofp_error_msg* oem = (ofp_error_msg*)
MakeOpenflowReply(
sizeof(*oem) + len, OFPT_ERROR, &buffer);
1014 oem->type = htons(
type);
1015 oem->code = htons(code);
1016 memcpy(oem->data,
data, len);
1023 uint32_t packet_uid,
1025 bool send_to_controller)
1027 sw_flow* flow = chain_lookup(
m_chain, &key);
1031 flow_used(flow, buffer);
1036 flow->sf_acts->actions,
1037 flow->sf_acts->actions_len,
1044 if (send_to_controller)
1053 ofpbuf_delete(buffer);
1060 ofpbuf* buffer =
data.buffer;
1066 if (flow_extract(buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) &&
1067 (
m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1069 ofpbuf_delete(buffer);
1077 mpls_h.value = ntohl(*((uint32_t*)buffer->l2_5));
1078 if (mpls_h.ttl == 1)
1093 if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
1094 config & (!eth_addr_equals(key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV
1095 : OFPPC_NO_RECV_STP))
1109 send_to_controller);
1115 ofpbuf* buffer =
m_packetData.find(packet_uid)->second.buffer;
1121 if (flow_extract(buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) &&
1122 (
m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1128 vport_table_entry* vpe = vport_table_lookup(&
m_vportTable, vport);
1140 vpe->port_acts->actions,
1141 vpe->port_acts->actions_len);
1142 vport_used(vpe, buffer);
1143 if (!vpe->parent_port_ptr)
1147 if (vpe->parent_port <=
1162 vpe = vpe->parent_port_ptr;
1171 ofp_port_mod* opm = (ofp_port_mod*)msg;
1173 int port = opm->port_no;
1174 if (
port < DP_MAX_PORTS)
1181 if (p.
netdev->GetAddress() != hw_addr)
1188 uint32_t config_mask = ntohl(opm->mask);
1189 p.
config &= ~config_mask;
1190 p.
config |= ntohl(opm->config) & config_mask;
1193 if (opm->mask & htonl(OFPPC_PORT_DOWN))
1195 if ((opm->config & htonl(OFPPC_PORT_DOWN)) && (p.
config & OFPPC_PORT_DOWN) == 0)
1197 p.
config |= OFPPC_PORT_DOWN;
1200 else if ((opm->config & htonl(OFPPC_PORT_DOWN)) == 0 && (p.
config & OFPPC_PORT_DOWN))
1202 p.
config &= ~OFPPC_PORT_DOWN;
1229 ofp_switch_config* osc =
1230 (ofp_switch_config*)
MakeOpenflowReply(
sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
1240 const ofp_switch_config* osc = (ofp_switch_config*)msg;
1242 int n_flags = ntohs(osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
1243 if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL &&
1244 (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
1246 n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1257 const ofp_packet_out* opo = (ofp_packet_out*)msg;
1259 size_t actions_len = ntohs(opo->actions_len);
1261 if (actions_len > (ntohs(opo->header.length) -
sizeof *opo))
1263 NS_LOG_DEBUG(
"message too short for number of actions");
1267 if (ntohl(opo->buffer_id) == (uint32_t)-1)
1270 int data_len = ntohs(opo->header.length) -
sizeof *opo - actions_len;
1271 buffer = ofpbuf_new(data_len);
1272 ofpbuf_put(buffer, (uint8_t*)opo->actions + actions_len, data_len);
1284 flow_extract(buffer, ntohs(opo->in_port), &key.flow);
1287 if (v_code != ACT_VALIDATION_OK)
1289 SendErrorMsg(OFPET_BAD_ACTION, v_code, msg, ntohs(opo->header.length));
1290 ofpbuf_delete(buffer);
1302 const ofp_vport_mod* ovpm = (ofp_vport_mod*)msg;
1304 uint16_t command = ntohs(ovpm->command);
1305 if (command == OFPVP_ADD)
1309 else if (command == OFPVP_DELETE)
1311 if (remove_vport_table_entry(&
m_vportTable, ntohl(ovpm->vport)))
1314 OFPET_VPORT_MOD_FAILED,
1316 ntohs(ovpm->header.length));
1326 size_t actions_len = ntohs(ofm->header.length) -
sizeof *ofm;
1329 sw_flow* flow = flow_alloc(actions_len);
1332 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1339 flow_extract_match(&flow->key, &ofm->match);
1342 if (v_code != ACT_VALIDATION_OK)
1344 SendErrorMsg(OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1346 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1354 flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
1355 flow->idle_timeout = ntohs(ofm->idle_timeout);
1356 flow->hard_timeout = ntohs(ofm->hard_timeout);
1357 flow->used = flow->created = time_now();
1358 flow->sf_acts->actions_len = actions_len;
1359 flow->byte_count = 0;
1360 flow->packet_count = 0;
1361 memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
1364 int error = chain_insert(
m_chain, flow);
1367 if (error == -ENOBUFS)
1370 OFPFMFC_ALL_TABLES_FULL,
1372 ntohs(ofm->header.length));
1375 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1389 flow_used(flow, buffer);
1390 flow_extract(buffer,
1391 ntohs(ofm->match.in_port),
1400 ofpbuf_delete(buffer);
1414 flow_extract_match(&key, &ofm->match);
1416 size_t actions_len = ntohs(ofm->header.length) -
sizeof *ofm;
1419 if (v_code != ACT_VALIDATION_OK)
1421 SendErrorMsg((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1422 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1429 uint16_t priority = key.wildcards ? ntohs(ofm->priority) : -1;
1430 int strict = (ofm->command == htons(OFPFC_MODIFY_STRICT)) ? 1 : 0;
1431 chain_modify(
m_chain, &key, priority, strict, ofm->actions, actions_len);
1438 sw_flow_key skb_key;
1439 flow_extract(buffer,
1440 ntohs(ofm->match.in_port),
1449 ofpbuf_delete(buffer);
1463 const ofp_flow_mod* ofm = (ofp_flow_mod*)msg;
1464 uint16_t command = ntohs(ofm->command);
1466 if (command == OFPFC_ADD)
1470 else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1474 else if (command == OFPFC_DELETE)
1477 flow_extract_match(&key, &ofm->match);
1478 return chain_delete(
m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1480 else if (command == OFPFC_DELETE_STRICT)
1484 flow_extract_match(&key, &ofm->match);
1485 priority = key.wildcards ? ntohs(ofm->priority) : -1;
1486 return chain_delete(
m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
1497 ofp_stats_reply* osr;
1506 osr = (ofp_stats_reply*)
MakeOpenflowReply(
sizeof *osr, OFPT_STATS_REPLY, &buffer);
1507 osr->type = htons(cb->
s->
type);
1520 osr = (ofp_stats_reply*)ofpbuf_at_assert(buffer, 0,
sizeof *osr);
1521 osr->flags = ntohs(OFPSF_REPLY_MORE);
1548 const ofp_stats_request* rq = (ofp_stats_request*)oh;
1549 size_t rq_len = ntohs(rq->header.length);
1550 int type = ntohs(rq->type);
1551 int body_len = rq_len - offsetof(ofp_stats_request, body);
1561 cb.
rq = (ofp_stats_request*)xmemdup(rq, rq_len);
1571 NS_LOG_WARN(
"failed initialization of stats request type " <<
type <<
": "
1585 "Switch needs to be registered to a controller in order to start the stats reply.");
1607 ofp_header* oh = (ofp_header*)msg;
1608 if (ntohs(oh->length) > length)
1612 assert(oh->version == OFP_VERSION);
1619 case OFPT_FEATURES_REQUEST:
1622 case OFPT_GET_CONFIG_REQUEST:
1625 case OFPT_SET_CONFIG:
1626 error = length <
sizeof(ofp_switch_config) ? -EFAULT :
ReceiveSetConfig(msg);
1628 case OFPT_PACKET_OUT:
1632 error = length <
sizeof(ofp_flow_mod) ? -EFAULT :
ReceiveFlow(msg);
1635 error = length <
sizeof(ofp_port_mod) ? -EFAULT :
ReceivePortMod(msg);
1637 case OFPT_STATS_REQUEST:
1640 case OFPT_ECHO_REQUEST:
1643 case OFPT_ECHO_REPLY:
1646 case OFPT_VPORT_MOD:
1647 error = length <
sizeof(ofp_vport_mod) ? -EFAULT :
ReceiveVPortMod(msg);
1649 case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1654 (ofp_bad_request_code)OFPBRC_BAD_TYPE,
1690 for (
size_t i = 0; i <
m_ports.size(); i++)
double f(double x, void *params)
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.
uint32_t Get() const
Get the host-order 32-bit IP address.
static const uint16_t PROT_NUMBER
Protocol number (0x0800)
Describes an IPv6 address.
static Mac48Address GetMulticast(Ipv4Address address)
static bool IsMatchingType(const Address &address)
void CopyFrom(const uint8_t buffer[6])
static Mac48Address ConvertFrom(const Address &address)
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)
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
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.
Ptr< Packet > Copy() const
performs a COW copy of the packet.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
uint64_t GetUid() const
Returns the packet's Uid.
Smart pointer class similar to boost::intrusive_ptr.
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
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 const uint8_t PROT_NUMBER
protocol number (0x6)
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.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static const uint8_t PROT_NUMBER
protocol number (0x11)
Hold an unsigned integer type.
void DoCleanup(void *state)
Cleans any state created by the init or dump functions.
int DoDump(Ptr< OpenFlowSwitchNetDevice > swtch, void *state, ofpbuf *buffer)
Appends statistics for OpenFlowSwitchNetDevice to 'buffer'.
int DoInit(const void *body, int body_len, void **state)
Prepares to dump some kind of statistics on the connected OpenFlowSwitchNetDevice.
ofp_stats_types type
Status type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#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.
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 AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
static uint64_t GenerateId()
Generate an ID.
void discard_buffer(uint32_t id)
ofpbuf * retrieve_buffer(uint32_t id)
#define OFP_SUPPORTED_CAPABILITIES
uint32_t save_buffer(ofpbuf *)
#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.
ofp_stats_request * rq
Current stats request.
Stats * s
Handler of the stats request.
void * state
Stats request state data.
Ptr< OpenFlowSwitchNetDevice > swtch
The switch that we're requesting data from.
bool done
Whether we are done requesting stats.