21 #include "ns3/udp-l4-protocol.h" 22 #include "ns3/tcp-l4-protocol.h" 33 return "The ns-3 team";
45 return "Simulated OpenFlow Switch";
57 uint8_t ea[ETH_ADDR_LEN];
59 return eth_addr_to_uint64 (ea);
65 static TypeId tid = TypeId (
"ns3::OpenFlowSwitchNetDevice")
67 .SetGroupName (
"Openflow")
70 "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for OpenFlow compatibility.",
71 UintegerValue (GenerateId ()),
73 MakeUintegerChecker<uint64_t> ())
74 .AddAttribute (
"FlowTableLookupDelay",
75 "A real switch will have an overhead for looking up in the flow table. For the default, we simulate a standard TCAM on an FPGA.",
79 .AddAttribute (
"Flags",
80 "Flags to turn different functionality on/off, such as whether to inform the controller when a flow expires, or how to handle fragments.",
83 MakeUintegerChecker<uint16_t> ())
84 .AddAttribute (
"FlowTableMissSendLength",
85 "When forwarding a packet the switch didn't match up to the controller, it can be more efficient to forward only the first x bytes.",
86 UintegerValue (OFP_DEFAULT_MISS_SEND_LEN),
88 MakeUintegerChecker<uint16_t> ())
100 m_channel = CreateObject<BridgeChannel> ();
108 m_chain = chain_create ();
111 NS_LOG_ERROR (
"Not enough memory to create the flow table.");
114 m_ports.reserve (DP_MAX_PORTS);
115 vport_table_init (&m_vportTable);
118 OpenFlowSwitchNetDevice::~OpenFlowSwitchNetDevice ()
124 OpenFlowSwitchNetDevice::DoDispose ()
128 for (Ports_t::iterator b = m_ports.begin (), e = m_ports.end (); b != e; b++)
130 SendPortStatus (*b, OFPPR_DELETE);
137 chain_destroy (m_chain);
138 RBTreeDestroy (m_vportTable.table);
141 NetDevice::DoDispose ();
145 OpenFlowSwitchNetDevice::SetController (Ptr<ofi::Controller> c)
147 if (m_controller != 0)
154 m_controller->AddSwitch (
this);
158 OpenFlowSwitchNetDevice::AddSwitchPort (Ptr<NetDevice> switchPort)
162 if (!Mac48Address::IsMatchingType (switchPort->GetAddress ()))
164 NS_FATAL_ERROR (
"Device does not support eui 48 addresses: cannot be added to switch.");
166 if (!switchPort->SupportsSendFrom ())
168 NS_FATAL_ERROR (
"Device does not support SendFrom: cannot be added to switch.");
170 if (m_address == Mac48Address ())
172 m_address = Mac48Address::ConvertFrom (switchPort->GetAddress ());
175 if (m_ports.size () < DP_MAX_PORTS)
179 p.netdev = switchPort;
180 m_ports.push_back (p);
183 SendPortStatus (p, OFPPR_ADD);
185 NS_LOG_DEBUG (
"RegisterProtocolHandler for " << switchPort->GetInstanceTypeId ().GetName ());
186 m_node->RegisterProtocolHandler (
MakeCallback (&OpenFlowSwitchNetDevice::ReceiveFromDevice,
this),
187 0, switchPort,
true);
188 m_channel->AddChannel (switchPort->GetChannel ());
199 OpenFlowSwitchNetDevice::SetIfIndex (
const uint32_t index)
206 OpenFlowSwitchNetDevice::GetIfIndex (
void)
const 213 OpenFlowSwitchNetDevice::GetChannel (
void)
const 220 OpenFlowSwitchNetDevice::SetAddress (Address
address)
223 m_address = Mac48Address::ConvertFrom (
address);
227 OpenFlowSwitchNetDevice::GetAddress (
void)
const 234 OpenFlowSwitchNetDevice::SetMtu (
const uint16_t mtu)
242 OpenFlowSwitchNetDevice::GetMtu (
void)
const 250 OpenFlowSwitchNetDevice::IsLinkUp (
void)
const 258 OpenFlowSwitchNetDevice::AddLinkChangeCallback (Callback<void> callback)
263 OpenFlowSwitchNetDevice::IsBroadcast (
void)
const 270 OpenFlowSwitchNetDevice::GetBroadcast (
void)
const 273 return Mac48Address (
"ff:ff:ff:ff:ff:ff");
284 OpenFlowSwitchNetDevice::GetMulticast (Ipv4Address multicastGroup)
const 287 Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
293 OpenFlowSwitchNetDevice::IsPointToPoint (
void)
const 300 OpenFlowSwitchNetDevice::IsBridge (
void)
const 307 OpenFlowSwitchNetDevice::DoOutput (uint32_t packet_uid,
int in_port,
size_t max_len,
int out_port,
bool ignore_no_fwd)
309 if (out_port != OFPP_CONTROLLER)
311 OutputPort (packet_uid, in_port, out_port, ignore_no_fwd);
315 OutputControl (packet_uid, in_port, max_len, OFPR_ACTION);
320 OpenFlowSwitchNetDevice::Send (Ptr<Packet> packet,
const Address& dest, uint16_t protocolNumber)
323 return SendFrom (packet, m_address, dest, protocolNumber);
327 OpenFlowSwitchNetDevice::SendFrom (Ptr<Packet> packet,
const Address& src,
const Address& dest, uint16_t protocolNumber)
331 ofpbuf *buffer = BufferFromPacket (packet,src,dest,GetMtu (),protocolNumber);
334 ofi::SwitchPacketMetadata
data;
335 data.packet = packet;
336 data.buffer = buffer;
337 data.protocolNumber = protocolNumber;
338 data.src = Address (src);
339 data.dst = Address (dest);
340 m_packetData.insert (std::make_pair (packet_uid,
data));
342 RunThroughFlowTable (packet_uid, -1);
349 OpenFlowSwitchNetDevice::GetNode (
void)
const 356 OpenFlowSwitchNetDevice::SetNode (Ptr<Node> node)
363 OpenFlowSwitchNetDevice::NeedsArp (
void)
const 370 OpenFlowSwitchNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
377 OpenFlowSwitchNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
380 m_promiscRxCallback = cb;
384 OpenFlowSwitchNetDevice::SupportsSendFrom ()
const 391 OpenFlowSwitchNetDevice::GetMulticast (Ipv6Address addr)
const 394 return Mac48Address::GetMulticast (addr);
399 OpenFlowSwitchNetDevice::AddVPort (
const ofp_vport_mod *ovpm)
401 size_t actions_len = ntohs (ovpm->header.length) -
sizeof *ovpm;
402 unsigned int vport = ntohl (ovpm->vport);
403 unsigned int parent_port = ntohl (ovpm->parent_port);
406 vport_table_entry *vpe = vport_table_lookup (&m_vportTable, vport);
410 SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
416 if (v_code != ACT_VALIDATION_OK)
418 SendErrorMsg (OFPET_BAD_ACTION, v_code, ovpm, ntohs (ovpm->header.length));
422 vpe = vport_table_entry_alloc (actions_len);
425 vpe->parent_port = parent_port;
426 if (vport < OFPP_VP_START || vport > OFPP_VP_END)
428 NS_LOG_ERROR (
"port " << vport <<
" is not in the virtual port range (" << OFPP_VP_START <<
"-" << OFPP_VP_END <<
")");
429 SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
430 free_vport_table_entry (vpe);
434 vpe->port_acts->actions_len = actions_len;
435 memcpy (vpe->port_acts->actions, ovpm->actions, actions_len);
437 int error = insert_vport_table_entry (&m_vportTable, vpe);
440 NS_LOG_ERROR (
"could not insert port table entry for port " << vport);
447 OpenFlowSwitchNetDevice::BufferFromPacket (Ptr<const Packet> constPacket, Address src, Address dst,
int mtu, uint16_t protocol)
449 NS_LOG_INFO (
"Creating Openflow buffer from packet.");
451 Ptr<Packet> packet = constPacket->Copy ();
457 const int headroom = 128 + 2;
458 const int hard_header = VLAN_ETH_HEADER_LEN;
459 ofpbuf *buffer = ofpbuf_new (headroom + hard_header + mtu);
460 buffer->data = (
char*)buffer->data + headroom + hard_header;
462 int l2_length = 0, l3_length = 0, l4_length = 0;
465 buffer->l2 =
new eth_header;
466 eth_header* eth_h = (eth_header*)buffer->l2;
467 dst.CopyTo (eth_h->eth_dst);
468 src.CopyTo (eth_h->eth_src);
469 if (protocol == ArpL3Protocol::PROT_NUMBER)
471 eth_h->eth_type = htons (ETH_TYPE_ARP);
473 else if (protocol == Ipv4L3Protocol::PROT_NUMBER)
475 eth_h->eth_type = htons (ETH_TYPE_IP);
479 NS_LOG_WARN (
"Protocol unsupported: " << protocol);
483 l2_length = ETH_HEADER_LEN;
486 if (protocol == Ipv4L3Protocol::PROT_NUMBER)
489 if (packet->PeekHeader (ip_hd))
491 buffer->l3 =
new ip_header;
492 ip_header* ip_h = (ip_header*)buffer->l3;
493 ip_h->ip_ihl_ver = IP_IHL_VER (5, IP_VERSION);
494 ip_h->ip_tos = ip_hd.GetTos ();
495 ip_h->ip_tot_len = packet->GetSize ();
496 ip_h->ip_id = ip_hd.GetIdentification ();
497 ip_h->ip_frag_off = ip_hd.GetFragmentOffset ();
498 ip_h->ip_ttl = ip_hd.GetTtl ();
499 ip_h->ip_proto = ip_hd.GetProtocol ();
500 ip_h->ip_src = htonl (ip_hd.GetSource ().Get ());
501 ip_h->ip_dst = htonl (ip_hd.GetDestination ().Get ());
502 ip_h->ip_csum = csum (&ip_h,
sizeof ip_h);
504 packet->RemoveHeader (ip_hd);
506 l3_length = IP_HEADER_LEN;
513 if (packet->PeekHeader (arp_hd))
515 buffer->l3 =
new arp_eth_header;
516 arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
517 arp_h->ar_hrd = ARP_HRD_ETHERNET;
518 arp_h->ar_pro = ARP_PRO_IP;
519 arp_h->ar_op = arp_hd.m_type;
520 arp_hd.GetDestinationHardwareAddress ().CopyTo (arp_h->ar_tha);
521 arp_hd.GetSourceHardwareAddress ().CopyTo (arp_h->ar_sha);
522 arp_h->ar_tpa = arp_hd.GetDestinationIpv4Address ().Get ();
523 arp_h->ar_spa = arp_hd.GetSourceIpv4Address ().Get ();
524 arp_h->ar_hln =
sizeof arp_h->ar_tha;
525 arp_h->ar_pln =
sizeof arp_h->ar_tpa;
527 packet->RemoveHeader (arp_hd);
529 l3_length = ARP_ETH_HEADER_LEN;
533 if (protocol == Ipv4L3Protocol::PROT_NUMBER)
535 ip_header* ip_h = (ip_header*)buffer->l3;
536 if (ip_h->ip_proto == TcpL4Protocol::PROT_NUMBER)
539 if (packet->PeekHeader (tcp_hd))
541 buffer->l4 =
new tcp_header;
542 tcp_header* tcp_h = (tcp_header*)buffer->l4;
543 tcp_h->tcp_src = htons (tcp_hd.GetSourcePort ());
544 tcp_h->tcp_dst = htons (tcp_hd.GetDestinationPort ());
545 tcp_h->tcp_seq = tcp_hd.GetSequenceNumber ().GetValue ();
546 tcp_h->tcp_ack = tcp_hd.GetAckNumber ().GetValue ();
547 tcp_h->tcp_ctl = TCP_FLAGS (tcp_hd.GetFlags ());
548 tcp_h->tcp_winsz = tcp_hd.GetWindowSize ();
549 tcp_h->tcp_urg = tcp_hd.GetUrgentPointer ();
550 tcp_h->tcp_csum = csum (&tcp_h,
sizeof tcp_h);
552 packet->RemoveHeader (tcp_hd);
554 l4_length = TCP_HEADER_LEN;
557 else if (ip_h->ip_proto == UdpL4Protocol::PROT_NUMBER)
560 if (packet->PeekHeader (udp_hd))
562 buffer->l4 =
new udp_header;
563 udp_header* udp_h = (udp_header*)buffer->l4;
564 udp_h->udp_src = htons (udp_hd.GetSourcePort ());
565 udp_h->udp_dst = htons (udp_hd.GetDestinationPort ());
566 udp_h->udp_len = htons (UDP_HEADER_LEN + packet->GetSize ());
568 ip_header* ip_h = (ip_header*)buffer->l3;
569 uint32_t udp_csum = csum_add32 (0, ip_h->ip_src);
570 udp_csum = csum_add32 (udp_csum, ip_h->ip_dst);
571 udp_csum = csum_add16 (udp_csum, IP_TYPE_UDP << 8);
572 udp_csum = csum_add16 (udp_csum, udp_h->udp_len);
573 udp_csum = csum_continue (udp_csum, udp_h,
sizeof udp_h);
574 udp_h->udp_csum = csum_finish (csum_continue (udp_csum, buffer->data, buffer->size));
576 packet->RemoveHeader (udp_hd);
578 l4_length = UDP_HEADER_LEN;
584 packet->CopyData ((uint8_t*)buffer->data, packet->GetSize ());
588 ofpbuf_push (buffer, buffer->l4, l4_length);
589 delete (tcp_header*)buffer->l4;
593 ofpbuf_push (buffer, buffer->l3, l3_length);
594 delete (ip_header*)buffer->l3;
598 ofpbuf_push (buffer, buffer->l2, l2_length);
599 delete (eth_header*)buffer->l2;
606 OpenFlowSwitchNetDevice::ReceiveFromDevice (Ptr<NetDevice> netdev, Ptr<const Packet> packet, uint16_t protocol,
607 const Address& src,
const Address& dst, PacketType packetType)
610 NS_LOG_INFO (
"--------------------------------------------");
613 if (!m_promiscRxCallback.IsNull ())
615 m_promiscRxCallback (
this, packet, protocol, src, dst, packetType);
618 Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
619 NS_LOG_INFO (
"Received packet from " << Mac48Address::ConvertFrom (src) <<
" looking for " << dst48);
621 for (
size_t i = 0; i < m_ports.size (); i++)
623 if (m_ports[i].netdev == netdev)
625 if (packetType == PACKET_HOST && dst48 == m_address)
627 m_rxCallback (
this, packet, protocol, src);
629 else if (packetType == PACKET_BROADCAST || packetType == PACKET_MULTICAST || packetType == PACKET_OTHERHOST)
631 if (packetType == PACKET_OTHERHOST && dst48 == m_address)
633 m_rxCallback (
this, packet, protocol, src);
637 if (packetType != PACKET_OTHERHOST)
639 m_rxCallback (
this, packet, protocol, src);
642 ofi::SwitchPacketMetadata
data;
643 data.packet = packet->Copy ();
645 ofpbuf *buffer = BufferFromPacket (
data.packet,src,dst,netdev->GetMtu (),protocol);
646 m_ports[i].rx_packets++;
647 m_ports[i].rx_bytes += buffer->size;
648 data.buffer = buffer;
651 data.protocolNumber = protocol;
652 data.src = Address (src);
653 data.dst = Address (dst);
654 m_packetData.insert (std::make_pair (packet_uid,
data));
656 RunThroughFlowTable (packet_uid, i);
666 if (now >=
Seconds (m_lastExecute.GetSeconds () + 1))
669 for (
size_t i = 0; i < m_ports.size (); i++)
671 if (UpdatePortStatus (m_ports[i]))
673 SendPortStatus (m_ports[i], OFPPR_MODIFY);
678 List deleted = LIST_INITIALIZER (&deleted);
680 chain_timeout (m_chain, &deleted);
681 LIST_FOR_EACH_SAFE (
f,
n, sw_flow, node, &deleted)
683 std::ostringstream str;
685 for (
int i = 0; i < 6; i++)
686 str << (i!=0 ?
":" :
"") << std::hex <<
f->key.flow.dl_src[i]/16 <<
f->key.flow.dl_src[i]%16;
688 for (
int i = 0; i < 6; i++)
689 str << (i!=0 ?
":" :
"") << std::hex <<
f->key.flow.dl_dst[i]/16 <<
f->key.flow.dl_dst[i]%16;
693 SendFlowExpired (
f, (ofp_flow_expired_reason)
f->reason);
694 list_remove (&
f->node);
703 OpenFlowSwitchNetDevice::OutputAll (uint32_t packet_uid,
int in_port,
bool flood)
709 for (
size_t i = 0; i < m_ports.size (); i++)
711 if (i == (
unsigned)in_port)
715 if (flood && m_ports[i].config & OFPPC_NO_FLOOD)
721 OutputPort (packet_uid, in_port, prev_port,
false);
727 OutputPort (packet_uid, in_port, prev_port,
false);
734 OpenFlowSwitchNetDevice::OutputPacket (uint32_t packet_uid,
int out_port)
736 if (out_port >= 0 && out_port < DP_MAX_PORTS)
738 ofi::Port& p = m_ports[out_port];
739 if (p.netdev != 0 && !(p.config & OFPPC_PORT_DOWN))
741 ofi::SwitchPacketMetadata
data = m_packetData.find (packet_uid)->second;
742 size_t bufsize =
data.buffer->size;
743 NS_LOG_INFO (
"Sending packet " <<
data.packet->GetUid () <<
" over port " << out_port);
744 if (p.netdev->SendFrom (
data.packet->Copy (),
data.src,
data.dst,
data.protocolNumber))
747 p.tx_bytes += bufsize;
757 NS_LOG_DEBUG (
"can't forward to bad port " << out_port);
761 OpenFlowSwitchNetDevice::OutputPort (uint32_t packet_uid,
int in_port,
int out_port,
bool ignore_no_fwd)
765 if (out_port == OFPP_FLOOD)
767 OutputAll (packet_uid, in_port,
true);
769 else if (out_port == OFPP_ALL)
771 OutputAll (packet_uid, in_port,
false);
773 else if (out_port == OFPP_CONTROLLER)
775 OutputControl (packet_uid, in_port, 0, OFPR_ACTION);
777 else if (out_port == OFPP_IN_PORT)
779 OutputPacket (packet_uid, in_port);
781 else if (out_port == OFPP_TABLE)
783 RunThroughFlowTable (packet_uid, in_port < DP_MAX_PORTS ? in_port : -1,
false);
785 else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
788 NS_LOG_INFO (
"packet sent to virtual port " << out_port);
789 if (in_port < DP_MAX_PORTS)
791 RunThroughVPortTable (packet_uid, in_port, out_port);
795 RunThroughVPortTable (packet_uid, -1, out_port);
798 else if (in_port == out_port)
804 OutputPacket (packet_uid, out_port);
809 OpenFlowSwitchNetDevice::MakeOpenflowReply (
size_t openflow_len, uint8_t type, ofpbuf **bufferp)
811 return make_openflow_xid (openflow_len, type, 0, bufferp);
815 OpenFlowSwitchNetDevice::SendOpenflowBuffer (ofpbuf *buffer)
817 if (m_controller != 0)
819 update_openflow_length (buffer);
820 m_controller->ReceiveFromSwitch (
this, buffer);
827 OpenFlowSwitchNetDevice::OutputControl (uint32_t packet_uid,
int in_port,
size_t max_len,
int reason)
831 ofpbuf* buffer = m_packetData.find (packet_uid)->second.buffer;
832 size_t total_len = buffer->size;
835 buffer->size = max_len;
838 ofp_packet_in *opi = (ofp_packet_in*)ofpbuf_push_uninit (buffer, offsetof (ofp_packet_in,
data));
839 opi->header.version = OFP_VERSION;
840 opi->header.type = OFPT_PACKET_IN;
841 opi->header.length = htons (buffer->size);
842 opi->header.xid = htonl (0);
843 opi->buffer_id = htonl (packet_uid);
844 opi->total_len = htons (total_len);
845 opi->in_port = htons (in_port);
846 opi->reason = reason;
848 SendOpenflowBuffer (buffer);
852 OpenFlowSwitchNetDevice::FillPortDesc (ofi::Port p, ofp_phy_port *desc)
854 desc->port_no = htons (GetSwitchPortIndex (p));
856 std::ostringstream nm;
857 nm <<
"eth" << GetSwitchPortIndex (p);
858 strncpy ((
char *)desc->name, nm.str ().c_str (),
sizeof desc->name);
860 p.netdev->GetAddress ().CopyTo (desc->hw_addr);
861 desc->config = htonl (p.config);
862 desc->state = htonl (p.state);
867 desc->advertised = 0;
872 OpenFlowSwitchNetDevice::SendFeaturesReply ()
875 ofp_switch_features *ofr = (ofp_switch_features*)MakeOpenflowReply (
sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
876 ofr->datapath_id = htonll (m_id);
877 ofr->n_tables = m_chain->n_tables;
882 for (
size_t i = 0; i < m_ports.size (); i++)
884 ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros (buffer,
sizeof *opp);
885 FillPortDesc (m_ports[i], opp);
888 SendOpenflowBuffer (buffer);
892 OpenFlowSwitchNetDevice::SendVPortTableFeatures ()
895 ofp_vport_table_features *ovtfr = (ofp_vport_table_features*)MakeOpenflowReply (
sizeof *ovtfr, OFPT_VPORT_TABLE_FEATURES_REPLY, &buffer);
897 ovtfr->max_vports = htonl (m_vportTable.max_vports);
898 ovtfr->max_chain_depth = htons (-1);
899 ovtfr->mixed_chaining =
true;
900 SendOpenflowBuffer (buffer);
904 OpenFlowSwitchNetDevice::UpdatePortStatus (ofi::Port& p)
906 uint32_t orig_config = p.config;
907 uint32_t orig_state = p.state;
910 p.config &= ~OFPPC_PORT_DOWN;
912 if (p.netdev->IsLinkUp ())
914 p.state &= ~OFPPS_LINK_DOWN;
918 p.state |= OFPPS_LINK_DOWN;
921 return ((orig_config != p.config) || (orig_state != p.state));
925 OpenFlowSwitchNetDevice::SendPortStatus (ofi::Port p, uint8_t status)
928 ofp_port_status *ops = (ofp_port_status*)MakeOpenflowReply (
sizeof *ops, OFPT_PORT_STATUS, &buffer);
929 ops->reason = status;
930 memset (ops->pad, 0,
sizeof ops->pad);
931 FillPortDesc (p, &ops->desc);
933 SendOpenflowBuffer (buffer);
934 ofpbuf_delete (buffer);
938 OpenFlowSwitchNetDevice::SendFlowExpired (sw_flow *flow,
enum ofp_flow_expired_reason reason)
941 ofp_flow_expired *ofe = (ofp_flow_expired*)MakeOpenflowReply (
sizeof *ofe, OFPT_FLOW_EXPIRED, &buffer);
942 flow_fill_match (&ofe->match, &flow->key);
944 ofe->priority = htons (flow->priority);
945 ofe->reason = reason;
946 memset (ofe->pad, 0,
sizeof ofe->pad);
948 ofe->duration = htonl (time_now () - flow->created);
949 memset (ofe->pad2, 0,
sizeof ofe->pad2);
950 ofe->packet_count = htonll (flow->packet_count);
951 ofe->byte_count = htonll (flow->byte_count);
952 SendOpenflowBuffer (buffer);
956 OpenFlowSwitchNetDevice::SendErrorMsg (uint16_t type, uint16_t code,
const void *
data,
size_t len)
959 ofp_error_msg *oem = (ofp_error_msg*)MakeOpenflowReply (
sizeof(*oem) + len, OFPT_ERROR, &buffer);
960 oem->type = htons (type);
961 oem->code = htons (code);
962 memcpy (oem->data,
data, len);
963 SendOpenflowBuffer (buffer);
967 OpenFlowSwitchNetDevice::FlowTableLookup (sw_flow_key key, ofpbuf* buffer, uint32_t packet_uid,
int port,
bool send_to_controller)
969 sw_flow *flow = chain_lookup (m_chain, &key);
973 flow_used (flow, buffer);
974 ofi::ExecuteActions (
this, packet_uid, buffer, &key, flow->sf_acts->actions, flow->sf_acts->actions_len,
false);
980 if (send_to_controller)
982 OutputControl (packet_uid,
port, m_missSendLen, OFPR_NO_MATCH);
987 m_packetData.erase (packet_uid);
989 ofpbuf_delete (buffer);
993 OpenFlowSwitchNetDevice::RunThroughFlowTable (uint32_t packet_uid,
int port,
bool send_to_controller)
995 ofi::SwitchPacketMetadata
data = m_packetData.find (packet_uid)->second;
996 ofpbuf* buffer =
data.buffer;
1001 if (flow_extract (buffer,
port != -1 ?
port : OFPP_NONE, &key.flow) && (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1003 ofpbuf_delete (buffer);
1011 mpls_h.value = ntohl (*((uint32_t*)buffer->l2_5));
1012 if (mpls_h.ttl == 1)
1017 m_ports[
port].mpls_ttl0_dropped++;
1026 uint32_t config = m_ports[
port].config;
1027 if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP)
1028 && config & (!eth_addr_equals (key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV : OFPPC_NO_RECV_STP))
1035 Simulator::Schedule (m_lookupDelay, &OpenFlowSwitchNetDevice::FlowTableLookup,
this, key, buffer, packet_uid,
port, send_to_controller);
1039 OpenFlowSwitchNetDevice::RunThroughVPortTable (uint32_t packet_uid,
int port, uint32_t vport)
1041 ofpbuf* buffer = m_packetData.find (packet_uid)->second.buffer;
1047 if (flow_extract (buffer,
port != -1 ?
port : OFPP_NONE, &key.flow)
1048 && (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1054 vport_table_entry *vpe = vport_table_lookup (&m_vportTable, vport);
1055 m_vportTable.lookup_count++;
1058 m_vportTable.port_match_count++;
1062 ofi::ExecuteVPortActions (
this, packet_uid, m_packetData.find (packet_uid)->second.buffer, &key, vpe->port_acts->actions, vpe->port_acts->actions_len);
1063 vport_used (vpe, buffer);
1064 if (vpe->parent_port_ptr == 0)
1068 if (vpe->parent_port <= OFPP_VP_START)
1070 OutputPort (packet_uid,
port != -1 ?
port : OFPP_NONE, vpe->parent_port,
false);
1079 m_vportTable.chain_match_count++;
1082 vpe = vpe->parent_port_ptr;
1089 OpenFlowSwitchNetDevice::ReceiveFeaturesRequest (
const void *msg)
1091 SendFeaturesReply ();
1096 OpenFlowSwitchNetDevice::ReceiveVPortTableFeaturesRequest (
const void *msg)
1098 SendVPortTableFeatures ();
1103 OpenFlowSwitchNetDevice::ReceiveGetConfigRequest (
const void *msg)
1106 ofp_switch_config *osc = (ofp_switch_config*)MakeOpenflowReply (
sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
1107 osc->flags = htons (m_flags);
1108 osc->miss_send_len = htons (m_missSendLen);
1110 return SendOpenflowBuffer (buffer);
1114 OpenFlowSwitchNetDevice::ReceiveSetConfig (
const void *msg)
1116 const ofp_switch_config *osc = (ofp_switch_config*)msg;
1118 int n_flags = ntohs (osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
1119 if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL && (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
1121 n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1125 m_missSendLen = ntohs (osc->miss_send_len);
1130 OpenFlowSwitchNetDevice::ReceivePacketOut (
const void *msg)
1132 const ofp_packet_out *opo = (ofp_packet_out*)msg;
1134 size_t actions_len = ntohs (opo->actions_len);
1136 if (actions_len > (ntohs (opo->header.length) -
sizeof *opo))
1138 NS_LOG_DEBUG (
"message too short for number of actions");
1142 if (ntohl (opo->buffer_id) == (uint32_t) -1)
1145 int data_len = ntohs (opo->header.length) -
sizeof *opo - actions_len;
1146 buffer = ofpbuf_new (data_len);
1147 ofpbuf_put (buffer, (uint8_t *)opo->actions + actions_len, data_len);
1159 flow_extract (buffer, ntohs(opo->in_port), &key.flow);
1162 if (v_code != ACT_VALIDATION_OK)
1164 SendErrorMsg (OFPET_BAD_ACTION, v_code, msg, ntohs (opo->header.length));
1165 ofpbuf_delete (buffer);
1169 ofi::ExecuteActions (
this, opo->buffer_id, buffer, &key, opo->actions, actions_len,
true);
1174 OpenFlowSwitchNetDevice::ReceivePortMod (
const void *msg)
1176 ofp_port_mod* opm = (ofp_port_mod*)msg;
1178 int port = opm->port_no;
1179 if (
port < DP_MAX_PORTS)
1181 ofi::Port& p = m_ports[
port];
1184 Mac48Address hw_addr = Mac48Address ();
1185 hw_addr.CopyFrom (opm->hw_addr);
1186 if (p.netdev->GetAddress () != hw_addr)
1193 uint32_t config_mask = ntohl (opm->mask);
1194 p.config &= ~config_mask;
1195 p.config |= ntohl (opm->config) & config_mask;
1198 if (opm->mask & htonl (OFPPC_PORT_DOWN))
1200 if ((opm->config & htonl (OFPPC_PORT_DOWN)) && (p.config & OFPPC_PORT_DOWN) == 0)
1202 p.config |= OFPPC_PORT_DOWN;
1205 else if ((opm->config & htonl (OFPPC_PORT_DOWN)) == 0 && (p.config & OFPPC_PORT_DOWN))
1207 p.config &= ~OFPPC_PORT_DOWN;
1218 OpenFlowSwitchNetDevice::ReceiveVPortMod (
const void *msg)
1220 const ofp_vport_mod *ovpm = (ofp_vport_mod*)msg;
1222 uint16_t command = ntohs (ovpm->command);
1223 if (command == OFPVP_ADD)
1225 return AddVPort (ovpm);
1227 else if (command == OFPVP_DELETE)
1229 if (remove_vport_table_entry (&m_vportTable, ntohl (ovpm->vport)))
1231 SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
1239 OpenFlowSwitchNetDevice::AddFlow (
const ofp_flow_mod *ofm)
1241 size_t actions_len = ntohs (ofm->header.length) -
sizeof *ofm;
1244 sw_flow *flow = flow_alloc (actions_len);
1247 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1254 flow_extract_match (&flow->key, &ofm->match);
1257 if (v_code != ACT_VALIDATION_OK)
1259 SendErrorMsg (OFPET_BAD_ACTION, v_code, ofm, ntohs (ofm->header.length));
1261 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1269 flow->priority = flow->key.wildcards ? ntohs (ofm->priority) : -1;
1270 flow->idle_timeout = ntohs (ofm->idle_timeout);
1271 flow->hard_timeout = ntohs (ofm->hard_timeout);
1272 flow->used = flow->created = time_now ();
1273 flow->sf_acts->actions_len = actions_len;
1274 flow->byte_count = 0;
1275 flow->packet_count = 0;
1276 memcpy (flow->sf_acts->actions, ofm->actions, actions_len);
1279 int error = chain_insert (m_chain, flow);
1282 if (error == -ENOBUFS)
1284 SendErrorMsg (OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL, ofm, ntohs (ofm->header.length));
1287 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1301 flow_used (flow, buffer);
1302 flow_extract (buffer, ntohs(ofm->match.in_port), &key.flow);
1303 ofi::ExecuteActions (
this, ofm->buffer_id, buffer, &key, ofm->actions, actions_len,
false);
1304 ofpbuf_delete (buffer);
1315 OpenFlowSwitchNetDevice::ModFlow (
const ofp_flow_mod *ofm)
1318 flow_extract_match (&key, &ofm->match);
1320 size_t actions_len = ntohs (ofm->header.length) -
sizeof *ofm;
1323 if (v_code != ACT_VALIDATION_OK)
1325 SendErrorMsg ((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs (ofm->header.length));
1326 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1333 uint16_t priority = key.wildcards ? ntohs (ofm->priority) : -1;
1334 int strict = (ofm->command == htons (OFPFC_MODIFY_STRICT)) ? 1 : 0;
1335 chain_modify (m_chain, &key, priority, strict, ofm->actions, actions_len);
1342 sw_flow_key skb_key;
1343 flow_extract (buffer, ntohs(ofm->match.in_port), &skb_key.flow);
1344 ofi::ExecuteActions (
this, ofm->buffer_id, buffer, &skb_key, ofm->actions, actions_len,
false);
1345 ofpbuf_delete (buffer);
1356 OpenFlowSwitchNetDevice::ReceiveFlow (
const void *msg)
1359 const ofp_flow_mod *ofm = (ofp_flow_mod*)msg;
1360 uint16_t command = ntohs (ofm->command);
1362 if (command == OFPFC_ADD)
1364 return AddFlow (ofm);
1366 else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1368 return ModFlow (ofm);
1370 else if (command == OFPFC_DELETE)
1373 flow_extract_match (&key, &ofm->match);
1374 return chain_delete (m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1376 else if (command == OFPFC_DELETE_STRICT)
1380 flow_extract_match (&key, &ofm->match);
1381 priority = key.wildcards ? ntohs (ofm->priority) : -1;
1382 return chain_delete (m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
1391 OpenFlowSwitchNetDevice::StatsDump (ofi::StatsDumpCallback *cb)
1393 ofp_stats_reply *osr;
1402 osr = (ofp_stats_reply*)MakeOpenflowReply (
sizeof *osr, OFPT_STATS_REPLY, &buffer);
1403 osr->type = htons (cb->s->type);
1406 err = cb->s->DoDump (
this, cb->state, buffer);
1416 osr = (ofp_stats_reply*)ofpbuf_at_assert (buffer, 0,
sizeof *osr);
1417 osr->flags = ntohs (OFPSF_REPLY_MORE);
1420 int err2 = SendOpenflowBuffer (buffer);
1431 OpenFlowSwitchNetDevice::StatsDone (ofi::StatsDumpCallback *cb)
1435 cb->s->DoCleanup (cb->state);
1442 OpenFlowSwitchNetDevice::ReceiveStatsRequest (
const void *oh)
1444 const ofp_stats_request *rq = (ofp_stats_request*)oh;
1445 size_t rq_len = ntohs (rq->header.length);
1446 int type = ntohs (rq->type);
1447 int body_len = rq_len - offsetof (ofp_stats_request, body);
1448 ofi::Stats* st =
new ofi::Stats ((ofp_stats_types)type, (
unsigned)body_len);
1455 ofi::StatsDumpCallback cb;
1457 cb.rq = (ofp_stats_request*)xmemdup (rq, rq_len);
1464 int err = cb.s->DoInit (rq->body, body_len, &cb.state);
1467 NS_LOG_WARN (
"failed initialization of stats request type " << type <<
": " << strerror (-err));
1473 if (m_controller != 0)
1475 m_controller->StartDump (&cb);
1479 NS_LOG_ERROR (
"Switch needs to be registered to a controller in order to start the stats reply.");
1486 OpenFlowSwitchNetDevice::ReceiveEchoRequest (
const void *oh)
1488 return SendOpenflowBuffer (make_echo_reply ((ofp_header*)oh));
1492 OpenFlowSwitchNetDevice::ReceiveEchoReply (
const void *oh)
1498 OpenFlowSwitchNetDevice::ForwardControlInput (
const void *msg,
size_t length)
1501 ofp_header *oh = (ofp_header*) msg;
1502 if (ntohs (oh->length) > length)
1506 assert (oh->version == OFP_VERSION);
1513 case OFPT_FEATURES_REQUEST:
1514 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveFeaturesRequest (msg);
1516 case OFPT_GET_CONFIG_REQUEST:
1517 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveGetConfigRequest (msg);
1519 case OFPT_SET_CONFIG:
1520 error = length <
sizeof(ofp_switch_config) ? -EFAULT : ReceiveSetConfig (msg);
1522 case OFPT_PACKET_OUT:
1523 error = length <
sizeof(ofp_packet_out) ? -EFAULT : ReceivePacketOut (msg);
1526 error = length <
sizeof(ofp_flow_mod) ? -EFAULT : ReceiveFlow (msg);
1529 error = length <
sizeof(ofp_port_mod) ? -EFAULT : ReceivePortMod (msg);
1531 case OFPT_STATS_REQUEST:
1532 error = length <
sizeof(ofp_stats_request) ? -EFAULT : ReceiveStatsRequest (msg);
1534 case OFPT_ECHO_REQUEST:
1535 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveEchoRequest (msg);
1537 case OFPT_ECHO_REPLY:
1538 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveEchoReply (msg);
1540 case OFPT_VPORT_MOD:
1541 error = length <
sizeof(ofp_vport_mod) ? -EFAULT : ReceiveVPortMod (msg);
1543 case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1544 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveVPortTableFeaturesRequest (msg);
1547 SendErrorMsg ((ofp_error_type)OFPET_BAD_REQUEST, (ofp_bad_request_code)OFPBRC_BAD_TYPE, msg, length);
1553 free ((ofpbuf*)msg);
1559 OpenFlowSwitchNetDevice::GetChain ()
1565 OpenFlowSwitchNetDevice::GetNSwitchPorts (
void)
const 1568 return m_ports.size ();
1572 OpenFlowSwitchNetDevice::GetSwitchPort (uint32_t
n)
const 1579 OpenFlowSwitchNetDevice::GetSwitchPortIndex (ofi::Port p)
1581 for (
size_t i = 0; i < m_ports.size (); i++)
1583 if (m_ports[i].netdev == p.netdev)
1592 OpenFlowSwitchNetDevice::GetVPortTable ()
1594 return m_vportTable;
1599 #endif // NS3_OPENFLOW void discard_buffer(uint32_t id)
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
static const char * GetSerialNumber()
uint16_t m_flags
Flags; configurable by the controller.
bool IsMulticast(const Address &ad)
Address family-independent test for a multicast address.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
static const char * GetHardwareDescription()
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
ofpbuf * retrieve_buffer(uint32_t id)
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
static TypeId GetTypeId(void)
Register this type.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
static const char * GetManufacturerDescription()
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.
uint64_t m_id
Unique identifier for this switch, needed for OpenFlow.
#define OFP_SUPPORTED_ACTIONS
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
uint32_t save_buffer(ofpbuf *)
static const char * GetSoftwareDescription()
double f(double x, void *params)
#define OFP_SUPPORTED_VPORT_TABLE_ACTIONS
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
OpenFlowSwitchNetDevice()
uint16_t ValidateActions(const sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Validates a list of flow table actions.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
uint16_t ValidateVPortActions(const ofp_action_header *actions, size_t actions_len)
Validates a list of virtual port table entry actions.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
uint16_t m_missSendLen
Flow Table Miss Send Length; configurable by the controller.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define OFP_SUPPORTED_CAPABILITIES
Time m_lookupDelay
Flow Table Lookup Delay [overhead].