1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  *
16  * Author: Blake Hurd  <naimorai@gmail.com>
17  */
18 #ifdef NS3_OPENFLOW
19 
20 #include "openflow-switch-net-device.h"
21 #include "ns3/udp-l4-protocol.h"
22 #include "ns3/tcp-l4-protocol.h"
23 
24 namespace ns3 {
25 
26 NS_LOG_COMPONENT_DEFINE ("OpenFlowSwitchNetDevice");
27 
28 NS_OBJECT_ENSURE_REGISTERED (OpenFlowSwitchNetDevice);
29 
30 const char *
GetManufacturerDescription()31 OpenFlowSwitchNetDevice::GetManufacturerDescription ()
32 {
33   return "The ns-3 team";
34 }
35 
36 const char *
GetHardwareDescription()37 OpenFlowSwitchNetDevice::GetHardwareDescription ()
38 {
39   return "N/A";
40 }
41 
42 const char *
GetSoftwareDescription()43 OpenFlowSwitchNetDevice::GetSoftwareDescription ()
44 {
45   return "Simulated OpenFlow Switch";
46 }
47 
48 const char *
GetSerialNumber()49 OpenFlowSwitchNetDevice::GetSerialNumber ()
50 {
51   return "N/A";
52 }
53 
54 static uint64_t
GenerateId()55 GenerateId ()
56 {
57   uint8_t ea[ETH_ADDR_LEN];
58   eth_addr_random (ea);
59   return eth_addr_to_uint64 (ea);
60 }
61 
62 TypeId
GetTypeId(void)63 OpenFlowSwitchNetDevice::GetTypeId (void)
64 {
65   static TypeId tid = TypeId ("ns3::OpenFlowSwitchNetDevice")
66     .SetParent<NetDevice> ()
67     .SetGroupName ("Openflow")
68     .AddConstructor<OpenFlowSwitchNetDevice> ()
69     .AddAttribute ("ID",
70                    "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for OpenFlow compatibility.",
71                    UintegerValue (GenerateId ()),
72                    MakeUintegerAccessor (&OpenFlowSwitchNetDevice::m_id),
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.",
76                    TimeValue (NanoSeconds (30)),
77                    MakeTimeAccessor (&OpenFlowSwitchNetDevice::m_lookupDelay),
78                    MakeTimeChecker ())
79     .AddAttribute ("Flags", // Note: The Controller can configure this value, overriding the user's setting.
80                    "Flags to turn different functionality on/off, such as whether to inform the controller when a flow expires, or how to handle fragments.",
81                    UintegerValue (0), // Look at the ofp_config_flags enum in openflow/include/openflow.h for options.
82                    MakeUintegerAccessor (&OpenFlowSwitchNetDevice::m_flags),
83                    MakeUintegerChecker<uint16_t> ())
84     .AddAttribute ("FlowTableMissSendLength", // Note: The Controller can configure this value, overriding the user's setting.
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), // 128 bytes
87                    MakeUintegerAccessor (&OpenFlowSwitchNetDevice::m_missSendLen),
88                    MakeUintegerChecker<uint16_t> ())
89   ;
90   return tid;
91 }
92 
OpenFlowSwitchNetDevice()93 OpenFlowSwitchNetDevice::OpenFlowSwitchNetDevice ()
94   : m_node (0),
95     m_ifIndex (0),
96     m_mtu (0xffff)
97 {
98   NS_LOG_FUNCTION_NOARGS ();
99 
100   m_channel = CreateObject<BridgeChannel> ();
101 
102   time_init (); // OFSI's clock; needed to use the buffer storage system.
103   // m_lastTimeout = time_now ();
104 
105   m_controller = 0;
106   // m_listenPVConn = 0;
107 
108   m_chain = chain_create ();
109   if (m_chain == 0)
110     {
111       NS_LOG_ERROR ("Not enough memory to create the flow table.");
112     }
113 
114   m_ports.reserve (DP_MAX_PORTS);
115   vport_table_init (&m_vportTable);
116 }
117 
~OpenFlowSwitchNetDevice()118 OpenFlowSwitchNetDevice::~OpenFlowSwitchNetDevice ()
119 {
120   NS_LOG_FUNCTION_NOARGS ();
121 }
122 
123 void
DoDispose()124 OpenFlowSwitchNetDevice::DoDispose ()
125 {
126   NS_LOG_FUNCTION_NOARGS ();
127 
128   for (Ports_t::iterator b = m_ports.begin (), e = m_ports.end (); b != e; b++)
129     {
130       SendPortStatus (*b, OFPPR_DELETE);
131       b->netdev = 0;
132     }
133   m_ports.clear ();
134 
135   m_controller = 0;
136 
137   chain_destroy (m_chain);
138   RBTreeDestroy (m_vportTable.table);
139   m_channel = 0;
140   m_node = 0;
141   NetDevice::DoDispose ();
142 }
143 
144 void
SetController(Ptr<ofi::Controller> c)145 OpenFlowSwitchNetDevice::SetController (Ptr<ofi::Controller> c)
146 {
147   if (m_controller != 0)
148     {
149       NS_LOG_ERROR ("Controller already set.");
150       return;
151     }
152 
153   m_controller = c;
154   m_controller->AddSwitch (this);
155 }
156 
157 int
AddSwitchPort(Ptr<NetDevice> switchPort)158 OpenFlowSwitchNetDevice::AddSwitchPort (Ptr<NetDevice> switchPort)
159 {
160   NS_LOG_FUNCTION_NOARGS ();
161   NS_ASSERT (switchPort != this);
162   if (!Mac48Address::IsMatchingType (switchPort->GetAddress ()))
163     {
164       NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be added to switch.");
165     }
166   if (!switchPort->SupportsSendFrom ())
167     {
168       NS_FATAL_ERROR ("Device does not support SendFrom: cannot be added to switch.");
169     }
170   if (m_address == Mac48Address ())
171     {
172       m_address = Mac48Address::ConvertFrom (switchPort->GetAddress ());
173     }
174 
175   if (m_ports.size () < DP_MAX_PORTS)
176     {
177       ofi::Port p;
178       p.config = 0;
179       p.netdev = switchPort;
180       m_ports.push_back (p);
181 
182       // Notify the controller that this port has been added
183       SendPortStatus (p, OFPPR_ADD);
184 
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 ());
189     }
190   else
191     {
192       return EXFULL;
193     }
194 
195   return 0;
196 }
197 
198 void
SetIfIndex(const uint32_t index)199 OpenFlowSwitchNetDevice::SetIfIndex (const uint32_t index)
200 {
201   NS_LOG_FUNCTION_NOARGS ();
202   m_ifIndex = index;
203 }
204 
205 uint32_t
GetIfIndex(void) const206 OpenFlowSwitchNetDevice::GetIfIndex (void) const
207 {
208   NS_LOG_FUNCTION_NOARGS ();
209   return m_ifIndex;
210 }
211 
212 Ptr<Channel>
GetChannel(void) const213 OpenFlowSwitchNetDevice::GetChannel (void) const
214 {
215   NS_LOG_FUNCTION_NOARGS ();
216   return m_channel;
217 }
218 
219 void
SetAddress(Address address)220 OpenFlowSwitchNetDevice::SetAddress (Address address)
221 {
222   NS_LOG_FUNCTION_NOARGS ();
223   m_address = Mac48Address::ConvertFrom (address);
224 }
225 
226 Address
GetAddress(void) const227 OpenFlowSwitchNetDevice::GetAddress (void) const
228 {
229   NS_LOG_FUNCTION_NOARGS ();
230   return m_address;
231 }
232 
233 bool
SetMtu(const uint16_t mtu)234 OpenFlowSwitchNetDevice::SetMtu (const uint16_t mtu)
235 {
236   NS_LOG_FUNCTION_NOARGS ();
237   m_mtu = mtu;
238   return true;
239 }
240 
241 uint16_t
GetMtu(void) const242 OpenFlowSwitchNetDevice::GetMtu (void) const
243 {
244   NS_LOG_FUNCTION_NOARGS ();
245   return m_mtu;
246 }
247 
248 
249 bool
IsLinkUp(void) const250 OpenFlowSwitchNetDevice::IsLinkUp (void) const
251 {
252   NS_LOG_FUNCTION_NOARGS ();
253   return true;
254 }
255 
256 
257 void
AddLinkChangeCallback(Callback<void> callback)258 OpenFlowSwitchNetDevice::AddLinkChangeCallback (Callback<void> callback)
259 {
260 }
261 
262 bool
IsBroadcast(void) const263 OpenFlowSwitchNetDevice::IsBroadcast (void) const
264 {
265   NS_LOG_FUNCTION_NOARGS ();
266   return true;
267 }
268 
269 Address
GetBroadcast(void) const270 OpenFlowSwitchNetDevice::GetBroadcast (void) const
271 {
272   NS_LOG_FUNCTION_NOARGS ();
273   return Mac48Address ("ff:ff:ff:ff:ff:ff");
274 }
275 
276 bool
IsMulticast(void) const277 OpenFlowSwitchNetDevice::IsMulticast (void) const
278 {
279   NS_LOG_FUNCTION_NOARGS ();
280   return true;
281 }
282 
283 Address
GetMulticast(Ipv4Address multicastGroup) const284 OpenFlowSwitchNetDevice::GetMulticast (Ipv4Address multicastGroup) const
285 {
286   NS_LOG_FUNCTION (this << multicastGroup);
287   Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
288   return multicast;
289 }
290 
291 
292 bool
IsPointToPoint(void) const293 OpenFlowSwitchNetDevice::IsPointToPoint (void) const
294 {
295   NS_LOG_FUNCTION_NOARGS ();
296   return false;
297 }
298 
299 bool
IsBridge(void) const300 OpenFlowSwitchNetDevice::IsBridge (void) const
301 {
302   NS_LOG_FUNCTION_NOARGS ();
303   return true;
304 }
305 
306 void
DoOutput(uint32_t packet_uid,int in_port,size_t max_len,int out_port,bool ignore_no_fwd)307 OpenFlowSwitchNetDevice::DoOutput (uint32_t packet_uid, int in_port, size_t max_len, int out_port, bool ignore_no_fwd)
308 {
309   if (out_port != OFPP_CONTROLLER)
310     {
311       OutputPort (packet_uid, in_port, out_port, ignore_no_fwd);
312     }
313   else
314     {
315       OutputControl (packet_uid, in_port, max_len, OFPR_ACTION);
316     }
317 }
318 
319 bool
Send(Ptr<Packet> packet,const Address & dest,uint16_t protocolNumber)320 OpenFlowSwitchNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
321 {
322   NS_LOG_FUNCTION_NOARGS ();
323   return SendFrom (packet, m_address, dest, protocolNumber);
324 }
325 
326 bool
SendFrom(Ptr<Packet> packet,const Address & src,const Address & dest,uint16_t protocolNumber)327 OpenFlowSwitchNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
328 {
329   NS_LOG_FUNCTION_NOARGS ();
330 
331   ofpbuf *buffer = BufferFromPacket (packet,src,dest,GetMtu (),protocolNumber);
332 
333   uint32_t packet_uid = save_buffer (buffer);
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));
341 
342   RunThroughFlowTable (packet_uid, -1);
343 
344   return true;
345 }
346 
347 
348 Ptr<Node>
GetNode(void) const349 OpenFlowSwitchNetDevice::GetNode (void) const
350 {
351   NS_LOG_FUNCTION_NOARGS ();
352   return m_node;
353 }
354 
355 void
SetNode(Ptr<Node> node)356 OpenFlowSwitchNetDevice::SetNode (Ptr<Node> node)
357 {
358   NS_LOG_FUNCTION_NOARGS ();
359   m_node = node;
360 }
361 
362 bool
NeedsArp(void) const363 OpenFlowSwitchNetDevice::NeedsArp (void) const
364 {
365   NS_LOG_FUNCTION_NOARGS ();
366   return true;
367 }
368 
369 void
SetReceiveCallback(NetDevice::ReceiveCallback cb)370 OpenFlowSwitchNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
371 {
372   NS_LOG_FUNCTION_NOARGS ();
373   m_rxCallback = cb;
374 }
375 
376 void
SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)377 OpenFlowSwitchNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
378 {
379   NS_LOG_FUNCTION_NOARGS ();
380   m_promiscRxCallback = cb;
381 }
382 
383 bool
SupportsSendFrom() const384 OpenFlowSwitchNetDevice::SupportsSendFrom () const
385 {
386   NS_LOG_FUNCTION_NOARGS ();
387   return true;
388 }
389 
390 Address
GetMulticast(Ipv6Address addr) const391 OpenFlowSwitchNetDevice::GetMulticast (Ipv6Address addr) const
392 {
393   NS_LOG_FUNCTION (this << addr);
394   return Mac48Address::GetMulticast (addr);
395 }
396 
397 // Add a virtual port table entry.
398 int
AddVPort(const ofp_vport_mod * ovpm)399 OpenFlowSwitchNetDevice::AddVPort (const ofp_vport_mod *ovpm)
400 {
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);
404 
405   // check whether port table entry exists for specified port number
406   vport_table_entry *vpe = vport_table_lookup (&m_vportTable, vport);
407   if (vpe != 0)
408     {
409       NS_LOG_ERROR ("vport " << vport << " already exists!");
410       SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
411       return EINVAL;
412     }
413 
414   // check whether actions are valid
415   uint16_t v_code = ofi::ValidateVPortActions (ovpm->actions, actions_len);
416   if (v_code != ACT_VALIDATION_OK)
417     {
418       SendErrorMsg (OFPET_BAD_ACTION, v_code, ovpm, ntohs (ovpm->header.length));
419       return EINVAL;
420     }
421 
422   vpe = vport_table_entry_alloc (actions_len);
423 
424   vpe->vport = vport;
425   vpe->parent_port = parent_port;
426   if (vport < OFPP_VP_START || vport > OFPP_VP_END)
427     {
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); // free allocated entry
431       return EINVAL;
432     }
433 
434   vpe->port_acts->actions_len = actions_len;
435   memcpy (vpe->port_acts->actions, ovpm->actions, actions_len);
436 
437   int error = insert_vport_table_entry (&m_vportTable, vpe);
438   if (error)
439     {
440       NS_LOG_ERROR ("could not insert port table entry for port " << vport);
441     }
442 
443   return error;
444 }
445 
446 ofpbuf *
BufferFromPacket(Ptr<const Packet> constPacket,Address src,Address dst,int mtu,uint16_t protocol)447 OpenFlowSwitchNetDevice::BufferFromPacket (Ptr<const Packet> constPacket, Address src, Address dst, int mtu, uint16_t protocol)
448 {
449   NS_LOG_INFO ("Creating Openflow buffer from packet.");
450 
451   Ptr<Packet> packet = constPacket->Copy ();
452   /*
453    * Allocate buffer with some headroom to add headers in forwarding
454    * to the controller or adding a vlan tag, plus an extra 2 bytes to
455    * allow IP headers to be aligned on a 4-byte boundary.
456    */
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;
461 
462   int l2_length = 0, l3_length = 0, l4_length = 0;
463 
464   //Parse Ethernet header
465   buffer->l2 = new eth_header;
466   eth_header* eth_h = (eth_header*)buffer->l2;
467   dst.CopyTo (eth_h->eth_dst);              // Destination Mac Address
468   src.CopyTo (eth_h->eth_src);              // Source Mac Address
469   if (protocol == ArpL3Protocol::PROT_NUMBER)
470     {
471       eth_h->eth_type = htons (ETH_TYPE_ARP);    // Ether Type
472     }
473   else if (protocol == Ipv4L3Protocol::PROT_NUMBER)
474     {
475       eth_h->eth_type = htons (ETH_TYPE_IP);    // Ether Type
476     }
477   else
478     {
479       NS_LOG_WARN ("Protocol unsupported: " << protocol);
480     }
481   NS_LOG_INFO ("Parsed EthernetHeader");
482 
483   l2_length = ETH_HEADER_LEN;
484 
485   // We have to wrap this because PeekHeader has an assert fail if we check for an Ipv4Header that isn't there.
486   if (protocol == Ipv4L3Protocol::PROT_NUMBER)
487     {
488       Ipv4Header ip_hd;
489       if (packet->PeekHeader (ip_hd))
490         {
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);       // Version
494           ip_h->ip_tos      = ip_hd.GetTos ();                  // Type of Service/Differentiated Services
495           ip_h->ip_tot_len  = packet->GetSize ();               // Total Length
496           ip_h->ip_id       = ip_hd.GetIdentification ();       // Identification
497           ip_h->ip_frag_off = ip_hd.GetFragmentOffset ();       // Fragment Offset
498           ip_h->ip_ttl      = ip_hd.GetTtl ();                  // Time to Live
499           ip_h->ip_proto    = ip_hd.GetProtocol ();             // Protocol
500           ip_h->ip_src      = htonl (ip_hd.GetSource ().Get ()); // Source Address
501           ip_h->ip_dst      = htonl (ip_hd.GetDestination ().Get ()); // Destination Address
502           ip_h->ip_csum     = csum (&ip_h, sizeof ip_h);        // Header Checksum
503           NS_LOG_INFO ("Parsed Ipv4Header");
504           packet->RemoveHeader (ip_hd);
505 
506           l3_length = IP_HEADER_LEN;
507         }
508     }
509   else
510     {
511       // ARP Packet; the underlying OpenFlow header isn't used to match, so this is probably superfluous.
512       ArpHeader arp_hd;
513       if (packet->PeekHeader (arp_hd))
514         {
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;                             // Hardware type.
518           arp_h->ar_pro = ARP_PRO_IP;                                   // Protocol type.
519           arp_h->ar_op = arp_hd.m_type;                                 // Opcode.
520           arp_hd.GetDestinationHardwareAddress ().CopyTo (arp_h->ar_tha); // Target hardware address.
521           arp_hd.GetSourceHardwareAddress ().CopyTo (arp_h->ar_sha);    // Sender hardware address.
522           arp_h->ar_tpa = arp_hd.GetDestinationIpv4Address ().Get ();   // Target protocol address.
523           arp_h->ar_spa = arp_hd.GetSourceIpv4Address ().Get ();        // Sender protocol address.
524           arp_h->ar_hln = sizeof arp_h->ar_tha;                         // Hardware address length.
525           arp_h->ar_pln = sizeof arp_h->ar_tpa;                         // Protocol address length.
526           NS_LOG_INFO ("Parsed ArpHeader");
527           packet->RemoveHeader (arp_hd);
528 
529           l3_length = ARP_ETH_HEADER_LEN;
530         }
531     }
532 
533   if (protocol == Ipv4L3Protocol::PROT_NUMBER)
534     {
535       ip_header* ip_h = (ip_header*)buffer->l3;
536       if (ip_h->ip_proto == TcpL4Protocol::PROT_NUMBER)
537         {
538           TcpHeader tcp_hd;
539           if (packet->PeekHeader (tcp_hd))
540             {
541               buffer->l4 = new tcp_header;
542               tcp_header* tcp_h = (tcp_header*)buffer->l4;
543               tcp_h->tcp_src = htons (tcp_hd.GetSourcePort ());         // Source Port
544               tcp_h->tcp_dst = htons (tcp_hd.GetDestinationPort ());    // Destination Port
545               tcp_h->tcp_seq = tcp_hd.GetSequenceNumber ().GetValue (); // Sequence Number
546               tcp_h->tcp_ack = tcp_hd.GetAckNumber ().GetValue ();      // ACK Number
547               tcp_h->tcp_ctl = TCP_FLAGS (tcp_hd.GetFlags ());  // Data Offset + Reserved + Flags
548               tcp_h->tcp_winsz = tcp_hd.GetWindowSize ();       // Window Size
549               tcp_h->tcp_urg = tcp_hd.GetUrgentPointer ();      // Urgent Pointer
550               tcp_h->tcp_csum = csum (&tcp_h, sizeof tcp_h);    // Header Checksum
551               NS_LOG_INFO ("Parsed TcpHeader");
552               packet->RemoveHeader (tcp_hd);
553 
554               l4_length = TCP_HEADER_LEN;
555             }
556         }
557       else if (ip_h->ip_proto == UdpL4Protocol::PROT_NUMBER)
558         {
559           UdpHeader udp_hd;
560           if (packet->PeekHeader (udp_hd))
561             {
562               buffer->l4 = new udp_header;
563               udp_header* udp_h = (udp_header*)buffer->l4;
564               udp_h->udp_src = htons (udp_hd.GetSourcePort ());     // Source Port
565               udp_h->udp_dst = htons (udp_hd.GetDestinationPort ()); // Destination Port
566               udp_h->udp_len = htons (UDP_HEADER_LEN + packet->GetSize ());
567 
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)); // Header Checksum
575               NS_LOG_INFO ("Parsed UdpHeader");
576               packet->RemoveHeader (udp_hd);
577 
578               l4_length = UDP_HEADER_LEN;
579             }
580         }
581     }
582 
583   // Load any remaining packet data into buffer data
584   packet->CopyData ((uint8_t*)buffer->data, packet->GetSize ());
585 
586   if (buffer->l4)
587     {
588       ofpbuf_push (buffer, buffer->l4, l4_length);
589       delete (tcp_header*)buffer->l4;
590     }
591   if (buffer->l3)
592     {
593       ofpbuf_push (buffer, buffer->l3, l3_length);
594       delete (ip_header*)buffer->l3;
595     }
596   if (buffer->l2)
597     {
598       ofpbuf_push (buffer, buffer->l2, l2_length);
599       delete (eth_header*)buffer->l2;
600     }
601 
602   return buffer;
603 }
604 
605 void
ReceiveFromDevice(Ptr<NetDevice> netdev,Ptr<const Packet> packet,uint16_t protocol,const Address & src,const Address & dst,PacketType packetType)606 OpenFlowSwitchNetDevice::ReceiveFromDevice (Ptr<NetDevice> netdev, Ptr<const Packet> packet, uint16_t protocol,
607                                             const Address& src, const Address& dst, PacketType packetType)
608 {
609   NS_LOG_FUNCTION_NOARGS ();
610   NS_LOG_INFO ("--------------------------------------------");
611   NS_LOG_DEBUG ("UID is " << packet->GetUid ());
612 
613   if (!m_promiscRxCallback.IsNull ())
614     {
615       m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
616     }
617 
618   Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
619   NS_LOG_INFO ("Received packet from " << Mac48Address::ConvertFrom (src) << " looking for " << dst48);
620 
621   for (size_t i = 0; i < m_ports.size (); i++)
622     {
623       if (m_ports[i].netdev == netdev)
624         {
625           if (packetType == PACKET_HOST && dst48 == m_address)
626             {
627               m_rxCallback (this, packet, protocol, src);
628             }
629           else if (packetType == PACKET_BROADCAST || packetType == PACKET_MULTICAST || packetType == PACKET_OTHERHOST)
630             {
631               if (packetType == PACKET_OTHERHOST && dst48 == m_address)
632                 {
633                   m_rxCallback (this, packet, protocol, src);
634                 }
635               else
636                 {
637                   if (packetType != PACKET_OTHERHOST)
638                     {
639                       m_rxCallback (this, packet, protocol, src);
640                     }
641 
642                   ofi::SwitchPacketMetadata data;
643                   data.packet = packet->Copy ();
644 
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;
649                   uint32_t packet_uid = save_buffer (buffer);
650 
651                   data.protocolNumber = protocol;
652                   data.src = Address (src);
653                   data.dst = Address (dst);
654                   m_packetData.insert (std::make_pair (packet_uid, data));
655 
656                   RunThroughFlowTable (packet_uid, i);
657                 }
658             }
659 
660           break;
661         }
662     }
663 
664   // Run periodic execution.
665   Time now = Simulator::Now ();
666   if (now >= Seconds (m_lastExecute.GetSeconds () + 1)) // If a second or more has passed from the simulation time, execute.
667     {
668       // If port status is modified in any way, notify the controller.
669       for (size_t i = 0; i < m_ports.size (); i++)
670         {
671           if (UpdatePortStatus (m_ports[i]))
672             {
673               SendPortStatus (m_ports[i], OFPPR_MODIFY);
674             }
675         }
676 
677       // If any flows have expired, delete them and notify the controller.
678       List deleted = LIST_INITIALIZER (&deleted);
679       sw_flow *f, *n;
680       chain_timeout (m_chain, &deleted);
681       LIST_FOR_EACH_SAFE (f, n, sw_flow, node, &deleted)
682       {
683         std::ostringstream str;
684         str << "Flow [";
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;
687         str << " -> ";
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;
690         str <<  "] expired.";
691 
692         NS_LOG_INFO (str.str ());
693         SendFlowExpired (f, (ofp_flow_expired_reason)f->reason);
694         list_remove (&f->node);
695         flow_free (f);
696       }
697 
698       m_lastExecute = now;
699     }
700 }
701 
702 int
OutputAll(uint32_t packet_uid,int in_port,bool flood)703 OpenFlowSwitchNetDevice::OutputAll (uint32_t packet_uid, int in_port, bool flood)
704 {
705   NS_LOG_FUNCTION_NOARGS ();
706   NS_LOG_INFO ("Flooding over ports.");
707 
708   int prev_port = -1;
709   for (size_t i = 0; i < m_ports.size (); i++)
710     {
711       if (i == (unsigned)in_port) // Originating port
712         {
713           continue;
714         }
715       if (flood && m_ports[i].config & OFPPC_NO_FLOOD) // Port configured to not allow flooding
716         {
717           continue;
718         }
719       if (prev_port != -1)
720         {
721           OutputPort (packet_uid, in_port, prev_port, false);
722         }
723       prev_port = i;
724     }
725   if (prev_port != -1)
726     {
727       OutputPort (packet_uid, in_port, prev_port, false);
728     }
729 
730   return 0;
731 }
732 
733 void
OutputPacket(uint32_t packet_uid,int out_port)734 OpenFlowSwitchNetDevice::OutputPacket (uint32_t packet_uid, int out_port)
735 {
736   if (out_port >= 0 && out_port < DP_MAX_PORTS)
737     {
738       ofi::Port& p = m_ports[out_port];
739       if (p.netdev != 0 && !(p.config & OFPPC_PORT_DOWN))
740         {
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))
745             {
746               p.tx_packets++;
747               p.tx_bytes += bufsize;
748             }
749           else
750             {
751               p.tx_dropped++;
752             }
753           return;
754         }
755     }
756 
757   NS_LOG_DEBUG ("can't forward to bad port " << out_port);
758 }
759 
760 void
OutputPort(uint32_t packet_uid,int in_port,int out_port,bool ignore_no_fwd)761 OpenFlowSwitchNetDevice::OutputPort (uint32_t packet_uid, int in_port, int out_port, bool ignore_no_fwd)
762 {
763   NS_LOG_FUNCTION_NOARGS ();
764 
765   if (out_port == OFPP_FLOOD)
766     {
767       OutputAll (packet_uid, in_port, true);
768     }
769   else if (out_port == OFPP_ALL)
770     {
771       OutputAll (packet_uid, in_port, false);
772     }
773   else if (out_port == OFPP_CONTROLLER)
774     {
775       OutputControl (packet_uid, in_port, 0, OFPR_ACTION);
776     }
777   else if (out_port == OFPP_IN_PORT)
778     {
779       OutputPacket (packet_uid, in_port);
780     }
781   else if (out_port == OFPP_TABLE)
782     {
783       RunThroughFlowTable (packet_uid, in_port < DP_MAX_PORTS ? in_port : -1, false);
784     }
785   else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
786     {
787       // port is a virtual port
788       NS_LOG_INFO ("packet sent to virtual port " << out_port);
789       if (in_port < DP_MAX_PORTS)
790         {
791           RunThroughVPortTable (packet_uid, in_port, out_port);
792         }
793       else
794         {
795           RunThroughVPortTable (packet_uid, -1, out_port);
796         }
797     }
798   else if (in_port == out_port)
799     {
800       NS_LOG_DEBUG ("can't directly forward to input port");
801     }
802   else
803     {
804       OutputPacket (packet_uid, out_port);
805     }
806 }
807 
808 void*
MakeOpenflowReply(size_t openflow_len,uint8_t type,ofpbuf ** bufferp)809 OpenFlowSwitchNetDevice::MakeOpenflowReply (size_t openflow_len, uint8_t type, ofpbuf **bufferp)
810 {
811   return make_openflow_xid (openflow_len, type, 0, bufferp);
812 }
813 
814 int
SendOpenflowBuffer(ofpbuf * buffer)815 OpenFlowSwitchNetDevice::SendOpenflowBuffer (ofpbuf *buffer)
816 {
817   if (m_controller != 0)
818     {
819       update_openflow_length (buffer);
820       m_controller->ReceiveFromSwitch (this, buffer);
821     }
822 
823   return 0;
824 }
825 
826 void
OutputControl(uint32_t packet_uid,int in_port,size_t max_len,int reason)827 OpenFlowSwitchNetDevice::OutputControl (uint32_t packet_uid, int in_port, size_t max_len, int reason)
828 {
829   NS_LOG_INFO ("Sending packet to controller");
830 
831   ofpbuf* buffer = m_packetData.find (packet_uid)->second.buffer;
832   size_t total_len = buffer->size;
833   if (packet_uid != std::numeric_limits<uint32_t>::max () && max_len != 0 && buffer->size > max_len)
834     {
835       buffer->size = max_len;
836     }
837 
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;
847   opi->pad            = 0;
848   SendOpenflowBuffer (buffer);
849 }
850 
851 void
FillPortDesc(ofi::Port p,ofp_phy_port * desc)852 OpenFlowSwitchNetDevice::FillPortDesc (ofi::Port p, ofp_phy_port *desc)
853 {
854   desc->port_no = htons (GetSwitchPortIndex (p));
855 
856   std::ostringstream nm;
857   nm << "eth" << GetSwitchPortIndex (p);
858   strncpy ((char *)desc->name, nm.str ().c_str (), sizeof desc->name);
859 
860   p.netdev->GetAddress ().CopyTo (desc->hw_addr);
861   desc->config = htonl (p.config);
862   desc->state = htonl (p.state);
863 
864   /// \todo This should probably be fixed eventually to specify different available features.
865   desc->curr = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_CURRENT));
866   desc->supported = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_SUPPORTED));
867   desc->advertised = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_ADVERTISED));
868   desc->peer = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_PEER));
869 }
870 
871 void
SendFeaturesReply()872 OpenFlowSwitchNetDevice::SendFeaturesReply ()
873 {
874   ofpbuf *buffer;
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;
878   ofr->n_buffers    = htonl (N_PKT_BUFFERS);
879   ofr->capabilities = htonl (OFP_SUPPORTED_CAPABILITIES);
880   ofr->actions      = htonl (OFP_SUPPORTED_ACTIONS);
881 
882   for (size_t i = 0; i < m_ports.size (); i++)
883     {
884       ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros (buffer, sizeof *opp);
885       FillPortDesc (m_ports[i], opp);
886     }
887 
888   SendOpenflowBuffer (buffer);
889 }
890 
891 void
SendVPortTableFeatures()892 OpenFlowSwitchNetDevice::SendVPortTableFeatures ()
893 {
894   ofpbuf *buffer;
895   ofp_vport_table_features *ovtfr = (ofp_vport_table_features*)MakeOpenflowReply (sizeof *ovtfr, OFPT_VPORT_TABLE_FEATURES_REPLY, &buffer);
896   ovtfr->actions = htonl (OFP_SUPPORTED_VPORT_TABLE_ACTIONS);
897   ovtfr->max_vports = htonl (m_vportTable.max_vports);
898   ovtfr->max_chain_depth = htons (-1); // support a chain depth of 2^16
899   ovtfr->mixed_chaining = true;
900   SendOpenflowBuffer (buffer);
901 }
902 
903 int
UpdatePortStatus(ofi::Port & p)904 OpenFlowSwitchNetDevice::UpdatePortStatus (ofi::Port& p)
905 {
906   uint32_t orig_config = p.config;
907   uint32_t orig_state = p.state;
908 
909   // Port is always enabled because the Net Device is always enabled.
910   p.config &= ~OFPPC_PORT_DOWN;
911 
912   if (p.netdev->IsLinkUp ())
913     {
914       p.state &= ~OFPPS_LINK_DOWN;
915     }
916   else
917     {
918       p.state |= OFPPS_LINK_DOWN;
919     }
920 
921   return ((orig_config != p.config) || (orig_state != p.state));
922 }
923 
924 void
SendPortStatus(ofi::Port p,uint8_t status)925 OpenFlowSwitchNetDevice::SendPortStatus (ofi::Port p, uint8_t status)
926 {
927   ofpbuf *buffer;
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);
932 
933   SendOpenflowBuffer (buffer);
934   ofpbuf_delete (buffer);
935 }
936 
937 void
SendFlowExpired(sw_flow * flow,enum ofp_flow_expired_reason reason)938 OpenFlowSwitchNetDevice::SendFlowExpired (sw_flow *flow, enum ofp_flow_expired_reason reason)
939 {
940   ofpbuf *buffer;
941   ofp_flow_expired *ofe = (ofp_flow_expired*)MakeOpenflowReply (sizeof *ofe, OFPT_FLOW_EXPIRED, &buffer);
942   flow_fill_match (&ofe->match, &flow->key);
943 
944   ofe->priority = htons (flow->priority);
945   ofe->reason = reason;
946   memset (ofe->pad, 0, sizeof ofe->pad);
947 
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);
953 }
954 
955 void
SendErrorMsg(uint16_t type,uint16_t code,const void * data,size_t len)956 OpenFlowSwitchNetDevice::SendErrorMsg (uint16_t type, uint16_t code, const void *data, size_t len)
957 {
958   ofpbuf *buffer;
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);
964 }
965 
966 void
FlowTableLookup(sw_flow_key key,ofpbuf * buffer,uint32_t packet_uid,int port,bool send_to_controller)967 OpenFlowSwitchNetDevice::FlowTableLookup (sw_flow_key key, ofpbuf* buffer, uint32_t packet_uid, int port, bool send_to_controller)
968 {
969   sw_flow *flow = chain_lookup (m_chain, &key);
970   if (flow != 0)
971     {
972       NS_LOG_INFO ("Flow matched");
973       flow_used (flow, buffer);
974       ofi::ExecuteActions (this, packet_uid, buffer, &key, flow->sf_acts->actions, flow->sf_acts->actions_len, false);
975     }
976   else
977     {
978       NS_LOG_INFO ("Flow not matched.");
979 
980       if (send_to_controller)
981         {
982           OutputControl (packet_uid, port, m_missSendLen, OFPR_NO_MATCH);
983         }
984     }
985 
986   // Clean up; at this point we're done with the packet.
987   m_packetData.erase (packet_uid);
988   discard_buffer (packet_uid);
989   ofpbuf_delete (buffer);
990 }
991 
992 void
RunThroughFlowTable(uint32_t packet_uid,int port,bool send_to_controller)993 OpenFlowSwitchNetDevice::RunThroughFlowTable (uint32_t packet_uid, int port, bool send_to_controller)
994 {
995   ofi::SwitchPacketMetadata data = m_packetData.find (packet_uid)->second;
996   ofpbuf* buffer = data.buffer;
997 
998   sw_flow_key key;
999   key.wildcards = 0; // Lookup cannot take wildcards.
1000   // Extract the matching key's flow data from the packet's headers; if the policy is to drop fragments and the message is a fragment, drop it.
1001   if (flow_extract (buffer, port != -1 ? port : OFPP_NONE, &key.flow) && (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1002     {
1003       ofpbuf_delete (buffer);
1004       return;
1005     }
1006 
1007   // drop MPLS packets with TTL 1
1008   if (buffer->l2_5)
1009     {
1010       mpls_header mpls_h;
1011       mpls_h.value = ntohl (*((uint32_t*)buffer->l2_5));
1012       if (mpls_h.ttl == 1)
1013         {
1014           // increment mpls drop counter
1015           if (port != -1)
1016             {
1017               m_ports[port].mpls_ttl0_dropped++;
1018             }
1019           return;
1020         }
1021     }
1022 
1023   // If we received the packet on a port, and opted not to receive any messages from it...
1024   if (port != -1)
1025     {
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))
1029         {
1030           return;
1031         }
1032     }
1033 
1034   NS_LOG_INFO ("Matching against the flow table.");
1035   Simulator::Schedule (m_lookupDelay, &OpenFlowSwitchNetDevice::FlowTableLookup, this, key, buffer, packet_uid, port, send_to_controller);
1036 }
1037 
1038 int
RunThroughVPortTable(uint32_t packet_uid,int port,uint32_t vport)1039 OpenFlowSwitchNetDevice::RunThroughVPortTable (uint32_t packet_uid, int port, uint32_t vport)
1040 {
1041   ofpbuf* buffer = m_packetData.find (packet_uid)->second.buffer;
1042 
1043   // extract the flow again since we need it
1044   // and the layer pointers may changed
1045   sw_flow_key key;
1046   key.wildcards = 0;
1047   if (flow_extract (buffer, port != -1 ? port : OFPP_NONE, &key.flow)
1048       && (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1049     {
1050       return 0;
1051     }
1052 
1053   // run through the chain of port table entries
1054   vport_table_entry *vpe = vport_table_lookup (&m_vportTable, vport);
1055   m_vportTable.lookup_count++;
1056   if (vpe)
1057     {
1058       m_vportTable.port_match_count++;
1059     }
1060   while (vpe != 0)
1061     {
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); // update counters for virtual port
1064       if (vpe->parent_port_ptr == 0)
1065         {
1066           // if a port table's parent_port_ptr is 0 then
1067           // the parent_port should be a physical port
1068           if (vpe->parent_port <= OFPP_VP_START) // done traversing port chain, send packet to output port
1069             {
1070               OutputPort (packet_uid, port != -1 ? port : OFPP_NONE, vpe->parent_port, false);
1071             }
1072           else
1073             {
1074               NS_LOG_ERROR ("virtual port points to parent port\n");
1075             }
1076         }
1077       else // increment the number of port entries accessed by chaining
1078         {
1079           m_vportTable.chain_match_count++;
1080         }
1081       // move to the parent port entry
1082       vpe = vpe->parent_port_ptr;
1083     }
1084 
1085   return 0;
1086 }
1087 
1088 int
ReceiveFeaturesRequest(const void * msg)1089 OpenFlowSwitchNetDevice::ReceiveFeaturesRequest (const void *msg)
1090 {
1091   SendFeaturesReply ();
1092   return 0;
1093 }
1094 
1095 int
ReceiveVPortTableFeaturesRequest(const void * msg)1096 OpenFlowSwitchNetDevice::ReceiveVPortTableFeaturesRequest (const void *msg)
1097 {
1098   SendVPortTableFeatures ();
1099   return 0;
1100 }
1101 
1102 int
ReceiveGetConfigRequest(const void * msg)1103 OpenFlowSwitchNetDevice::ReceiveGetConfigRequest (const void *msg)
1104 {
1105   ofpbuf *buffer;
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);
1109 
1110   return SendOpenflowBuffer (buffer);
1111 }
1112 
1113 int
ReceiveSetConfig(const void * msg)1114 OpenFlowSwitchNetDevice::ReceiveSetConfig (const void *msg)
1115 {
1116   const ofp_switch_config *osc = (ofp_switch_config*)msg;
1117 
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)
1120     {
1121       n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1122     }
1123 
1124   m_flags = n_flags;
1125   m_missSendLen = ntohs (osc->miss_send_len);
1126   return 0;
1127 }
1128 
1129 int
ReceivePacketOut(const void * msg)1130 OpenFlowSwitchNetDevice::ReceivePacketOut (const void *msg)
1131 {
1132   const ofp_packet_out *opo = (ofp_packet_out*)msg;
1133   ofpbuf *buffer;
1134   size_t actions_len = ntohs (opo->actions_len);
1135 
1136   if (actions_len > (ntohs (opo->header.length) - sizeof *opo))
1137     {
1138       NS_LOG_DEBUG ("message too short for number of actions");
1139       return -EINVAL;
1140     }
1141 
1142   if (ntohl (opo->buffer_id) == (uint32_t) -1)
1143     {
1144       // FIXME: can we avoid copying data here?
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);
1148     }
1149   else
1150     {
1151       buffer = retrieve_buffer (ntohl (opo->buffer_id));
1152       if (buffer == 0)
1153         {
1154           return -ESRCH;
1155         }
1156     }
1157 
1158   sw_flow_key key;
1159   flow_extract (buffer, ntohs(opo->in_port), &key.flow); // ntohs(opo->in_port)
1160 
1161   uint16_t v_code = ofi::ValidateActions (&key, opo->actions, actions_len);
1162   if (v_code != ACT_VALIDATION_OK)
1163     {
1164       SendErrorMsg (OFPET_BAD_ACTION, v_code, msg, ntohs (opo->header.length));
1165       ofpbuf_delete (buffer);
1166       return -EINVAL;
1167     }
1168 
1169   ofi::ExecuteActions (this, opo->buffer_id, buffer, &key, opo->actions, actions_len, true);
1170   return 0;
1171 }
1172 
1173 int
ReceivePortMod(const void * msg)1174 OpenFlowSwitchNetDevice::ReceivePortMod (const void *msg)
1175 {
1176   ofp_port_mod* opm = (ofp_port_mod*)msg;
1177 
1178   int port = opm->port_no; // ntohs(opm->port_no);
1179   if (port < DP_MAX_PORTS)
1180     {
1181       ofi::Port& p = m_ports[port];
1182 
1183       // Make sure the port id hasn't changed since this was sent
1184       Mac48Address hw_addr = Mac48Address ();
1185       hw_addr.CopyFrom (opm->hw_addr);
1186       if (p.netdev->GetAddress () != hw_addr)
1187         {
1188           return 0;
1189         }
1190 
1191       if (opm->mask)
1192         {
1193           uint32_t config_mask = ntohl (opm->mask);
1194           p.config &= ~config_mask;
1195           p.config |= ntohl (opm->config) & config_mask;
1196         }
1197 
1198       if (opm->mask & htonl (OFPPC_PORT_DOWN))
1199         {
1200           if ((opm->config & htonl (OFPPC_PORT_DOWN)) && (p.config & OFPPC_PORT_DOWN) == 0)
1201             {
1202               p.config |= OFPPC_PORT_DOWN;
1203               /// \todo Possibly disable the Port's Net Device via the appropriate interface.
1204             }
1205           else if ((opm->config & htonl (OFPPC_PORT_DOWN)) == 0 && (p.config & OFPPC_PORT_DOWN))
1206             {
1207               p.config &= ~OFPPC_PORT_DOWN;
1208               /// \todo Possibly enable the Port's Net Device via the appropriate interface.
1209             }
1210         }
1211     }
1212 
1213   return 0;
1214 }
1215 
1216 // add or remove a virtual port table entry
1217 int
ReceiveVPortMod(const void * msg)1218 OpenFlowSwitchNetDevice::ReceiveVPortMod (const void *msg)
1219 {
1220   const ofp_vport_mod *ovpm = (ofp_vport_mod*)msg;
1221 
1222   uint16_t command = ntohs (ovpm->command);
1223   if (command == OFPVP_ADD)
1224     {
1225       return AddVPort (ovpm);
1226     }
1227   else if (command == OFPVP_DELETE)
1228     {
1229       if (remove_vport_table_entry (&m_vportTable, ntohl (ovpm->vport)))
1230         {
1231           SendErrorMsg (OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs (ovpm->header.length));
1232         }
1233     }
1234 
1235   return 0;
1236 }
1237 
1238 int
AddFlow(const ofp_flow_mod * ofm)1239 OpenFlowSwitchNetDevice::AddFlow (const ofp_flow_mod *ofm)
1240 {
1241   size_t actions_len = ntohs (ofm->header.length) - sizeof *ofm;
1242 
1243   // Allocate memory.
1244   sw_flow *flow = flow_alloc (actions_len);
1245   if (flow == 0)
1246     {
1247       if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1248         {
1249           discard_buffer (ntohl (ofm->buffer_id));
1250         }
1251       return -ENOMEM;
1252     }
1253 
1254   flow_extract_match (&flow->key, &ofm->match);
1255 
1256   uint16_t v_code = ofi::ValidateActions (&flow->key, ofm->actions, actions_len);
1257   if (v_code != ACT_VALIDATION_OK)
1258     {
1259       SendErrorMsg (OFPET_BAD_ACTION, v_code, ofm, ntohs (ofm->header.length));
1260       flow_free (flow);
1261       if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1262         {
1263           discard_buffer (ntohl (ofm->buffer_id));
1264         }
1265       return -ENOMEM;
1266     }
1267 
1268   // Fill out flow.
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);
1277 
1278   // Act.
1279   int error = chain_insert (m_chain, flow);
1280   if (error)
1281     {
1282       if (error == -ENOBUFS)
1283         {
1284           SendErrorMsg (OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL, ofm, ntohs (ofm->header.length));
1285         }
1286       flow_free (flow);
1287       if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1288         {
1289           discard_buffer (ntohl (ofm->buffer_id));
1290         }
1291       return error;
1292     }
1293 
1294   NS_LOG_INFO ("Added new flow.");
1295   if (ntohl (ofm->buffer_id) != std::numeric_limits<uint32_t>::max ())
1296     {
1297       ofpbuf *buffer = retrieve_buffer (ofm->buffer_id); // ntohl(ofm->buffer_id)
1298       if (buffer)
1299         {
1300           sw_flow_key key;
1301           flow_used (flow, buffer);
1302           flow_extract (buffer, ntohs(ofm->match.in_port), &key.flow); // ntohs(ofm->match.in_port);
1303           ofi::ExecuteActions (this, ofm->buffer_id, buffer, &key, ofm->actions, actions_len, false);
1304           ofpbuf_delete (buffer);
1305         }
1306       else
1307         {
1308           return -ESRCH;
1309         }
1310     }
1311   return 0;
1312 }
1313 
1314 int
ModFlow(const ofp_flow_mod * ofm)1315 OpenFlowSwitchNetDevice::ModFlow (const ofp_flow_mod *ofm)
1316 {
1317   sw_flow_key key;
1318   flow_extract_match (&key, &ofm->match);
1319 
1320   size_t actions_len = ntohs (ofm->header.length) - sizeof *ofm;
1321 
1322   uint16_t v_code = ofi::ValidateActions (&key, ofm->actions, actions_len);
1323   if (v_code != ACT_VALIDATION_OK)
1324     {
1325       SendErrorMsg ((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs (ofm->header.length));
1326       if (ntohl (ofm->buffer_id) != (uint32_t) -1)
1327         {
1328           discard_buffer (ntohl (ofm->buffer_id));
1329         }
1330       return -ENOMEM;
1331     }
1332 
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);
1336 
1337   if (ntohl (ofm->buffer_id) != std::numeric_limits<uint32_t>::max ())
1338     {
1339       ofpbuf *buffer = retrieve_buffer (ofm->buffer_id); // ntohl (ofm->buffer_id)
1340       if (buffer)
1341         {
1342           sw_flow_key skb_key;
1343           flow_extract (buffer, ntohs(ofm->match.in_port), &skb_key.flow); // ntohs(ofm->match.in_port);
1344           ofi::ExecuteActions (this, ofm->buffer_id, buffer, &skb_key, ofm->actions, actions_len, false);
1345           ofpbuf_delete (buffer);
1346         }
1347       else
1348         {
1349           return -ESRCH;
1350         }
1351     }
1352   return 0;
1353 }
1354 
1355 int
ReceiveFlow(const void * msg)1356 OpenFlowSwitchNetDevice::ReceiveFlow (const void *msg)
1357 {
1358   NS_LOG_FUNCTION_NOARGS ();
1359   const ofp_flow_mod *ofm = (ofp_flow_mod*)msg;
1360   uint16_t command = ntohs (ofm->command);
1361 
1362   if (command == OFPFC_ADD)
1363     {
1364       return AddFlow (ofm);
1365     }
1366   else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1367     {
1368       return ModFlow (ofm);
1369     }
1370   else if (command == OFPFC_DELETE)
1371     {
1372       sw_flow_key key;
1373       flow_extract_match (&key, &ofm->match);
1374       return chain_delete (m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1375     }
1376   else if (command == OFPFC_DELETE_STRICT)
1377     {
1378       sw_flow_key key;
1379       uint16_t priority;
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;
1383     }
1384   else
1385     {
1386       return -ENODEV;
1387     }
1388 }
1389 
1390 int
StatsDump(ofi::StatsDumpCallback * cb)1391 OpenFlowSwitchNetDevice::StatsDump (ofi::StatsDumpCallback *cb)
1392 {
1393   ofp_stats_reply *osr;
1394   ofpbuf *buffer;
1395   int err;
1396 
1397   if (cb->done)
1398     {
1399       return 0;
1400     }
1401 
1402   osr = (ofp_stats_reply*)MakeOpenflowReply (sizeof *osr, OFPT_STATS_REPLY, &buffer);
1403   osr->type = htons (cb->s->type);
1404   osr->flags = 0;
1405 
1406   err = cb->s->DoDump (this, cb->state, buffer);
1407   if (err >= 0)
1408     {
1409       if (err == 0)
1410         {
1411           cb->done = true;
1412         }
1413       else
1414         {
1415           // Buffer might have been reallocated, so find our data again.
1416           osr = (ofp_stats_reply*)ofpbuf_at_assert (buffer, 0, sizeof *osr);
1417           osr->flags = ntohs (OFPSF_REPLY_MORE);
1418         }
1419 
1420       int err2 = SendOpenflowBuffer (buffer);
1421       if (err2)
1422         {
1423           err = err2;
1424         }
1425     }
1426 
1427   return err;
1428 }
1429 
1430 void
StatsDone(ofi::StatsDumpCallback * cb)1431 OpenFlowSwitchNetDevice::StatsDone (ofi::StatsDumpCallback *cb)
1432 {
1433   if (cb)
1434     {
1435       cb->s->DoCleanup (cb->state);
1436       free (cb->s);
1437       free (cb);
1438     }
1439 }
1440 
1441 int
ReceiveStatsRequest(const void * oh)1442 OpenFlowSwitchNetDevice::ReceiveStatsRequest (const void *oh)
1443 {
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);
1449 
1450   if (st == 0)
1451     {
1452       return -EINVAL;
1453     }
1454 
1455   ofi::StatsDumpCallback cb;
1456   cb.done = false;
1457   cb.rq = (ofp_stats_request*)xmemdup (rq, rq_len);
1458   cb.s = st;
1459   cb.state = 0;
1460   cb.swtch = this;
1461 
1462   if (cb.s)
1463     {
1464       int err = cb.s->DoInit (rq->body, body_len, &cb.state);
1465       if (err)
1466         {
1467           NS_LOG_WARN ("failed initialization of stats request type " << type << ": " << strerror (-err));
1468           free (cb.rq);
1469           return err;
1470         }
1471     }
1472 
1473   if (m_controller != 0)
1474     {
1475       m_controller->StartDump (&cb);
1476     }
1477   else
1478     {
1479       NS_LOG_ERROR ("Switch needs to be registered to a controller in order to start the stats reply.");
1480     }
1481 
1482   return 0;
1483 }
1484 
1485 int
ReceiveEchoRequest(const void * oh)1486 OpenFlowSwitchNetDevice::ReceiveEchoRequest (const void *oh)
1487 {
1488   return SendOpenflowBuffer (make_echo_reply ((ofp_header*)oh));
1489 }
1490 
1491 int
ReceiveEchoReply(const void * oh)1492 OpenFlowSwitchNetDevice::ReceiveEchoReply (const void *oh)
1493 {
1494   return 0;
1495 }
1496 
1497 int
ForwardControlInput(const void * msg,size_t length)1498 OpenFlowSwitchNetDevice::ForwardControlInput (const void *msg, size_t length)
1499 {
1500   // Check encapsulated length.
1501   ofp_header *oh = (ofp_header*) msg;
1502   if (ntohs (oh->length) > length)
1503     {
1504       return -EINVAL;
1505     }
1506   assert (oh->version == OFP_VERSION);
1507 
1508   int error = 0;
1509 
1510   // Figure out how to handle it.
1511   switch (oh->type)
1512     {
1513     case OFPT_FEATURES_REQUEST:
1514       error = length < sizeof(ofp_header) ? -EFAULT : ReceiveFeaturesRequest (msg);
1515       break;
1516     case OFPT_GET_CONFIG_REQUEST:
1517       error = length < sizeof(ofp_header) ? -EFAULT : ReceiveGetConfigRequest (msg);
1518       break;
1519     case OFPT_SET_CONFIG:
1520       error = length < sizeof(ofp_switch_config) ? -EFAULT : ReceiveSetConfig (msg);
1521       break;
1522     case OFPT_PACKET_OUT:
1523       error = length < sizeof(ofp_packet_out) ? -EFAULT : ReceivePacketOut (msg);
1524       break;
1525     case OFPT_FLOW_MOD:
1526       error = length < sizeof(ofp_flow_mod) ? -EFAULT : ReceiveFlow (msg);
1527       break;
1528     case OFPT_PORT_MOD:
1529       error = length < sizeof(ofp_port_mod) ? -EFAULT : ReceivePortMod (msg);
1530       break;
1531     case OFPT_STATS_REQUEST:
1532       error = length < sizeof(ofp_stats_request) ? -EFAULT : ReceiveStatsRequest (msg);
1533       break;
1534     case OFPT_ECHO_REQUEST:
1535       error = length < sizeof(ofp_header) ? -EFAULT : ReceiveEchoRequest (msg);
1536       break;
1537     case OFPT_ECHO_REPLY:
1538       error = length < sizeof(ofp_header) ? -EFAULT : ReceiveEchoReply (msg);
1539       break;
1540     case OFPT_VPORT_MOD:
1541       error = length < sizeof(ofp_vport_mod) ? -EFAULT : ReceiveVPortMod (msg);
1542       break;
1543     case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1544       error = length < sizeof(ofp_header) ? -EFAULT : ReceiveVPortTableFeaturesRequest (msg);
1545       break;
1546     default:
1547       SendErrorMsg ((ofp_error_type)OFPET_BAD_REQUEST, (ofp_bad_request_code)OFPBRC_BAD_TYPE, msg, length);
1548       error = -EINVAL;
1549     }
1550 
1551   if (msg != 0)
1552     {
1553       free ((ofpbuf*)msg);
1554     }
1555   return error;
1556 }
1557 
1558 sw_chain*
GetChain()1559 OpenFlowSwitchNetDevice::GetChain ()
1560 {
1561   return m_chain;
1562 }
1563 
1564 uint32_t
GetNSwitchPorts(void) const1565 OpenFlowSwitchNetDevice::GetNSwitchPorts (void) const
1566 {
1567   NS_LOG_FUNCTION_NOARGS ();
1568   return m_ports.size ();
1569 }
1570 
1571 ofi::Port
GetSwitchPort(uint32_t n) const1572 OpenFlowSwitchNetDevice::GetSwitchPort (uint32_t n) const
1573 {
1574   NS_LOG_FUNCTION_NOARGS ();
1575   return m_ports[n];
1576 }
1577 
1578 int
GetSwitchPortIndex(ofi::Port p)1579 OpenFlowSwitchNetDevice::GetSwitchPortIndex (ofi::Port p)
1580 {
1581   for (size_t i = 0; i < m_ports.size (); i++)
1582     {
1583       if (m_ports[i].netdev == p.netdev)
1584         {
1585           return i;
1586         }
1587     }
1588   return -1;
1589 }
1590 
1591 vport_table_t
GetVPortTable()1592 OpenFlowSwitchNetDevice::GetVPortTable ()
1593 {
1594   return m_vportTable;
1595 }
1596 
1597 } // namespace ns3
1598 
1599 #endif // NS3_OPENFLOW
1600