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;
515 if (packet->PeekHeader(ip_hd))
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);
530 packet->RemoveHeader(ip_hd);
532 l3_length = IP_HEADER_LEN;
540 if (packet->PeekHeader(arp_hd))
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;
555 packet->RemoveHeader(arp_hd);
557 l3_length = ARP_ETH_HEADER_LEN;
563 ip_header* ip_h = (ip_header*)buffer->l3;
567 if (packet->PeekHeader(tcp_hd))
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);
580 packet->RemoveHeader(tcp_hd);
582 l4_length = TCP_HEADER_LEN;
588 if (packet->PeekHeader(udp_hd))
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));
605 packet->RemoveHeader(udp_hd);
607 l4_length = UDP_HEADER_LEN;
613 packet->CopyData((uint8_t*)buffer->data, packet->GetSize());
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)
678 data.packet = packet->Copy();
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;
880 if (packet_uid != std::numeric_limits<uint32_t>::max() && max_len != 0 &&
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;
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);
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)
1383 if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
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);
1433 if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
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)
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 AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
#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.
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.