internet: GSoC-22 generate ARP/NDISC cache automatically
This commit is contained in:
committed by
Tommaso Pecorella
parent
5334c1e460
commit
87fb2ddcbf
@@ -12,6 +12,7 @@ set(source_files
|
||||
helper/ipv6-list-routing-helper.cc
|
||||
helper/ipv6-routing-helper.cc
|
||||
helper/ipv6-static-routing-helper.cc
|
||||
helper/neighbor-cache-helper.cc
|
||||
helper/rip-helper.cc
|
||||
helper/ripng-helper.cc
|
||||
model/arp-cache.cc
|
||||
@@ -143,6 +144,7 @@ set(header_files
|
||||
helper/ipv6-list-routing-helper.h
|
||||
helper/ipv6-routing-helper.h
|
||||
helper/ipv6-static-routing-helper.h
|
||||
helper/neighbor-cache-helper.h
|
||||
helper/rip-helper.h
|
||||
helper/ripng-helper.h
|
||||
model/arp-cache.h
|
||||
@@ -279,6 +281,7 @@ set(test_sources
|
||||
test/ipv6-raw-test.cc
|
||||
test/ipv6-ripng-test.cc
|
||||
test/ipv6-test.cc
|
||||
test/neighbor-cache-test.cc
|
||||
test/rtt-test.cc
|
||||
test/tcp-advertised-window-test.cc
|
||||
test/tcp-bbr-test.cc
|
||||
|
||||
@@ -224,6 +224,7 @@ codepoint.
|
||||
|
||||
RFC 6621 duplicate packet detection
|
||||
***********************************
|
||||
|
||||
To support mesh network protocols over broadcast-capable networks (e.g. Wi-Fi),
|
||||
it is useful to have support for duplicate packet detection and filtering,
|
||||
since nodes in a network may receive multiple copies of flooded multicast
|
||||
@@ -233,3 +234,48 @@ Section 6.2.2 of (:rfc:`6621`). The model, disabled by default, must be
|
||||
enabled by setting ``EnableRFC6621`` to true. A second attribute,
|
||||
``DuplicateExpire``, sets the expiration delay for erasing the cache entry
|
||||
of a packet in the duplicate cache; the delay value defaults to 1ms.
|
||||
|
||||
NeighborCache
|
||||
*************
|
||||
|
||||
NeighborCacheHelper provides a way to generate ARP cache automatically. It
|
||||
generates needed ARP cache before simulation start to avoid the delay and mesage overhead of
|
||||
address resolution in simulations that are focused on other performance aspects.
|
||||
The state of entries which are generated by NeighborCacheHelper is ``STATIC_AUTOGENERATED``,
|
||||
which is similar to ``PERMANENT``, but they are not manually added or removed by user, they
|
||||
will be managed by NeighborCacheHelper when user need pre-generate cache.
|
||||
The source code for NeighborCache is located in ``src/internet/helper/neighbor-cache-helper``
|
||||
A complete example is in ``src/internet/examples/neighbor-cache-example.cc``.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The typical usages are::
|
||||
|
||||
* Populate neighbor ARP caches for all devices:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
NeighborCacheHelper neighborCache;
|
||||
neighborCache.PopulateNeighborCache ();
|
||||
|
||||
* Populate neighbor ARP caches for a given channel:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
NeighborCacheHelper neighborCache;
|
||||
neighborCache.PopulateNeighborCache (channel); // channel is the Ptr<Channel> want to generate ARP caches
|
||||
|
||||
* Populate neighbor ARP caches for devices in a given NetDeviceContainer:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
NeighborCacheHelper neighborCache;
|
||||
neighborCache.PopulateNeighborCache (netDevices); // netDevices is the NetDeviceContainer want to generate ARP caches
|
||||
|
||||
* Populate neighbor ARP caches for a given Ipv4InterfaceContainer:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
NeighborCacheHelper neighborCache;
|
||||
neighborCache.PopulateNeighborCache (interfaces); // interfaces is the Ipv4InterfaceContainer want to generate ARP caches
|
||||
|
||||
@@ -492,3 +492,27 @@ The IPv6 protocols has not yet been extensively validated against real implement
|
||||
The actual tests involve mainly performing checks of the .pcap trace files with Wireshark,
|
||||
and the results are positive.
|
||||
|
||||
NeighborCache
|
||||
*************
|
||||
|
||||
NeighborCacheHelper provides a way to generate NDISC cache automatically. It generates
|
||||
needed NDISC cache before simulation start to avoid the delay and mesage overhead of
|
||||
neighbor discovery in simulations that are focused on other performance aspects.
|
||||
The state of entries generate by NeighborCacheHelper is ``STATIC_AUTOGENERATED``,
|
||||
which is similar to ``PERMANENT``, but they are not manually added or removed by user, they
|
||||
will be managed by NeighborCacheHelper when user need pre-generate cache.
|
||||
The source code for NeighborCache is located in ``src/internet/helper/neighbor-cache-helper``
|
||||
A complete example is in ``src/internet/examples/neighbor-cache-example.cc``.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The usages for generating NDISC cache is almost the same as generating ARP cache, see
|
||||
``src/internet/doc/ipv4.rst``
|
||||
|
||||
* Populate neighbor ARP caches for a given Ipv6InterfaceContainer:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
NeighborCacheHelper neighborCache;
|
||||
neighborCache.PopulateNeighborCache (interfaces); // interfaces is the Ipv6InterfaceContainer want to generate ARP caches
|
||||
|
||||
@@ -6,3 +6,13 @@ build_lib_example(
|
||||
${libinternet}
|
||||
${libapplications}
|
||||
)
|
||||
|
||||
build_lib_example(
|
||||
NAME neighbor-cache-example
|
||||
SOURCE_FILES neighbor-cache-example.cc
|
||||
LIBRARIES_TO_LINK
|
||||
${libapplications}
|
||||
${libcsma}
|
||||
${libinternet}
|
||||
${libnetwork}
|
||||
)
|
||||
|
||||
535
src/internet/examples/neighbor-cache-example.cc
Normal file
535
src/internet/examples/neighbor-cache-example.cc
Normal file
@@ -0,0 +1,535 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2022 ZHIHENG DONG
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Zhiheng Dong <dzh2077@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* This example shows how to generate neighbor caches on the scope of
|
||||
* a channel, a NetDeviceContainer, an InterfaceContainer and globally.
|
||||
* The example also shows a scenario that auto-generated neighbor caches
|
||||
* can avoid droping packets because of ARP message or Neighbor Discover
|
||||
* message.
|
||||
* If the user runs the example without any command line option, NeighborCacheHelper
|
||||
* will generate neighbor cache for all devices and the output is their
|
||||
* ARP table or NDISC table, the user can also generate neighbor cache on different
|
||||
* scope by adding command line option --useChannel (on specific channel),
|
||||
* --useNetDeviceContainer (on specific netDeviceContainer) and --useInterfaceContainer
|
||||
* (on specific netDeviceContainer), --noGenerate (don't generate neighbor cache).
|
||||
* The user can also enable --sendTraffic flag to send a data stream from n0 to n1,
|
||||
* the output will be the information of received packets, which shows the packets loss
|
||||
* are reduced after pre-generate neighbor caches.
|
||||
*
|
||||
* IPv4 Network Topology
|
||||
* \verbatim
|
||||
|
||||
LAN 10.1.1.0/24
|
||||
n0 --------------- n1 n2 n3
|
||||
| | |
|
||||
===============
|
||||
LAN 10.1.2.0/24
|
||||
\endverbatim
|
||||
*
|
||||
*IPv6 Network Topology
|
||||
* \verbatim
|
||||
|
||||
LAN 2001:1::/64
|
||||
n0 --------------- n1 n2 n3
|
||||
| | |
|
||||
===============
|
||||
LAN 2001:2::/64
|
||||
\endverbatim
|
||||
*
|
||||
* Expected Outputs:
|
||||
* IPv4 (default):
|
||||
* Generate ARP caches for all deveices (default) :
|
||||
* \verbatim
|
||||
ARP Cache of node 0 at time 0
|
||||
10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 1 at time 0
|
||||
10.1.1.1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED
|
||||
10.1.2.2 dev 1 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
10.1.2.3 dev 1 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 2 at time 0
|
||||
10.1.2.1 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
10.1.2.3 dev 0 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 3 at time 0
|
||||
10.1.2.1 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
10.1.2.2 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
\endverbatim
|
||||
*
|
||||
* Generate ARP caches for the left channel (--useChannel):
|
||||
* \verbatim
|
||||
ARP Cache of node 0 at time 0
|
||||
10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 1 at time 0
|
||||
10.1.1.1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 2 at time 0
|
||||
ARP Cache of node 3 at time 0
|
||||
\endverbatim
|
||||
*
|
||||
* Generate ARP caches for devices on the right side (--useNetDeviceContainer):
|
||||
* \verbatim
|
||||
ARP Cache of node 0 at time 0
|
||||
ARP Cache of node 1 at time 0
|
||||
10.1.2.2 dev 1 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
10.1.2.3 dev 1 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 2 at time 0
|
||||
10.1.2.1 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
10.1.2.3 dev 0 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 3 at time 0
|
||||
10.1.2.1 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
10.1.2.2 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
\endverbatim
|
||||
*
|
||||
* Generate ARP caches for specific interfaces (--useInterfaceContainer):
|
||||
* \verbatim
|
||||
ARP Cache of node 0 at time 0
|
||||
10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
ARP Cache of node 1 at time 0
|
||||
ARP Cache of node 2 at time 0
|
||||
ARP Cache of node 3 at time 0
|
||||
10.1.2.1 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
10.1.2.2 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
\endverbatim
|
||||
*
|
||||
* Do not generate neighbor cache (--noGenerate):
|
||||
* \verbatim
|
||||
ARP Cache of node 0 at time 0
|
||||
ARP Cache of node 1 at time 0
|
||||
ARP Cache of node 2 at time 0
|
||||
ARP Cache of node 3 at time 0
|
||||
\endverbatim
|
||||
*
|
||||
* sending packet with pre-generated neighbor caches(--sendTraffic)
|
||||
* \verbatim
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=0 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=1 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=2 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=3 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=4 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=5 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=6 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=7 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=8 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=9 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=10 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=11 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=12 time=+1.00001s)
|
||||
\endverbatim
|
||||
*
|
||||
* sending packet without pre-generated neighbor caches(--sendTraffic --noGenerate)
|
||||
* \verbatim
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=0 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=1 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=2 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=8 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=9 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=10 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=11 time=+1s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=12 time=+1.00001s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=13 time=+1.00001s)
|
||||
Rx pkt from 03-07-0a:01:01:01:01:c0:00 to 03-07-0a:01:01:02:09:00:00 -> (size=512) AND (seq=14 time=+1.00001s)
|
||||
\endverbatim
|
||||
*
|
||||
* IPv6 (--useIPv6):
|
||||
* Generate NDISC caches for all deveices (default) :
|
||||
* \verbatim
|
||||
NDISC Cache of node 0 at time +0s
|
||||
2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 1 at time +0s
|
||||
2001:1::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:4 dev 1 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:5 dev 1 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:4 dev 1 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:5 dev 1 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 2 at time +0s
|
||||
2001:2::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:5 dev 0 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:5 dev 0 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 3 at time +0s
|
||||
2001:2::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
\endverbatim
|
||||
*
|
||||
* Generate NDISC caches for the left channel (--useChannel):
|
||||
* \verbatim
|
||||
NDISC Cache of node 0 at time +0s
|
||||
2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 1 at time +0s
|
||||
2001:1::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 2 at time +0s
|
||||
NDISC Cache of node 3 at time +0s
|
||||
\endverbatim
|
||||
*
|
||||
* Generate NDISC caches for devices on the right side (--useNetDeviceContainer):
|
||||
* \verbatim
|
||||
NDISC Cache of node 0 at time +0s
|
||||
NDISC Cache of node 1 at time +0s
|
||||
2001:2::200:ff:fe00:4 dev 1 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:5 dev 1 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:4 dev 1 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:5 dev 1 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 2 at time +0s
|
||||
2001:2::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:5 dev 0 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:5 dev 0 lladdr 02-06-00:00:00:00:00:05 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 3 at time +0s
|
||||
2001:2::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
\endverbatim
|
||||
*
|
||||
* Generate NDISC caches for specific interfaces (--useInterfaceContainer):
|
||||
* \verbatim
|
||||
NDISC Cache of node 0 at time +0s
|
||||
2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED
|
||||
NDISC Cache of node 1 at time +0s
|
||||
NDISC Cache of node 2 at time +0s
|
||||
NDISC Cache of node 3 at time +0s
|
||||
2001:2::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
2001:2::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED
|
||||
fe80::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:04 STATIC_AUTOGENERATED
|
||||
\endverbatim
|
||||
*
|
||||
* Do not generate neighbor cache (--noGenerate):
|
||||
* \verbatim
|
||||
NDISC Cache of node 0 at time +0s
|
||||
NDISC Cache of node 1 at time +0s
|
||||
NDISC Cache of node 2 at time +0s
|
||||
NDISC Cache of node 3 at time +0s
|
||||
\endverbatim
|
||||
*
|
||||
* sending packet with pre-generated neighbor caches(--sendTraffic)
|
||||
* \verbatim
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=0 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=1 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=2 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=3 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=4 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=5 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=6 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=7 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=8 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=9 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=10 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=11 time=+1s)
|
||||
\endverbatim
|
||||
*
|
||||
* sending packet without pre-generated neighbor caches(--sendTraffic --noGenerate)
|
||||
* \verbatim
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=8 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=9 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=10 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=11 time=+1s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=12 time=+1.00001s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=13 time=+1.00001s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=14 time=+1.00001s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=15 time=+1.00001s)
|
||||
Rx pkt from 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:01:01:c0 to 04-12-20:01:00:01:00:00:00:00:02:00:00:ff:fe:00:00:02:09:00 -> (size=512) AND (seq=16 time=+1.00001s)
|
||||
\endverbatim
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/csma-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("NeighborCacheExample");
|
||||
|
||||
/**
|
||||
* Neigbor Cache example class.
|
||||
*
|
||||
* It handles the creation and run of an example.
|
||||
*/
|
||||
class NeighborCacheExample
|
||||
{
|
||||
public:
|
||||
NeighborCacheExample ();
|
||||
|
||||
/**
|
||||
* Run the example.
|
||||
*/
|
||||
void Run ();
|
||||
|
||||
/**
|
||||
* \brief description the command-line parameters.
|
||||
* \param argc The argument count.
|
||||
* \param argv The argument vector.
|
||||
*/
|
||||
void CommandSetup (int argc, char **argv);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Print the information of receive data.
|
||||
* \param pkt The received packet.
|
||||
* \param from The sender.
|
||||
* \param dst The receiver.
|
||||
* \param header The header with a sequence, a timestamp, and a "size" attribute
|
||||
*/
|
||||
void ReceivePacket (Ptr<const Packet> pkt, const Address &from, const Address &dst, const SeqTsSizeHeader& header);
|
||||
|
||||
bool m_useIpv6 {false}; //!< Use IPv6 instead of IPv4
|
||||
bool m_enableLog {false}; //!< Enable ArpL3Protocol and Icmpv6L4Protocol logging
|
||||
bool m_useChannel {false}; //!< Generate neighbor cache for specific Channel
|
||||
bool m_useNetDeviceContainer {false}; //!< Generate neighbor cache for specific netDeviceContainer
|
||||
bool m_useInterfaceContainer {false}; //!< Generate neighbor cache for specific interfaceContainer
|
||||
bool m_noGenerate {false}; //!< do not generate neighbor cache automatically
|
||||
bool m_sendTraffic {false}; //!< send data stream from n0 to n1
|
||||
|
||||
};
|
||||
|
||||
NeighborCacheExample::NeighborCacheExample ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheExample::ReceivePacket (Ptr<const Packet> pkt, const Address &from, const Address &dst, const SeqTsSizeHeader& header)
|
||||
{
|
||||
std::cout << "Rx pkt from " << from << " to " << dst << " -> " << header << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheExample::CommandSetup (int argc, char **argv)
|
||||
{
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("useIPv6", "Use IPv6 instead of IPv4", m_useIpv6);
|
||||
cmd.AddValue ("enableLog", "Enable ArpL3Protocol and Icmpv6L4Protocol logging", m_enableLog);
|
||||
cmd.AddValue ("useChannel", "Generate neighbor cache for specific Channel", m_useChannel);
|
||||
cmd.AddValue ("useNetDeviceContainer", "Generate neighbor cache for specific netDeviceContainer", m_useNetDeviceContainer);
|
||||
cmd.AddValue ("useInterfaceContainer", "Generate neighbor cache for specific interfaceContainer", m_useInterfaceContainer);
|
||||
cmd.AddValue ("noGenerate", "do not generate neighbor cache automatically", m_noGenerate);
|
||||
cmd.AddValue ("sendTraffic", "send data stream from n0 to n1", m_sendTraffic);
|
||||
|
||||
cmd.Parse (argc, argv);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
NeighborCacheExample example;
|
||||
example.CommandSetup (argc,argv);
|
||||
example.Run ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheExample::Run ()
|
||||
{
|
||||
if (m_enableLog)
|
||||
{
|
||||
LogComponentEnable ("ArpL3Protocol", LOG_LEVEL_LOGIC);
|
||||
LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_LOGIC);
|
||||
}
|
||||
uint32_t nCsmaLeft = 2;
|
||||
uint32_t nCsmaRight = 2;
|
||||
|
||||
NodeContainer csmaNodesLeft;
|
||||
csmaNodesLeft.Create (nCsmaLeft);
|
||||
NodeContainer csmaNodesRight;
|
||||
csmaNodesRight.Add (csmaNodesLeft.Get (1));
|
||||
csmaNodesRight.Create (nCsmaRight);
|
||||
|
||||
CsmaHelper csmaLeft;
|
||||
csmaLeft.SetChannelAttribute ("DataRate", StringValue ("20Gbps"));
|
||||
// The 1 microSeconds delay is only for showing packets dropped effect without generating neighbor caches.
|
||||
csmaLeft.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));
|
||||
CsmaHelper csmaRight;
|
||||
csmaRight.SetChannelAttribute ("DataRate", StringValue ("20Gbps"));
|
||||
csmaRight.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));
|
||||
|
||||
NetDeviceContainer csmaDevicesLeft;
|
||||
csmaDevicesLeft = csmaLeft.Install (csmaNodesLeft);
|
||||
NetDeviceContainer csmaDevicesRight;
|
||||
csmaDevicesRight = csmaRight.Install (csmaNodesRight);
|
||||
|
||||
InternetStackHelper stack;
|
||||
// disabled Ipv4ArpJitter and Ipv6NsRsJitter to avoid the influence on packet dropped
|
||||
stack.SetIpv4ArpJitter (false);
|
||||
stack.SetIpv6NsRsJitter (false);
|
||||
stack.Install (csmaNodesLeft.Get (0));
|
||||
stack.Install (csmaNodesRight);
|
||||
|
||||
if (!m_useIpv6)
|
||||
{
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer csmaInterfacesLeft;
|
||||
csmaInterfacesLeft = address.Assign (csmaDevicesLeft);
|
||||
address.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer csmaInterfacesRight;
|
||||
csmaInterfacesRight = address.Assign (csmaDevicesRight);
|
||||
|
||||
// Populate ARP caches
|
||||
NeighborCacheHelper neighborCache;
|
||||
if (m_useChannel)
|
||||
{
|
||||
// Populate ARP caches for given channel
|
||||
Ptr<Channel> csmaChannel = csmaDevicesLeft.Get (0)->GetChannel ();
|
||||
neighborCache.PopulateNeighborCache (csmaChannel);
|
||||
}
|
||||
else if (m_useNetDeviceContainer)
|
||||
{
|
||||
// Populate ARP caches for given netDeviceContainer
|
||||
neighborCache.PopulateNeighborCache (csmaDevicesRight);
|
||||
}
|
||||
else if (m_useInterfaceContainer)
|
||||
{
|
||||
std::pair<Ptr<Ipv4>, uint32_t> txInterface = csmaInterfacesLeft.Get (0);
|
||||
Ptr<Ipv4> ipv41 = txInterface.first;
|
||||
uint32_t index1 = txInterface.second;
|
||||
std::pair<Ptr<Ipv4>, uint32_t> rxInterface = csmaInterfacesRight.Get (nCsmaRight);
|
||||
Ptr<Ipv4> ipv42 = rxInterface.first;
|
||||
uint32_t index2 = rxInterface.second;
|
||||
|
||||
// Populate ARP caches for given interfaceContainer
|
||||
Ipv4InterfaceContainer interfaces;
|
||||
interfaces.Add (ipv41,index1);
|
||||
interfaces.Add (ipv42,index2);
|
||||
neighborCache.PopulateNeighborCache (interfaces);
|
||||
}
|
||||
else if (!m_noGenerate)
|
||||
{
|
||||
// Populate ARP caches for all devices
|
||||
neighborCache.PopulateNeighborCache ();
|
||||
}
|
||||
|
||||
if (m_sendTraffic)
|
||||
{
|
||||
// send Packet from n0 to n1
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (csmaInterfacesLeft.GetAddress (1), port)));
|
||||
onoff.SetConstantRate (DataRate ("10Gbps"));
|
||||
onoff.SetAttribute ("EnableSeqTsSizeHeader", BooleanValue (true));
|
||||
ApplicationContainer apps = onoff.Install (csmaNodesLeft.Get (0));
|
||||
apps.Start (Seconds (1.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
|
||||
sink.SetAttribute ("EnableSeqTsSizeHeader", BooleanValue (true));
|
||||
apps = sink.Install (csmaNodesLeft);
|
||||
apps.Get (1)->TraceConnectWithoutContext ("RxWithSeqTsSize", MakeCallback (&NeighborCacheExample::ReceivePacket,this));
|
||||
AsciiTraceHelper ascii;
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("neighbor-cache-example.tr");
|
||||
csmaLeft.EnableAsciiAll (stream);
|
||||
csmaLeft.EnablePcapAll ("neighbor-cache-example");
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<OutputStreamWrapper> outputStream = Create<OutputStreamWrapper> (&std::cout);
|
||||
Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), outputStream);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Ipv6AddressHelper address;
|
||||
address.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer csmaInterfacesLeft;
|
||||
csmaInterfacesLeft = address.Assign (csmaDevicesLeft);
|
||||
csmaInterfacesLeft.SetForwarding (1, true);
|
||||
csmaInterfacesLeft.SetDefaultRouteInAllNodes (1);
|
||||
|
||||
address.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer csmaInterfacesRight;
|
||||
csmaInterfacesRight = address.Assign (csmaDevicesRight);
|
||||
csmaInterfacesRight.SetForwarding (0, true);
|
||||
csmaInterfacesRight.SetDefaultRouteInAllNodes (0);
|
||||
|
||||
// Populate neighbor NDISC caches
|
||||
NeighborCacheHelper neighborCache;
|
||||
if (m_useChannel)
|
||||
{
|
||||
// Populate NDISC caches for given channel
|
||||
Ptr<Channel> csmaChannel = csmaDevicesLeft.Get (0)->GetChannel ();
|
||||
neighborCache.PopulateNeighborCache (csmaChannel);
|
||||
}
|
||||
else if (m_useNetDeviceContainer)
|
||||
{
|
||||
// Populate NDISC caches for given netDeviceContainer
|
||||
neighborCache.PopulateNeighborCache (csmaDevicesRight);
|
||||
}
|
||||
else if (m_useInterfaceContainer)
|
||||
{
|
||||
std::pair<Ptr<Ipv6>, uint32_t> txInterface = csmaInterfacesLeft.Get (0);
|
||||
Ptr<Ipv6> ipv61 = txInterface.first;
|
||||
uint32_t index1 = txInterface.second;
|
||||
std::pair<Ptr<Ipv6>, uint32_t> rxInterface = csmaInterfacesRight.Get (nCsmaRight);
|
||||
Ptr<Ipv6> ipv62 = rxInterface.first;
|
||||
uint32_t index2 = rxInterface.second;
|
||||
|
||||
// Populate NDISC caches for given interfaceContainer
|
||||
Ipv6InterfaceContainer interfaces;
|
||||
interfaces.Add (ipv61,index1);
|
||||
interfaces.Add (ipv62,index2);
|
||||
neighborCache.PopulateNeighborCache (interfaces);
|
||||
}
|
||||
else if (!m_noGenerate)
|
||||
{
|
||||
// Populate NDISC caches for all devices
|
||||
neighborCache.PopulateNeighborCache ();
|
||||
}
|
||||
|
||||
if (m_sendTraffic)
|
||||
{
|
||||
// send Packet from n0 to n1
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
OnOffHelper onoff ("ns3::UdpSocketFactory",
|
||||
Address (Inet6SocketAddress (csmaInterfacesLeft.GetAddress (1, 1), port)));
|
||||
onoff.SetConstantRate (DataRate ("10Gbps"));
|
||||
onoff.SetAttribute ("EnableSeqTsSizeHeader", BooleanValue (true));
|
||||
ApplicationContainer apps = onoff.Install (csmaNodesLeft.Get (0));
|
||||
apps.Start (Seconds (1.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
PacketSinkHelper sink ("ns3::UdpSocketFactory",
|
||||
Address (Inet6SocketAddress (Ipv6Address::GetAny (), port)));
|
||||
sink.SetAttribute ("EnableSeqTsSizeHeader", BooleanValue (true));
|
||||
apps = sink.Install (csmaNodesLeft);
|
||||
apps.Get (1)->TraceConnectWithoutContext ("RxWithSeqTsSize", MakeCallback (&NeighborCacheExample::ReceivePacket, this));
|
||||
AsciiTraceHelper ascii;
|
||||
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("neighbor-cache-example.tr");
|
||||
csmaLeft.EnableAsciiAll (stream);
|
||||
csmaLeft.EnablePcapAll ("neighbor-cache-example");
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<OutputStreamWrapper> outputStream = Create<OutputStreamWrapper> (&std::cout);
|
||||
Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), outputStream);
|
||||
}
|
||||
}
|
||||
Simulator::Stop (Seconds (1.00002));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
339
src/internet/helper/neighbor-cache-helper.cc
Normal file
339
src/internet/helper/neighbor-cache-helper.cc
Normal file
@@ -0,0 +1,339 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2022 ZHIHENG DONG
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Zhiheng Dong <dzh2077@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/ipv6.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/channel-list.h"
|
||||
#include "ns3/neighbor-cache-helper.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("NeighborCacheHelper");
|
||||
|
||||
NeighborCacheHelper::NeighborCacheHelper ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
NeighborCacheHelper::~NeighborCacheHelper ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborCache (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (uint32_t i = 0; i < ChannelList::GetNChannels (); ++i)
|
||||
{
|
||||
Ptr<Channel> channel = ChannelList::GetChannel (i);
|
||||
PopulateNeighborCache (channel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborCache (Ptr<Channel> channel) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << channel);
|
||||
for (std::size_t i = 0; i < channel->GetNDevices (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> netDevice = channel->GetDevice (i);
|
||||
Ptr<Node> node = netDevice->GetNode ();
|
||||
int32_t ipv4InterfaceIndex = node->GetObject<Ipv4> ()->GetInterfaceForDevice (netDevice);
|
||||
int32_t ipv6InterfaceIndex = node->GetObject<Ipv6> ()->GetInterfaceForDevice (netDevice);
|
||||
for (std::size_t j = 0; j < channel->GetNDevices (); ++j)
|
||||
{
|
||||
Ptr<NetDevice> neighborDevice = channel->GetDevice (j);
|
||||
Ptr<Node> neighborNode = neighborDevice->GetNode ();
|
||||
int32_t ipv4NeighborInterfaceIndex = neighborNode->GetObject<Ipv4> ()->GetInterfaceForDevice (neighborDevice);
|
||||
int32_t ipv6NeighborInterfaceIndex = neighborNode->GetObject<Ipv6> ()->GetInterfaceForDevice (neighborDevice);
|
||||
if (neighborDevice != netDevice)
|
||||
{
|
||||
if (ipv4InterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv4Interface> ipv4Interface = node->GetObject<Ipv4L3Protocol> ()->GetInterface (ipv4InterfaceIndex);
|
||||
if (ipv4NeighborInterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv4Interface> ipv4NeighborInterface = neighborNode->GetObject<Ipv4L3Protocol> ()->GetInterface (ipv4NeighborInterfaceIndex);
|
||||
PopulateNeighborEntriesIpv4 (ipv4Interface, ipv4NeighborInterface);
|
||||
}
|
||||
}
|
||||
if (ipv6InterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv6Interface> ipv6Interface = node->GetObject<Ipv6L3Protocol> ()->GetInterface (ipv6InterfaceIndex);
|
||||
if (ipv6NeighborInterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv6Interface> ipv6NeighborInterface = neighborNode->GetObject<Ipv6L3Protocol> ()->GetInterface (ipv6NeighborInterfaceIndex);
|
||||
PopulateNeighborEntriesIpv6 (ipv6Interface, ipv6NeighborInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborCache (const NetDeviceContainer& c) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> netDevice = c.Get (i);
|
||||
Ptr<Channel> channel = netDevice->GetChannel ();
|
||||
Ptr<Node> node = netDevice->GetNode ();
|
||||
int32_t ipv4InterfaceIndex = node->GetObject<Ipv4> ()->GetInterfaceForDevice (netDevice);
|
||||
int32_t ipv6InterfaceIndex = node->GetObject<Ipv6> ()->GetInterfaceForDevice (netDevice);
|
||||
for (std::size_t j = 0; j < channel->GetNDevices (); ++j)
|
||||
{
|
||||
Ptr<NetDevice> neighborDevice = channel->GetDevice (j);
|
||||
Ptr<Node> neighborNode = neighborDevice->GetNode ();
|
||||
int32_t ipv4NeighborInterfaceIndex = neighborNode->GetObject<Ipv4> ()->GetInterfaceForDevice (neighborDevice);
|
||||
int32_t ipv6NeighborInterfaceIndex = neighborNode->GetObject<Ipv6> ()->GetInterfaceForDevice (neighborDevice);
|
||||
if (neighborDevice != netDevice)
|
||||
{
|
||||
if (ipv4InterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv4Interface> ipv4Interface = node->GetObject<Ipv4L3Protocol> ()->GetInterface (ipv4InterfaceIndex);
|
||||
if (ipv4NeighborInterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv4Interface> ipv4NeighborInterface = neighborNode->GetObject<Ipv4L3Protocol> ()->GetInterface (ipv4NeighborInterfaceIndex);
|
||||
PopulateNeighborEntriesIpv4 (ipv4Interface, ipv4NeighborInterface);
|
||||
}
|
||||
}
|
||||
if (ipv6InterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv6Interface> ipv6Interface = node->GetObject<Ipv6L3Protocol> ()->GetInterface (ipv6InterfaceIndex);
|
||||
if (ipv6NeighborInterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv6Interface> ipv6NeighborInterface = neighborNode->GetObject<Ipv6L3Protocol> ()->GetInterface (ipv6NeighborInterfaceIndex);
|
||||
PopulateNeighborEntriesIpv6 (ipv6Interface, ipv6NeighborInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborCache (const Ipv4InterfaceContainer &c) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
std::pair<Ptr<Ipv4>, uint32_t> returnValue = c.Get (i);
|
||||
Ptr<Ipv4> ipv4 = returnValue.first;
|
||||
uint32_t index = returnValue.second;
|
||||
Ptr<Ipv4Interface> ipv4Interface = DynamicCast<Ipv4L3Protocol> (ipv4)->GetInterface (index);
|
||||
if (ipv4Interface)
|
||||
{
|
||||
Ptr<NetDevice> netDevice = ipv4Interface->GetDevice ();
|
||||
Ptr<Channel> channel = netDevice->GetChannel ();
|
||||
for (std::size_t j = 0; j < channel->GetNDevices (); ++j)
|
||||
{
|
||||
Ptr<NetDevice> neighborDevice = channel->GetDevice (j);
|
||||
if (neighborDevice != netDevice)
|
||||
{
|
||||
Ptr<Node> neighborNode = neighborDevice->GetNode ();
|
||||
int32_t ipv4NeighborInterfaceIndex = neighborNode->GetObject<Ipv4> ()->GetInterfaceForDevice (neighborDevice);
|
||||
if (ipv4NeighborInterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv4Interface> ipv4NeighborInterface = neighborNode->GetObject<Ipv4L3Protocol> ()->GetInterface (ipv4NeighborInterfaceIndex);
|
||||
PopulateNeighborEntriesIpv4 (ipv4Interface, ipv4NeighborInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborCache (const Ipv6InterfaceContainer &c) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
std::pair<Ptr<Ipv6>, uint32_t> returnValue = c.Get (i);
|
||||
Ptr<Ipv6> ipv6 = returnValue.first;
|
||||
uint32_t index = returnValue.second;
|
||||
Ptr<Ipv6Interface> ipv6Interface = DynamicCast<Ipv6L3Protocol> (ipv6)->GetInterface (index);
|
||||
if (ipv6Interface)
|
||||
{
|
||||
Ptr<NetDevice> netDevice = ipv6Interface->GetDevice ();
|
||||
Ptr<Channel> channel = netDevice->GetChannel ();
|
||||
for (std::size_t j = 0; j < channel->GetNDevices (); ++j)
|
||||
{
|
||||
Ptr<NetDevice> neighborDevice = channel->GetDevice (j);
|
||||
if (neighborDevice != netDevice)
|
||||
{
|
||||
Ptr<Node> neighborNode = neighborDevice->GetNode ();
|
||||
int32_t ipv6NeighborInterfaceIndex = neighborNode->GetObject<Ipv6> ()->GetInterfaceForDevice (neighborDevice);
|
||||
if (ipv6NeighborInterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv6Interface> ipv6NeighborInterface = neighborNode->GetObject<Ipv6L3Protocol> ()->GetInterface (ipv6NeighborInterfaceIndex);
|
||||
PopulateNeighborEntriesIpv6 (ipv6Interface, ipv6NeighborInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborEntriesIpv4 (Ptr<Ipv4Interface> ipv4Interface, Ptr<Ipv4Interface> neighborDeviceInterface) const
|
||||
{
|
||||
uint32_t netDeviceAddresses = ipv4Interface->GetNAddresses ();
|
||||
uint32_t neighborDeviceAddresses = neighborDeviceInterface->GetNAddresses ();
|
||||
for (uint32_t n = 0; n < netDeviceAddresses; ++n)
|
||||
{
|
||||
Ipv4InterfaceAddress netDeviceIfAddr = ipv4Interface->GetAddress (n);
|
||||
for (uint32_t m = 0; m < neighborDeviceAddresses; ++m)
|
||||
{
|
||||
Ipv4InterfaceAddress neighborDeviceIfAddr = neighborDeviceInterface->GetAddress (m);
|
||||
if (netDeviceIfAddr.IsInSameSubnet (neighborDeviceIfAddr.GetLocal ()))
|
||||
{
|
||||
Ptr<NetDevice> neighborDevice = neighborDeviceInterface->GetDevice ();
|
||||
// Add Arp entry of neighbor interface to current interface's Arp cache
|
||||
AddEntry (ipv4Interface, neighborDeviceIfAddr.GetAddress (),neighborDevice->GetAddress () );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::PopulateNeighborEntriesIpv6 (Ptr<Ipv6Interface> ipv6Interface, Ptr<Ipv6Interface> neighborDeviceInterface) const
|
||||
{
|
||||
uint32_t netDeviceAddresses = ipv6Interface->GetNAddresses ();
|
||||
uint32_t neighborDeviceAddresses = neighborDeviceInterface->GetNAddresses ();
|
||||
for (uint32_t n = 0; n < netDeviceAddresses; ++n)
|
||||
{
|
||||
Ipv6InterfaceAddress netDeviceIfAddr = ipv6Interface->GetAddress (n);
|
||||
// Ignore if it is a linklocal address, which will be added along with the global address
|
||||
if (netDeviceIfAddr.GetScope () == Ipv6InterfaceAddress::LINKLOCAL || netDeviceIfAddr.GetScope () == Ipv6InterfaceAddress::HOST)
|
||||
{
|
||||
NS_LOG_LOGIC ("Skip the LINKLOCAL or LOCALHOST interface " << netDeviceIfAddr);
|
||||
continue;
|
||||
}
|
||||
for (uint32_t m = 0; m < neighborDeviceAddresses; ++m)
|
||||
{
|
||||
// Ignore if it is a linklocal address, which will be added along with the global address
|
||||
Ipv6InterfaceAddress neighborDeviceIfAddr = neighborDeviceInterface->GetAddress (m);
|
||||
if (neighborDeviceIfAddr.GetScope () == Ipv6InterfaceAddress::LINKLOCAL || neighborDeviceIfAddr.GetScope () == Ipv6InterfaceAddress::HOST)
|
||||
{
|
||||
NS_LOG_LOGIC ("Skip the LINKLOCAL or LOCALHOST interface " << neighborDeviceIfAddr);
|
||||
continue;
|
||||
}
|
||||
if (netDeviceIfAddr.IsInSameSubnet (neighborDeviceIfAddr.GetAddress ()))
|
||||
{
|
||||
Ptr<NetDevice> neighborDevice = neighborDeviceInterface->GetDevice ();
|
||||
// Add neighbor's Ndisc entries of global address and linklocal address to current interface's Ndisc cache
|
||||
AddEntry (ipv6Interface, neighborDeviceIfAddr.GetAddress (), neighborDevice->GetAddress () );
|
||||
Ipv6InterfaceAddress neighborlinkLocalAddr = neighborDeviceInterface->GetLinkLocalAddress ();
|
||||
AddEntry (ipv6Interface, neighborlinkLocalAddr.GetAddress (),neighborDevice->GetAddress () );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::AddEntry (Ptr<Ipv4Interface> netDeviceInterface, Ipv4Address ipv4Address, Address macAddress) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << netDeviceInterface << ipv4Address << macAddress);
|
||||
Ptr<ArpCache> arpCache = netDeviceInterface->GetArpCache ();
|
||||
if (!arpCache)
|
||||
{
|
||||
NS_LOG_LOGIC ("ArpCache doesn't exist, might be a point-to-point NetDevice without ArpCache");
|
||||
return;
|
||||
}
|
||||
ArpCache::Entry *entry = arpCache->Lookup (ipv4Address);
|
||||
if (!entry)
|
||||
{
|
||||
NS_LOG_FUNCTION ("ADD an ARP entry");
|
||||
entry = arpCache->Add (ipv4Address);
|
||||
}
|
||||
entry->SetMacAddress (macAddress);
|
||||
entry->MarkAutoGenerated ();
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::AddEntry (Ptr<Ipv6Interface> netDeviceInterface, Ipv6Address ipv6Address, Address macAddress) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << netDeviceInterface << ipv6Address << macAddress);
|
||||
Ptr<NdiscCache> ndiscCache = netDeviceInterface->GetNdiscCache ();
|
||||
if (!ndiscCache)
|
||||
{
|
||||
NS_LOG_LOGIC ("NdiscCache doesn't exist, might be a point-to-point NetDevice without NdiscCache");
|
||||
return;
|
||||
}
|
||||
NdiscCache::Entry* entry = ndiscCache->Lookup (ipv6Address);
|
||||
if (!entry)
|
||||
{
|
||||
NS_LOG_FUNCTION ("ADD a NDISC entry");
|
||||
entry = ndiscCache->Add (ipv6Address);
|
||||
}
|
||||
entry->SetMacAddress (macAddress);
|
||||
entry->MarkAutoGenerated ();
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheHelper::FlushAutoGenerated (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (uint32_t i = 0; i < NodeList::GetNNodes (); ++i)
|
||||
{
|
||||
Ptr<Node> node = NodeList::GetNode (i);
|
||||
for (uint32_t j = 0; j < node->GetNDevices (); ++j)
|
||||
{
|
||||
Ptr<NetDevice> netDevice = node->GetDevice (j);
|
||||
int32_t ipv4InterfaceIndex = node->GetObject<Ipv4> ()->GetInterfaceForDevice (netDevice);
|
||||
int32_t ipv6InterfaceIndex = node->GetObject<Ipv6> ()->GetInterfaceForDevice (netDevice);
|
||||
if (ipv4InterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv4Interface> ipv4Interface = node->GetObject<Ipv4L3Protocol> ()->GetInterface (ipv4InterfaceIndex);
|
||||
Ptr<ArpCache> arpCache = ipv4Interface->GetArpCache ();
|
||||
if (arpCache)
|
||||
{
|
||||
NS_LOG_FUNCTION ("Remove an ARP entry");
|
||||
arpCache->RemoveAutoGeneratedEntries ();
|
||||
}
|
||||
}
|
||||
if (ipv6InterfaceIndex != -1)
|
||||
{
|
||||
Ptr<Ipv6Interface> ipv6Interface = node->GetObject<Ipv6L3Protocol> ()->GetInterface (ipv6InterfaceIndex);
|
||||
Ptr<NdiscCache> ndiscCache = ipv6Interface->GetNdiscCache ();
|
||||
if (ndiscCache)
|
||||
{
|
||||
NS_LOG_FUNCTION ("Remove a NDISC entry");
|
||||
ndiscCache->RemoveAutoGeneratedEntries ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
132
src/internet/helper/neighbor-cache-helper.h
Normal file
132
src/internet/helper/neighbor-cache-helper.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2022 ZHIHENG DONG
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Zhiheng Dong <dzh2077@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef NEIGHBOR_CACHE_HELPER_H
|
||||
#define NEIGHBOR_CACHE_HELPER_H
|
||||
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/net-device-container.h"
|
||||
#include "ns3/ipv4-interface-container.h"
|
||||
#include "ns3/ipv6-interface-container.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/ipv4-interface.h"
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/channel.h"
|
||||
#include "ns3/arp-l3-protocol.h"
|
||||
#include "ns3/arp-header.h"
|
||||
#include "ns3/arp-cache.h"
|
||||
#include "ns3/ipv6-interface.h"
|
||||
#include "ns3/icmpv6-l4-protocol.h"
|
||||
#include "ns3/ipv6-l3-protocol.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup NeighborCacheHelper
|
||||
*
|
||||
* @brief A helper class to populate neighbor cache.
|
||||
*
|
||||
* This class is used to populate neighbor cache. Permanent entries will be added
|
||||
* on the scope of a channel, a NetDeviceContainer, an InterfaceContainer or globally.
|
||||
*/
|
||||
class NeighborCacheHelper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a helper class to make life easier while creating neighbor cache
|
||||
*/
|
||||
NeighborCacheHelper ();
|
||||
~NeighborCacheHelper ();
|
||||
|
||||
/**
|
||||
* \brief Populate neighbor ARP and NDISC caches for all devices.
|
||||
* This method walks the global ChannelList.
|
||||
*/
|
||||
void PopulateNeighborCache (void) const;
|
||||
|
||||
/**
|
||||
* \brief Populate neighbor ARP and NDISC caches for all devices in the given
|
||||
* Channel.
|
||||
* \param channel the Channel to process
|
||||
*/
|
||||
void PopulateNeighborCache (Ptr<Channel> channel) const;
|
||||
|
||||
/**
|
||||
* \brief Populate neighbor ARP and NDISC caches for all devices in the given
|
||||
* NetDeviceContainer.
|
||||
* \param c the NetDevice container to process
|
||||
*/
|
||||
void PopulateNeighborCache (const NetDeviceContainer &c) const;
|
||||
|
||||
/**
|
||||
* \brief Populate neighbor ARP caches for all IPv4 interfaces in the given
|
||||
* Ipv4InterfaceContainer.
|
||||
* \param c the Ipv4InterfaceContainer to process
|
||||
*/
|
||||
void PopulateNeighborCache (const Ipv4InterfaceContainer &c) const;
|
||||
|
||||
/**
|
||||
* \brief Populate neighbor NDISC caches for all IPv6 interfaces in the given
|
||||
* Ipv6InterfaceContainer.
|
||||
* \param c the Ipv6InterfaceContainer to process
|
||||
*/
|
||||
void PopulateNeighborCache (const Ipv6InterfaceContainer &c) const;
|
||||
|
||||
/**
|
||||
* \brief Remove entries generated from NeighborCacheHelper from ARP cache and NDISC cache
|
||||
*/
|
||||
void FlushAutoGenerated (void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Populate neighbor ARP entries for given IPv4 interface.
|
||||
* \param ipv4Interface the Ipv4Interface to process
|
||||
* \param neighborDeviceInterface the potential neighbor Ipv4Interface
|
||||
*/
|
||||
void PopulateNeighborEntriesIpv4 (Ptr<Ipv4Interface> ipv4Interface, Ptr<Ipv4Interface> neighborDeviceInterface) const;
|
||||
|
||||
/**
|
||||
* \brief Populate neighbor NDISC entries for given IPv6 interface.
|
||||
* \param ipv6Interface the Ipv6Interface to process
|
||||
* \param neighborDeviceInterface the potential neighbor Ipv6Interface
|
||||
*/
|
||||
void PopulateNeighborEntriesIpv6 (Ptr<Ipv6Interface> ipv6Interface, Ptr<Ipv6Interface> neighborDeviceInterface) const;
|
||||
|
||||
/**
|
||||
* \brief Add an auto_generated entry to the ARP cache of an interface.
|
||||
* \param netDeviceInterface the Ipv4Interface that ARP cache belongs to
|
||||
* \param ipv4Address the IPv4 address will be added to the cache.
|
||||
* \param macAddress the MAC address will be added to the cache.
|
||||
*/
|
||||
void AddEntry (Ptr<Ipv4Interface> netDeviceInterface, Ipv4Address ipv4Address, Address macAddress) const;
|
||||
|
||||
/**
|
||||
* \brief Add an auto_generated entry to the NDISC cache of an interface.
|
||||
* \param netDeviceInterface the Ipv6Interface that NDISC cache belongs to
|
||||
* \param ipv6Address the IPv6 address will be added to the cache.
|
||||
* \param macAddress the MAC address will be added to the cache.
|
||||
*/
|
||||
void AddEntry (Ptr<Ipv6Interface> netDeviceInterface, Ipv6Address ipv6Address, Address macAddress) const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* NEIGHBOR_CACHE_HELPER_H */
|
||||
@@ -214,7 +214,7 @@ ArpCache::HandleWaitReplyTimeout (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("node="<<m_device->GetNode ()->GetId () <<
|
||||
NS_LOG_LOGIC ("node="<< m_device->GetNode ()->GetId () <<
|
||||
", wait reply for " << entry->GetIpv4Address () <<
|
||||
" expired -- drop since max retries exceeded: " <<
|
||||
entry->GetRetries ());
|
||||
@@ -286,9 +286,13 @@ ArpCache::PrintArpCache (Ptr<OutputStreamWrapper> stream)
|
||||
*os << " DELAY\n";
|
||||
}
|
||||
else if (i->second->IsPermanent ())
|
||||
{
|
||||
*os << " PERMANENT\n";
|
||||
}
|
||||
{
|
||||
*os << " PERMANENT\n";
|
||||
}
|
||||
else if (i->second->IsAutoGenerated ())
|
||||
{
|
||||
*os << " STATIC_AUTOGENERATED\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
*os << " STALE\n";
|
||||
@@ -296,6 +300,23 @@ ArpCache::PrintArpCache (Ptr<OutputStreamWrapper> stream)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ArpCache::RemoveAutoGeneratedEntries (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (CacheI i = m_arpCache.begin (); i != m_arpCache.end ();)
|
||||
{
|
||||
if (i->second->IsAutoGenerated ())
|
||||
{
|
||||
i->second->ClearPendingPacket (); //clear the pending packets for entry's ipaddress
|
||||
delete i->second;
|
||||
m_arpCache.erase (i++);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<ArpCache::Entry *>
|
||||
ArpCache::LookupInverse (Address to)
|
||||
{
|
||||
@@ -389,6 +410,12 @@ ArpCache::Entry::IsPermanent (void)
|
||||
NS_LOG_FUNCTION (this);
|
||||
return (m_state == PERMANENT);
|
||||
}
|
||||
bool
|
||||
ArpCache::Entry::IsAutoGenerated (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return (m_state == STATIC_AUTOGENERATED);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
@@ -420,6 +447,16 @@ ArpCache::Entry::MarkPermanent (void)
|
||||
ClearRetries ();
|
||||
UpdateSeen ();
|
||||
}
|
||||
void
|
||||
ArpCache::Entry::MarkAutoGenerated (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << m_macAddress);
|
||||
NS_ASSERT (!m_macAddress.IsInvalid ());
|
||||
|
||||
m_state = STATIC_AUTOGENERATED;
|
||||
ClearRetries ();
|
||||
UpdateSeen ();
|
||||
}
|
||||
bool
|
||||
ArpCache::Entry::UpdateWaitReply (Ipv4PayloadHeaderPair waiting)
|
||||
{
|
||||
@@ -478,20 +515,20 @@ Time
|
||||
ArpCache::Entry::GetTimeout (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
switch (m_state) {
|
||||
case ArpCache::Entry::WAIT_REPLY:
|
||||
return m_arp->GetWaitReplyTimeout ();
|
||||
case ArpCache::Entry::DEAD:
|
||||
return m_arp->GetDeadTimeout ();
|
||||
case ArpCache::Entry::ALIVE:
|
||||
return m_arp->GetAliveTimeout ();
|
||||
case ArpCache::Entry::PERMANENT:
|
||||
return Time::Max ();
|
||||
default:
|
||||
NS_ASSERT (false);
|
||||
return Seconds (0);
|
||||
/* NOTREACHED */
|
||||
switch (m_state)
|
||||
{
|
||||
case ArpCache::Entry::WAIT_REPLY:
|
||||
return m_arp->GetWaitReplyTimeout ();
|
||||
case ArpCache::Entry::DEAD:
|
||||
return m_arp->GetDeadTimeout ();
|
||||
case ArpCache::Entry::ALIVE:
|
||||
return m_arp->GetAliveTimeout ();
|
||||
case ArpCache::Entry::PERMANENT:
|
||||
return Time::Max ();
|
||||
case ArpCache::Entry::STATIC_AUTOGENERATED:
|
||||
return Time::Max ();
|
||||
}
|
||||
return Time (); // Silence compiler warning
|
||||
}
|
||||
bool
|
||||
ArpCache::Entry::IsExpired (void) const
|
||||
|
||||
@@ -167,6 +167,11 @@ public:
|
||||
*/
|
||||
void PrintArpCache (Ptr<OutputStreamWrapper> stream);
|
||||
|
||||
/**
|
||||
* \brief Clear the ArpCache of all Auto-Generated entries
|
||||
*/
|
||||
void RemoveAutoGeneratedEntries (void);
|
||||
|
||||
/**
|
||||
* \brief Pair of a packet and an Ipv4 header.
|
||||
*/
|
||||
@@ -201,6 +206,12 @@ public:
|
||||
* The entry must have a valid MacAddress.
|
||||
*/
|
||||
void MarkPermanent (void);
|
||||
/**
|
||||
* \brief Changes the state of this entry to auto-generated.
|
||||
*
|
||||
* The entry must have a valid MacAddress.
|
||||
*/
|
||||
void MarkAutoGenerated (void);
|
||||
/**
|
||||
* \param waiting
|
||||
* \return
|
||||
@@ -222,6 +233,10 @@ public:
|
||||
* \return True if the state of this entry is permanent; false otherwise.
|
||||
*/
|
||||
bool IsPermanent (void);
|
||||
/**
|
||||
* \return True if the state of this entry is auto-generated; false otherwise.
|
||||
*/
|
||||
bool IsAutoGenerated (void);
|
||||
/**
|
||||
* \return The MacAddress of this entry
|
||||
*/
|
||||
@@ -277,11 +292,13 @@ private:
|
||||
/**
|
||||
* \brief ARP cache entry states
|
||||
*/
|
||||
enum ArpCacheEntryState_e {
|
||||
enum ArpCacheEntryState_e
|
||||
{
|
||||
ALIVE,
|
||||
WAIT_REPLY,
|
||||
DEAD,
|
||||
PERMANENT
|
||||
PERMANENT,
|
||||
STATIC_AUTOGENERATED
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -336,7 +336,7 @@ ArpL3Protocol::Lookup (Ptr<Packet> packet, const Ipv4Header & ipHeader, Ipv4Addr
|
||||
m_dropTrace (packet);
|
||||
}
|
||||
}
|
||||
else if (entry-> IsPermanent ())
|
||||
else if (entry->IsPermanent () || entry->IsAutoGenerated ())
|
||||
{
|
||||
NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
|
||||
", permanent for " << destination << "valid -- send");
|
||||
|
||||
@@ -825,7 +825,7 @@ void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv
|
||||
entry->MarkReachable (lla.GetAddress ());
|
||||
}
|
||||
}
|
||||
if (!entry->IsPermanent ())
|
||||
if (!entry->IsPermanent () )
|
||||
{
|
||||
entry->StartReachableTimer ();
|
||||
}
|
||||
@@ -1443,7 +1443,7 @@ bool Icmpv6L4Protocol::Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<Ndisc
|
||||
NdiscCache::Entry* entry = cache->Lookup (dst);
|
||||
if (entry)
|
||||
{
|
||||
if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
|
||||
if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent () || entry->IsAutoGenerated ())
|
||||
{
|
||||
*hardwareDestination = entry->GetMacAddress ();
|
||||
return true;
|
||||
@@ -1477,7 +1477,7 @@ bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, const Ipv6Header & ipHeader, Ipv6A
|
||||
NdiscCache::Entry* entry = cache->Lookup (dst);
|
||||
if (entry)
|
||||
{
|
||||
if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
|
||||
if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent () || entry->IsAutoGenerated ())
|
||||
{
|
||||
/* XXX check reachability time */
|
||||
/* send packet */
|
||||
|
||||
@@ -1642,7 +1642,7 @@ bool Ipv6L3Protocol::ReachabilityHint (uint32_t ipInterfaceIndex, Ipv6Address ad
|
||||
{
|
||||
entry->UpdateReachableTimer ();
|
||||
}
|
||||
else if (entry->IsPermanent ())
|
||||
else if (entry->IsPermanent () || entry->IsAutoGenerated ())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -218,6 +218,10 @@ void NdiscCache::PrintNdiscCache (Ptr<OutputStreamWrapper> stream)
|
||||
{
|
||||
*os << " PERMANENT\n";
|
||||
}
|
||||
else if (i->second->IsAutoGenerated ())
|
||||
{
|
||||
*os << " STATIC_AUTOGENERATED\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Test for possibly unreachable code-- please file a bug report, with a test case, if this is ever hit");
|
||||
@@ -554,6 +558,13 @@ void NdiscCache::Entry::MarkPermanent ()
|
||||
m_state = PERMANENT;
|
||||
}
|
||||
|
||||
void NdiscCache::Entry::MarkAutoGenerated ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
StopNudTimer ();
|
||||
m_state = STATIC_AUTOGENERATED;
|
||||
}
|
||||
|
||||
bool NdiscCache::Entry::IsStale () const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
@@ -590,6 +601,12 @@ bool NdiscCache::Entry::IsPermanent () const
|
||||
return (m_state == PERMANENT);
|
||||
}
|
||||
|
||||
bool NdiscCache::Entry::IsAutoGenerated () const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return (m_state == STATIC_AUTOGENERATED);
|
||||
}
|
||||
|
||||
Address NdiscCache::Entry::GetMacAddress () const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
@@ -606,26 +623,46 @@ void NdiscCache::Entry::Print (std::ostream &os) const
|
||||
{
|
||||
os << m_ipv6Address << " lladdr " << m_macAddress << " state ";
|
||||
switch (m_state)
|
||||
{
|
||||
case INCOMPLETE:
|
||||
os << "INCOMPLETE";
|
||||
break;
|
||||
case REACHABLE:
|
||||
os << "REACHABLE";
|
||||
break;
|
||||
case STALE:
|
||||
os << "STALE";
|
||||
break;
|
||||
case DELAY:
|
||||
os << "DELAY";
|
||||
break;
|
||||
case PROBE:
|
||||
os << "PROBE";
|
||||
break;
|
||||
case PERMANENT:
|
||||
os << "PERMANENT";
|
||||
break;
|
||||
}
|
||||
{
|
||||
case INCOMPLETE:
|
||||
os << "INCOMPLETE";
|
||||
break;
|
||||
case REACHABLE:
|
||||
os << "REACHABLE";
|
||||
break;
|
||||
case STALE:
|
||||
os << "STALE";
|
||||
break;
|
||||
case DELAY:
|
||||
os << "DELAY";
|
||||
break;
|
||||
case PROBE:
|
||||
os << "PROBE";
|
||||
break;
|
||||
case PERMANENT:
|
||||
os << "PERMANENT";
|
||||
break;
|
||||
case STATIC_AUTOGENERATED:
|
||||
os << "PERMANENT";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NdiscCache::RemoveAutoGeneratedEntries (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
for (CacheI i = m_ndCache.begin (); i != m_ndCache.end (); )
|
||||
{
|
||||
if (i->second->IsAutoGenerated ())
|
||||
{
|
||||
i->second->ClearWaitingPacket ();
|
||||
delete i->second;
|
||||
m_ndCache.erase (i++);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator << (std::ostream& os, NdiscCache::Entry const& entry)
|
||||
|
||||
@@ -147,6 +147,11 @@ public:
|
||||
*/
|
||||
void PrintNdiscCache (Ptr<OutputStreamWrapper> stream);
|
||||
|
||||
/**
|
||||
* \brief Clear the NDISC cache of all Auto-Generated entries
|
||||
*/
|
||||
void RemoveAutoGeneratedEntries (void);
|
||||
|
||||
/**
|
||||
* \brief Pair of a packet and an Ipv4 header.
|
||||
*/
|
||||
@@ -213,6 +218,13 @@ public:
|
||||
*/
|
||||
void MarkPermanent ();
|
||||
|
||||
/**
|
||||
* \brief Changes the state of this entry to auto-generated.
|
||||
*
|
||||
* The entry must have a valid MacAddress.
|
||||
*/
|
||||
void MarkAutoGenerated (void);
|
||||
|
||||
/**
|
||||
* \brief Add a packet (or replace old value) in the queue.
|
||||
* \param p packet to add
|
||||
@@ -260,6 +272,12 @@ public:
|
||||
*/
|
||||
bool IsPermanent () const;
|
||||
|
||||
/**
|
||||
* \brief Is the entry STATIC_AUTOGENERATED
|
||||
* \return True if the state of this entry is auto-generated; false otherwise.
|
||||
*/
|
||||
bool IsAutoGenerated () const;
|
||||
|
||||
/**
|
||||
* \brief Get the MAC address of this entry.
|
||||
* \return the L2 address
|
||||
@@ -383,7 +401,9 @@ private:
|
||||
STALE, /**< Mapping is stale */
|
||||
DELAY, /**< Try to wait contact from remote host */
|
||||
PROBE, /**< Try to contact IPv6 address to know again its L2 address */
|
||||
PERMANENT /**< Permanent Mapping exists between IPv6 and L2 addresses */
|
||||
PERMANENT, /**< Permanent Mapping exists between IPv6 and L2 addresses */
|
||||
STATIC_AUTOGENERATED /**< similar to Permanent populate by NeighborCacheHelper */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
292
src/internet/test/neighbor-cache-test.cc
Normal file
292
src/internet/test/neighbor-cache-test.cc
Normal file
@@ -0,0 +1,292 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2022 ZHIHENG DONG
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Author: Zhiheng Dong <dzh2077@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/udp-socket-factory.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/simple-channel.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/socket.h"
|
||||
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/icmpv4-l4-protocol.h"
|
||||
#include "ns3/ipv6-address-helper.h"
|
||||
#include "ns3/ipv6-l3-protocol.h"
|
||||
#include "ns3/icmpv6-l4-protocol.h"
|
||||
#include "ns3/udp-l4-protocol.h"
|
||||
#include "ns3/ipv4-routing-helper.h"
|
||||
#include "ns3/ipv6-routing-helper.h"
|
||||
#include "ns3/neighbor-cache-helper.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/**
|
||||
* \ingroup internet-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Neighbor cache Test
|
||||
*/
|
||||
class NeighborCacheTest : public TestCase
|
||||
{
|
||||
Ptr<Packet> m_receivedPacket; //!< Received packet
|
||||
|
||||
/**
|
||||
* \brief Send data immediately after being called.
|
||||
* \param socket The sending socket.
|
||||
* \param to IPv4 Destination address.
|
||||
*/
|
||||
void DoSendDatav4 (Ptr<Socket> socket, Ipv4Address to);
|
||||
|
||||
/**
|
||||
* \brief Send data immediately after being called.
|
||||
* \param socket The sending socket.
|
||||
* \param to IPv6 Destination address.
|
||||
*/
|
||||
void DoSendDatav6 (Ptr<Socket> socket, Ipv6Address to);
|
||||
|
||||
/**
|
||||
* \brief Schedules the DoSendData () function to send the data.
|
||||
* \param socket The sending socket.
|
||||
* \param to IPv4 Destination address.
|
||||
*/
|
||||
void SendData (Ptr<Socket> socket, Ipv4Address to);
|
||||
|
||||
/**
|
||||
* \brief Schedules the DoSendData () function to send the data.
|
||||
* \param socket The sending socket.
|
||||
* \param to IPv6 Destination address.
|
||||
*/
|
||||
void SendData (Ptr<Socket> socket, Ipv6Address to);
|
||||
|
||||
public:
|
||||
virtual void DoRun (void);
|
||||
|
||||
NeighborCacheTest ();
|
||||
|
||||
/**
|
||||
* \brief Receive data.
|
||||
* \param socket The receiving socket.
|
||||
*/
|
||||
void ReceivePkt (Ptr<Socket> socket);
|
||||
|
||||
std::vector<uint32_t> m_receivedPacketSizes; //!< Received packet sizes
|
||||
};
|
||||
|
||||
NeighborCacheTest::NeighborCacheTest ()
|
||||
: TestCase ("NeighborCache")
|
||||
{}
|
||||
|
||||
void NeighborCacheTest::ReceivePkt (Ptr<Socket> socket)
|
||||
{
|
||||
[[maybe_unused]] uint32_t availableData;
|
||||
availableData = socket->GetRxAvailable ();
|
||||
m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
|
||||
NS_TEST_ASSERT_MSG_EQ (availableData, m_receivedPacket->GetSize (), "Received Packet size is not equal to the Rx buffer size");
|
||||
m_receivedPacketSizes.push_back (m_receivedPacket->GetSize ());
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheTest::DoSendDatav4 (Ptr<Socket> socket, Ipv4Address to)
|
||||
{
|
||||
Address realTo = InetSocketAddress (to, 1234);
|
||||
NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
|
||||
123, "100");
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheTest::DoSendDatav6 (Ptr<Socket> socket, Ipv6Address to)
|
||||
{
|
||||
Address realTo = Inet6SocketAddress (to, 1234);
|
||||
NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
|
||||
123, "100");
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheTest::SendData (Ptr<Socket> socket, Ipv4Address to)
|
||||
{
|
||||
m_receivedPacket = Create<Packet> ();
|
||||
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
|
||||
&NeighborCacheTest::DoSendDatav4, this, socket, to);
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheTest::SendData (Ptr<Socket> socket, Ipv6Address to)
|
||||
{
|
||||
m_receivedPacket = Create<Packet> ();
|
||||
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
|
||||
&NeighborCacheTest::DoSendDatav6, this, socket, to);
|
||||
}
|
||||
|
||||
void
|
||||
NeighborCacheTest::DoRun (void)
|
||||
{
|
||||
Ptr<Node> txNode = CreateObject<Node> ();
|
||||
Ptr<Node> rxNode = CreateObject<Node> ();
|
||||
Ptr<Node> snifferNode = CreateObject<Node> ();
|
||||
|
||||
NodeContainer all (txNode, rxNode, snifferNode);
|
||||
|
||||
std::ostringstream stringStream1v4;
|
||||
Ptr<OutputStreamWrapper> arpStream = Create<OutputStreamWrapper> (&stringStream1v4);
|
||||
std::ostringstream stringStream1v6;
|
||||
Ptr<OutputStreamWrapper> ndiscStream = Create<OutputStreamWrapper> (&stringStream1v6);
|
||||
|
||||
InternetStackHelper internetNodes;
|
||||
internetNodes.Install (all);
|
||||
|
||||
NetDeviceContainer net;
|
||||
// Sender Node
|
||||
Ptr<SimpleNetDevice> txDev;
|
||||
{
|
||||
txDev = CreateObject<SimpleNetDevice> ();
|
||||
txDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
|
||||
txNode->AddDevice (txDev);
|
||||
}
|
||||
net.Add (txDev);
|
||||
|
||||
// Recieve node
|
||||
Ptr<SimpleNetDevice> rxDev;
|
||||
{
|
||||
rxDev = CreateObject<SimpleNetDevice> ();
|
||||
rxDev->SetAddress (Mac48Address ("00:00:00:00:00:02"));
|
||||
rxNode->AddDevice (rxDev);
|
||||
}
|
||||
net.Add (rxDev);
|
||||
|
||||
// Sniffer node
|
||||
Ptr<SimpleNetDevice> snifferDev;
|
||||
{
|
||||
snifferDev = CreateObject<SimpleNetDevice> ();
|
||||
snifferDev->SetAddress (Mac48Address ("00:00:00:00:00:03"));
|
||||
snifferNode->AddDevice (snifferDev);
|
||||
}
|
||||
net.Add (snifferDev);
|
||||
|
||||
// link the channels
|
||||
Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
|
||||
txDev->SetChannel (channel);
|
||||
rxDev->SetChannel (channel);
|
||||
snifferDev->SetChannel (channel);
|
||||
|
||||
// Setup IPv4 addresses
|
||||
Ipv4AddressHelper ipv4;
|
||||
ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer icv4 = ipv4.Assign (net);
|
||||
|
||||
//Setup IPv6 addresses
|
||||
Ipv6AddressHelper ipv6;
|
||||
ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer icv6 = ipv6.Assign (net);
|
||||
|
||||
//Populate perfect caches.
|
||||
NeighborCacheHelper neighborCache;
|
||||
neighborCache.PopulateNeighborCache ();
|
||||
|
||||
//Print cache.
|
||||
Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream);
|
||||
Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream);
|
||||
|
||||
// Create the UDP sockets
|
||||
Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> rxSocketv4 = rxSocketFactory->CreateSocket ();
|
||||
Ptr<Socket> rxSocketv6 = rxSocketFactory->CreateSocket ();
|
||||
NS_TEST_EXPECT_MSG_EQ (rxSocketv4->Bind (InetSocketAddress (Ipv4Address ("10.0.1.2"), 1234)), 0, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (rxSocketv6->Bind (Inet6SocketAddress (Ipv6Address ("2001:0::200:ff:fe00:2"), 1234)), 0, "trivial");
|
||||
rxSocketv4->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this));
|
||||
rxSocketv6->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this));
|
||||
|
||||
Ptr<SocketFactory> snifferSocketFactory = snifferNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> snifferSocketv4 = snifferSocketFactory->CreateSocket ();
|
||||
Ptr<Socket> snifferSocketv6 = snifferSocketFactory->CreateSocket ();
|
||||
NS_TEST_EXPECT_MSG_EQ (snifferSocketv4->Bind (InetSocketAddress (Ipv4Address ("10.0.1.3"), 1234)), 0, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (snifferSocketv6->Bind (Inet6SocketAddress (Ipv6Address ("2001:0::200:ff:fe00:3"), 1234)), 0, "trivial");
|
||||
snifferSocketv4->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this));
|
||||
snifferSocketv6->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this));
|
||||
|
||||
Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
|
||||
txSocket->SetAllowBroadcast (true);
|
||||
|
||||
// ------ Now the tests ------------
|
||||
|
||||
// Unicast test
|
||||
SendData (txSocket, Ipv4Address ("10.0.1.2"));
|
||||
SendData (txSocket, Ipv6Address ("2001:0::200:ff:fe00:2"));
|
||||
|
||||
Simulator::Stop (Seconds (66));
|
||||
Simulator::Run ();
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes[0], 123, "Perfect Arp should work.");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes[1], 123, "Perfect Ndp should work.");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes.size (), 2, "Perfect Arp and perfect Ndp should have received only 1 packet.");
|
||||
|
||||
// Test the Cache
|
||||
constexpr auto arpCache = "ARP Cache of node 0 at time 0\n"
|
||||
"10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
|
||||
"10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"
|
||||
"ARP Cache of node 1 at time 0\n"
|
||||
"10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n"
|
||||
"10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"
|
||||
"ARP Cache of node 2 at time 0\n"
|
||||
"10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n"
|
||||
"10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n";
|
||||
NS_TEST_EXPECT_MSG_EQ (stringStream1v4.str (), arpCache, "Arp cache is incorrect.");
|
||||
|
||||
constexpr auto NdiscCache = "NDISC Cache of node 0 at time +0s\n"
|
||||
"2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
|
||||
"2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"
|
||||
"fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
|
||||
"fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"
|
||||
"NDISC Cache of node 1 at time +0s\n"
|
||||
"2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n"
|
||||
"2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"
|
||||
"fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n"
|
||||
"fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"
|
||||
"NDISC Cache of node 2 at time +0s\n"
|
||||
"2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n"
|
||||
"2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
|
||||
"fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n"
|
||||
"fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n";
|
||||
NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect.");
|
||||
|
||||
m_receivedPacket->RemoveAllByteTags ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup internet-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief IPv4 RIP TestSuite
|
||||
*/
|
||||
class NeighborCacheTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
NeighborCacheTestSuite () : TestSuite ("neighbor-cache", UNIT)
|
||||
{
|
||||
AddTestCase (new NeighborCacheTest, TestCase::QUICK);
|
||||
}
|
||||
};
|
||||
|
||||
static NeighborCacheTestSuite g_neighborcacheTestSuite; //!< Static variable for test initialization
|
||||
Reference in New Issue
Block a user