00001 /*! 00002 \page net-device How to create a new OSI layer 1 + 2 implementation ? 00003 \anchor howtos-net-device 00004 00005 <b>Question:</b> How do I integrate a new OSI layer 1 + 2 implementation ? 00006 00007 <b>Answer:</b> The OSI layers 1 and 2 are represented by the ns3::NetDevice 00008 and ns3::Channel classes. To plug transparently in ns-3, a new layer 1+2 model 00009 thus simply needs to provide two new subclasses of these two base classes. 00010 00011 To make that subclassing process easy, two skeleton classes are provided in 00012 the src/node directory: simple-net-device.h (ns3::SimpleNetDevice) and 00013 simple-channel.h (ns3::SimpleChannel) implement a broadcast passthru medium 00014 using 48bit MAC addresses without any kind of MAC access algorithm or PHY 00015 layer modeling. 00016 00017 The ns3::SimpleChannel class is really very simple: it provides 00018 an implementation for the ns3::Channel::GetNDevices and ns3::Channel::GetDevice 00019 methods defined in the Channel base class and, then defines the channel-specific 00020 send and add methods: 00021 - The Add method is used by SimpleNetDevice::SetChannel to register a new 00022 SimpleNetDevice with its associated channel. 00023 - The Send method is used by SimpleNetDevice::Send to send a packet over the 00024 broadcast medium and ensure that it gets delivered to all associated devices 00025 (except the sender). 00026 00027 \code 00028 class SimpleChannel : public Channel 00029 { 00030 public: 00031 static TypeId GetTypeId (void); 00032 SimpleChannel (); 00033 00034 void Send (Ptr<Packet> p, uint16_t protocol, Mac48Address to, Mac48Address from, 00035 Ptr<SimpleNetDevice> sender); 00036 00037 void Add (Ptr<SimpleNetDevice> device); 00038 00039 // inherited from ns3::Channel 00040 virtual uint32_t GetNDevices (void) const; 00041 virtual Ptr<NetDevice> GetDevice (uint32_t i) const; 00042 00043 private: 00044 std::vector<Ptr<SimpleNetDevice> > m_devices; 00045 }; 00046 \endcode 00047 00048 The SimpleNetDevice class is also trivial since it implements no special 00049 MAC-layer processing: 00050 \code 00051 class SimpleNetDevice : public NetDevice 00052 { 00053 public: 00054 static TypeId GetTypeId (void); 00055 SimpleNetDevice (); 00056 00057 void Receive (Ptr<Packet> packet, uint16_t protocol, Mac48Address to, Mac48Address from); 00058 void SetChannel (Ptr<SimpleChannel> channel); 00059 void SetAddress (Mac48Address address); 00060 00061 // inherited from NetDevice base class. 00062 virtual void SetName(const std::string name); 00063 ... 00064 }; 00065 \endcode 00066 00067 The code below illustrates how the three model-specific methods defined above are 00068 implemented: 00069 00070 \code 00071 void 00072 SimpleNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol, 00073 Mac48Address to, Mac48Address from) 00074 { 00075 if (to == m_address || to == Mac48Address::GetBroadcast ()) 00076 { 00077 m_rxCallback (this, packet, protocol, from); 00078 } 00079 } 00080 void 00081 SimpleNetDevice::SetChannel (Ptr<SimpleChannel> channel) 00082 { 00083 m_channel = channel; 00084 m_channel->Add (this); 00085 } 00086 void 00087 SimpleNetDevice::SetAddress (Mac48Address address) 00088 { 00089 m_address = address; 00090 } 00091 \endcode 00092 00093 Building a topology with such a device is then a matter of 00094 instanciating a set of SimpleNetDevice objects connected on a shared 00095 SimpleChannel: 00096 \code 00097 NodeContainer nodes; 00098 nodes.Create (10); 00099 Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> (); 00100 for (uint32_t i = 0; i < nodes.GetN (); ++i) 00101 { 00102 CreateSimpleDevice (nodes.Get (i), channel); 00103 } 00104 \endcode 00105 00106 With the following CreateSimpleDevice function: 00107 \code 00108 static Ptr<SimpleNetDevice> 00109 CreateSimpleDevice (Ptr<Node> node, Ptr<SimpleChannel> channel) 00110 { 00111 Ptr<SimpleNetDevice> device = CreateObject<SimpleNetDevice> (); 00112 device->SetAddress (Mac48Address:Allocate ()); 00113 device->SetChannel (channel); 00114 node->AddDevice (device); 00115 return device; 00116 } 00117 \endcode 00118 00119 Of course, ultimately, you need to provide a helper class for this new device and channel 00120 to save each user from having to re-implement their own CreateSimpleDevice helper 00121 function: 00122 00123 \code 00124 class SimpleHelper 00125 { 00126 public: 00127 NetDeviceContainer Install (NodeContainer nodes, Ptr<SimpleChannel> channel); 00128 NetDeviceContainer Install (NodeContainer nodes); 00129 }; 00130 \endcode 00131 00132 with the following straightforward implementation, inspired by the CreateSimpleDevice 00133 function defined above: 00134 00135 \code 00136 NetDeviceContainer 00137 SimpleHelper::Install (NodeContainer nodes, Ptr<SimpleChannel> channel) 00138 { 00139 NetDeviceContainer devices; 00140 for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) 00141 { 00142 Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> (); 00143 dev->SetAddress (Mac48Address::Allocate ()); 00144 dev->SetChannel (channel); 00145 (*i)->AddDevice (dev); 00146 devices.Add (dev); 00147 } 00148 return devices; 00149 } 00150 NetDeviceContainer 00151 SimpleHelper::Install (NodeContainer nodes) 00152 { 00153 return Install (nodes, CreateObject<SimpleChannel> ()); 00154 } 00155 \endcode 00156 00157 Of course, at some point, this device helper class should also contain a couple of 00158 ascii and pcap tracing helper functions but, since the default SimpleNetDevice 00159 class we used as an example here does not report any trace event, it would 00160 be of little use. 00161 00162 */