diff --git a/.hgtags b/.hgtags index 45520a625..b4fa52149 100644 --- a/.hgtags +++ b/.hgtags @@ -7,3 +7,4 @@ 267e2ebc28e4e4ae2f579e1cfc29902acade0c34 buffer-working-before-breaking 606df29888e7573b825fc891a002f0757166b616 release ns-3.0.6 36472385a1cc7c44d34fb7a5951b930010f4e8d2 release ns-3.0.7 +560a5091e0e6ded47d269e2f2dee780f13950a63 release ns-3.0.8 diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 4aff62726..3c6a78ebb 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,6 +3,11 @@ This file contains ns-3 release notes (most recent releases first). +Release 3.0.8 (2007/11/15) +======================== + - A simple error model + - Source files for ns-3 tutorial + Release 3.0.7 (2007/10/15) ======================== - OLSR routing protocol diff --git a/VERSION b/VERSION index 2451c27ca..67786e246 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.7 +3.0.8 diff --git a/src/node/drop-tail-queue.cc b/src/node/drop-tail-queue.cc index a4fb979bb..7b88231ab 100644 --- a/src/node/drop-tail-queue.cc +++ b/src/node/drop-tail-queue.cc @@ -111,4 +111,69 @@ DropTailQueue::DoPeek (Packet& p) return true; } +} // namespace ns3 + + +#ifdef RUN_SELF_TESTS + +#include "ns3/test.h" + +namespace ns3 { + +class DropTailQueueTest: public Test { +public: + virtual bool RunTests (void); + DropTailQueueTest (); +}; + + +DropTailQueueTest::DropTailQueueTest () + : Test ("DropTailQueue") {} + + +bool +DropTailQueueTest::RunTests (void) +{ + bool result = true; + + DropTailQueue queue; + queue.SetMaxPackets (3); + + Packet p1, p2, p3, p4; + + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 0); + queue.Enqueue (p1); + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 1); + queue.Enqueue (p2); + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 2); + queue.Enqueue (p3); + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 3); + queue.Enqueue (p4); // will be dropped + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 3); + + Packet p; + + NS_TEST_ASSERT (queue.Dequeue (p)); + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 2); + NS_TEST_ASSERT_EQUAL (p.GetUid (), p1.GetUid ()); + + NS_TEST_ASSERT (queue.Dequeue (p)); + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 1); + NS_TEST_ASSERT_EQUAL (p.GetUid (), p2.GetUid ()); + + NS_TEST_ASSERT (queue.Dequeue (p)); + NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 0); + NS_TEST_ASSERT_EQUAL (p.GetUid (), p3.GetUid ()); + + NS_TEST_ASSERT (!queue.Dequeue (p)); + + return result; +} + + +static DropTailQueueTest gDropTailQueueTest; + }; // namespace ns3 + +#endif /* RUN_SELF_TESTS */ + diff --git a/src/node/packet-socket.cc b/src/node/packet-socket.cc index 448b84334..000d95966 100644 --- a/src/node/packet-socket.cc +++ b/src/node/packet-socket.cc @@ -222,22 +222,26 @@ PacketSocket::SendTo(const Address &address, const Packet &p) PacketSocketAddress ad; if (m_state == STATE_CLOSED) { + NS_LOG_LOGIC ("ERROR_BADF"); m_errno = ERROR_BADF; return -1; } if (m_state == STATE_OPEN) { // XXX should return another error here. + NS_LOG_LOGIC ("ERROR_INVAL"); m_errno = ERROR_INVAL; return -1; } if (m_shutdownSend) { + NS_LOG_LOGIC ("ERROR_SHUTDOWN"); m_errno = ERROR_SHUTDOWN; return -1; } if (!PacketSocketAddress::IsMatchingType (address)) { + NS_LOG_LOGIC ("ERROR_AFNOSUPPORT"); m_errno = ERROR_AFNOSUPPORT; return -1; } @@ -250,6 +254,7 @@ PacketSocket::SendTo(const Address &address, const Packet &p) Ptr device = m_node->GetDevice (ad.GetSingleDevice ()); if (!device->Send (p, dest, ad.GetProtocol ())) { + NS_LOG_LOGIC ("error: NetDevice::Send error"); error = true; } } @@ -260,6 +265,7 @@ PacketSocket::SendTo(const Address &address, const Packet &p) Ptr device = m_node->GetDevice (i); if (!device->Send (p, dest, ad.GetProtocol ())) { + NS_LOG_LOGIC ("error: NetDevice::Send error"); error = true; } } @@ -271,6 +277,7 @@ PacketSocket::SendTo(const Address &address, const Packet &p) if (error) { + NS_LOG_LOGIC ("ERROR_INVAL 2"); m_errno = ERROR_INVAL; return -1; } diff --git a/tutorial/ipv4-address-generator.cc b/tutorial/ipv4-address-generator.cc new file mode 100644 index 000000000..dc28b4ddc --- /dev/null +++ b/tutorial/ipv4-address-generator.cc @@ -0,0 +1,255 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/simulation-singleton.h" +#include "ipv4-address-generator.h" + +NS_LOG_COMPONENT_DEFINE("Ipv4AddressGenerator"); + +namespace ns3 { + +class Ipv4NetworkGeneratorImpl +{ +public: + Ipv4NetworkGeneratorImpl (); + virtual ~Ipv4NetworkGeneratorImpl (); + + Ipv4Address Allocate (const Ipv4Mask mask); + void Seed (const Ipv4Mask mask, const Ipv4Address network); + +private: + static const uint32_t N_BITS = 32; + class State + { + public: + uint32_t mask; + uint32_t network; + }; + State m_state[N_BITS]; +}; + +Ipv4NetworkGeneratorImpl::Ipv4NetworkGeneratorImpl () +{ + NS_LOG_FUNCTION; + + uint32_t mask = 0; + + for (uint32_t i = 0; i < N_BITS; ++i) + { + m_state[i].mask = mask; + mask >>= 1; + mask |= 0x80000000; + m_state[i].network = 0; + NS_LOG_LOGIC ("m_state[" << i << "]"); + NS_LOG_LOGIC ("mask = " << std::hex << m_state[i].mask); + NS_LOG_LOGIC ("network = " << std::hex << m_state[i].network); + } +} + +Ipv4NetworkGeneratorImpl::~Ipv4NetworkGeneratorImpl () +{ + NS_LOG_FUNCTION; +} + + void +Ipv4NetworkGeneratorImpl::Seed ( + const Ipv4Mask mask, + const Ipv4Address network) +{ + NS_LOG_FUNCTION; + + uint32_t maskBits = mask.GetHostOrder (); + uint32_t networkBits = network.GetHostOrder (); + + for (uint32_t i = 0; i < N_BITS; ++i) + { + if (maskBits & 1) + { + uint32_t nMaskBits = N_BITS - i; + NS_ASSERT(nMaskBits >= 0 && nMaskBits < N_BITS); + m_state[nMaskBits].network = networkBits >> (N_BITS - i); + return; + } + maskBits >>= 1; + } + NS_ASSERT_MSG(false, "Impossible"); + return; +} + + Ipv4Address +Ipv4NetworkGeneratorImpl::Allocate (const Ipv4Mask mask) +{ + NS_LOG_FUNCTION; + + uint32_t bits = mask.GetHostOrder (); + + for (uint32_t i = 0; i < N_BITS; ++i) + { + if (bits & 1) + { + uint32_t nBits = N_BITS - i; + NS_ASSERT(nBits >= 0 && nBits < N_BITS); + Ipv4Address addr (m_state[nBits].network << i); + ++m_state[nBits].network; + return addr; + } + bits >>= 1; + } + NS_ASSERT_MSG(false, "Impossible"); + return Ipv4Address (bits); +} + +class Ipv4AddressGeneratorImpl +{ +public: + Ipv4AddressGeneratorImpl (); + virtual ~Ipv4AddressGeneratorImpl (); + + Ipv4Address Allocate (const Ipv4Mask mask, const Ipv4Address network); + void Seed (const Ipv4Mask mask, const Ipv4Address address); + +private: + static const uint32_t N_BITS = 32; + class State + { + public: + uint32_t mask; + uint32_t address; + }; + State m_state[N_BITS]; +}; + +Ipv4AddressGeneratorImpl::Ipv4AddressGeneratorImpl () +{ + NS_LOG_FUNCTION; + + uint32_t mask = 0; + + for (uint32_t i = 0; i < N_BITS; ++i) + { + m_state[i].mask = mask; + mask >>= 1; + mask |= 0x80000000; + m_state[i].address = 0; + NS_LOG_LOGIC ("m_state[" << i << "]"); + NS_LOG_LOGIC ("mask = " << std::hex << m_state[i].mask); + NS_LOG_LOGIC ("address = " << std::hex << m_state[i].address); + } +} + +Ipv4AddressGeneratorImpl::~Ipv4AddressGeneratorImpl () +{ + NS_LOG_FUNCTION; +} + + void +Ipv4AddressGeneratorImpl::Seed ( + const Ipv4Mask mask, + const Ipv4Address address) +{ + NS_LOG_FUNCTION; + + uint32_t maskBits = mask.GetHostOrder (); + uint32_t addressBits = address.GetHostOrder (); + + for (uint32_t i = 0; i < N_BITS; ++i) + { + if (maskBits & 1) + { + uint32_t nMaskBits = N_BITS - i; + NS_ASSERT(nMaskBits >= 0 && nMaskBits < N_BITS); + m_state[nMaskBits].address = addressBits; + return; + } + maskBits >>= 1; + } + NS_ASSERT_MSG(false, "Impossible"); + return; +} + + Ipv4Address +Ipv4AddressGeneratorImpl::Allocate ( + const Ipv4Mask mask, + const Ipv4Address network) +{ + NS_LOG_FUNCTION; + + uint32_t bits = mask.GetHostOrder (); + uint32_t net = network.GetHostOrder (); + + for (uint32_t i = 0; i < N_BITS; ++i) + { + if (bits & 1) + { + uint32_t nBits = N_BITS - i; + NS_ASSERT(nBits >= 0 && nBits < N_BITS); + Ipv4Address addr (net | m_state[nBits].address); + ++m_state[nBits].address; + NS_ASSERT_MSG((m_state[nBits].mask & m_state[nBits].address) == 0, + "Ipv4AddressGeneratorImpl::Allocate(): Overflow"); + return addr; + } + bits >>= 1; + } + NS_ASSERT_MSG(false, "Impossible"); + return Ipv4Address (bits); +} + + void +Ipv4AddressGenerator::SeedAddress ( + const Ipv4Mask mask, + const Ipv4Address address) +{ + NS_LOG_FUNCTION; + + SimulationSingleton::Get ()->Seed (mask, address); +} + + Ipv4Address +Ipv4AddressGenerator::AllocateAddress ( + const Ipv4Mask mask, + const Ipv4Address network) +{ + NS_LOG_FUNCTION; + + return SimulationSingleton::Get ()-> + Allocate (mask, network); +} + + void +Ipv4AddressGenerator::SeedNetwork ( + const Ipv4Mask mask, + const Ipv4Address address) +{ + NS_LOG_FUNCTION; + + SimulationSingleton::Get ()->Seed (mask, address); +} + + Ipv4Address +Ipv4AddressGenerator::AllocateNetwork (const Ipv4Mask mask) +{ + NS_LOG_FUNCTION; + + return SimulationSingleton::Get ()-> + Allocate (mask); +} + +}; // namespace ns3 diff --git a/tutorial/ipv4-address-generator.h b/tutorial/ipv4-address-generator.h new file mode 100644 index 000000000..2962940d3 --- /dev/null +++ b/tutorial/ipv4-address-generator.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef IPV4_ADDRESS_GENERATOR_H +#define IPV4_ADDRESS_GENERATOR_H + +#include +#include + +#include "ns3/ipv4-address.h" + +namespace ns3 { + +class Ipv4AddressGenerator { +public: + static void SeedAddress (const Ipv4Mask mask, + const Ipv4Address address); + + static Ipv4Address AllocateAddress (const Ipv4Mask mask, + const Ipv4Address network); + + static void SeedNetwork (const Ipv4Mask mask, + const Ipv4Address address); + + static Ipv4Address AllocateNetwork (const Ipv4Mask mask); +}; + +}; // namespace ns3 + +#endif /* IPV4_ADDRESS_GENERATOR_H */ diff --git a/tutorial/ipv4-bus-network.cc b/tutorial/ipv4-bus-network.cc new file mode 100644 index 000000000..898816c1b --- /dev/null +++ b/tutorial/ipv4-bus-network.cc @@ -0,0 +1,79 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/mac48-address.h" +#include "ns3/csma-net-device.h" +#include "ns3/csma-topology.h" +#include "ns3/csma-ipv4-topology.h" + +#include "ipv4-bus-network.h" +#include "ipv4-address-generator.h" + +namespace ns3 { + +Ipv4Network::Ipv4Network ( + Ipv4Address network, + Ipv4Mask mask, + Ipv4Address address) +: + m_network (network), m_mask (mask), m_baseAddress (address) +{ +} + +Ipv4Network::~Ipv4Network () +{ +} + +Ipv4BusNetwork::Ipv4BusNetwork ( + Ipv4Address network, + Ipv4Mask mask, + Ipv4Address baseAddress, + DataRate bps, + Time delay, + uint32_t n) +: + Ipv4Network (network, mask, baseAddress) +{ + Ipv4AddressGenerator::SeedNetwork (mask, network); + Ipv4AddressGenerator::SeedAddress (mask, baseAddress); + + m_channel = CsmaTopology::CreateCsmaChannel (bps, delay); + + for (uint32_t i = 0; i < n; ++i) + { + Ptr node = Create (); + uint32_t nd = CsmaIpv4Topology::AddIpv4CsmaNetDevice (node, m_channel, + Mac48Address::Allocate ()); + Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask, + network); + CsmaIpv4Topology::AddIpv4Address (node, nd, address, mask); + m_nodes.push_back (node); + } +} + +Ipv4BusNetwork::~Ipv4BusNetwork () +{ +} + + Ptr +Ipv4BusNetwork::GetNode (uint32_t n) +{ + return m_nodes[n]; +} + +}; // namespace ns3 diff --git a/tutorial/ipv4-bus-network.h b/tutorial/ipv4-bus-network.h new file mode 100644 index 000000000..de90f7bf7 --- /dev/null +++ b/tutorial/ipv4-bus-network.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef IPV4_BUS_NETWORK_H +#define IPV4_BUS_NETWORK_H + +#include +#include "ns3/ptr.h" +#include "ns3/node.h" +#include "ns3/ipv4-address.h" +#include "ns3/data-rate.h" +#include "ns3/csma-channel.h" + +namespace ns3 { + +class Ipv4Network +{ +public: + Ipv4Network (Ipv4Address network, Ipv4Mask mask, Ipv4Address address); + virtual ~Ipv4Network (); + + Ipv4Address m_network; + Ipv4Mask m_mask; + Ipv4Address m_baseAddress; +}; + +class Ipv4BusNetwork : public Ipv4Network +{ +public: + Ipv4BusNetwork ( + Ipv4Address network, + Ipv4Mask mask, + Ipv4Address baseAddress, + DataRate bps, + Time delay, + uint32_t n); + + virtual ~Ipv4BusNetwork (); + + Ptr GetNode (uint32_t n); + +private: + std::vector > m_nodes; + Ptr m_channel; +}; + +}; // namespace ns3 + +#endif /* IPV4_BUS_NETWORK_H */ diff --git a/tutorial/point-to-point-ipv4-topology.cc b/tutorial/point-to-point-ipv4-topology.cc new file mode 100644 index 000000000..d508f84d5 --- /dev/null +++ b/tutorial/point-to-point-ipv4-topology.cc @@ -0,0 +1,73 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/nstime.h" +#include "ns3/internet-node.h" +#include "ns3/ipv4-address.h" +#include "ns3/ipv4.h" +#include "ns3/queue.h" + +#include "ns3/point-to-point-channel.h" +#include "ns3/point-to-point-net-device.h" +#include "point-to-point-ipv4-topology.h" + +namespace ns3 { + + Ptr +PointToPointIpv4Topology::CreateChannel ( + const DataRate& bps, + const Time& delay) +{ + return Create (bps, delay); +} + + uint32_t +PointToPointIpv4Topology::AddNetDevice ( + Ptr node, + Ptr channel) +{ + NS_ASSERT (channel->GetNDevices () <= 1); + + Ptr nd = Create (node); + + Ptr q = Queue::CreateDefault (); + nd->AddQueue(q); + nd->Attach (channel); + + return nd->GetIfIndex (); +} + + uint32_t +PointToPointIpv4Topology::AddAddress ( + Ptr node, + uint32_t netDeviceNumber, + Ipv4Address address, + Ipv4Mask mask) +{ + Ptr nd = node->GetDevice(netDeviceNumber); + Ptr ipv4 = node->QueryInterface (Ipv4::iid); + uint32_t ifIndex = ipv4->AddInterface (nd); + + ipv4->SetAddress (ifIndex, address); + ipv4->SetNetworkMask (ifIndex, mask); + ipv4->SetUp (ifIndex); + + return ifIndex; +} + +} // namespace ns3 diff --git a/tutorial/point-to-point-ipv4-topology.h b/tutorial/point-to-point-ipv4-topology.h new file mode 100644 index 000000000..c2a9a4391 --- /dev/null +++ b/tutorial/point-to-point-ipv4-topology.h @@ -0,0 +1,49 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef POINT_TO_POINT_IPV4_TOPOLOGY_H +#define POINT_TO_POINT_IPV4_TOPOLOGY_H + +#include "ns3/ptr.h" + +namespace ns3 { + +class PointToPointChannel; +class Node; +class Ipv4Address; +class Ipv4Mask; +class DataRate; + +class PointToPointIpv4Topology { +public: + static Ptr CreateChannel ( + const DataRate& dataRate, const Time& delay); + + static uint32_t AddNetDevice( + Ptr node, + Ptr channel); + + static uint32_t AddAddress( + Ptr node, + uint32_t ndIndex, + Ipv4Address address, + Ipv4Mask mask); +}; + +} // namespace ns3 + +#endif // POINT_TO_POINT_IPV4_TOPOLOGY_H + diff --git a/tutorial/testipv4.cc b/tutorial/testipv4.cc new file mode 100644 index 000000000..dcad2e387 --- /dev/null +++ b/tutorial/testipv4.cc @@ -0,0 +1,62 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/log.h" +#include "ipv4-address-generator.h" + +NS_LOG_COMPONENT_DEFINE ("TestIpv4"); + +using namespace ns3; + +int +main (int argc, char *argv[]) +{ + LogComponentEnable ("TestIpv4", LOG_LEVEL_ALL); + + NS_LOG_INFO ("Test Ipv4"); + + Ipv4Mask mask1 ("255.0.0.0"); + + for (uint32_t i = 0; i < 10; ++i) + { + Ipv4Address network = Ipv4AddressGenerator::AllocateNetwork (mask1); + Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask1, + network); + NS_LOG_INFO ("address = " << address); + } + + Ipv4Mask mask2 ("255.255.0.0"); + Ipv4AddressGenerator::SeedNetwork (mask2, "192.168.0.0"); + Ipv4AddressGenerator::SeedAddress (mask2, "0.0.0.3"); + + Ipv4Address network1 = Ipv4AddressGenerator::AllocateNetwork (mask2); + for (uint32_t i = 0; i < 10; ++i) + { + Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask2, + network1); + NS_LOG_INFO ("address = " << address); + } + + Ipv4Mask mask3 ("255.255.255.0"); + + for (uint32_t i = 0; i < 10; ++i) + { + Ipv4Address network = Ipv4AddressGenerator::AllocateNetwork (mask3); + Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask3, + network); + NS_LOG_INFO ("address = " << address); + } +} diff --git a/tutorial/tutorial-bus-network.cc b/tutorial/tutorial-bus-network.cc new file mode 100644 index 000000000..7013eadbe --- /dev/null +++ b/tutorial/tutorial-bus-network.cc @@ -0,0 +1,62 @@ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/log.h" +#include "ns3/ipv4-address.h" +#include "ns3/udp-echo-client.h" +#include "ns3/udp-echo-server.h" +#include "ns3/simulator.h" +#include "ns3/nstime.h" +#include "ns3/ascii-trace.h" + +#include "ipv4-bus-network.h" + +NS_LOG_COMPONENT_DEFINE ("BusNetworkSimulation"); + +using namespace ns3; + +int +main (int argc, char *argv[]) +{ + LogComponentEnable ("BusNetworkSimulation", LOG_LEVEL_ALL); + + NS_LOG_INFO ("Bus Network Simulation"); + + Ipv4BusNetwork bus ("10.1.0.0", "255.255.0.0", "0.0.0.3", + DataRate(10000000), MilliSeconds(20), 10); + + uint32_t port = 7; + + Ptr n0 = bus.GetNode (0); + Ptr client = Create (n0, "10.1.0.1", port, + 1, Seconds(1.), 1024); + + Ptr n1 = bus.GetNode (1); + Ptr server = Create (n1, port); + + server->Start(Seconds(1.)); + client->Start(Seconds(2.)); + + server->Stop (Seconds(10.)); + client->Stop (Seconds(10.)); + + AsciiTrace asciitrace ("tutorial.tr"); + asciitrace.TraceAllQueues (); + asciitrace.TraceAllNetDeviceRx (); + + Simulator::Run (); + Simulator::Destroy (); +} diff --git a/tutorial/tutorial-naive-dumbbell.cc b/tutorial/tutorial-linear-dumbbell.cc similarity index 72% rename from tutorial/tutorial-naive-dumbbell.cc rename to tutorial/tutorial-linear-dumbbell.cc index e203ef9f3..c39abd963 100644 --- a/tutorial/tutorial-naive-dumbbell.cc +++ b/tutorial/tutorial-linear-dumbbell.cc @@ -51,10 +51,11 @@ int main (int argc, char *argv[]) { LogComponentEnable ("DumbbellSimulation", LOG_LEVEL_INFO); -// LogComponentEnableAll (LOG_LEVEL_ALL, LOG_DECORATE_ALL); NS_LOG_INFO ("Dumbbell Topology Simulation"); - +// +// Create the lan on the left side of the dumbbell. +// Ptr n0 = Create (); Ptr n1 = Create (); Ptr n2 = Create (); @@ -79,7 +80,9 @@ main (int argc, char *argv[]) CsmaIpv4Topology::AddIpv4Address (n1, nd1, "10.1.1.2", "255.255.255.0"); CsmaIpv4Topology::AddIpv4Address (n2, nd2, "10.1.1.3", "255.255.255.0"); CsmaIpv4Topology::AddIpv4Address (n3, nd3, "10.1.1.4", "255.255.255.0"); - +// +// Create the lan on the right side of the dumbbell. +// Ptr n4 = Create (); Ptr n5 = Create (); Ptr n6 = Create (); @@ -104,31 +107,62 @@ main (int argc, char *argv[]) CsmaIpv4Topology::AddIpv4Address (n5, nd5, "10.1.2.2", "255.255.255.0"); CsmaIpv4Topology::AddIpv4Address (n6, nd6, "10.1.2.3", "255.255.255.0"); CsmaIpv4Topology::AddIpv4Address (n7, nd7, "10.1.2.4", "255.255.255.0"); - +// +// Create the point-to-point link to connect the two lans. +// Ptr link = PointToPointTopology::AddPointToPointLink ( n3, n4, DataRate (38400), MilliSeconds (20)); PointToPointTopology::AddIpv4Addresses (link, n3, "10.1.3.1", n4, "10.1.3.2"); - +// +// Create data flows across the link: +// n0 ==> n4 ==> n0 +// n1 ==> n5 ==> n1 +// n2 ==> n6 ==> n2 +// n3 ==> n7 ==> n3 +// uint16_t port = 7; - Ptr client = Create (n0, "10.1.2.4", port, - 1, Seconds(1.), 1024); + Ptr client0 = Create (n0, "10.1.2.1", port, + 100, Seconds(.01), 1024); + Ptr client1 = Create (n1, "10.1.2.2", port, + 100, Seconds(.01), 1024); + Ptr client2 = Create (n2, "10.1.2.3", port, + 100, Seconds(.01), 1024); + Ptr client3 = Create (n3, "10.1.2.4", port, + 100, Seconds(.01), 1024); - Ptr server = Create (n7, port); + Ptr server4 = Create (n4, port); + Ptr server5 = Create (n5, port); + Ptr server6 = Create (n6, port); + Ptr server7 = Create (n7, port); - server->Start(Seconds(1.)); - client->Start(Seconds(2.)); + server4->Start(Seconds(1.)); + server5->Start(Seconds(1.)); + server6->Start(Seconds(1.)); + server7->Start(Seconds(1.)); - server->Stop (Seconds(10.)); - client->Stop (Seconds(10.)); + client0->Start(Seconds(2.)); + client1->Start(Seconds(2.1)); + client2->Start(Seconds(2.2)); + client3->Start(Seconds(2.3)); - AsciiTrace asciitrace ("tutorial-4.tr"); + server4->Stop (Seconds(10.)); + server5->Stop (Seconds(10.)); + server6->Stop (Seconds(10.)); + server7->Stop (Seconds(10.)); + + client0->Stop (Seconds(10.)); + client1->Stop (Seconds(10.)); + client2->Stop (Seconds(10.)); + client3->Stop (Seconds(10.)); + + AsciiTrace asciitrace ("tutorial.tr"); asciitrace.TraceAllQueues (); asciitrace.TraceAllNetDeviceRx (); - PcapTrace pcaptrace ("tutorial-4.pcap"); + PcapTrace pcaptrace ("tutorial.pcap"); pcaptrace.TraceAllIp (); GlobalRouteManager::PopulateRoutingTables (); diff --git a/tutorial/tutorial-point-to-point.cc b/tutorial/tutorial-point-to-point.cc new file mode 100644 index 000000000..30e1b02d7 --- /dev/null +++ b/tutorial/tutorial-point-to-point.cc @@ -0,0 +1,78 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/log.h" +#include "ns3/ptr.h" +#include "ns3/internet-node.h" +#include "ns3/point-to-point-channel.h" +#include "ns3/mac48-address.h" +#include "ns3/point-to-point-net-device.h" +#include "ns3/point-to-point-topology.h" +#include "ns3/udp-echo-client.h" +#include "ns3/udp-echo-server.h" +#include "ns3/simulator.h" +#include "ns3/nstime.h" +#include "ns3/ascii-trace.h" +#include "ns3/pcap-trace.h" +#include "ns3/global-route-manager.h" + +NS_LOG_COMPONENT_DEFINE ("PointToPointSimulation"); + +using namespace ns3; + +// Network topology +// +// point to point +// +--------------+ +// | | +// n0 n1 +// +int +main (int argc, char *argv[]) +{ + LogComponentEnable ("PointToPointSimulation", LOG_LEVEL_INFO); + + NS_LOG_INFO ("Point to Point Topology Simulation"); + + Ptr n0 = Create (); + Ptr n1 = Create (); + + Ptr link = PointToPointTopology::AddPointToPointLink ( + n0, n1, DataRate (38400), MilliSeconds (20)); + + PointToPointTopology::AddIpv4Addresses (link, n0, "10.1.1.1", + n1, "10.1.1.2"); + + uint16_t port = 7; + + Ptr client = Create (n0, "10.1.1.2", port, + 1, Seconds(1.), 1024); + + Ptr server = Create (n1, port); + + server->Start(Seconds(1.)); + client->Start(Seconds(2.)); + + server->Stop (Seconds(10.)); + client->Stop (Seconds(10.)); + + AsciiTrace asciitrace ("tutorial.tr"); + asciitrace.TraceAllQueues (); + asciitrace.TraceAllNetDeviceRx (); + + Simulator::Run (); + Simulator::Destroy (); +} diff --git a/tutorial/tutorial-star-routing.cc b/tutorial/tutorial-star-routing.cc new file mode 100644 index 000000000..765b3ee4c --- /dev/null +++ b/tutorial/tutorial-star-routing.cc @@ -0,0 +1,167 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/log.h" +#include "ns3/ptr.h" +#include "ns3/internet-node.h" +#include "ns3/point-to-point-channel.h" +#include "ns3/mac48-address.h" +#include "ns3/point-to-point-net-device.h" +#include "ns3/udp-echo-client.h" +#include "ns3/udp-echo-server.h" +#include "ns3/simulator.h" +#include "ns3/nstime.h" +#include "ns3/ascii-trace.h" +#include "ns3/pcap-trace.h" +#include "ns3/global-route-manager.h" + +#include "point-to-point-ipv4-topology.h" + +NS_LOG_COMPONENT_DEFINE ("StarRoutingSimulation"); + +using namespace ns3; + +// Network topology +// +// n3 n2 +// | / +// | / +// n4 --- n0 --- n1 +// / | +// / | +// n5 n6 + +int +main (int argc, char *argv[]) +{ + LogComponentEnable ("StarRoutingSimulation", LOG_LEVEL_INFO); + + NS_LOG_INFO ("Star Topology with Routing Simulation"); + + Ptr n0 = Create (); + Ptr n1 = Create (); + Ptr n2 = Create (); + Ptr n3 = Create (); + Ptr n4 = Create (); + Ptr n5 = Create (); + Ptr n6 = Create (); + + Ptr link01 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd01 = PointToPointIpv4Topology::AddNetDevice (n0, + link01); + + Ptr link02 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd02 = PointToPointIpv4Topology::AddNetDevice (n0, + link02); + + Ptr link03 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd03 = PointToPointIpv4Topology::AddNetDevice (n0, + link03); + + Ptr link04 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd04 = PointToPointIpv4Topology::AddNetDevice (n0, + link04); + + Ptr link05 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd05 = PointToPointIpv4Topology::AddNetDevice (n0, + link05); + + Ptr link06 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd06 = PointToPointIpv4Topology::AddNetDevice (n0, link06); + + uint32_t nd1 = PointToPointIpv4Topology::AddNetDevice (n1, link01); + uint32_t nd2 = PointToPointIpv4Topology::AddNetDevice (n2, link02); + uint32_t nd3 = PointToPointIpv4Topology::AddNetDevice (n3, link03); + uint32_t nd4 = PointToPointIpv4Topology::AddNetDevice (n4, link04); + uint32_t nd5 = PointToPointIpv4Topology::AddNetDevice (n5, link05); + uint32_t nd6 = PointToPointIpv4Topology::AddNetDevice (n6, link06); + + PointToPointIpv4Topology::AddAddress (n0, nd01, "10.1.1.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n1, nd1, "10.1.1.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd02, "10.1.2.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n2, nd2, "10.1.2.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd03, "10.1.3.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n3, nd3, "10.1.2.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd04, "10.1.4.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n4, nd4, "10.1.4.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd05, "10.1.5.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n5, nd5, "10.1.5.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd06, "10.1.6.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n6, nd6, "10.1.6.2", + "255.255.255.252"); + + uint16_t port = 7; + + Ptr client = Create (n4, "10.1.1.2", port, + 1, Seconds(1.), 1024); + + Ptr server = Create (n1, port); + + server->Start(Seconds(1.)); + client->Start(Seconds(2.)); + + server->Stop (Seconds(10.)); + client->Stop (Seconds(10.)); + + AsciiTrace asciitrace ("tutorial.tr"); + asciitrace.TraceAllQueues (); + asciitrace.TraceAllNetDeviceRx (); + + GlobalRouteManager::PopulateRoutingTables (); + + Simulator::Run (); + Simulator::Destroy (); +} diff --git a/tutorial/tutorial-star.cc b/tutorial/tutorial-star.cc new file mode 100644 index 000000000..fbcccf5a9 --- /dev/null +++ b/tutorial/tutorial-star.cc @@ -0,0 +1,165 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/log.h" +#include "ns3/ptr.h" +#include "ns3/internet-node.h" +#include "ns3/point-to-point-channel.h" +#include "ns3/mac48-address.h" +#include "ns3/point-to-point-net-device.h" +#include "ns3/udp-echo-client.h" +#include "ns3/udp-echo-server.h" +#include "ns3/simulator.h" +#include "ns3/nstime.h" +#include "ns3/ascii-trace.h" +#include "ns3/pcap-trace.h" +#include "ns3/global-route-manager.h" + +#include "point-to-point-ipv4-topology.h" + +NS_LOG_COMPONENT_DEFINE ("StarSimulation"); + +using namespace ns3; + +// Network topology +// +// n3 n2 +// | / +// | / +// n4 --- n0 --- n1 +// / | +// / | +// n5 n6 + +int +main (int argc, char *argv[]) +{ + LogComponentEnable ("StarSimulation", LOG_LEVEL_INFO); + + NS_LOG_INFO ("Star Topology Simulation"); + + Ptr n0 = Create (); + Ptr n1 = Create (); + Ptr n2 = Create (); + Ptr n3 = Create (); + Ptr n4 = Create (); + Ptr n5 = Create (); + Ptr n6 = Create (); + + Ptr link01 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd01 = PointToPointIpv4Topology::AddNetDevice (n0, + link01); + + Ptr link02 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd02 = PointToPointIpv4Topology::AddNetDevice (n0, + link02); + + Ptr link03 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd03 = PointToPointIpv4Topology::AddNetDevice (n0, + link03); + + Ptr link04 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd04 = PointToPointIpv4Topology::AddNetDevice (n0, + link04); + + Ptr link05 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd05 = PointToPointIpv4Topology::AddNetDevice (n0, + link05); + + Ptr link06 = + PointToPointIpv4Topology::CreateChannel (DataRate (38400), + MilliSeconds (20)); + + uint32_t nd06 = PointToPointIpv4Topology::AddNetDevice (n0, link06); + + uint32_t nd1 = PointToPointIpv4Topology::AddNetDevice (n1, link01); + uint32_t nd2 = PointToPointIpv4Topology::AddNetDevice (n2, link02); + uint32_t nd3 = PointToPointIpv4Topology::AddNetDevice (n3, link03); + uint32_t nd4 = PointToPointIpv4Topology::AddNetDevice (n4, link04); + uint32_t nd5 = PointToPointIpv4Topology::AddNetDevice (n5, link05); + uint32_t nd6 = PointToPointIpv4Topology::AddNetDevice (n6, link06); + + PointToPointIpv4Topology::AddAddress (n0, nd01, "10.1.1.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n1, nd1, "10.1.1.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd02, "10.1.2.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n2, nd2, "10.1.2.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd03, "10.1.3.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n3, nd3, "10.1.2.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd04, "10.1.4.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n4, nd4, "10.1.4.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd05, "10.1.5.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n5, nd5, "10.1.5.2", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n0, nd06, "10.1.6.1", + "255.255.255.252"); + + PointToPointIpv4Topology::AddAddress (n6, nd6, "10.1.6.2", + "255.255.255.252"); + + uint16_t port = 7; + + Ptr client = Create (n0, "10.1.1.2", port, + 1, Seconds(1.), 1024); + + Ptr server = Create (n1, port); + + server->Start(Seconds(1.)); + client->Start(Seconds(2.)); + + server->Stop (Seconds(10.)); + client->Stop (Seconds(10.)); + + AsciiTrace asciitrace ("tutorial.tr"); + asciitrace.TraceAllQueues (); + asciitrace.TraceAllNetDeviceRx (); + + Simulator::Run (); + Simulator::Destroy (); +} diff --git a/tutorial/wscript b/tutorial/wscript index b7d90bdf5..388c9f21b 100644 --- a/tutorial/wscript +++ b/tutorial/wscript @@ -1,22 +1,36 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def build(bld): - obj = bld.create_ns3_program('hello-simulator', - ['core']) + obj = bld.create_ns3_program('hello-simulator', ['core']) obj.source = 'hello-simulator.cc' - obj = bld.create_ns3_program('tutorial-csma-echo', - ['core']) + obj = bld.create_ns3_program('tutorial-csma-echo', ['core']) obj.source = 'tutorial-csma-echo.cc' - obj = bld.create_ns3_program('tutorial-csma-echo-ascii-trace', - ['core']) + obj = bld.create_ns3_program('tutorial-csma-echo-ascii-trace', ['core']) obj.source = 'tutorial-csma-echo-ascii-trace.cc' - obj = bld.create_ns3_program('tutorial-csma-echo-pcap-trace', - ['core']) + obj = bld.create_ns3_program('tutorial-csma-echo-pcap-trace', ['core']) obj.source = 'tutorial-csma-echo-pcap-trace.cc' - obj = bld.create_ns3_program('tutorial-naive-dumbbell', - ['core']) - obj.source = 'tutorial-naive-dumbbell.cc' + obj = bld.create_ns3_program('tutorial-point-to-point', ['core']) + obj.source = 'tutorial-point-to-point.cc' + + obj = bld.create_ns3_program('tutorial-star', ['core']) + obj.source = ['tutorial-star.cc', + 'point-to-point-ipv4-topology.cc'] + + obj = bld.create_ns3_program('tutorial-star-routing', ['core']) + obj.source = ['tutorial-star-routing.cc', + 'point-to-point-ipv4-topology.cc'] + + obj = bld.create_ns3_program('tutorial-linear-dumbbell', ['core']) + obj.source = 'tutorial-linear-dumbbell.cc' + + obj = bld.create_ns3_program('testipv4', ['core']) + obj.source = ['testipv4.cc', 'ipv4-address-generator.cc'] + + obj = bld.create_ns3_program('tutorial-bus-network', ['core']) + obj.source = ['tutorial-bus-network.cc', + 'ipv4-bus-network.cc', + 'ipv4-address-generator.cc']