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.
AttributeValue implementation for Time.
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,...
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Ptr< const AttributeChecker > MakeUintegerChecker()
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#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.
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...
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.
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.