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 
19 /**
20  * \defgroup openflow OpenFlow Switch Device
21  * This section documents the API of the ns-3 OpenFlow module. For a generic functional description, please refer to the ns-3 manual.
22  */
23 
24 #ifndef OPENFLOW_SWITCH_NET_DEVICE_H
25 #define OPENFLOW_SWITCH_NET_DEVICE_H
26 
27 #include "ns3/simulator.h"
28 #include "ns3/log.h"
29 #include "ns3/mac48-address.h"
30 
31 #include "ns3/ethernet-header.h"
32 #include "ns3/arp-header.h"
33 #include "ns3/tcp-header.h"
34 #include "ns3/udp-header.h"
35 
36 #include "ns3/ipv4-l3-protocol.h"
37 #include "ns3/arp-l3-protocol.h"
38 
39 #include "ns3/bridge-channel.h"
40 #include "ns3/node.h"
41 #include "ns3/enum.h"
42 #include "ns3/string.h"
43 #include "ns3/integer.h"
44 #include "ns3/uinteger.h"
45 
46 #include <map>
47 #include <set>
48 
49 #include "openflow-interface.h"
50 
51 namespace ns3 {
52 
53 /**
54  * \ingroup openflow
55  * \brief A net device that switches multiple LAN segments via an OpenFlow-compatible flow table
56  *
57  * The OpenFlowSwitchNetDevice object aggregates multiple netdevices as ports
58  * and acts like a switch. It implements OpenFlow-compatibility,
59  * according to the OpenFlow Switch Specification v0.8.9
60  * <www.openflowswitch.org/documents/openflow-spec-v0.8.9.pdf>.
61  * It implements a flow table that all received packets are run through.
62  * It implements a connection to a controller via a subclass of the Controller class,
63  * which can send messages to manipulate the flow table, thereby manipulating
64  * how the OpenFlow switch behaves.
65  *
66  * There are two controllers available in the original package. DropController
67  * builds a flow for each received packet to drop all packets it matches (this
68  * demonstrates the flow table's basic implementation), and the LearningController
69  * implements a "learning switch" algorithm (see 802.1D), where incoming unicast
70  * frames from one port may occasionally be forwarded throughout all other ports,
71  * but usually they are forwarded only to a single correct output port.
72  *
73  * \attention The Spanning Tree Protocol part of 802.1D is not
74  * implemented.  Therefore, you have to be careful not to create
75  * bridging loops, or else the network will collapse.
76  *
77  * \attention Each NetDevice used must only be assigned a Mac Address, adding it
78  * to an Ipv4 or Ipv6 layer will cause an error. It also must support a SendFrom
79  * call.
80  */
81 
82 /**
83  * \ingroup openflow
84  * \brief A net device that switches multiple LAN segments via an OpenFlow-compatible flow table
85  */
86 class OpenFlowSwitchNetDevice : public NetDevice
87 {
88 public:
89   /**
90    * Register this type.
91    * \return The TypeId.
92    */
93   static TypeId GetTypeId (void);
94 
95   /**
96    * \name Descriptive Data
97    * \brief OpenFlowSwitchNetDevice Description Data
98    *
99    * These four data describe the OpenFlowSwitchNetDevice as if it were
100    * a real OpenFlow switch.
101    *
102    * There is a type of stats request that OpenFlow switches are supposed
103    * to handle that returns the description of the OpenFlow switch. Currently
104    * manufactured by "The ns-3 team", software description is "Simulated
105    * OpenFlow Switch", and the other two are "N/A".
106    * @{
107    */
108   /** \returns The descriptive string. */
109   static const char * GetManufacturerDescription ();
110   static const char * GetHardwareDescription ();
111   static const char * GetSoftwareDescription ();
112   static const char * GetSerialNumber ();
113   /**@}*/
114 
115   OpenFlowSwitchNetDevice ();
116   virtual ~OpenFlowSwitchNetDevice ();
117 
118   /**
119    * \brief Set up the Switch's controller connection.
120    *
121    * \param c Pointer to a Controller.
122    */
123   void SetController (Ptr<ofi::Controller> c);
124 
125   /**
126    * \brief Add a 'port' to a switch device
127    *
128    * This method adds a new switch port to a OpenFlowSwitchNetDevice, so that
129    * the new switch port NetDevice becomes part of the switch and L2
130    * frames start being forwarded to/from this NetDevice.
131    *
132    * \note The netdevice that is being added as switch port must
133    * _not_ have an IP address.  In order to add IP connectivity to a
134    * bridging node you must enable IP on the OpenFlowSwitchNetDevice itself,
135    * never on its port netdevices.
136    *
137    * \param switchPort The port to add.
138    * \return 0 if everything's ok, otherwise an error number.
139    * \sa #EXFULL
140    */
141   int AddSwitchPort (Ptr<NetDevice> switchPort);
142 
143   /**
144    * \brief Add a virtual port to a switch device
145    *
146    * The Ericsson OFSID has the concept of virtual ports and virtual
147    * port tables. These are implemented in the OpenFlowSwitchNetDevice, but
148    * don't have an understood use [perhaps it may have to do with
149    * MPLS integration].
150    *
151    * \sa #EINVAL
152    *
153    * \param ovpm The data for adding a virtual port.
154    * \return 0 if everything's ok, otherwise an error number.
155    */
156   int AddVPort (const ofp_vport_mod *ovpm);
157 
158   /**
159    * \brief Stats callback is ready for a dump.
160    *
161    * Controllers have a callback system for status requests which calls this function.
162    *
163    * \param cb_ The callback data.
164    * \return 0 if everything's ok, otherwise an error number.
165    */
166   int StatsDump (ofi::StatsDumpCallback *cb_);
167 
168   /**
169    * \brief Stats callback is done.
170    *
171    * Controllers have a callback system for status requests which calls this function.
172    *
173    * \param cb_ The callback data.
174    */
175   void StatsDone (ofi::StatsDumpCallback *cb_);
176 
177   /**
178    * \brief Called from the OpenFlow Interface to output the Packet on either a Port or the Controller
179    *
180    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
181    * \param in_port The index of the port the Packet was initially received on.
182    * \param max_len The maximum number of bytes the caller wants to be sent; a value of 0 indicates the entire packet should be sent. Used when outputting to controller.
183    * \param out_port The port we want to output on.
184    * \param ignore_no_fwd If true, Ports that are set to not forward are forced to forward.
185    */
186   void DoOutput (uint32_t packet_uid, int in_port, size_t max_len, int out_port, bool ignore_no_fwd);
187 
188   /**
189    * \brief The registered controller calls this method when sending a message to the switch.
190    *
191    * \param msg The message received from the controller.
192    * \param length Length of the message.
193    * \return 0 if everything's ok, otherwise an error number.
194    */
195   int ForwardControlInput (const void *msg, size_t length);
196 
197   /**
198    * \return The flow table chain.
199    */
200   sw_chain* GetChain ();
201 
202   /**
203    * \return Number of switch ports attached to this switch.
204    */
205   uint32_t GetNSwitchPorts (void) const;
206 
207   /**
208    * \param p The Port to get the index of.
209    * \return The index of the provided Port.
210    */
211   int GetSwitchPortIndex (ofi::Port p);
212 
213   /**
214    * \param n index of the Port.
215    * \return The Port.
216    */
217   ofi::Port GetSwitchPort (uint32_t n) const;
218 
219   /**
220    * \return The virtual port table.
221    */
222   vport_table_t GetVPortTable ();
223 
224   // From NetDevice
225   virtual void SetIfIndex (const uint32_t index);
226   virtual uint32_t GetIfIndex (void) const;
227   virtual Ptr<Channel> GetChannel (void) const;
228   virtual void SetAddress (Address address);
229   virtual Address GetAddress (void) const;
230   virtual bool SetMtu (const uint16_t mtu);
231   virtual uint16_t GetMtu (void) const;
232   virtual bool IsLinkUp (void) const;
233   virtual void AddLinkChangeCallback (Callback<void> callback);
234   virtual bool IsBroadcast (void) const;
235   virtual Address GetBroadcast (void) const;
236   virtual bool IsMulticast (void) const;
237   virtual Address GetMulticast (Ipv4Address multicastGroup) const;
238   virtual bool IsPointToPoint (void) const;
239   virtual bool IsBridge (void) const;
240   virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
241   virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
242   virtual Ptr<Node> GetNode (void) const;
243   virtual void SetNode (Ptr<Node> node);
244   virtual bool NeedsArp (void) const;
245   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
246   virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
247   virtual bool SupportsSendFrom () const;
248   virtual Address GetMulticast (Ipv6Address addr) const;
249 
250 protected:
251   virtual void DoDispose (void);
252 
253   /**
254    * Called when a packet is received on one of the switch's ports.
255    *
256    * \param netdev The port the packet was received on.
257    * \param packet The Packet itself.
258    * \param protocol The protocol defining the Packet.
259    * \param src The source address of the Packet.
260    * \param dst The destination address of the Packet.
261    * \param PacketType Type of the packet.
262    */
263   void ReceiveFromDevice (Ptr<NetDevice> netdev, Ptr<const Packet> packet, uint16_t protocol, const Address& src, const Address& dst, PacketType packetType);
264 
265   /**
266    * Takes a packet and generates an OpenFlow buffer from it, loading the packet data as well as its headers.
267    *
268    * \param packet The packet.
269    * \param src The source address.
270    * \param dst The destination address.
271    * \param mtu The Maximum Transmission Unit.
272    * \param protocol The protocol defining the packet.
273    * \return The OpenFlow Buffer created from the packet.
274    */
275   ofpbuf * BufferFromPacket (Ptr<const Packet> packet, Address src, Address dst, int mtu, uint16_t protocol);
276 
277 private:
278   /**
279    * Add a flow.
280    *
281    * \sa #ENOMEM, #ENOBUFS, #ESRCH
282    *
283    * \param ofm The flow data to add.
284    * \return 0 if everything's ok, otherwise an error number.
285    */
286   int AddFlow (const ofp_flow_mod *ofm);
287 
288   /**
289    * Modify a flow.
290    *
291    * \param ofm The flow data to modify.
292    * \return 0 if everything's ok, otherwise an error number.
293    */
294   int ModFlow (const ofp_flow_mod *ofm);
295 
296   /**
297    * Send packets out all the ports except the originating one
298    *
299    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
300    * \param in_port The index of the port the Packet was initially received on. This port doesn't forward when flooding.
301    * \param flood If true, don't send out on the ports with flooding disabled.
302    * \return 0 if everything's ok, otherwise an error number.
303    */
304   int OutputAll (uint32_t packet_uid, int in_port, bool flood);
305 
306   /**
307    * Sends a copy of the Packet over the provided output port
308    *
309    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
310    */
311   void OutputPacket (uint32_t packet_uid, int out_port);
312 
313   /**
314    * Seeks to send out a Packet over the provided output port. This is called generically
315    * when we may or may not know the specific port we're outputting on. There are many
316    * pre-set types of port options besides a Port that's hooked to our OpenFlowSwitchNetDevice.
317    * For example, it could be outputting as a flood, or seeking to output to the controller.
318    *
319    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
320    * \param in_port The index of the port the Packet was initially received on.
321    * \param out_port The port we want to output on.
322    * \param ignore_no_fwd If true, Ports that are set to not forward are forced to forward.
323    */
324   void OutputPort (uint32_t packet_uid, int in_port, int out_port, bool ignore_no_fwd);
325 
326   /**
327    * Sends a copy of the Packet to the controller. If the packet can be saved
328    * in an OpenFlow buffer, then only the first 'max_len' bytes of the packet
329    * are sent; otherwise, all of the packet is sent.
330    *
331    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
332    * \param in_port The index of the port the Packet was initially received on.
333    * \param max_len The maximum number of bytes that the caller wants to be sent; a value of 0 indicates the entire packet should be sent.
334    * \param reason Why the packet is being sent.
335    */
336   void OutputControl (uint32_t packet_uid, int in_port, size_t max_len, int reason);
337 
338   /**
339    * If an error message happened during the controller's request, send it to the controller.
340    *
341    * \param type The type of error.
342    * \param code The error code.
343    * \param data The faulty data that lead to the error.
344    * \param len The length of the faulty data.
345    */
346   void SendErrorMsg (uint16_t type, uint16_t code, const void *data, size_t len);
347 
348   /**
349    * Send a reply about this OpenFlow switch's features to the controller.
350    *
351    * List of capabilities and actions to support are found in the specification
352    * <www.openflowswitch.org/documents/openflow-spec-v0.8.9.pdf>.
353    *
354    * Supported capabilities and actions are defined in the openflow interface.
355    * To recap, flow status, flow table status, port status, virtual port table
356    * status can all be requested. It can also transmit over multiple physical
357    * interfaces.
358    *
359    * It supports every action: outputting over a port, and all of the flow table
360    * manipulation actions: setting the 802.1q VLAN ID, the 802.1q priority,
361    * stripping the 802.1 header, setting the Ethernet source address and destination,
362    * setting the IP source address and destination, setting the TCP/UDP source address
363    * and destination, and setting the MPLS label and EXP bits.
364    *
365    * \attention Capabilities STP (Spanning Tree Protocol) and IP packet
366    * reassembly are not currently supported.
367    *
368    */
369   void SendFeaturesReply ();
370 
371   /**
372    * Send a reply to the controller that a specific flow has expired.
373    *
374    * \param flow The flow that expired.
375    * \param reason The reason for sending this expiration notification.
376    */
377   void SendFlowExpired (sw_flow *flow, enum ofp_flow_expired_reason reason);
378 
379   /**
380    * Send a reply about a Port's status to the controller.
381    *
382    * \param p The port to get status from.
383    * \param status The reason for sending this reply.
384    */
385   void SendPortStatus (ofi::Port p, uint8_t status);
386 
387   /**
388    * Send a reply about this OpenFlow switch's virtual port table features to the controller.
389    */
390   void SendVPortTableFeatures ();
391 
392   /**
393    * Send a message to the controller. This method is the key
394    * to communicating with the controller, it does the actual
395    * sending. The other Send methods call this one when they
396    * are ready to send a message.
397    *
398    * \param buffer Buffer of the message to send out.
399    * \return 0 if successful, otherwise an error number.
400    */
401   int SendOpenflowBuffer (ofpbuf *buffer);
402 
403   /**
404    * Run the packet through the flow table. Looks up in the flow table for a match.
405    * If it doesn't match, it forwards the packet to the registered controller, if the flag is set.
406    *
407    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
408    * \param port The port this packet was received over.
409    * \param send_to_controller If set, sends to the controller if the packet isn't matched.
410    */
411   void RunThroughFlowTable (uint32_t packet_uid, int port, bool send_to_controller = true);
412 
413   /**
414    * Run the packet through the vport table. As with AddVPort,
415    * this doesn't have an understood use yet.
416    *
417    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
418    * \param port The port this packet was received over.
419    * \param vport The virtual port this packet identifies itself by.
420    * \return 0 if everything's ok, otherwise an error number.
421    */
422   int RunThroughVPortTable (uint32_t packet_uid, int port, uint32_t vport);
423 
424   /**
425    * Called by RunThroughFlowTable on a scheduled delay
426    * to account for the flow table lookup overhead.
427    *
428    * \param key Matching key to look up in the flow table.
429    * \param buffer Buffer of the packet received.
430    * \param packet_uid Packet UID; used to fetch the packet and its metadata.
431    * \param port The port the packet was received over.
432    * \param send_to_controller
433    */
434   void FlowTableLookup (sw_flow_key key, ofpbuf* buffer, uint32_t packet_uid, int port, bool send_to_controller);
435 
436   /**
437    * Update the port status field of the switch port.
438    * A non-zero return value indicates some field has changed.
439    *
440    * \param p A reference to a Port; used to change its config and flag fields.
441    * \return true if the status of the Port is changed, false if unchanged (was already the right status).
442    */
443   int UpdatePortStatus (ofi::Port& p);
444 
445   /**
446    * Fill out a description of the switch port.
447    *
448    * \param p The port to get the description from.
449    * \param desc A pointer to the description message; used to fill the description message with the data from the port.
450    */
451   void FillPortDesc (ofi::Port p, ofp_phy_port *desc);
452 
453   /**
454    * Generates an OpenFlow reply message based on the type.
455    *
456    * \param openflow_len Length of the reply to make.
457    * \param type Type of reply message to make.
458    * \param bufferp Message buffer; used to make the reply.
459    * \return The OpenFlow reply message.
460    */
461   void* MakeOpenflowReply (size_t openflow_len, uint8_t type, ofpbuf **bufferp);
462 
463   /**
464    * \name Receive Methods
465    *
466    * Actions to do when a specific OpenFlow message/packet is received
467    *
468    * @{
469    */
470   /**
471    * \param msg The OpenFlow message received.
472    * \return 0 if everything's ok, otherwise an error number.
473    */
474   int ReceiveFeaturesRequest (const void *msg);
475   int ReceiveGetConfigRequest (const void *msg);
476   int ReceiveSetConfig (const void *msg);
477   int ReceivePacketOut (const void *msg);
478   int ReceiveFlow (const void *msg);
479   int ReceivePortMod (const void *msg);
480   int ReceiveStatsRequest (const void *oh);
481   int ReceiveEchoRequest (const void *oh);
482   int ReceiveEchoReply (const void *oh);
483   int ReceiveVPortMod (const void *msg);
484   int ReceiveVPortTableFeaturesRequest (const void *msg);
485   /**@}*/
486 
487   /// Callbacks
488   NetDevice::ReceiveCallback m_rxCallback;
489   NetDevice::PromiscReceiveCallback m_promiscRxCallback;
490 
491   Mac48Address m_address;               ///< Address of this device.
492   Ptr<Node> m_node;                     ///< Node this device is installed on.
493   Ptr<BridgeChannel> m_channel;         ///< Collection of port channels into the Switch Channel.
494   uint32_t m_ifIndex;                   ///< Interface Index
495   uint16_t m_mtu;                       ///< Maximum Transmission Unit
496 
497   typedef std::map<uint32_t,ofi::SwitchPacketMetadata> PacketData_t;
498   PacketData_t m_packetData;            ///< Packet data
499 
500   typedef std::vector<ofi::Port> Ports_t;
501   Ports_t m_ports;                      ///< Switch's ports
502 
503   Ptr<ofi::Controller> m_controller;    ///< Connection to controller.
504 
505   uint64_t m_id;                        ///< Unique identifier for this switch, needed for OpenFlow
506   Time m_lookupDelay;                   ///< Flow Table Lookup Delay [overhead].
507 
508   Time m_lastExecute;                   ///< Last time the periodic execution occurred.
509   uint16_t m_flags;                     ///< Flags; configurable by the controller.
510   uint16_t m_missSendLen;               ///< Flow Table Miss Send Length; configurable by the controller.
511 
512   sw_chain *m_chain;             ///< Flow Table; forwarding rules.
513   vport_table_t m_vportTable;    ///< Virtual Port Table
514 };
515 
516 } // namespace ns3
517 
518 #endif /* OPENFLOW_SWITCH_NET_DEVICE_H */
519