31 return "The ns-3 team";
43 return "Simulated OpenFlow Switch";
55 uint8_t ea[ETH_ADDR_LEN];
57 return eth_addr_to_uint64 (ea);
63 static TypeId tid = TypeId (
"ns3::OpenFlowSwitchNetDevice")
65 .AddConstructor<OpenFlowSwitchNetDevice> ()
67 "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for OpenFlow compatibility.",
68 UintegerValue (GenerateId ()),
70 MakeUintegerChecker<uint64_t> ())
72 "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.",
73 TimeValue (NanoSeconds (30)),
77 "Flags to turn different functionality on/off, such as whether to inform the controller when a flow expires, or how to handle fragments.",
80 MakeUintegerChecker<uint16_t> ())
82 "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.",
83 UintegerValue (OFP_DEFAULT_MISS_SEND_LEN),
85 MakeUintegerChecker<uint16_t> ())
97 m_channel = CreateObject<BridgeChannel> ();
105 m_chain = chain_create ();
108 NS_LOG_ERROR (
"Not enough memory to create the flow table.");
111 m_ports.reserve (DP_MAX_PORTS);
112 vport_table_init (&m_vportTable);
115 OpenFlowSwitchNetDevice::~OpenFlowSwitchNetDevice ()
121 OpenFlowSwitchNetDevice::DoDispose ()
125 for (Ports_t::iterator b = m_ports.begin (), e = m_ports.end (); b != e; b++)
127 SendPortStatus (*b, OFPPR_DELETE);
134 chain_destroy (m_chain);
135 RBTreeDestroy (m_vportTable.table);
138 NetDevice::DoDispose ();
142 OpenFlowSwitchNetDevice::SetController (Ptr<ofi::Controller> c)
144 if (m_controller != 0)
151 m_controller->AddSwitch (
this);
155 OpenFlowSwitchNetDevice::AddSwitchPort (Ptr<NetDevice> switchPort)
159 if (!Mac48Address::IsMatchingType (switchPort->GetAddress ()))
161 NS_FATAL_ERROR (
"Device does not support eui 48 addresses: cannot be added to switch.");
163 if (!switchPort->SupportsSendFrom ())
165 NS_FATAL_ERROR (
"Device does not support SendFrom: cannot be added to switch.");
167 if (m_address == Mac48Address ())
169 m_address = Mac48Address::ConvertFrom (switchPort->GetAddress ());
172 if (m_ports.size () < DP_MAX_PORTS)
176 p.netdev = switchPort;
177 m_ports.push_back (p);
180 SendPortStatus (p, OFPPR_ADD);
182 NS_LOG_DEBUG (
"RegisterProtocolHandler for " << switchPort->GetInstanceTypeId ().GetName ());
183 m_node->RegisterProtocolHandler (
MakeCallback (&OpenFlowSwitchNetDevice::ReceiveFromDevice,
this),
184 0, switchPort,
true);
185 m_channel->AddChannel (switchPort->GetChannel ());
196 OpenFlowSwitchNetDevice::SetIfIndex (
const uint32_t index)
203 OpenFlowSwitchNetDevice::GetIfIndex (
void)
const
210 OpenFlowSwitchNetDevice::GetChannel (
void)
const
217 OpenFlowSwitchNetDevice::SetAddress (Address
address)
220 m_address = Mac48Address::ConvertFrom (address);
224 OpenFlowSwitchNetDevice::GetAddress (
void)
const
231 OpenFlowSwitchNetDevice::SetMtu (
const uint16_t mtu)
239 OpenFlowSwitchNetDevice::GetMtu (
void)
const
247 OpenFlowSwitchNetDevice::IsLinkUp (
void)
const
255 OpenFlowSwitchNetDevice::AddLinkChangeCallback (Callback<void> callback)
260 OpenFlowSwitchNetDevice::IsBroadcast (
void)
const
267 OpenFlowSwitchNetDevice::GetBroadcast (
void)
const
270 return Mac48Address (
"ff:ff:ff:ff:ff:ff");
281 OpenFlowSwitchNetDevice::GetMulticast (Ipv4Address multicastGroup)
const
284 Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
290 OpenFlowSwitchNetDevice::IsPointToPoint (
void)
const
297 OpenFlowSwitchNetDevice::IsBridge (
void)
const
304 OpenFlowSwitchNetDevice::DoOutput (uint32_t packet_uid,
int in_port,
size_t max_len,
int out_port,
bool ignore_no_fwd)
306 if (out_port != OFPP_CONTROLLER)
308 OutputPort (packet_uid, in_port, out_port, ignore_no_fwd);
312 OutputControl (packet_uid, in_port, max_len, OFPR_ACTION);
317 OpenFlowSwitchNetDevice::Send (Ptr<Packet> packet,
const Address& dest, uint16_t protocolNumber)
320 return SendFrom (packet, m_address, dest, protocolNumber);
324 OpenFlowSwitchNetDevice::SendFrom (Ptr<Packet> packet,
const Address& src,
const Address& dest, uint16_t protocolNumber)
328 ofpbuf *buffer = BufferFromPacket (packet,src,dest,GetMtu (),protocolNumber);
331 ofi::SwitchPacketMetadata
data;
332 data.packet = packet;
333 data.buffer = buffer;
334 data.protocolNumber = protocolNumber;
335 data.src = Address (src);
336 data.dst = Address (dest);
337 m_packetData.insert (std::make_pair (packet_uid, data));
339 RunThroughFlowTable (packet_uid, -1);
346 OpenFlowSwitchNetDevice::GetNode (
void)
const
353 OpenFlowSwitchNetDevice::SetNode (Ptr<Node> node)
360 OpenFlowSwitchNetDevice::NeedsArp (
void)
const
367 OpenFlowSwitchNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
374 OpenFlowSwitchNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
377 m_promiscRxCallback = cb;
381 OpenFlowSwitchNetDevice::SupportsSendFrom ()
const
388 OpenFlowSwitchNetDevice::GetMulticast (Ipv6Address addr)
const
391 return Mac48Address::GetMulticast (addr);
396 OpenFlowSwitchNetDevice::AddVPort (
const ofp_vport_mod *ovpm)
398 size_t actions_len = ntohs (ovpm->header.length) -
sizeof *ovpm;
399 unsigned int vport = ntohl (ovpm->vport);
400 unsigned int parent_port = ntohl (ovpm->parent_port);
403 vport_table_entry *vpe = vport_table_lookup (&m_vportTable, vport);
407 SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
413 if (v_code != ACT_VALIDATION_OK)
415 SendErrorMsg (OFPET_BAD_ACTION, v_code, ovpm, ntohs (ovpm->header.length));
419 vpe = vport_table_entry_alloc (actions_len);
422 vpe->parent_port = parent_port;
423 if (vport < OFPP_VP_START || vport > OFPP_VP_END)
425 NS_LOG_ERROR (
"port " << vport <<
" is not in the virtual port range (" << OFPP_VP_START <<
"-" << OFPP_VP_END <<
")");
426 SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
427 free_vport_table_entry (vpe);
431 vpe->port_acts->actions_len = actions_len;
432 memcpy (vpe->port_acts->actions, ovpm->actions, actions_len);
434 int error = insert_vport_table_entry (&m_vportTable, vpe);
437 NS_LOG_ERROR (
"could not insert port table entry for port " << vport);
444 OpenFlowSwitchNetDevice::BufferFromPacket (Ptr<Packet> packet, Address src, Address dst,
int mtu, uint16_t protocol)
446 NS_LOG_INFO (
"Creating Openflow buffer from packet.");
453 const int headroom = 128 + 2;
454 const int hard_header = VLAN_ETH_HEADER_LEN;
455 ofpbuf *buffer = ofpbuf_new (headroom + hard_header + mtu);
456 buffer->data = (
char*)buffer->data + headroom + hard_header;
458 int l2_length = 0, l3_length = 0, l4_length = 0;
461 EthernetHeader eth_hd;
462 if (packet->PeekHeader (eth_hd))
464 buffer->l2 =
new eth_header;
465 eth_header* eth_h = (eth_header*)buffer->l2;
466 dst.CopyTo (eth_h->eth_dst);
467 src.CopyTo (eth_h->eth_src);
468 eth_h->eth_type = htons (ETH_TYPE_IP);
471 l2_length = ETH_HEADER_LEN;
475 if (protocol == Ipv4L3Protocol::PROT_NUMBER)
478 if (packet->PeekHeader (ip_hd))
480 buffer->l3 =
new ip_header;
481 ip_header* ip_h = (ip_header*)buffer->l3;
482 ip_h->ip_ihl_ver = IP_IHL_VER (5, IP_VERSION);
483 ip_h->ip_tos = ip_hd.GetTos ();
484 ip_h->ip_tot_len = packet->GetSize ();
485 ip_h->ip_id = ip_hd.GetIdentification ();
486 ip_h->ip_frag_off = ip_hd.GetFragmentOffset ();
487 ip_h->ip_ttl = ip_hd.GetTtl ();
488 ip_h->ip_proto = ip_hd.GetProtocol ();
489 ip_h->ip_src = htonl (ip_hd.GetSource ().Get ());
490 ip_h->ip_dst = htonl (ip_hd.GetDestination ().Get ());
491 ip_h->ip_csum = csum (&ip_h,
sizeof ip_h);
494 l3_length = IP_HEADER_LEN;
501 if (packet->PeekHeader (arp_hd))
503 buffer->l3 =
new arp_eth_header;
504 arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
505 arp_h->ar_hrd = ARP_HRD_ETHERNET;
506 arp_h->ar_pro = ARP_PRO_IP;
507 arp_h->ar_op = arp_hd.m_type;
508 arp_hd.GetDestinationHardwareAddress ().CopyTo (arp_h->ar_tha);
509 arp_hd.GetSourceHardwareAddress ().CopyTo (arp_h->ar_sha);
510 arp_h->ar_tpa = arp_hd.GetDestinationIpv4Address ().Get ();
511 arp_h->ar_spa = arp_hd.GetSourceIpv4Address ().Get ();
512 arp_h->ar_hln =
sizeof arp_h->ar_tha;
513 arp_h->ar_pln =
sizeof arp_h->ar_tpa;
516 l3_length = ARP_ETH_HEADER_LEN;
521 if (packet->PeekHeader (tcp_hd))
523 buffer->l4 =
new tcp_header;
524 tcp_header* tcp_h = (tcp_header*)buffer->l4;
525 tcp_h->tcp_src = htons (tcp_hd.GetSourcePort ());
526 tcp_h->tcp_dst = htons (tcp_hd.GetDestinationPort ());
527 tcp_h->tcp_seq = tcp_hd.GetSequenceNumber ().GetValue ();
528 tcp_h->tcp_ack = tcp_hd.GetAckNumber ().GetValue ();
529 tcp_h->tcp_ctl = TCP_FLAGS (tcp_hd.GetFlags ());
530 tcp_h->tcp_winsz = tcp_hd.GetWindowSize ();
531 tcp_h->tcp_urg = tcp_hd.GetUrgentPointer ();
532 tcp_h->tcp_csum = csum (&tcp_h,
sizeof tcp_h);
535 l4_length = TCP_HEADER_LEN;
540 if (packet->PeekHeader (udp_hd))
542 buffer->l4 =
new udp_header;
543 udp_header* udp_h = (udp_header*)buffer->l4;
544 udp_h->udp_src = htons (udp_hd.GetSourcePort ());
545 udp_h->udp_dst = htons (udp_hd.GetDestinationPort ());
546 udp_h->udp_len = htons (UDP_HEADER_LEN + packet->GetSize ());
548 if (protocol == Ipv4L3Protocol::PROT_NUMBER)
550 ip_header* ip_h = (ip_header*)buffer->l3;
551 uint32_t udp_csum = csum_add32 (0, ip_h->ip_src);
552 udp_csum = csum_add32 (udp_csum, ip_h->ip_dst);
553 udp_csum = csum_add16 (udp_csum, IP_TYPE_UDP << 8);
554 udp_csum = csum_add16 (udp_csum, udp_h->udp_len);
555 udp_csum = csum_continue (udp_csum, udp_h,
sizeof udp_h);
556 udp_h->udp_csum = csum_finish (csum_continue (udp_csum, buffer->data, buffer->size));
560 udp_h->udp_csum = htons (0);
564 l4_length = UDP_HEADER_LEN;
569 packet->CopyData ((uint8_t*)buffer->data, packet->GetSize ());
573 ofpbuf_push (buffer, buffer->l4, l4_length);
574 delete (tcp_header*)buffer->l4;
578 ofpbuf_push (buffer, buffer->l3, l3_length);
579 delete (ip_header*)buffer->l3;
583 ofpbuf_push (buffer, buffer->l2, l2_length);
584 delete (eth_header*)buffer->l2;
591 OpenFlowSwitchNetDevice::ReceiveFromDevice (Ptr<NetDevice> netdev, Ptr<const Packet> packet, uint16_t protocol,
592 const Address& src,
const Address& dst, PacketType packetType)
595 NS_LOG_INFO (
"--------------------------------------------");
598 if (!m_promiscRxCallback.IsNull ())
600 m_promiscRxCallback (
this, packet, protocol, src, dst, packetType);
603 Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
604 NS_LOG_INFO (
"Received packet from " << Mac48Address::ConvertFrom (src) <<
" looking for " << dst48);
606 for (
size_t i = 0; i < m_ports.size (); i++)
608 if (m_ports[i].netdev == netdev)
610 if (packetType == PACKET_HOST && dst48 == m_address)
612 m_rxCallback (
this, packet, protocol, src);
614 else if (packetType == PACKET_BROADCAST || packetType == PACKET_MULTICAST || packetType == PACKET_OTHERHOST)
616 if (packetType == PACKET_OTHERHOST && dst48 == m_address)
618 m_rxCallback (
this, packet, protocol, src);
622 if (packetType != PACKET_OTHERHOST)
624 m_rxCallback (
this, packet, protocol, src);
627 ofi::SwitchPacketMetadata
data;
628 data.packet = packet->Copy ();
630 ofpbuf *buffer = BufferFromPacket (data.packet,src,dst,netdev->GetMtu (),protocol);
631 m_ports[i].rx_packets++;
632 m_ports[i].rx_bytes += buffer->size;
633 data.buffer = buffer;
636 data.protocolNumber = protocol;
637 data.src = Address (src);
638 data.dst = Address (dst);
639 m_packetData.insert (std::make_pair (packet_uid, data));
641 RunThroughFlowTable (packet_uid, i);
651 if (now >=
Seconds (m_lastExecute.GetSeconds () + 1))
654 for (
size_t i = 0; i < m_ports.size (); i++)
656 if (UpdatePortStatus (m_ports[i]))
658 SendPortStatus (m_ports[i], OFPPR_MODIFY);
663 List deleted = LIST_INITIALIZER (&deleted);
665 chain_timeout (m_chain, &deleted);
666 LIST_FOR_EACH_SAFE (f, n, sw_flow, node, &deleted)
668 std::ostringstream str;
670 for (
int i = 0; i < 6; i++)
671 str << (i!=0 ?
":" :
"") << std::hex << f->key.flow.dl_src[i]/16 << f->key.flow.dl_src[i]%16;
673 for (
int i = 0; i < 6; i++)
674 str << (i!=0 ?
":" :
"") << std::hex << f->key.flow.dl_dst[i]/16 << f->key.flow.dl_dst[i]%16;
678 SendFlowExpired (f, (ofp_flow_expired_reason)f->reason);
679 list_remove (&f->node);
688 OpenFlowSwitchNetDevice::OutputAll (uint32_t packet_uid,
int in_port,
bool flood)
694 for (
size_t i = 0; i < m_ports.size (); i++)
696 if (i == (
unsigned)in_port)
700 if (flood && m_ports[i].config & OFPPC_NO_FLOOD)
706 OutputPort (packet_uid, in_port, prev_port,
false);
712 OutputPort (packet_uid, in_port, prev_port,
false);
719 OpenFlowSwitchNetDevice::OutputPacket (uint32_t packet_uid,
int out_port)
721 if (out_port >= 0 && out_port < DP_MAX_PORTS)
723 ofi::Port& p = m_ports[out_port];
724 if (p.netdev != 0 && !(p.config & OFPPC_PORT_DOWN))
726 ofi::SwitchPacketMetadata data = m_packetData.find (packet_uid)->second;
727 size_t bufsize = data.buffer->size;
728 NS_LOG_INFO (
"Sending packet " << data.packet->GetUid () <<
" over port " << out_port);
729 if (p.netdev->SendFrom (data.packet->Copy (), data.src, data.dst, data.protocolNumber))
732 p.tx_bytes += bufsize;
742 NS_LOG_DEBUG (
"can't forward to bad port " << out_port);
746 OpenFlowSwitchNetDevice::OutputPort (uint32_t packet_uid,
int in_port,
int out_port,
bool ignore_no_fwd)
750 if (out_port == OFPP_FLOOD)
752 OutputAll (packet_uid, in_port,
true);
754 else if (out_port == OFPP_ALL)
756 OutputAll (packet_uid, in_port,
false);
758 else if (out_port == OFPP_CONTROLLER)
760 OutputControl (packet_uid, in_port, 0, OFPR_ACTION);
762 else if (out_port == OFPP_IN_PORT)
764 OutputPacket (packet_uid, in_port);
766 else if (out_port == OFPP_TABLE)
768 RunThroughFlowTable (packet_uid, in_port < DP_MAX_PORTS ? in_port : -1,
false);
770 else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
773 NS_LOG_INFO (
"packet sent to virtual port " << out_port);
774 if (in_port < DP_MAX_PORTS)
776 RunThroughVPortTable (packet_uid, in_port, out_port);
780 RunThroughVPortTable (packet_uid, -1, out_port);
783 else if (in_port == out_port)
789 OutputPacket (packet_uid, out_port);
794 OpenFlowSwitchNetDevice::MakeOpenflowReply (
size_t openflow_len, uint8_t type, ofpbuf **bufferp)
796 return make_openflow_xid (openflow_len, type, 0, bufferp);
800 OpenFlowSwitchNetDevice::SendOpenflowBuffer (ofpbuf *buffer)
802 if (m_controller != 0)
804 update_openflow_length (buffer);
805 m_controller->ReceiveFromSwitch (
this, buffer);
812 OpenFlowSwitchNetDevice::OutputControl (uint32_t packet_uid,
int in_port,
size_t max_len,
int reason)
816 ofpbuf* buffer = m_packetData.find (packet_uid)->second.buffer;
817 size_t total_len = buffer->size;
818 if (packet_uid != std::numeric_limits<uint32_t>::max () && max_len != 0 && buffer->size > max_len)
820 buffer->size = max_len;
823 ofp_packet_in *opi = (ofp_packet_in*)ofpbuf_push_uninit (buffer, offsetof (ofp_packet_in, data));
824 opi->header.version = OFP_VERSION;
825 opi->header.type = OFPT_PACKET_IN;
826 opi->header.length = htons (buffer->size);
827 opi->header.xid = htonl (0);
828 opi->buffer_id = htonl (packet_uid);
829 opi->total_len = htons (total_len);
830 opi->in_port = htons (in_port);
831 opi->reason = reason;
833 SendOpenflowBuffer (buffer);
837 OpenFlowSwitchNetDevice::FillPortDesc (ofi::Port p, ofp_phy_port *desc)
839 desc->port_no = htons (GetSwitchPortIndex (p));
841 std::ostringstream nm;
842 nm <<
"eth" << GetSwitchPortIndex (p);
843 strncpy ((
char *)desc->name, nm.str ().c_str (),
sizeof desc->name);
845 p.netdev->GetAddress ().CopyTo (desc->hw_addr);
846 desc->config = htonl (p.config);
847 desc->state = htonl (p.state);
852 desc->advertised = 0;
857 OpenFlowSwitchNetDevice::SendFeaturesReply ()
860 ofp_switch_features *ofr = (ofp_switch_features*)MakeOpenflowReply (
sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
861 ofr->datapath_id = htonll (m_id);
862 ofr->n_tables = m_chain->n_tables;
867 for (
size_t i = 0; i < m_ports.size (); i++)
869 ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros (buffer,
sizeof *opp);
870 FillPortDesc (m_ports[i], opp);
873 SendOpenflowBuffer (buffer);
877 OpenFlowSwitchNetDevice::SendVPortTableFeatures ()
880 ofp_vport_table_features *ovtfr = (ofp_vport_table_features*)MakeOpenflowReply (
sizeof *ovtfr, OFPT_VPORT_TABLE_FEATURES_REPLY, &buffer);
882 ovtfr->max_vports = htonl (m_vportTable.max_vports);
883 ovtfr->max_chain_depth = htons (-1);
884 ovtfr->mixed_chaining =
true;
885 SendOpenflowBuffer (buffer);
889 OpenFlowSwitchNetDevice::UpdatePortStatus (ofi::Port& p)
891 uint32_t orig_config = p.config;
892 uint32_t orig_state = p.state;
895 p.config &= ~OFPPC_PORT_DOWN;
897 if (p.netdev->IsLinkUp ())
899 p.state &= ~OFPPS_LINK_DOWN;
903 p.state |= OFPPS_LINK_DOWN;
906 return ((orig_config != p.config) || (orig_state != p.state));
910 OpenFlowSwitchNetDevice::SendPortStatus (ofi::Port p, uint8_t status)
913 ofp_port_status *ops = (ofp_port_status*)MakeOpenflowReply (
sizeof *ops, OFPT_PORT_STATUS, &buffer);
914 ops->reason = status;
915 memset (ops->pad, 0,
sizeof ops->pad);
916 FillPortDesc (p, &ops->desc);
918 SendOpenflowBuffer (buffer);
919 ofpbuf_delete (buffer);
923 OpenFlowSwitchNetDevice::SendFlowExpired (sw_flow *flow,
enum ofp_flow_expired_reason reason)
926 ofp_flow_expired *ofe = (ofp_flow_expired*)MakeOpenflowReply (
sizeof *ofe, OFPT_FLOW_EXPIRED, &buffer);
927 flow_fill_match (&ofe->match, &flow->key);
929 ofe->priority = htons (flow->priority);
930 ofe->reason = reason;
931 memset (ofe->pad, 0,
sizeof ofe->pad);
933 ofe->duration = htonl (time_now () - flow->created);
934 memset (ofe->pad2, 0,
sizeof ofe->pad2);
935 ofe->packet_count = htonll (flow->packet_count);
936 ofe->byte_count = htonll (flow->byte_count);
937 SendOpenflowBuffer (buffer);
941 OpenFlowSwitchNetDevice::SendErrorMsg (uint16_t type, uint16_t code,
const void *data,
size_t len)
944 ofp_error_msg *oem = (ofp_error_msg*)MakeOpenflowReply (
sizeof(*oem) + len, OFPT_ERROR, &buffer);
945 oem->type = htons (type);
946 oem->code = htons (code);
947 memcpy (oem->data, data, len);
948 SendOpenflowBuffer (buffer);
952 OpenFlowSwitchNetDevice::FlowTableLookup (sw_flow_key key, ofpbuf* buffer, uint32_t packet_uid,
int port,
bool send_to_controller)
954 sw_flow *flow = chain_lookup (m_chain, &key);
958 flow_used (flow, buffer);
959 ofi::ExecuteActions (
this, packet_uid, buffer, &key, flow->sf_acts->actions, flow->sf_acts->actions_len,
false);
965 if (send_to_controller)
967 OutputControl (packet_uid, port, m_missSendLen, OFPR_NO_MATCH);
972 m_packetData.erase (packet_uid);
974 ofpbuf_delete (buffer);
978 OpenFlowSwitchNetDevice::RunThroughFlowTable (uint32_t packet_uid,
int port,
bool send_to_controller)
980 ofi::SwitchPacketMetadata data = m_packetData.find (packet_uid)->second;
981 ofpbuf* buffer = data.buffer;
986 if (flow_extract (buffer, port != -1 ? port : OFPP_NONE, &key.flow) && (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
988 ofpbuf_delete (buffer);
996 mpls_h.value = ntohl (*((uint32_t*)buffer->l2_5));
1002 m_ports[
port].mpls_ttl0_dropped++;
1011 uint32_t config = m_ports[
port].config;
1012 if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP)
1013 && config & (!eth_addr_equals (key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV : OFPPC_NO_RECV_STP))
1020 Simulator::Schedule (m_lookupDelay, &OpenFlowSwitchNetDevice::FlowTableLookup,
this, key, buffer, packet_uid, port, send_to_controller);
1024 OpenFlowSwitchNetDevice::RunThroughVPortTable (uint32_t packet_uid,
int port, uint32_t vport)
1026 ofpbuf* buffer = m_packetData.find (packet_uid)->second.buffer;
1032 if (flow_extract (buffer, port != -1 ? port : OFPP_NONE, &key.flow)
1033 && (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1039 vport_table_entry *vpe = vport_table_lookup (&m_vportTable, vport);
1040 m_vportTable.lookup_count++;
1043 m_vportTable.port_match_count++;
1047 ofi::ExecuteVPortActions (
this, packet_uid, m_packetData.find (packet_uid)->second.buffer, &key, vpe->port_acts->actions, vpe->port_acts->actions_len);
1048 vport_used (vpe, buffer);
1049 if (vpe->parent_port_ptr == 0)
1053 if (vpe->parent_port <= OFPP_VP_START)
1055 OutputPort (packet_uid, port != -1 ? port : OFPP_NONE, vpe->parent_port,
false);
1064 m_vportTable.chain_match_count++;
1067 vpe = vpe->parent_port_ptr;
1074 OpenFlowSwitchNetDevice::ReceiveFeaturesRequest (
const void *msg)
1076 SendFeaturesReply ();
1081 OpenFlowSwitchNetDevice::ReceiveVPortTableFeaturesRequest (
const void *msg)
1083 SendVPortTableFeatures ();
1088 OpenFlowSwitchNetDevice::ReceiveGetConfigRequest (
const void *msg)
1091 ofp_switch_config *osc = (ofp_switch_config*)MakeOpenflowReply (
sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
1092 osc->flags = htons (m_flags);
1093 osc->miss_send_len = htons (m_missSendLen);
1095 return SendOpenflowBuffer (buffer);
1099 OpenFlowSwitchNetDevice::ReceiveSetConfig (
const void *msg)
1101 const ofp_switch_config *osc = (ofp_switch_config*)msg;
1103 int n_flags = ntohs (osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
1104 if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL && (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
1106 n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1110 m_missSendLen = ntohs (osc->miss_send_len);
1115 OpenFlowSwitchNetDevice::ReceivePacketOut (
const void *msg)
1117 const ofp_packet_out *opo = (ofp_packet_out*)msg;
1119 size_t actions_len = ntohs (opo->actions_len);
1121 if (actions_len > (ntohs (opo->header.length) -
sizeof *opo))
1123 NS_LOG_DEBUG (
"message too short for number of actions");
1127 if (ntohl (opo->buffer_id) == (uint32_t) -1)
1130 int data_len = ntohs (opo->header.length) -
sizeof *opo - actions_len;
1131 buffer = ofpbuf_new (data_len);
1132 ofpbuf_put (buffer, (uint8_t *)opo->actions + actions_len, data_len);
1144 flow_extract (buffer, opo->in_port, &key.flow);
1147 if (v_code != ACT_VALIDATION_OK)
1149 SendErrorMsg (OFPET_BAD_ACTION, v_code, msg, ntohs (opo->header.length));
1150 ofpbuf_delete (buffer);
1154 ofi::ExecuteActions (
this, opo->buffer_id, buffer, &key, opo->actions, actions_len,
true);
1159 OpenFlowSwitchNetDevice::ReceivePortMod (
const void *msg)
1161 ofp_port_mod* opm = (ofp_port_mod*)msg;
1163 int port = opm->port_no;
1164 if (port < DP_MAX_PORTS)
1166 ofi::Port& p = m_ports[
port];
1169 Mac48Address hw_addr = Mac48Address ();
1170 hw_addr.CopyFrom (opm->hw_addr);
1171 if (p.netdev->GetAddress () != hw_addr)
1178 uint32_t config_mask = ntohl (opm->mask);
1179 p.config &= ~config_mask;
1180 p.config |= ntohl (opm->config) & config_mask;
1183 if (opm->mask & htonl (OFPPC_PORT_DOWN))
1185 if ((opm->config & htonl (OFPPC_PORT_DOWN)) && (p.config & OFPPC_PORT_DOWN) == 0)
1187 p.config |= OFPPC_PORT_DOWN;
1190 else if ((opm->config & htonl (OFPPC_PORT_DOWN)) == 0 && (p.config & OFPPC_PORT_DOWN))
1192 p.config &= ~OFPPC_PORT_DOWN;
1203 OpenFlowSwitchNetDevice::ReceiveVPortMod (
const void *msg)
1205 const ofp_vport_mod *ovpm = (ofp_vport_mod*)msg;
1207 uint16_t command = ntohs (ovpm->command);
1208 if (command == OFPVP_ADD)
1210 return AddVPort (ovpm);
1212 else if (command == OFPVP_DELETE)
1214 if (remove_vport_table_entry (&m_vportTable, ntohl (ovpm->vport)))
1216 SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
1224 OpenFlowSwitchNetDevice::AddFlow (
const ofp_flow_mod *ofm)
1226 size_t actions_len = ntohs (ofm->header.length) -
sizeof *ofm;
1229 sw_flow *flow = flow_alloc (actions_len);
1232 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1239 flow_extract_match (&flow->key, &ofm->match);
1242 if (v_code != ACT_VALIDATION_OK)
1244 SendErrorMsg (OFPET_BAD_ACTION, v_code, ofm, ntohs (ofm->header.length));
1246 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1254 flow->priority = flow->key.wildcards ? ntohs (ofm->priority) : -1;
1255 flow->idle_timeout = ntohs (ofm->idle_timeout);
1256 flow->hard_timeout = ntohs (ofm->hard_timeout);
1257 flow->used = flow->created = time_now ();
1258 flow->sf_acts->actions_len = actions_len;
1259 flow->byte_count = 0;
1260 flow->packet_count = 0;
1261 memcpy (flow->sf_acts->actions, ofm->actions, actions_len);
1264 int error = chain_insert (m_chain, flow);
1267 if (error == -ENOBUFS)
1269 SendErrorMsg (OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL, ofm, ntohs (ofm->header.length));
1272 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1280 if (ntohl (ofm->buffer_id) != std::numeric_limits<uint32_t>::max ())
1286 flow_used (flow, buffer);
1287 flow_extract (buffer, ofm->match.in_port, &key.flow);
1288 ofi::ExecuteActions (
this, ofm->buffer_id, buffer, &key, ofm->actions, actions_len,
false);
1289 ofpbuf_delete (buffer);
1300 OpenFlowSwitchNetDevice::ModFlow (
const ofp_flow_mod *ofm)
1303 flow_extract_match (&key, &ofm->match);
1305 size_t actions_len = ntohs (ofm->header.length) -
sizeof *ofm;
1308 if (v_code != ACT_VALIDATION_OK)
1310 SendErrorMsg ((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs (ofm->header.length));
1311 if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1318 uint16_t priority = key.wildcards ? ntohs (ofm->priority) : -1;
1319 int strict = (ofm->command == htons (OFPFC_MODIFY_STRICT)) ? 1 : 0;
1320 chain_modify (m_chain, &key, priority, strict, ofm->actions, actions_len);
1322 if (ntohl (ofm->buffer_id) != std::numeric_limits<uint32_t>::max ())
1327 sw_flow_key skb_key;
1328 flow_extract (buffer, ofm->match.in_port, &skb_key.flow);
1329 ofi::ExecuteActions (
this, ofm->buffer_id, buffer, &skb_key, ofm->actions, actions_len,
false);
1330 ofpbuf_delete (buffer);
1341 OpenFlowSwitchNetDevice::ReceiveFlow (
const void *msg)
1344 const ofp_flow_mod *ofm = (ofp_flow_mod*)msg;
1345 uint16_t command = ntohs (ofm->command);
1347 if (command == OFPFC_ADD)
1349 return AddFlow (ofm);
1351 else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1353 return ModFlow (ofm);
1355 else if (command == OFPFC_DELETE)
1358 flow_extract_match (&key, &ofm->match);
1359 return chain_delete (m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1361 else if (command == OFPFC_DELETE_STRICT)
1365 flow_extract_match (&key, &ofm->match);
1366 priority = key.wildcards ? ntohs (ofm->priority) : -1;
1367 return chain_delete (m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
1376 OpenFlowSwitchNetDevice::StatsDump (ofi::StatsDumpCallback *cb)
1378 ofp_stats_reply *osr;
1387 osr = (ofp_stats_reply*)MakeOpenflowReply (
sizeof *osr, OFPT_STATS_REPLY, &buffer);
1388 osr->type = htons (cb->s->type);
1391 err = cb->s->DoDump (
this, cb->state, buffer);
1401 osr = (ofp_stats_reply*)ofpbuf_at_assert (buffer, 0,
sizeof *osr);
1402 osr->flags = ntohs (OFPSF_REPLY_MORE);
1405 int err2 = SendOpenflowBuffer (buffer);
1416 OpenFlowSwitchNetDevice::StatsDone (ofi::StatsDumpCallback *cb)
1420 cb->s->DoCleanup (cb->state);
1427 OpenFlowSwitchNetDevice::ReceiveStatsRequest (
const void *oh)
1429 const ofp_stats_request *rq = (ofp_stats_request*)oh;
1430 size_t rq_len = ntohs (rq->header.length);
1431 int type = ntohs (rq->type);
1432 int body_len = rq_len - offsetof (ofp_stats_request, body);
1433 ofi::Stats* st =
new ofi::Stats ((ofp_stats_types)type, (
unsigned)body_len);
1440 ofi::StatsDumpCallback cb;
1442 cb.rq = (ofp_stats_request*)xmemdup (rq, rq_len);
1449 int err = cb.s->DoInit (rq->body, body_len, &cb.state);
1452 NS_LOG_WARN (
"failed initialization of stats request type " << type <<
": " << strerror (-err));
1458 if (m_controller != 0)
1460 m_controller->StartDump (&cb);
1464 NS_LOG_ERROR (
"Switch needs to be registered to a controller in order to start the stats reply.");
1471 OpenFlowSwitchNetDevice::ReceiveEchoRequest (
const void *oh)
1473 return SendOpenflowBuffer (make_echo_reply ((ofp_header*)oh));
1477 OpenFlowSwitchNetDevice::ReceiveEchoReply (
const void *oh)
1483 OpenFlowSwitchNetDevice::ForwardControlInput (
const void *msg,
size_t length)
1486 ofp_header *oh = (ofp_header*) msg;
1487 if (ntohs (oh->length) > length)
1491 assert (oh->version == OFP_VERSION);
1498 case OFPT_FEATURES_REQUEST:
1499 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveFeaturesRequest (msg);
1501 case OFPT_GET_CONFIG_REQUEST:
1502 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveGetConfigRequest (msg);
1504 case OFPT_SET_CONFIG:
1505 error = length <
sizeof(ofp_switch_config) ? -EFAULT : ReceiveSetConfig (msg);
1507 case OFPT_PACKET_OUT:
1508 error = length <
sizeof(ofp_packet_out) ? -EFAULT : ReceivePacketOut (msg);
1511 error = length <
sizeof(ofp_flow_mod) ? -EFAULT : ReceiveFlow (msg);
1514 error = length <
sizeof(ofp_port_mod) ? -EFAULT : ReceivePortMod (msg);
1516 case OFPT_STATS_REQUEST:
1517 error = length <
sizeof(ofp_stats_request) ? -EFAULT : ReceiveStatsRequest (msg);
1519 case OFPT_ECHO_REQUEST:
1520 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveEchoRequest (msg);
1522 case OFPT_ECHO_REPLY:
1523 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveEchoReply (msg);
1525 case OFPT_VPORT_MOD:
1526 error = length <
sizeof(ofp_vport_mod) ? -EFAULT : ReceiveVPortMod (msg);
1528 case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1529 error = length <
sizeof(ofp_header) ? -EFAULT : ReceiveVPortTableFeaturesRequest (msg);
1532 SendErrorMsg ((ofp_error_type)OFPET_BAD_REQUEST, (ofp_bad_request_code)OFPBRC_BAD_TYPE, msg, length);
1538 free ((ofpbuf*)msg);
1544 OpenFlowSwitchNetDevice::GetChain ()
1550 OpenFlowSwitchNetDevice::GetNSwitchPorts (
void)
const
1553 return m_ports.size ();
1557 OpenFlowSwitchNetDevice::GetSwitchPort (uint32_t n)
const
1564 OpenFlowSwitchNetDevice::GetSwitchPortIndex (ofi::Port p)
1566 for (
size_t i = 0; i < m_ports.size (); i++)
1568 if (m_ports[i].netdev == p.netdev)
1577 OpenFlowSwitchNetDevice::GetVPortTable ()
1579 return m_vportTable;
1584 #endif // NS3_OPENFLOW
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
void discard_buffer(uint32_t id)
#define NS_LOG_FUNCTION(parameters)
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.
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)
#define NS_LOG_COMPONENT_DEFINE(name)
static const char * GetHardwareDescription()
#define NS_LOG_FUNCTION_NOARGS()
ofpbuf * retrieve_buffer(uint32_t id)
#define NS_FATAL_ERROR(msg)
fatal error handling
static TypeId GetTypeId(void)
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
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
uint32_t save_buffer(ofpbuf *)
static const char * GetSoftwareDescription()
TypeId AddAttribute(std::string name, std::string help, const AttributeValue &initialValue, Ptr< const AttributeAccessor > accessor, Ptr< const AttributeChecker > checker)
#define OFP_SUPPORTED_VPORT_TABLE_ACTIONS
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.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
#define NS_LOG_DEBUG(msg)
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range. Both limits are inclusive.
#define NS_LOG_ERROR(msg)
uint16_t ValidateVPortActions(const ofp_action_header *actions, size_t actions_len)
Validates a list of virtual port table entry actions.
uint16_t m_missSendLen
Flow Table Miss Send Length; configurable by the controller.
TypeId SetParent(TypeId tid)
#define OFP_SUPPORTED_CAPABILITIES
Time m_lookupDelay
Flow Table Lookup Delay [overhead].