21 #include "ns3/tcp-l4-protocol.h"
22 #include "ns3/udp-l4-protocol.h"
34 return "The ns-3 team";
46 return "Simulated OpenFlow Switch";
58 uint8_t ea[ETH_ADDR_LEN];
60 return eth_addr_to_uint64(ea);
67 TypeId(
"ns3::OpenFlowSwitchNetDevice")
69 .SetGroupName(
"Openflow")
72 "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for "
73 "OpenFlow compatibility.",
74 UintegerValue(GenerateId()),
76 MakeUintegerChecker<uint64_t>())
77 .AddAttribute(
"FlowTableLookupDelay",
78 "A real switch will have an overhead for looking up in the flow table. "
79 "For the default, we simulate a standard TCAM on an FPGA.",
83 .AddAttribute(
"Flags",
85 "Flags to turn different functionality on/off, such as whether to inform "
86 "the controller when a flow expires, or how to handle fragments.",
90 MakeUintegerChecker<uint16_t>())
91 .AddAttribute(
"FlowTableMissSendLength",
93 "When forwarding a packet the switch didn't match up to the controller, "
94 "it can be more efficient to forward only the first x bytes.",
95 UintegerValue(OFP_DEFAULT_MISS_SEND_LEN),
97 MakeUintegerChecker<uint16_t>());
108 m_channel = CreateObject<BridgeChannel>();
113 m_controller =
nullptr;
116 m_chain = chain_create();
119 NS_LOG_ERROR(
"Not enough memory to create the flow table.");
122 m_ports.reserve(DP_MAX_PORTS);
123 vport_table_init(&m_vportTable);
126 OpenFlowSwitchNetDevice::~OpenFlowSwitchNetDevice()
132 OpenFlowSwitchNetDevice::DoDispose()
136 for (Ports_t::iterator b = m_ports.begin(), e = m_ports.end(); b != e; b++)
138 SendPortStatus(*b, OFPPR_DELETE);
143 m_controller =
nullptr;
145 chain_destroy(m_chain);
146 RBTreeDestroy(m_vportTable.table);
149 NetDevice::DoDispose();
153 OpenFlowSwitchNetDevice::SetController(Ptr<ofi::Controller> c)
162 m_controller->AddSwitch(
this);
166 OpenFlowSwitchNetDevice::AddSwitchPort(Ptr<NetDevice> switchPort)
170 if (!Mac48Address::IsMatchingType(switchPort->GetAddress()))
172 NS_FATAL_ERROR(
"Device does not support eui 48 addresses: cannot be added to switch.");
174 if (!switchPort->SupportsSendFrom())
176 NS_FATAL_ERROR(
"Device does not support SendFrom: cannot be added to switch.");
178 if (m_address == Mac48Address())
180 m_address = Mac48Address::ConvertFrom(switchPort->GetAddress());
183 if (m_ports.size() < DP_MAX_PORTS)
187 p.netdev = switchPort;
188 m_ports.push_back(p);
191 SendPortStatus(p, OFPPR_ADD);
193 NS_LOG_DEBUG(
"RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
194 m_node->RegisterProtocolHandler(
195 MakeCallback(&OpenFlowSwitchNetDevice::ReceiveFromDevice,
this),
199 m_channel->AddChannel(switchPort->GetChannel());
210 OpenFlowSwitchNetDevice::SetIfIndex(
const uint32_t index)
217 OpenFlowSwitchNetDevice::GetIfIndex()
const
224 OpenFlowSwitchNetDevice::GetChannel()
const
231 OpenFlowSwitchNetDevice::SetAddress(Address
address)
234 m_address = Mac48Address::ConvertFrom(
address);
238 OpenFlowSwitchNetDevice::GetAddress()
const
245 OpenFlowSwitchNetDevice::SetMtu(
const uint16_t mtu)
253 OpenFlowSwitchNetDevice::GetMtu()
const
260 OpenFlowSwitchNetDevice::IsLinkUp()
const
267 OpenFlowSwitchNetDevice::AddLinkChangeCallback(Callback<void> callback)
272 OpenFlowSwitchNetDevice::IsBroadcast()
const
279 OpenFlowSwitchNetDevice::GetBroadcast()
const
282 return Mac48Address(
"ff:ff:ff:ff:ff:ff");
293 OpenFlowSwitchNetDevice::GetMulticast(Ipv4Address multicastGroup)
const
296 Mac48Address multicast = Mac48Address::GetMulticast(multicastGroup);
301 OpenFlowSwitchNetDevice::IsPointToPoint()
const
308 OpenFlowSwitchNetDevice::IsBridge()
const
315 OpenFlowSwitchNetDevice::DoOutput(uint32_t packet_uid,
321 if (out_port != OFPP_CONTROLLER)
323 OutputPort(packet_uid, in_port, out_port, ignore_no_fwd);
327 OutputControl(packet_uid, in_port, max_len, OFPR_ACTION);
335 return SendFrom(packet, m_address, dest, protocolNumber);
339 OpenFlowSwitchNetDevice::SendFrom(Ptr<Packet> packet,
342 uint16_t protocolNumber)
346 ofpbuf* buffer =
BufferFromPacket(packet, src, dest, GetMtu(), protocolNumber);
349 ofi::SwitchPacketMetadata
data;
350 data.packet = packet;
351 data.buffer = buffer;
352 data.protocolNumber = protocolNumber;
353 data.src = Address(src);
354 data.dst = Address(dest);
355 m_packetData.insert(std::make_pair(packet_uid,
data));
357 RunThroughFlowTable(packet_uid, -1);
363 OpenFlowSwitchNetDevice::GetNode()
const
370 OpenFlowSwitchNetDevice::SetNode(Ptr<Node> node)
377 OpenFlowSwitchNetDevice::NeedsArp()
const
384 OpenFlowSwitchNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
391 OpenFlowSwitchNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
394 m_promiscRxCallback = cb;
398 OpenFlowSwitchNetDevice::SupportsSendFrom()
const
405 OpenFlowSwitchNetDevice::GetMulticast(Ipv6Address addr)
const
408 return Mac48Address::GetMulticast(addr);
413 OpenFlowSwitchNetDevice::AddVPort(
const ofp_vport_mod* ovpm)
415 size_t actions_len = ntohs(ovpm->header.length) -
sizeof *ovpm;
416 unsigned int vport = ntohl(ovpm->vport);
417 unsigned int parent_port = ntohl(ovpm->parent_port);
420 vport_table_entry* vpe = vport_table_lookup(&m_vportTable, vport);
424 SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
430 if (v_code != ACT_VALIDATION_OK)
432 SendErrorMsg(OFPET_BAD_ACTION, v_code, ovpm, ntohs(ovpm->header.length));
436 vpe = vport_table_entry_alloc(actions_len);
439 vpe->parent_port = parent_port;
440 if (vport < OFPP_VP_START || vport > OFPP_VP_END)
442 NS_LOG_ERROR(
"port " << vport <<
" is not in the virtual port range (" << OFPP_VP_START
443 <<
"-" << OFPP_VP_END <<
")");
444 SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
445 free_vport_table_entry(vpe);
449 vpe->port_acts->actions_len = actions_len;
450 memcpy(vpe->port_acts->actions, ovpm->actions, actions_len);
452 int error = insert_vport_table_entry(&m_vportTable, vpe);
455 NS_LOG_ERROR(
"could not insert port table entry for port " << vport);
468 NS_LOG_INFO(
"Creating Openflow buffer from packet.");
470 Ptr<Packet> packet = constPacket->Copy();
476 const int headroom = 128 + 2;
477 const int hard_header = VLAN_ETH_HEADER_LEN;
478 ofpbuf* buffer = ofpbuf_new(headroom + hard_header + mtu);
479 buffer->data = (
char*)buffer->data + headroom + hard_header;
486 buffer->l2 =
new eth_header;
487 eth_header* eth_h = (eth_header*)buffer->l2;
488 dst.CopyTo(eth_h->eth_dst);
489 src.CopyTo(eth_h->eth_src);
490 if (protocol == ArpL3Protocol::PROT_NUMBER)
492 eth_h->eth_type = htons(ETH_TYPE_ARP);
494 else if (protocol == Ipv4L3Protocol::PROT_NUMBER)
496 eth_h->eth_type = htons(ETH_TYPE_IP);
504 l2_length = ETH_HEADER_LEN;
508 if (protocol == Ipv4L3Protocol::PROT_NUMBER)
511 if (packet->PeekHeader(ip_hd))
513 buffer->l3 =
new ip_header;
514 ip_header* ip_h = (ip_header*)buffer->l3;
515 ip_h->ip_ihl_ver = IP_IHL_VER(5, IP_VERSION);
516 ip_h->ip_tos = ip_hd.GetTos();
517 ip_h->ip_tot_len = packet->GetSize();
518 ip_h->ip_id = ip_hd.GetIdentification();
519 ip_h->ip_frag_off = ip_hd.GetFragmentOffset();
520 ip_h->ip_ttl = ip_hd.GetTtl();
521 ip_h->ip_proto = ip_hd.GetProtocol();
522 ip_h->ip_src = htonl(ip_hd.GetSource().Get());
523 ip_h->ip_dst = htonl(ip_hd.GetDestination().Get());
524 ip_h->ip_csum = csum(&ip_h,
sizeof ip_h);
526 packet->RemoveHeader(ip_hd);
528 l3_length = IP_HEADER_LEN;
536 if (packet->PeekHeader(arp_hd))
538 buffer->l3 =
new arp_eth_header;
539 arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
540 arp_h->ar_hrd = ARP_HRD_ETHERNET;
541 arp_h->ar_pro = ARP_PRO_IP;
542 arp_h->ar_op = arp_hd.m_type;
543 arp_hd.GetDestinationHardwareAddress().CopyTo(
545 arp_hd.GetSourceHardwareAddress().CopyTo(arp_h->ar_sha);
546 arp_h->ar_tpa = arp_hd.GetDestinationIpv4Address().Get();
547 arp_h->ar_spa = arp_hd.GetSourceIpv4Address().Get();
548 arp_h->ar_hln =
sizeof arp_h->ar_tha;
549 arp_h->ar_pln =
sizeof arp_h->ar_tpa;
551 packet->RemoveHeader(arp_hd);
553 l3_length = ARP_ETH_HEADER_LEN;
557 if (protocol == Ipv4L3Protocol::PROT_NUMBER)
559 ip_header* ip_h = (ip_header*)buffer->l3;
560 if (ip_h->ip_proto == TcpL4Protocol::PROT_NUMBER)
563 if (packet->PeekHeader(tcp_hd))
565 buffer->l4 =
new tcp_header;
566 tcp_header* tcp_h = (tcp_header*)buffer->l4;
567 tcp_h->tcp_src = htons(tcp_hd.GetSourcePort());
568 tcp_h->tcp_dst = htons(tcp_hd.GetDestinationPort());
569 tcp_h->tcp_seq = tcp_hd.GetSequenceNumber().GetValue();
570 tcp_h->tcp_ack = tcp_hd.GetAckNumber().GetValue();
571 tcp_h->tcp_ctl = TCP_FLAGS(tcp_hd.GetFlags());
572 tcp_h->tcp_winsz = tcp_hd.GetWindowSize();
573 tcp_h->tcp_urg = tcp_hd.GetUrgentPointer();
574 tcp_h->tcp_csum = csum(&tcp_h,
sizeof tcp_h);
576 packet->RemoveHeader(tcp_hd);
578 l4_length = TCP_HEADER_LEN;
581 else if (ip_h->ip_proto == UdpL4Protocol::PROT_NUMBER)
584 if (packet->PeekHeader(udp_hd))
586 buffer->l4 =
new udp_header;
587 udp_header* udp_h = (udp_header*)buffer->l4;
588 udp_h->udp_src = htons(udp_hd.GetSourcePort());
589 udp_h->udp_dst = htons(udp_hd.GetDestinationPort());
590 udp_h->udp_len = htons(UDP_HEADER_LEN + packet->GetSize());
592 ip_header* ip_h = (ip_header*)buffer->l3;
593 uint32_t udp_csum = csum_add32(0, ip_h->ip_src);
594 udp_csum = csum_add32(udp_csum, ip_h->ip_dst);
595 udp_csum = csum_add16(udp_csum, IP_TYPE_UDP << 8);
596 udp_csum = csum_add16(udp_csum, udp_h->udp_len);
597 udp_csum = csum_continue(udp_csum, udp_h,
sizeof udp_h);
598 udp_h->udp_csum = csum_finish(
599 csum_continue(udp_csum, buffer->data, buffer->size));
601 packet->RemoveHeader(udp_hd);
603 l4_length = UDP_HEADER_LEN;
609 packet->CopyData((uint8_t*)buffer->data, packet->GetSize());
613 ofpbuf_push(buffer, buffer->l4, l4_length);
614 delete (tcp_header*)buffer->l4;
618 ofpbuf_push(buffer, buffer->l3, l3_length);
619 delete (ip_header*)buffer->l3;
623 ofpbuf_push(buffer, buffer->l2, l2_length);
624 delete (eth_header*)buffer->l2;
631 OpenFlowSwitchNetDevice::ReceiveFromDevice(Ptr<NetDevice> netdev,
632 Ptr<const Packet> packet,
636 PacketType packetType)
639 NS_LOG_INFO(
"--------------------------------------------");
642 if (!m_promiscRxCallback.IsNull())
644 m_promiscRxCallback(
this, packet, protocol, src, dst, packetType);
647 Mac48Address dst48 = Mac48Address::ConvertFrom(dst);
648 NS_LOG_INFO(
"Received packet from " << Mac48Address::ConvertFrom(src) <<
" looking for "
651 for (
size_t i = 0; i < m_ports.size(); i++)
653 if (m_ports[i].netdev == netdev)
655 if (packetType == PACKET_HOST && dst48 == m_address)
657 m_rxCallback(
this, packet, protocol, src);
659 else if (packetType == PACKET_BROADCAST || packetType == PACKET_MULTICAST ||
660 packetType == PACKET_OTHERHOST)
662 if (packetType == PACKET_OTHERHOST && dst48 == m_address)
664 m_rxCallback(
this, packet, protocol, src);
668 if (packetType != PACKET_OTHERHOST)
670 m_rxCallback(
this, packet, protocol, src);
673 ofi::SwitchPacketMetadata
data;
674 data.packet = packet->Copy();
678 m_ports[i].rx_packets++;
679 m_ports[i].rx_bytes += buffer->size;
680 data.buffer = buffer;
683 data.protocolNumber = protocol;
684 data.src = Address(src);
685 data.dst = Address(dst);
686 m_packetData.insert(std::make_pair(packet_uid,
data));
688 RunThroughFlowTable(packet_uid, i);
698 if (now >=
Seconds(m_lastExecute.GetSeconds() +
702 for (
size_t i = 0; i < m_ports.size(); i++)
704 if (UpdatePortStatus(m_ports[i]))
706 SendPortStatus(m_ports[i], OFPPR_MODIFY);
711 List deleted = LIST_INITIALIZER(&deleted);
714 chain_timeout(m_chain, &deleted);
715 LIST_FOR_EACH_SAFE(
f, n, sw_flow, node, &deleted)
717 std::ostringstream str;
719 for (
int i = 0; i < 6; i++)
721 str << (i != 0 ?
":" :
"") << std::hex <<
f->key.flow.dl_src[i] / 16
722 <<
f->key.flow.dl_src[i] % 16;
725 for (
int i = 0; i < 6; i++)
727 str << (i != 0 ?
":" :
"") << std::hex <<
f->key.flow.dl_dst[i] / 16
728 <<
f->key.flow.dl_dst[i] % 16;
733 SendFlowExpired(
f, (ofp_flow_expired_reason)
f->reason);
734 list_remove(&
f->node);
743 OpenFlowSwitchNetDevice::OutputAll(uint32_t packet_uid,
int in_port,
bool flood)
749 for (
size_t i = 0; i < m_ports.size(); i++)
751 if (i == (
unsigned)in_port)
755 if (flood && m_ports[i].config & OFPPC_NO_FLOOD)
761 OutputPort(packet_uid, in_port, prev_port,
false);
767 OutputPort(packet_uid, in_port, prev_port,
false);
774 OpenFlowSwitchNetDevice::OutputPacket(uint32_t packet_uid,
int out_port)
776 if (out_port >= 0 && out_port < DP_MAX_PORTS)
778 ofi::Port& p = m_ports[out_port];
779 if (p.netdev && !(p.config & OFPPC_PORT_DOWN))
781 ofi::SwitchPacketMetadata
data = m_packetData.find(packet_uid)->second;
782 size_t bufsize =
data.buffer->size;
783 NS_LOG_INFO(
"Sending packet " <<
data.packet->GetUid() <<
" over port " << out_port);
784 if (p.netdev->SendFrom(
data.packet->Copy(),
data.src,
data.dst,
data.protocolNumber))
787 p.tx_bytes += bufsize;
801 OpenFlowSwitchNetDevice::OutputPort(uint32_t packet_uid,
808 if (out_port == OFPP_FLOOD)
810 OutputAll(packet_uid, in_port,
true);
812 else if (out_port == OFPP_ALL)
814 OutputAll(packet_uid, in_port,
false);
816 else if (out_port == OFPP_CONTROLLER)
818 OutputControl(packet_uid, in_port, 0, OFPR_ACTION);
820 else if (out_port == OFPP_IN_PORT)
822 OutputPacket(packet_uid, in_port);
824 else if (out_port == OFPP_TABLE)
826 RunThroughFlowTable(packet_uid, in_port < DP_MAX_PORTS ? in_port : -1,
false);
828 else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
831 NS_LOG_INFO(
"packet sent to virtual port " << out_port);
832 if (in_port < DP_MAX_PORTS)
834 RunThroughVPortTable(packet_uid, in_port, out_port);
838 RunThroughVPortTable(packet_uid, -1, out_port);
841 else if (in_port == out_port)
847 OutputPacket(packet_uid, out_port);
852 OpenFlowSwitchNetDevice::MakeOpenflowReply(
size_t openflow_len, uint8_t
type, ofpbuf** bufferp)
854 return make_openflow_xid(openflow_len,
type, 0, bufferp);
858 OpenFlowSwitchNetDevice::SendOpenflowBuffer(ofpbuf* buffer)
862 update_openflow_length(buffer);
863 m_controller->ReceiveFromSwitch(
this, buffer);
870 OpenFlowSwitchNetDevice::OutputControl(uint32_t packet_uid,
int in_port,
size_t max_len,
int reason)
874 ofpbuf* buffer = m_packetData.find(packet_uid)->second.buffer;
875 size_t total_len = buffer->size;
877 buffer->size > max_len)
879 buffer->size = max_len;
882 ofp_packet_in* opi = (ofp_packet_in*)ofpbuf_push_uninit(buffer, offsetof(ofp_packet_in,
data));
883 opi->header.version = OFP_VERSION;
884 opi->header.type = OFPT_PACKET_IN;
885 opi->header.length = htons(buffer->size);
886 opi->header.xid = htonl(0);
887 opi->buffer_id = htonl(packet_uid);
888 opi->total_len = htons(total_len);
889 opi->in_port = htons(in_port);
890 opi->reason = reason;
892 SendOpenflowBuffer(buffer);
896 OpenFlowSwitchNetDevice::FillPortDesc(ofi::Port p, ofp_phy_port* desc)
898 desc->port_no = htons(GetSwitchPortIndex(p));
900 std::ostringstream nm;
901 nm <<
"eth" << GetSwitchPortIndex(p);
902 strncpy((
char*)desc->name, nm.str().c_str(),
sizeof desc->name);
904 p.netdev->GetAddress().CopyTo(desc->hw_addr);
905 desc->config = htonl(p.config);
906 desc->state = htonl(p.state);
911 desc->advertised = 0;
916 OpenFlowSwitchNetDevice::SendFeaturesReply()
919 ofp_switch_features* ofr =
920 (ofp_switch_features*)MakeOpenflowReply(
sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
921 ofr->datapath_id = htonll(m_id);
922 ofr->n_tables = m_chain->n_tables;
927 for (
size_t i = 0; i < m_ports.size(); i++)
929 ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros(buffer,
sizeof *opp);
930 FillPortDesc(m_ports[i], opp);
933 SendOpenflowBuffer(buffer);
937 OpenFlowSwitchNetDevice::SendVPortTableFeatures()
940 ofp_vport_table_features* ovtfr =
941 (ofp_vport_table_features*)MakeOpenflowReply(
sizeof *ovtfr,
942 OFPT_VPORT_TABLE_FEATURES_REPLY,
945 ovtfr->max_vports = htonl(m_vportTable.max_vports);
946 ovtfr->max_chain_depth = htons(-1);
947 ovtfr->mixed_chaining =
true;
948 SendOpenflowBuffer(buffer);
952 OpenFlowSwitchNetDevice::UpdatePortStatus(ofi::Port& p)
954 uint32_t orig_config = p.config;
955 uint32_t orig_state = p.state;
958 p.config &= ~OFPPC_PORT_DOWN;
960 if (p.netdev->IsLinkUp())
962 p.state &= ~OFPPS_LINK_DOWN;
966 p.state |= OFPPS_LINK_DOWN;
969 return ((orig_config != p.config) || (orig_state != p.state));
973 OpenFlowSwitchNetDevice::SendPortStatus(ofi::Port p, uint8_t status)
976 ofp_port_status* ops =
977 (ofp_port_status*)MakeOpenflowReply(
sizeof *ops, OFPT_PORT_STATUS, &buffer);
978 ops->reason = status;
979 memset(ops->pad, 0,
sizeof ops->pad);
980 FillPortDesc(p, &ops->desc);
982 SendOpenflowBuffer(buffer);
983 ofpbuf_delete(buffer);
987 OpenFlowSwitchNetDevice::SendFlowExpired(sw_flow* flow,
enum ofp_flow_expired_reason reason)
990 ofp_flow_expired* ofe =
991 (ofp_flow_expired*)MakeOpenflowReply(
sizeof *ofe, OFPT_FLOW_EXPIRED, &buffer);
992 flow_fill_match(&ofe->match, &flow->key);
994 ofe->priority = htons(flow->priority);
995 ofe->reason = reason;
996 memset(ofe->pad, 0,
sizeof ofe->pad);
998 ofe->duration = htonl(
time_now() - flow->created);
999 memset(ofe->pad2, 0,
sizeof ofe->pad2);
1000 ofe->packet_count = htonll(flow->packet_count);
1001 ofe->byte_count = htonll(flow->byte_count);
1002 SendOpenflowBuffer(buffer);
1006 OpenFlowSwitchNetDevice::SendErrorMsg(uint16_t
type, uint16_t code,
const void*
data,
size_t len)
1009 ofp_error_msg* oem = (ofp_error_msg*)MakeOpenflowReply(
sizeof(*oem) + len, OFPT_ERROR, &buffer);
1010 oem->type = htons(
type);
1011 oem->code = htons(code);
1012 memcpy(oem->data,
data, len);
1013 SendOpenflowBuffer(buffer);
1017 OpenFlowSwitchNetDevice::FlowTableLookup(sw_flow_key key,
1019 uint32_t packet_uid,
1021 bool send_to_controller)
1023 sw_flow* flow = chain_lookup(m_chain, &key);
1027 flow_used(flow, buffer);
1032 flow->sf_acts->actions,
1033 flow->sf_acts->actions_len,
1040 if (send_to_controller)
1042 OutputControl(packet_uid,
port, m_missSendLen, OFPR_NO_MATCH);
1047 m_packetData.erase(packet_uid);
1049 ofpbuf_delete(buffer);
1053 OpenFlowSwitchNetDevice::RunThroughFlowTable(uint32_t packet_uid,
int port,
bool send_to_controller)
1055 ofi::SwitchPacketMetadata
data = m_packetData.find(packet_uid)->second;
1056 ofpbuf* buffer =
data.buffer;
1062 if (flow_extract(buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) &&
1063 (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1065 ofpbuf_delete(buffer);
1073 mpls_h.value = ntohl(*((uint32_t*)buffer->l2_5));
1074 if (mpls_h.ttl == 1)
1079 m_ports[
port].mpls_ttl0_dropped++;
1088 uint32_t config = m_ports[
port].config;
1089 if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
1090 config & (!eth_addr_equals(key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV
1091 : OFPPC_NO_RECV_STP))
1098 Simulator::Schedule(m_lookupDelay,
1099 &OpenFlowSwitchNetDevice::FlowTableLookup,
1105 send_to_controller);
1109 OpenFlowSwitchNetDevice::RunThroughVPortTable(uint32_t packet_uid,
int port, uint32_t vport)
1111 ofpbuf* buffer = m_packetData.find(packet_uid)->second.buffer;
1117 if (flow_extract(buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) &&
1118 (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1124 vport_table_entry* vpe = vport_table_lookup(&m_vportTable, vport);
1125 m_vportTable.lookup_count++;
1128 m_vportTable.port_match_count++;
1134 m_packetData.find(packet_uid)->second.buffer,
1136 vpe->port_acts->actions,
1137 vpe->port_acts->actions_len);
1138 vport_used(vpe, buffer);
1139 if (!vpe->parent_port_ptr)
1143 if (vpe->parent_port <=
1146 OutputPort(packet_uid,
port != -1 ?
port : OFPP_NONE, vpe->parent_port,
false);
1155 m_vportTable.chain_match_count++;
1158 vpe = vpe->parent_port_ptr;
1165 OpenFlowSwitchNetDevice::ReceiveFeaturesRequest(
const void* msg)
1167 SendFeaturesReply();
1172 OpenFlowSwitchNetDevice::ReceiveVPortTableFeaturesRequest(
const void* msg)
1174 SendVPortTableFeatures();
1179 OpenFlowSwitchNetDevice::ReceiveGetConfigRequest(
const void* msg)
1182 ofp_switch_config* osc =
1183 (ofp_switch_config*)MakeOpenflowReply(
sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
1184 osc->flags = htons(m_flags);
1185 osc->miss_send_len = htons(m_missSendLen);
1187 return SendOpenflowBuffer(buffer);
1191 OpenFlowSwitchNetDevice::ReceiveSetConfig(
const void* msg)
1193 const ofp_switch_config* osc = (ofp_switch_config*)msg;
1195 int n_flags = ntohs(osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
1196 if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL &&
1197 (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
1199 n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1203 m_missSendLen = ntohs(osc->miss_send_len);
1208 OpenFlowSwitchNetDevice::ReceivePacketOut(
const void* msg)
1210 const ofp_packet_out* opo = (ofp_packet_out*)msg;
1212 size_t actions_len = ntohs(opo->actions_len);
1214 if (actions_len > (ntohs(opo->header.length) -
sizeof *opo))
1216 NS_LOG_DEBUG(
"message too short for number of actions");
1220 if (ntohl(opo->buffer_id) == (uint32_t)-1)
1223 int data_len = ntohs(opo->header.length) -
sizeof *opo - actions_len;
1224 buffer = ofpbuf_new(data_len);
1225 ofpbuf_put(buffer, (uint8_t*)opo->actions + actions_len, data_len);
1237 flow_extract(buffer, ntohs(opo->in_port), &key.flow);
1240 if (v_code != ACT_VALIDATION_OK)
1242 SendErrorMsg(OFPET_BAD_ACTION, v_code, msg, ntohs(opo->header.length));
1243 ofpbuf_delete(buffer);
1252 OpenFlowSwitchNetDevice::ReceivePortMod(
const void* msg)
1254 ofp_port_mod* opm = (ofp_port_mod*)msg;
1256 int port = opm->port_no;
1257 if (
port < DP_MAX_PORTS)
1259 ofi::Port& p = m_ports[
port];
1262 Mac48Address hw_addr = Mac48Address();
1263 hw_addr.CopyFrom(opm->hw_addr);
1264 if (p.netdev->GetAddress() != hw_addr)
1271 uint32_t config_mask = ntohl(opm->mask);
1272 p.config &= ~config_mask;
1273 p.config |= ntohl(opm->config) & config_mask;
1276 if (opm->mask & htonl(OFPPC_PORT_DOWN))
1278 if ((opm->config & htonl(OFPPC_PORT_DOWN)) && (p.config & OFPPC_PORT_DOWN) == 0)
1280 p.config |= OFPPC_PORT_DOWN;
1283 else if ((opm->config & htonl(OFPPC_PORT_DOWN)) == 0 && (p.config & OFPPC_PORT_DOWN))
1285 p.config &= ~OFPPC_PORT_DOWN;
1296 OpenFlowSwitchNetDevice::ReceiveVPortMod(
const void* msg)
1298 const ofp_vport_mod* ovpm = (ofp_vport_mod*)msg;
1300 uint16_t command = ntohs(ovpm->command);
1301 if (command == OFPVP_ADD)
1303 return AddVPort(ovpm);
1305 else if (command == OFPVP_DELETE)
1307 if (remove_vport_table_entry(&m_vportTable, ntohl(ovpm->vport)))
1309 SendErrorMsg(OFPET_BAD_ACTION,
1310 OFPET_VPORT_MOD_FAILED,
1312 ntohs(ovpm->header.length));
1320 OpenFlowSwitchNetDevice::AddFlow(
const ofp_flow_mod* ofm)
1322 size_t actions_len = ntohs(ofm->header.length) -
sizeof *ofm;
1325 sw_flow* flow = flow_alloc(actions_len);
1328 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1335 flow_extract_match(&flow->key, &ofm->match);
1338 if (v_code != ACT_VALIDATION_OK)
1340 SendErrorMsg(OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1342 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1350 flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
1351 flow->idle_timeout = ntohs(ofm->idle_timeout);
1352 flow->hard_timeout = ntohs(ofm->hard_timeout);
1353 flow->used = flow->created =
time_now();
1354 flow->sf_acts->actions_len = actions_len;
1355 flow->byte_count = 0;
1356 flow->packet_count = 0;
1357 memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
1360 int error = chain_insert(m_chain, flow);
1363 if (error == -ENOBUFS)
1365 SendErrorMsg(OFPET_FLOW_MOD_FAILED,
1366 OFPFMFC_ALL_TABLES_FULL,
1368 ntohs(ofm->header.length));
1371 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1385 flow_used(flow, buffer);
1386 flow_extract(buffer,
1387 ntohs(ofm->match.in_port),
1396 ofpbuf_delete(buffer);
1407 OpenFlowSwitchNetDevice::ModFlow(
const ofp_flow_mod* ofm)
1410 flow_extract_match(&key, &ofm->match);
1412 size_t actions_len = ntohs(ofm->header.length) -
sizeof *ofm;
1415 if (v_code != ACT_VALIDATION_OK)
1417 SendErrorMsg((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1418 if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1425 uint16_t priority = key.wildcards ? ntohs(ofm->priority) : -1;
1426 int strict = (ofm->command == htons(OFPFC_MODIFY_STRICT)) ? 1 : 0;
1427 chain_modify(m_chain, &key, priority, strict, ofm->actions, actions_len);
1434 sw_flow_key skb_key;
1435 flow_extract(buffer,
1436 ntohs(ofm->match.in_port),
1445 ofpbuf_delete(buffer);
1456 OpenFlowSwitchNetDevice::ReceiveFlow(
const void* msg)
1459 const ofp_flow_mod* ofm = (ofp_flow_mod*)msg;
1460 uint16_t command = ntohs(ofm->command);
1462 if (command == OFPFC_ADD)
1464 return AddFlow(ofm);
1466 else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1468 return ModFlow(ofm);
1470 else if (command == OFPFC_DELETE)
1473 flow_extract_match(&key, &ofm->match);
1474 return chain_delete(m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1476 else if (command == OFPFC_DELETE_STRICT)
1480 flow_extract_match(&key, &ofm->match);
1481 priority = key.wildcards ? ntohs(ofm->priority) : -1;
1482 return chain_delete(m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
1491 OpenFlowSwitchNetDevice::StatsDump(ofi::StatsDumpCallback* cb)
1493 ofp_stats_reply* osr;
1502 osr = (ofp_stats_reply*)MakeOpenflowReply(
sizeof *osr, OFPT_STATS_REPLY, &buffer);
1503 osr->type = htons(cb->s->type);
1506 err = cb->s->DoDump(
this, cb->state, buffer);
1516 osr = (ofp_stats_reply*)ofpbuf_at_assert(buffer, 0,
sizeof *osr);
1517 osr->flags = ntohs(OFPSF_REPLY_MORE);
1520 int err2 = SendOpenflowBuffer(buffer);
1531 OpenFlowSwitchNetDevice::StatsDone(ofi::StatsDumpCallback* cb)
1535 cb->s->DoCleanup(cb->state);
1542 OpenFlowSwitchNetDevice::ReceiveStatsRequest(
const void* oh)
1544 const ofp_stats_request* rq = (ofp_stats_request*)oh;
1545 size_t rq_len = ntohs(rq->header.length);
1546 int type = ntohs(rq->type);
1547 int body_len = rq_len - offsetof(ofp_stats_request, body);
1548 ofi::Stats* st =
new ofi::Stats((ofp_stats_types)
type, (
unsigned)body_len);
1555 ofi::StatsDumpCallback cb;
1557 cb.rq = (ofp_stats_request*)xmemdup(rq, rq_len);
1564 int err = cb.s->DoInit(rq->body, body_len, &cb.state);
1567 NS_LOG_WARN(
"failed initialization of stats request type " <<
type <<
": "
1576 m_controller->StartDump(&cb);
1581 "Switch needs to be registered to a controller in order to start the stats reply.");
1588 OpenFlowSwitchNetDevice::ReceiveEchoRequest(
const void* oh)
1590 return SendOpenflowBuffer(make_echo_reply((ofp_header*)oh));
1594 OpenFlowSwitchNetDevice::ReceiveEchoReply(
const void* oh)
1600 OpenFlowSwitchNetDevice::ForwardControlInput(
const void* msg,
size_t length)
1603 ofp_header* oh = (ofp_header*)msg;
1604 if (ntohs(oh->length) > length)
1608 assert(oh->version == OFP_VERSION);
1615 case OFPT_FEATURES_REQUEST:
1616 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveFeaturesRequest(msg);
1618 case OFPT_GET_CONFIG_REQUEST:
1619 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveGetConfigRequest(msg);
1621 case OFPT_SET_CONFIG:
1622 error = length <
sizeof(ofp_switch_config) ? -EFAULT : ReceiveSetConfig(msg);
1624 case OFPT_PACKET_OUT:
1625 error = length <
sizeof(ofp_packet_out) ? -EFAULT : ReceivePacketOut(msg);
1628 error = length <
sizeof(ofp_flow_mod) ? -EFAULT : ReceiveFlow(msg);
1631 error = length <
sizeof(ofp_port_mod) ? -EFAULT : ReceivePortMod(msg);
1633 case OFPT_STATS_REQUEST:
1634 error = length <
sizeof(ofp_stats_request) ? -EFAULT : ReceiveStatsRequest(msg);
1636 case OFPT_ECHO_REQUEST:
1637 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveEchoRequest(msg);
1639 case OFPT_ECHO_REPLY:
1640 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveEchoReply(msg);
1642 case OFPT_VPORT_MOD:
1643 error = length <
sizeof(ofp_vport_mod) ? -EFAULT : ReceiveVPortMod(msg);
1645 case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1646 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveVPortTableFeaturesRequest(msg);
1649 SendErrorMsg((ofp_error_type)OFPET_BAD_REQUEST,
1650 (ofp_bad_request_code)OFPBRC_BAD_TYPE,
1664 OpenFlowSwitchNetDevice::GetChain()
1670 OpenFlowSwitchNetDevice::GetNSwitchPorts()
const
1673 return m_ports.size();
1677 OpenFlowSwitchNetDevice::GetSwitchPort(uint32_t n)
const
1684 OpenFlowSwitchNetDevice::GetSwitchPortIndex(ofi::Port p)
1686 for (
size_t i = 0; i < m_ports.size(); i++)
1688 if (m_ports[i].netdev == p.netdev)
1697 OpenFlowSwitchNetDevice::GetVPortTable()
1699 return m_vportTable;
double f(double x, void *params)
uint64_t m_id
Unique identifier for this switch, needed for OpenFlow.
OpenFlowSwitchNetDevice()
static const char * GetSerialNumber()
static const char * GetSoftwareDescription()
uint16_t m_flags
Flags; configurable by the controller.
static const char * GetManufacturerDescription()
uint16_t m_missSendLen
Flow Table Miss Send Length; configurable by the controller.
static TypeId GetTypeId()
Register this type.
static const char * GetHardwareDescription()
Time m_lookupDelay
Flow Table Lookup Delay [overhead].
TypeId AddConstructor()
Record in this TypeId the fact that the default constructor is accessible.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
#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 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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
struct ofpbuf * BufferFromPacket(Ptr< const Packet > packet, size_t bodyRoom, size_t headRoom)
Create an internal BOFUSS buffer from ns3::Packet.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
bool IsMulticast(const Address &ad)
Address family-independent test for a multicast address.
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...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
time_t time_now(void)
Overriding BOFUSS time_now weak function from timeval.c.
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