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].