nsc: move nsc glue code from nsc-tcp-l4-protocol to node/nsc-glue.cc.
known problems:
- sim_interface.h is duplicated
- nsc-glue.cc adds hooks in node.cc, "hijacks" incoming packets
- nsc-glue exports NSCs INetStack (instead of wrapping it completely)
- nsc-tcp-l4-protocol and nsc-tcp-socket-impl make calls into nsc-glue
- nsc-tcp-socket-impl should really be "nsc-socket-core" (or something
like that)
needs fixing on nsc side:
- no support for multiple interfaces yet (also not yet supported
on nsc side)
- nsc initialisation still tied to IP (Adding an Interface and assigning the
IP address is a single step; it should be separate)
maybe there is more.
There is a NSC_NEXT define in nsc-glue.h, its main purpose is to flag
the places where the NSC API needs to be adapted to support multiple
interfaces in nsc.
3 #include "ns3/boolean.h"
5 #include "ns3/ipv4-l3-protocol.h"
7 #include "ns3/ipv4-interface.h"
8 #include "ns3/object.h"
9 #include "ns3/packet.h"
11 #include "ns3/nstime.h"
16 #include <netinet/ip.h>
17 #include <arpa/inet.h>
21 NS_OBJECT_ENSURE_REGISTERED (NscGlue);
24 NscGlue::GetTypeId (void)
26 static TypeId tid = TypeId ("ns3::NscGlue")
27 .SetParent <Object> ()
32 NscGlue::NscGlue(void)
33 : m_wakeupCallbacks(0),
39 NscGlue::SetNode(Ptr<Node> n)
45 NscGlue::PassPacketToNsc (Ptr<const Packet> packet, int idx)
47 uint32_t packetSize = packet->GetSize();
48 const uint8_t *data = const_cast<uint8_t *>(packet->PeekData());
50 // deliver complete packet to the NSC network stack
51 m_nscStack->if_receive_packet(idx, data, packetSize);
56 NscGlue::IsNscProtocol (uint16_t proto)
58 return proto == 0x0800; // NSC can only handle ipv4 at the moment.
61 static int external_rand(void)
63 return 1; // XXX: check which NSC stacks actually use this
67 NscGlue::SetNscLibrary(const std::string &soname)
69 NS_ASSERT(!m_dlopenHandle);
70 m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
71 if (m_dlopenHandle == NULL)
72 NS_FATAL_ERROR (dlerror());
74 FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
76 m_nscStack = create(this, this, external_rand);
77 int hzval = m_nscStack->get_hz();
81 m_softTimer.SetFunction (&NscGlue::SoftRtcInterrupt, this);
82 m_softTimer.SetDelay (MilliSeconds (1000/hzval));
83 // This enables stack and NSC debug messages
84 m_nscStack->set_diagnostic(10);
85 m_nscStack->init(hzval);
87 Ptr<Ns3NscStack> nscStack = Create<Ns3NscStack> ();
88 nscStack->SetStack (m_nscStack);
89 m_node->AggregateObject (nscStack);
91 m_softTimer.Schedule ();
92 // its likely no ns-3 interface exits at this point, so
93 // we delay adding the nsc interface until the start of the simulation.
94 Simulator::ScheduleNow(&NscGlue::AddIface, this);
96 m_nscLibrary = soname;
100 NscGlue::GetNscLibrary () const
106 void NscGlue::wakeup()
109 // this should schedule a timer to read from all tcp sockets now... this is
110 // an indication that data might be waiting on the socket
111 for (std::list<Callback<void> >::iterator i = m_wakeupCallbacks.begin ();
112 i != m_wakeupCallbacks.end (); i++)
114 Callback<void> cb = *i;
119 void NscGlue::SoftRtcInterrupt (void)
121 m_nscStack->timer_interrupt ();
122 m_nscStack->increment_ticks ();
123 m_softTimer.Schedule ();
126 void NscGlue::gettime(unsigned int* sec, unsigned int* usec)
128 // Only used by the Linux network stack, e.g. during ISN generation
129 // and in the kernel rng initialization routine. Also used in Linux
131 Time t = Simulator::Now ();
132 int64_t us = t.GetMicroSeconds ();
133 *sec = us / (1000*1000);
134 *usec = us - *sec * (1000*1000);
138 void NscGlue::send_callback(int idx, const void* data, unsigned int datalen)
140 void NscGlue::send_callback(/* int idx,*/ const void* data, unsigned int datalen)
149 NS_ASSERT(datalen > 20);
151 // FIXME: XXX: This won't really work when NSC is able to use
152 // L3 protocols other than AF_INET. We really really really
153 // should be able to do all routing decisions inside nsc and just
154 // pass packets to whatever network interface without looking at its contents.
155 const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(data);
157 p = Create<Packet> (rawdata, datalen);
159 // we need the destination ipv4 address for Send ().
160 const uint32_t *ipheader = reinterpret_cast<const uint32_t *>(data);
162 ipv4Daddr = *(ipheader+4);
164 Ipv4Address daddr(ntohl(ipv4Daddr));
166 Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
167 NS_ASSERT_MSG (ipv4, "nsc callback invoked, but node has no ipv4 object");
168 // FIXME: do _all_ routing via NSC and provide a ns3-nsc mapping that
169 // tells us which ns-3 interface the nsc interface "idx" is corresponding to.
170 //NS_LOG_LOGIC ("ns3: xmit via device number " << idx);
171 Ptr<Ipv4Interface> outInterface = ipv4->GetInterface ( idx + 1);
173 NS_ASSERT (outInterface);
174 outInterface->Send (p, daddr);
175 m_nscStack->if_send_finish(0);
179 void NscGlue::RegisterWakeupCallback(Callback<void> cb)
181 m_wakeupCallbacks.push_back (cb);
184 void NscGlue::AddIface(void)
186 Ptr<Ipv4> ip = m_node->GetObject<Ipv4> ();
188 const uint32_t nInterfaces = ip->GetNInterfaces ();
189 // start from 1, ignore the loopback interface (HACK)
191 for (uint32_t i = 1; i < nInterfaces; i++)
193 Ipv4InterfaceAddress ifAddr = ip->GetAddress (i, 0);
194 Ipv4Address addr = ifAddr.GetLocal ();
195 Ipv4Mask mask = ifAddr.GetMask ();
197 uint16_t mtu = ip->GetMtu (i);
199 std::ostringstream addrOss, maskOss;
204 // NS_LOG_LOGIC ("if_attach " << addrOss.str().c_str() << " " << maskOss.str().c_str() << " " << mtu);
206 std::string addrStr = addrOss.str();
207 std::string maskStr = maskOss.str();
208 const char* addrCStr = addrStr.c_str();
209 const char* maskCStr = maskStr.c_str();
210 NS_ASSERT_MSG (m_nscStack, "m_nscStackError");
211 m_nscStack->if_attach(addrCStr, maskCStr, mtu);
215 // We need to come up with a default gateway here. Can't guarantee this to be
218 uint8_t addrBytes[4];
219 addr.Serialize(addrBytes);
221 // XXX: this is all a bit of a horrible hack
223 // Just increment the last octet, this gives a decent chance of this being
226 // All we need is another address on the same network as the interface. This
227 // will force the stack to output the packet out of the network interface.
229 addr.Deserialize(addrBytes);
232 m_nscStack->add_default_gateway(addrOss.str().c_str());