9#include "ns3/tcp-l4-protocol.h"
10#include "ns3/udp-l4-protocol.h"
27 uint8_t ea[ETH_ADDR_LEN];
29 return eth_addr_to_uint64(ea);
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.");
167 if (!switchPort->SupportsSendFrom())
169 NS_FATAL_ERROR(
"Device does not support SendFrom: cannot be added to switch.");
176 if (
m_ports.size() < DP_MAX_PORTS)
186 NS_LOG_DEBUG(
"RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
192 m_channel->AddChannel(switchPort->GetChannel());
314 if (out_port != OFPP_CONTROLLER)
316 OutputPort(packet_uid, in_port, out_port, ignore_no_fwd);
335 uint16_t protocolNumber)
343 data.packet = packet;
344 data.buffer = buffer;
345 data.protocolNumber = protocolNumber;
408 size_t actions_len = ntohs(ovpm->header.length) -
sizeof *ovpm;
409 unsigned int vport = ntohl(ovpm->vport);
410 unsigned int parent_port = ntohl(ovpm->parent_port);
413 vport_table_entry* vpe = vport_table_lookup(&
m_vportTable, vport);
417 SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
423 if (v_code != ACT_VALIDATION_OK)
425 SendErrorMsg(OFPET_BAD_ACTION, v_code, ovpm, ntohs(ovpm->header.length));
429 vpe = vport_table_entry_alloc(actions_len);
432 vpe->parent_port = parent_port;
433 if (vport < OFPP_VP_START || vport > OFPP_VP_END)
435 NS_LOG_ERROR(
"port " << vport <<
" is not in the virtual port range (" << OFPP_VP_START
436 <<
"-" << OFPP_VP_END <<
")");
437 SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
438 free_vport_table_entry(vpe);
442 vpe->port_acts->actions_len = actions_len;
443 memcpy(vpe->port_acts->actions, ovpm->actions, actions_len);
445 int error = insert_vport_table_entry(&
m_vportTable, vpe);
448 NS_LOG_ERROR(
"could not insert port table entry for port " << vport);
461 NS_LOG_INFO(
"Creating Openflow buffer from packet.");
469 const int headroom = 128 + 2;
470 const int hard_header = VLAN_ETH_HEADER_LEN;
471 ofpbuf* buffer = ofpbuf_new(headroom + hard_header + mtu);
472 buffer->data = (
char*)buffer->data + headroom + hard_header;
479 buffer->l2 =
new eth_header;
480 eth_header* eth_h = (eth_header*)buffer->l2;
481 dst.
CopyTo(eth_h->eth_dst);
482 src.
CopyTo(eth_h->eth_src);
485 eth_h->eth_type = htons(ETH_TYPE_ARP);
489 eth_h->eth_type = htons(ETH_TYPE_IP);
497 l2_length = ETH_HEADER_LEN;
504 if (packet->PeekHeader(ip_hd))
506 buffer->l3 =
new ip_header;
507 ip_header* ip_h = (ip_header*)buffer->l3;
508 ip_h->ip_ihl_ver = IP_IHL_VER(5, IP_VERSION);
509 ip_h->ip_tos = ip_hd.
GetTos();
510 ip_h->ip_tot_len = packet->GetSize();
513 ip_h->ip_ttl = ip_hd.
GetTtl();
517 ip_h->ip_csum = csum(&ip_h,
sizeof ip_h);
519 packet->RemoveHeader(ip_hd);
521 l3_length = IP_HEADER_LEN;
529 if (packet->PeekHeader(arp_hd))
531 buffer->l3 =
new arp_eth_header;
532 arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
533 arp_h->ar_hrd = ARP_HRD_ETHERNET;
534 arp_h->ar_pro = ARP_PRO_IP;
535 arp_h->ar_op = arp_hd.
m_type;
541 arp_h->ar_hln =
sizeof arp_h->ar_tha;
542 arp_h->ar_pln =
sizeof arp_h->ar_tpa;
544 packet->RemoveHeader(arp_hd);
546 l3_length = ARP_ETH_HEADER_LEN;
552 ip_header* ip_h = (ip_header*)buffer->l3;
556 if (packet->PeekHeader(tcp_hd))
558 buffer->l4 =
new tcp_header;
559 tcp_header* tcp_h = (tcp_header*)buffer->l4;
564 tcp_h->tcp_ctl = TCP_FLAGS(tcp_hd.
GetFlags());
567 tcp_h->tcp_csum = csum(&tcp_h,
sizeof tcp_h);
569 packet->RemoveHeader(tcp_hd);
571 l4_length = TCP_HEADER_LEN;
577 if (packet->PeekHeader(udp_hd))
579 buffer->l4 =
new udp_header;
580 udp_header* udp_h = (udp_header*)buffer->l4;
583 udp_h->udp_len = htons(UDP_HEADER_LEN + packet->GetSize());
585 ip_header* ip_h = (ip_header*)buffer->l3;
586 uint32_t udp_csum = csum_add32(0, ip_h->ip_src);
587 udp_csum = csum_add32(udp_csum, ip_h->ip_dst);
588 udp_csum = csum_add16(udp_csum, IP_TYPE_UDP << 8);
589 udp_csum = csum_add16(udp_csum, udp_h->udp_len);
590 udp_csum = csum_continue(udp_csum, udp_h,
sizeof udp_h);
591 udp_h->udp_csum = csum_finish(
592 csum_continue(udp_csum, buffer->data, buffer->size));
594 packet->RemoveHeader(udp_hd);
596 l4_length = UDP_HEADER_LEN;
602 packet->CopyData((uint8_t*)buffer->data, packet->GetSize());
606 ofpbuf_push(buffer, buffer->l4, l4_length);
607 delete (tcp_header*)buffer->l4;
611 ofpbuf_push(buffer, buffer->l3, l3_length);
612 delete (ip_header*)buffer->l3;
616 ofpbuf_push(buffer, buffer->l2, l2_length);
617 delete (eth_header*)buffer->l2;
632 NS_LOG_INFO(
"--------------------------------------------");
644 for (
size_t i = 0; i <
m_ports.size(); i++)
646 if (
m_ports[i].netdev == netdev)
667 data.packet = packet->Copy();
672 m_ports[i].rx_bytes += buffer->size;
673 data.buffer = buffer;
676 data.protocolNumber = protocol;
695 for (
size_t i = 0; i <
m_ports.size(); i++)
704 List deleted = LIST_INITIALIZER(&deleted);
707 chain_timeout(
m_chain, &deleted);
708 LIST_FOR_EACH_SAFE(f, n, sw_flow, node, &deleted)
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;
727 list_remove(&f->node);
742 for (
size_t i = 0; i <
m_ports.size(); i++)
744 if (i == (
unsigned)in_port)
748 if (flood &&
m_ports[i].config & OFPPC_NO_FLOOD)
754 OutputPort(packet_uid, in_port, prev_port,
false);
760 OutputPort(packet_uid, in_port, prev_port,
false);
769 if (out_port >= 0 && out_port < DP_MAX_PORTS)
775 size_t bufsize =
data.buffer->size;
776 NS_LOG_INFO(
"Sending packet " <<
data.packet->GetUid() <<
" over port " << out_port);
801 if (out_port == OFPP_FLOOD)
805 else if (out_port == OFPP_ALL)
809 else if (out_port == OFPP_CONTROLLER)
813 else if (out_port == OFPP_IN_PORT)
817 else if (out_port == OFPP_TABLE)
821 else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
824 NS_LOG_INFO(
"packet sent to virtual port " << out_port);
825 if (in_port < DP_MAX_PORTS)
834 else if (in_port == out_port)
847 return make_openflow_xid(openflow_len, type, 0, bufferp);
855 update_openflow_length(buffer);
867 ofpbuf* buffer =
m_packetData.find(packet_uid)->second.buffer;
868 size_t total_len = buffer->size;
869 if (packet_uid != std::numeric_limits<uint32_t>::max() && max_len != 0 &&
870 buffer->size > max_len)
872 buffer->size = max_len;
875 ofp_packet_in* opi = (ofp_packet_in*)ofpbuf_push_uninit(buffer, offsetof(ofp_packet_in,
data));
876 opi->header.version = OFP_VERSION;
877 opi->header.type = OFPT_PACKET_IN;
878 opi->header.length = htons(buffer->size);
879 opi->header.xid = htonl(0);
880 opi->buffer_id = htonl(packet_uid);
881 opi->total_len = htons(total_len);
882 opi->in_port = htons(in_port);
883 opi->reason = reason;
893 std::ostringstream nm;
895 strncpy((
char*)desc->name, nm.str().c_str(),
sizeof desc->name);
897 p.
netdev->GetAddress().CopyTo(desc->hw_addr);
898 desc->config = htonl(p.
config);
899 desc->state = htonl(p.
state);
904 desc->advertised = 0;
912 ofp_switch_features* ofr =
913 (ofp_switch_features*)
MakeOpenflowReply(
sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
914 ofr->datapath_id = htonll(
m_id);
915 ofr->n_tables =
m_chain->n_tables;
920 for (
size_t i = 0; i <
m_ports.size(); i++)
922 ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros(buffer,
sizeof *opp);
933 ofp_vport_table_features* ovtfr =
935 OFPT_VPORT_TABLE_FEATURES_REPLY,
939 ovtfr->max_chain_depth = htons(-1);
940 ovtfr->mixed_chaining =
true;
951 p.
config &= ~OFPPC_PORT_DOWN;
955 p.
state &= ~OFPPS_LINK_DOWN;
959 p.
state |= OFPPS_LINK_DOWN;
962 return ((orig_config != p.
config) || (orig_state != p.
state));
969 ofp_port_status* ops =
971 ops->reason = status;
972 memset(ops->pad, 0,
sizeof ops->pad);
976 ofpbuf_delete(buffer);
983 ofp_flow_expired* ofe =
985 flow_fill_match(&ofe->match, &flow->key);
987 ofe->priority = htons(flow->priority);
988 ofe->reason = reason;
989 memset(ofe->pad, 0,
sizeof ofe->pad);
991 ofe->duration = htonl(time_now() - flow->created);
992 memset(ofe->pad2, 0,
sizeof ofe->pad2);
993 ofe->packet_count = htonll(flow->packet_count);
994 ofe->byte_count = htonll(flow->byte_count);
1002 ofp_error_msg* oem = (ofp_error_msg*)
MakeOpenflowReply(
sizeof(*oem) + len, OFPT_ERROR, &buffer);
1003 oem->type = htons(type);
1004 oem->code = htons(code);
1005 memcpy(oem->data,
data, len);
1014 bool send_to_controller)
1016 sw_flow* flow = chain_lookup(
m_chain, &key);
1020 flow_used(flow, buffer);
1025 flow->sf_acts->actions,
1026 flow->sf_acts->actions_len,
1033 if (send_to_controller)
1042 ofpbuf_delete(buffer);
1049 ofpbuf* buffer =
data.buffer;
1055 if (flow_extract(buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) &&
1056 (
m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1058 ofpbuf_delete(buffer);
1066 mpls_h.value = ntohl(*((
uint32_t*)buffer->l2_5));
1067 if (mpls_h.ttl == 1)
1082 if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
1083 config & (!eth_addr_equals(key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV
1084 : OFPPC_NO_RECV_STP))
1098 send_to_controller);
1104 ofpbuf* buffer =
m_packetData.find(packet_uid)->second.buffer;
1110 if (flow_extract(buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) &&
1111 (
m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1117 vport_table_entry* vpe = vport_table_lookup(&
m_vportTable, vport);
1129 vpe->port_acts->actions,
1130 vpe->port_acts->actions_len);
1131 vport_used(vpe, buffer);
1132 if (!vpe->parent_port_ptr)
1136 if (vpe->parent_port <=
1151 vpe = vpe->parent_port_ptr;
1160 ofp_port_mod* opm = (ofp_port_mod*)msg;
1162 int port = opm->port_no;
1163 if (
port < DP_MAX_PORTS)
1170 if (p.
netdev->GetAddress() != hw_addr)
1177 uint32_t config_mask = ntohl(opm->mask);
1178 p.
config &= ~config_mask;
1179 p.
config |= ntohl(opm->config) & config_mask;
1182 if (opm->mask & htonl(OFPPC_PORT_DOWN))
1184 if ((opm->config & htonl(OFPPC_PORT_DOWN)) && (p.
config & OFPPC_PORT_DOWN) == 0)
1186 p.
config |= OFPPC_PORT_DOWN;
1189 else if ((opm->config & htonl(OFPPC_PORT_DOWN)) == 0 && (p.
config & OFPPC_PORT_DOWN))
1191 p.
config &= ~OFPPC_PORT_DOWN;
1218 ofp_switch_config* osc =
1219 (ofp_switch_config*)
MakeOpenflowReply(
sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
1229 const ofp_switch_config* osc = (ofp_switch_config*)msg;
1231 int n_flags = ntohs(osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
1232 if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL &&
1233 (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
1235 n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1246 const ofp_packet_out* opo = (ofp_packet_out*)msg;
1248 size_t actions_len = ntohs(opo->actions_len);
1250 if (actions_len > (ntohs(opo->header.length) -
sizeof *opo))
1252 NS_LOG_DEBUG(
"message too short for number of actions");
1256 if (ntohl(opo->buffer_id) == (
uint32_t)-1)
1259 int data_len = ntohs(opo->header.length) -
sizeof *opo - actions_len;
1260 buffer = ofpbuf_new(data_len);
1261 ofpbuf_put(buffer, (uint8_t*)opo->actions + actions_len, data_len);
1273 flow_extract(buffer, ntohs(opo->in_port), &key.flow);
1276 if (v_code != ACT_VALIDATION_OK)
1278 SendErrorMsg(OFPET_BAD_ACTION, v_code, msg, ntohs(opo->header.length));
1279 ofpbuf_delete(buffer);
1291 const ofp_vport_mod* ovpm = (ofp_vport_mod*)msg;
1293 uint16_t command = ntohs(ovpm->command);
1294 if (command == OFPVP_ADD)
1298 else if (command == OFPVP_DELETE)
1300 if (remove_vport_table_entry(&
m_vportTable, ntohl(ovpm->vport)))
1303 OFPET_VPORT_MOD_FAILED,
1305 ntohs(ovpm->header.length));
1315 size_t actions_len = ntohs(ofm->header.length) -
sizeof *ofm;
1318 sw_flow* flow = flow_alloc(actions_len);
1321 if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
1328 flow_extract_match(&flow->key, &ofm->match);
1331 if (v_code != ACT_VALIDATION_OK)
1333 SendErrorMsg(OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1335 if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
1343 flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
1344 flow->idle_timeout = ntohs(ofm->idle_timeout);
1345 flow->hard_timeout = ntohs(ofm->hard_timeout);
1346 flow->used = flow->created = time_now();
1347 flow->sf_acts->actions_len = actions_len;
1348 flow->byte_count = 0;
1349 flow->packet_count = 0;
1350 memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
1353 int error = chain_insert(
m_chain, flow);
1356 if (error == -ENOBUFS)
1359 OFPFMFC_ALL_TABLES_FULL,
1361 ntohs(ofm->header.length));
1364 if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
1372 if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
1378 flow_used(flow, buffer);
1379 flow_extract(buffer,
1380 ntohs(ofm->match.in_port),
1389 ofpbuf_delete(buffer);
1403 flow_extract_match(&key, &ofm->match);
1405 size_t actions_len = ntohs(ofm->header.length) -
sizeof *ofm;
1408 if (v_code != ACT_VALIDATION_OK)
1410 SendErrorMsg((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1411 if (ntohl(ofm->buffer_id) != (
uint32_t)-1)
1418 uint16_t priority = key.wildcards ? ntohs(ofm->priority) : -1;
1419 int strict = (ofm->command == htons(OFPFC_MODIFY_STRICT)) ? 1 : 0;
1420 chain_modify(
m_chain, &key, priority, strict, ofm->actions, actions_len);
1422 if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
1427 sw_flow_key skb_key;
1428 flow_extract(buffer,
1429 ntohs(ofm->match.in_port),
1438 ofpbuf_delete(buffer);
1452 const ofp_flow_mod* ofm = (ofp_flow_mod*)msg;
1453 uint16_t command = ntohs(ofm->command);
1455 if (command == OFPFC_ADD)
1459 else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1463 else if (command == OFPFC_DELETE)
1466 flow_extract_match(&key, &ofm->match);
1467 return chain_delete(
m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1469 else if (command == OFPFC_DELETE_STRICT)
1473 flow_extract_match(&key, &ofm->match);
1474 priority = key.wildcards ? ntohs(ofm->priority) : -1;
1475 return chain_delete(
m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
1486 ofp_stats_reply* osr;
1495 osr = (ofp_stats_reply*)
MakeOpenflowReply(
sizeof *osr, OFPT_STATS_REPLY, &buffer);
1496 osr->type = htons(cb->
s->
type);
1509 osr = (ofp_stats_reply*)ofpbuf_at_assert(buffer, 0,
sizeof *osr);
1510 osr->flags = ntohs(OFPSF_REPLY_MORE);
1537 const ofp_stats_request* rq = (ofp_stats_request*)oh;
1538 size_t rq_len = ntohs(rq->header.length);
1539 int type = ntohs(rq->type);
1540 int body_len = rq_len - offsetof(ofp_stats_request, body);
1550 cb.
rq = (ofp_stats_request*)xmemdup(rq, rq_len);
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.");
1596 ofp_header* oh = (ofp_header*)msg;
1597 if (ntohs(oh->length) > length)
1601 assert(oh->version == OFP_VERSION);
1608 case OFPT_FEATURES_REQUEST:
1611 case OFPT_GET_CONFIG_REQUEST:
1614 case OFPT_SET_CONFIG:
1615 error = length <
sizeof(ofp_switch_config) ? -EFAULT :
ReceiveSetConfig(msg);
1617 case OFPT_PACKET_OUT:
1621 error = length <
sizeof(ofp_flow_mod) ? -EFAULT :
ReceiveFlow(msg);
1624 error = length <
sizeof(ofp_port_mod) ? -EFAULT :
ReceivePortMod(msg);
1626 case OFPT_STATS_REQUEST:
1629 case OFPT_ECHO_REQUEST:
1632 case OFPT_ECHO_REPLY:
1635 case OFPT_VPORT_MOD:
1636 error = length <
sizeof(ofp_vport_mod) ? -EFAULT :
ReceiveVPortMod(msg);
1638 case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1643 (ofp_bad_request_code)OFPBRC_BAD_TYPE,
1679 for (
size_t i = 0; i <
m_ports.size(); i++)
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)
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.
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.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
#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 AttributeChecker > MakeUintegerChecker()
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.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
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.
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.