diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/AUTHORS ns-3.46/AUTHORS
--- ns-3.45/AUTHORS	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/AUTHORS	2025-10-01 18:46:32.000000000 -0700
@@ -74,6 +74,7 @@
 Luca Costantino (luca.costantino@gmail.com)
 Matthieu Coudron (matthieu.coudron@lip6.fr)
 Michael R. Davis (mrdvt92@yahoo.com)
+@DavisRobertson1 at GitLab.com
 Alexander D'souza (moijes12@gmail.com)
 Ankit Deepak (adadeepak8@gmail.com)
 Christophe Delahaye (christophe.delahaye@orange.com)
@@ -156,6 +157,7 @@
 Raghuram Kannan (raghuramkannan40@gmail.com)
 Vignesh Kannan (vignesh2496@gmail.com)
 Nihar Kapasi (niharkkapasi@gmail.com)
+Arnav Kapoor (kapoorarnav43@gmail.com)
 Ouassim Karrakchou (okarr102@uottawa.ca)
 Tanmay Kathpalia (tanmay.kathpalia@landisgyr.com)
 Konstantinos Katsaros (dinos.katsaros@gmail.com)
@@ -185,6 +187,7 @@
 Sandra Lagen (sandra.lagen@cttc.es)
 Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca)
 Harsh Lara (harshapplefan@gmail.com)
+Hugo Le Dirach (hugo.le_dirach@onera.fr)
 Mattia Lecci (mattia.lecci@gmail.com)
 Ben Lee (limjcst@163.com)
 Robin Lee (xinyashuai1987@163.com)
@@ -241,6 +244,7 @@
 Michael Nowatkowski (nowatkom@gmail.com)
 Anh Nguyen (annguyen@ittc.ku.edu)
 Duy Nguyen (duy@soe.ucsc.edu)
+Ryo Okuda (c611901200@tokushima-u.ac.jp)
 Alfonso Oliveira (af.oliveira.16@gmail.com)
 Wouter Overmeire (lodagro@gmail.com)
 Luis Pacheco (luisbelem@gmail.com)
@@ -262,6 +266,7 @@
 Eduardo Pinto (epmcj@hotmail.com)
 Giuseppe Piro (g.piro@poliba.it)
 Randall Plate (rplate@spawar.navy.mil)
+Max Plekh (mplekh@gmail.com)
 Yana Podkosova (yanapdk@rambler.ru)
 Michele Polese (michele.polese@gmail.com)
 Ovidiu Poncea (ovidiu.poncea@cs.pub.ro)
@@ -273,6 +278,7 @@
 Alberto Gallegos Ramonet (alramonet@is.tokushima-u.ac.jp)
 Manoj Kumar Rana (manoj24.rana@gmail.com)
 Andrea Ranieri (andreran@uno.it)
+Ashish Reddy (ashishajr@gmail.com)
 Bruno Ranieri (Yrrsinn@googlemail.com)
 Deepti Rajagopal (deeptir96@gmail.com)
 Satyarth Ratnani (satyarthratnani@gmail.com)
@@ -379,4 +385,3 @@
 Parth Pratim (GCI 2018)
 ra1nst0rm3d (GCI 2019)
 SaiMyGuy (GCI 2019)
-Ryo Okuda (c611901200@tokushima-u.ac.jp)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/bindings/python/ns__init__.py ns-3.46/bindings/python/ns__init__.py
--- ns-3.45/bindings/python/ns__init__.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/bindings/python/ns__init__.py	2025-10-01 18:46:32.000000000 -0700
@@ -8,6 +8,14 @@
 
 DEFAULT_INCLUDE_DIR = sysconfig.get_config_var("INCLUDEDIR")
 DEFAULT_LIB_DIR = sysconfig.get_config_var("LIBDIR")
+BUILD_TYPES = (
+    "debug",
+    "default",
+    "optimized",
+    "release",
+    "relwithdebinfo",
+    "minsizerel",
+)
 
 
 def find_ns3_lock() -> str:
@@ -169,7 +177,7 @@
     try:
         with open(os.path.abspath(library_path), "rb") as f:
             linked_libs = re.findall(
-                b"\x00(lib.*?.%b)" % LIBRARY_EXTENSION.encode("utf-8"), f.read()
+                b"\x00(lib[^\\x00]*?\\.%b)(?![\\w.])" % LIBRARY_EXTENSION.encode("utf-8"), f.read()
             )
     except Exception as e:
         print(f"Failed to extract libraries used by {library_path} with exception:{e}")
@@ -313,14 +321,7 @@
         components.pop(0)
 
     # Drop build profile suffix and test libraries
-    if components[-1] in [
-        "debug",
-        "default",
-        "optimized",
-        "release",
-        "relwithdebinfo",
-        "minsizerel",
-    ]:
+    if components[-1] in BUILD_TYPES:
         components.pop(-1)
     return "-".join(components)
 
@@ -521,12 +522,22 @@
                 if os.path.isdir(linked_lib_include_dir):
                     cppyy.add_include_path(linked_lib_include_dir)
 
-    for module in modules:
-        cppyy.include(f"ns3/{module}-module.h")
+    # Get build type
+    build_type = ""  # release
+    for type in BUILD_TYPES:
+        if type in libraries_to_load[-1]:
+            build_type = type
 
-    # After including all headers, we finally load the modules
+    # Load a module, then its module header
     for library in libraries_to_load:
         cppyy.load_library(library)
+        for module in modules:
+            library_name_from_module = (
+                f"{version}-{module}{'-' if len(build_type)>0 else ''}{build_type}."
+            )
+            if library_name_from_module in library:
+                cppyy.include(f"ns3/{module}-module.h")
+                break
 
     # We expose cppyy to consumers of this module as ns.cppyy
     setattr(cppyy.gbl.ns3, "cppyy", cppyy)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/cmake-format.yaml ns-3.46/build-support/cmake-format.yaml
--- ns-3.45/build-support/cmake-format.yaml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/cmake-format.yaml	2025-10-01 18:46:32.000000000 -0700
@@ -64,6 +64,19 @@
             PUBLIC_HEADER_FILES: '*'
             DEPRECATED_HEADER_FILES: '*'
             PRIVATE_HEADER_FILES: '*'
+    try_compile:
+        pargs:
+            nargs: 3
+        kwargs:
+            OUTPUT_VARIABLE: '1'
+            CXX_STANDARD: '1'
+            CXX_STANDARD_REQUIRED: '1'
+            CXX_EXTENSIONS: '1'
+            SOURCES: '*'
+            CMAKE_FLAGS: '*'
+            COMPILE_DEFINITIONS: '*'
+            LINK_OPTIONS: '*'
+            LINK_LIBRARIES: '*'
 
 format:
   tab_size: 2
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/core-config-template.h ns-3.46/build-support/core-config-template.h
--- ns-3.45/build-support/core-config-template.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/core-config-template.h	2025-10-01 18:46:32.000000000 -0700
@@ -6,13 +6,9 @@
 #cmakedefine INT64X64_USE_128
 #cmakedefine INT64X64_USE_DOUBLE
 #cmakedefine INT64X64_USE_CAIRO
-#cmakedefine01 HAVE_STDINT_H
-#cmakedefine01 HAVE_INTTYPES_H
-#cmakedefine HAVE_SYS_INT_TYPES_H
 #cmakedefine01 HAVE_SYS_TYPES_H
 #cmakedefine01 HAVE_SYS_STAT_H
 #cmakedefine01 HAVE_DIRENT_H
-#cmakedefine01 HAVE_STDLIB_H
 #cmakedefine01 HAVE_GETENV
 #cmakedefine01 HAVE_SIGNAL_H
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/custom-modules/ns3-check-dependencies.cmake ns-3.46/build-support/custom-modules/ns3-check-dependencies.cmake
--- ns-3.45/build-support/custom-modules/ns3-check-dependencies.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/custom-modules/ns3-check-dependencies.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -40,6 +40,27 @@
     )
     if(NOT (${return_code} EQUAL 0))
       list(APPEND local_missing_deps ${package})
+    else()
+      # To make sure CMake import files can be found from venv site packages, we
+      # manually add them to CMAKE_PREFIX_PATH
+      execute_process(
+        COMMAND
+          ${Python3_EXECUTABLE} -c
+          "import os; import ${package}; print(os.path.abspath(os.path.dirname(${package}.__file__)))"
+        OUTPUT_VARIABLE venv_site_packages_path
+      )
+      # Remove newlines (\n, \r, \r\n)
+      string(REGEX REPLACE "[\r\n]+$" "" venv_site_packages_path
+                           "${venv_site_packages_path}"
+      )
+      if(EXISTS ${venv_site_packages_path})
+        if(NOT (DEFINED CMAKE_PREFIX_PATH))
+          set(CMAKE_PREFIX_PATH "" PARENT_SCOPE)
+        endif()
+        set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${venv_site_packages_path}"
+            PARENT_SCOPE
+        )
+      endif()
     endif()
   endforeach()
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/custom-modules/ns3-compiler-workarounds.cmake ns-3.46/build-support/custom-modules/ns3-compiler-workarounds.cmake
--- ns-3.45/build-support/custom-modules/ns3-compiler-workarounds.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/custom-modules/ns3-compiler-workarounds.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -3,3 +3,101 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 # Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
+
+include(CheckCXXSourceCompiles)
+
+# Some versions of clang (17) have issues with stdlibc++, so we check if we can
+# fallback to libc++ instead
+if(CLANG)
+  try_compile(
+    CLANG_STDLIBCPP_WORKS
+    SOURCES ${PROJECT_SOURCE_DIR}/build-support/test-clang17-stdlibcpp-map.cc
+    COMPILE_DEFINITIONS -stdlib=libstdc++
+    LINK_OPTIONS -stdlib=libstdc++
+    CXX_STANDARD 23
+    CXX_STANDARD_REQUIRED TRUE
+    CXX_EXTENSIONS FALSE
+  )
+
+  try_compile(
+    CLANG_LIBCPP_WORKS
+    SOURCES ${PROJECT_SOURCE_DIR}/build-support/test-clang17-stdlibcpp-map.cc
+    COMPILE_DEFINITIONS -stdlib=libc++
+    LINK_OPTIONS -stdlib=libc++
+    CXX_STANDARD 23
+    CXX_STANDARD_REQUIRED TRUE
+    CXX_EXTENSIONS FALSE
+  )
+  if((NOT ${CLANG_STDLIBCPP_WORKS}) AND (NOT ${CLANG_LIBCPP_WORKS}))
+    message(
+      FATAL_ERROR
+        "This clang version ${CMAKE_CXX_COMPILER_VERSION} is not compatible with using std::tuple as std::map keys"
+    )
+  elseif(${CLANG_STDLIBCPP_WORKS})
+    message(
+      STATUS
+        "This clang version ${CMAKE_CXX_COMPILER_VERSION} is compatible with using std::tuple as std::map keys"
+    )
+  else()
+    message(
+      ${HIGHLIGHTED_STATUS}
+      "This clang version ${CMAKE_CXX_COMPILER_VERSION} requires libc++ to use std::tuple as std::map keys"
+    )
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+  endif()
+endif()
+
+# Some compilers (e.g. GCC <= 15) do not link std::stacktrace by default. If the
+# sample program can be linked, it means it is indeed linked by default.
+# Otherwise, we link it manually.
+# https://en.cppreference.com/w/cpp/header/stacktrace
+set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS} -std=c++23)
+check_cxx_source_compiles(
+  "
+  #if __has_include(<stacktrace>)
+  int main()
+  {
+    return 0;
+  }
+  #endif
+  "
+  STACKTRACE_LIBRARY_ENABLED
+)
+mark_as_advanced(stacktrace_flags)
+set(stacktrace_flags "" CACHE INTERNAL "")
+if(STACKTRACE_LIBRARY_ENABLED)
+  if(GCC)
+    if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0.0")
+      # GCC does not support stacktracing
+    elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0.0")
+      set(stacktrace_flags -lstdc++_libbacktrace CACHE INTERNAL "")
+    else()
+      set(stacktrace_flags -lstdc++exp CACHE INTERNAL "")
+    endif()
+  elseif(CLANG AND (NOT ("${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC")))
+    set(stacktrace_flags -lstdc++_libbacktrace CACHE INTERNAL "")
+  else()
+    # Most likely MSVC, which does not need custom flags for this
+  endif()
+  set(CMAKE_REQUIRED_LIBRARIES ${stacktrace_flags})
+  string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+  check_cxx_source_compiles(
+    "
+    #include <iostream>
+    #include <stacktrace>
+
+    int main()
+    {
+      std::cout << std::stacktrace::current() << std::endl;
+      return 0;
+    }
+    "
+    STACKTRACE_LIBRARY_IS_LINKED
+  )
+
+  if(STACKTRACE_LIBRARY_IS_LINKED)
+    add_definitions(-DSTACKTRACE_LIBRARY_IS_LINKED=1)
+  else()
+    set(stacktrace_flags "" CACHE INTERNAL "")
+  endif()
+endif()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/custom-modules/ns3-configtable.cmake ns-3.46/build-support/custom-modules/ns3-configtable.cmake
--- ns-3.45/build-support/custom-modules/ns3-configtable.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/custom-modules/ns3-configtable.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -44,7 +44,7 @@
 # sixlowpan                 spectrum                  stats
 # tap-bridge                test (no Python)          topology-read
 # traffic-control           uan                       virtual-net-device
-# wave                      wifi                      wimax
+# wave                      wifi
 #
 # Modules not built (see ns-3 tutorial for explanation):
 # brite                     click                     dpdk-net-device
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/custom-modules/ns3-find-external-library.cmake ns-3.46/build-support/custom-modules/ns3-find-external-library.cmake
--- ns-3.45/build-support/custom-modules/ns3-find-external-library.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/custom-modules/ns3-find-external-library.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -162,22 +162,6 @@
         # cmake-format: on
     # Or enable NS3_VERBOSE to print the searched paths
 
-    # Print tested paths to the searched library and if it was found
-    if(${NS3_VERBOSE} AND (${CMAKE_VERSION} VERSION_LESS "3.17.0"))
-      log_find_searched_paths(
-        TARGET_TYPE
-        Library
-        TARGET_NAME
-        ${library}
-        SEARCH_RESULT
-        ${name}_library_internal_${library}
-        SEARCH_PATHS
-        ${library_search_paths}
-        SEARCH_SUFFIXES
-        ${suffixes}
-      )
-    endif()
-
     # After searching the library, the internal variable should have either the
     # absolute path to the library or the name of the variable appended with
     # -NOTFOUND
@@ -260,22 +244,6 @@
               PATH_SUFFIXES ${suffixes}
     )
 
-    # Print tested paths to the searched header and if it was found
-    if(${NS3_VERBOSE} AND (${CMAKE_VERSION} VERSION_LESS "3.17.0"))
-      log_find_searched_paths(
-        TARGET_TYPE
-        Header
-        TARGET_NAME
-        ${header}
-        SEARCH_RESULT
-        ${name}_header_internal_${header}
-        SEARCH_PATHS
-        ${header_search_paths}
-        SEARCH_SUFFIXES
-        ${suffixes}
-      )
-    endif()
-
     # If the header file was not found, append to the not-found list
     if("${${name}_header_internal_${header}}" STREQUAL
        "${name}_header_internal_${header}-NOTFOUND"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/custom-modules/ns3-module-macros.cmake ns-3.46/build-support/custom-modules/ns3-module-macros.cmake
--- ns-3.45/build-support/custom-modules/ns3-module-macros.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/custom-modules/ns3-module-macros.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -288,8 +288,8 @@
 function(build_lib_reexport_third_party_libraries libname libraries_to_link)
   # Separate ns-3 and non-ns-3 libraries to manage their propagation properly
   separate_ns3_from_non_ns3_libs(
-    "${libname}" "${libraries_to_link}" ns_libraries_to_link
-    non_ns_libraries_to_link
+    "${libname}" "${libraries_to_link};${stacktrace_flags}"
+    ns_libraries_to_link non_ns_libraries_to_link
   )
 
   set(ns3-external-libs "${non_ns_libraries_to_link};${ns3-external-libs}"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/custom-modules/ns3-platform-support.cmake ns-3.46/build-support/custom-modules/ns3-platform-support.cmake
--- ns-3.45/build-support/custom-modules/ns3-platform-support.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/custom-modules/ns3-platform-support.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -111,7 +111,11 @@
     _CRT_SECURE_NO_WARNINGS NS_MSVC NOMINMAX
   )
 
-  # Allow unresolved symbols as in most cases they are simply in other ns-3
-  # libraries
-  add_link_options("/FORCE:UNRESOLVED")
+  # Disable inlining (trust me, it is either that or moving every single inlined
+  # code to .cc)
+  add_compile_options(/Ob0)
+
+  # Prevent linker from eliminating unused functions and increase stack size to
+  # 8MB to match Linux
+  add_link_options(/OPT:NOREF /STACK:8388608)
 endif()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/macros-and-definitions.cmake ns-3.46/build-support/macros-and-definitions.cmake
--- ns-3.45/build-support/macros-and-definitions.cmake	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/build-support/macros-and-definitions.cmake	2025-10-01 18:46:32.000000000 -0700
@@ -54,13 +54,12 @@
 
 # Set compiler options and get command to force unused function linkage (useful
 # for libraries)
-set(CXX_UNSUPPORTED_STANDARDS 98 11 14 17)
-set(CMAKE_CXX_STANDARD_MINIMUM 20)
+set(CXX_UNSUPPORTED_STANDARDS 98 11 14 17 20)
+set(CMAKE_CXX_STANDARD_MINIMUM 23)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 
 # Include CMake files used for compiler checks
-include(CheckIncludeFile) # Used to check a single C header at a time
 include(CheckIncludeFileCXX) # Used to check a single C++ header at a time
 include(CheckIncludeFiles) # Used to check multiple headers at once
 include(CheckFunctionExists)
@@ -259,13 +258,21 @@
 
   if(${NS3_CLANG_TIDY})
     find_program(
-      CLANG_TIDY NAMES clang-tidy clang-tidy-15 clang-tidy-16 clang-tidy-17
-                       clang-tidy-18 clang-tidy-19
+      CLANG_TIDY
+      NAMES clang-tidy
+            clang-tidy-15
+            clang-tidy-16
+            clang-tidy-17
+            clang-tidy-18
+            clang-tidy-19
+            clang-tidy-20
     )
     if("${CLANG_TIDY}" STREQUAL "CLANG_TIDY-NOTFOUND")
       message(FATAL_ERROR "Clang-tidy was not found")
     else()
-      set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY}")
+      set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY}
+                               -config-file=${CMAKE_SOURCE_DIR}/.clang-tidy
+      ) # --fix)
     endif()
   else()
     unset(CMAKE_CXX_CLANG_TIDY)
@@ -529,14 +536,7 @@
 
   set(ENABLE_SQLITE False)
   if(${NS3_SQLITE})
-    # find_package(SQLite3 QUIET) # unsupported in CMake 3.10 We emulate the
-    # behavior of find_package below
-    find_external_library(
-      DEPENDENCY_NAME SQLite3
-      HEADER_NAME sqlite3.h
-      LIBRARY_NAME sqlite3
-      OUTPUT_VARIABLE "ENABLE_SQLITE_REASON"
-    )
+    find_package(SQLite3 QUIET)
 
     if(${SQLite3_FOUND})
       set(ENABLE_SQLITE True)
@@ -634,16 +634,11 @@
   set(Python3_FOUND FALSE)
   set(Python3_INCLUDE_DIRS)
   set(Python3_Interpreter_FOUND FALSE)
+  set(Python3_FIND_VIRTUALENV FIRST)
   if(${NS3_PYTHON_BINDINGS})
     find_package(Python3 COMPONENTS Interpreter Development)
   else()
-    # If Python was not set yet, use the version found by check_deps
-    check_deps(python3_deps EXECUTABLES python3)
-    if(python3_deps)
-      message(FATAL_ERROR "Python3 was not found")
-    else()
-      set(Python3_EXECUTABLE ${PYTHON3})
-    endif()
+    find_package(Python3 COMPONENTS Interpreter)
   endif()
 
   # Check if both Python interpreter and development libraries were found
@@ -1074,20 +1069,18 @@
   # Process core-config If INT128 is not found, fallback to CAIRO
   if(${NS3_INT64X64} MATCHES "INT128")
     check_cxx_source_compiles(
-      "#include <stdint.h>
+      "#include <cstdint>
        int main()
          {
-            if ((uint128_t *) 0) return 0;
             if (sizeof (uint128_t)) return 0;
             return 1;
          }"
       HAVE_UINT128_T
     )
     check_cxx_source_compiles(
-      "#include <stdint.h>
+      "#include <cstdint>
        int main()
          {
-           if ((__uint128_t *) 0) return 0;
            if (sizeof (__uint128_t)) return 0;
            return 1;
         }"
@@ -1129,14 +1122,11 @@
 
   # Check for required headers and functions, set flags if they're found or warn
   # if they're not found
-  check_include_file("stdint.h" "HAVE_STDINT_H")
-  check_include_file("inttypes.h" "HAVE_INTTYPES_H")
-  check_include_file("sys/types.h" "HAVE_SYS_TYPES_H")
-  check_include_file("sys/stat.h" "HAVE_SYS_STAT_H")
-  check_include_file("dirent.h" "HAVE_DIRENT_H")
-  check_include_file("stdlib.h" "HAVE_STDLIB_H")
-  check_include_file("signal.h" "HAVE_SIGNAL_H")
-  check_include_file("netpacket/packet.h" "HAVE_PACKETH")
+  check_include_file_cxx("sys/types.h" "HAVE_SYS_TYPES_H")
+  check_include_file_cxx("sys/stat.h" "HAVE_SYS_STAT_H")
+  check_include_file_cxx("dirent.h" "HAVE_DIRENT_H")
+  check_include_file_cxx("signal.h" "HAVE_SIGNAL_H")
+  check_include_file_cxx("netpacket/packet.h" "HAVE_PACKETH")
   check_function_exists("getenv" "HAVE_GETENV")
 
   configure_file(
@@ -1177,6 +1167,15 @@
     set(ENABLE_TAP OFF)
     set(ENABLE_EMU OFF)
     set(ENABLE_FDNETDEV FALSE)
+    mark_as_advanced(
+      ENABLE_FDNETDEV ENABLE_DPDKDEVNET ENABLE_TAPNETDEV ENABLE_EMUNETDEV
+      ENABLE_NETMAP_EMU
+    )
+    set(ENABLE_FDNETDEV False CACHE INTERNAL "")
+    set(ENABLE_DPDKDEVNET False CACHE INTERNAL "")
+    set(ENABLE_TAPNETDEV False CACHE INTERNAL "")
+    set(ENABLE_EMUNETDEV False CACHE INTERNAL "")
+    set(ENABLE_NETMAP_EMU False CACHE INTERNAL "")
     list(REMOVE_ITEM libs_to_build fd-net-device)
     message(
       STATUS
@@ -1225,7 +1224,7 @@
         ${HIGHLIGHTED_STATUS}
         "Clang-tidy is incompatible with precompiled headers. Continuing without them."
       )
-    elseif(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
+    else()
       # If ccache is not enable or was not found, we can continue with
       # precompiled headers
       if((NOT ${NS3_CCACHE}) OR ("${CCACHE}" STREQUAL "CCACHE-NOTFOUND"))
@@ -1255,11 +1254,6 @@
           )
         endif()
       endif()
-    else()
-      message(
-        STATUS
-          "CMake ${CMAKE_VERSION} does not support precompiled headers. Continuing without them"
-      )
     endif()
   endif()
 
@@ -1287,13 +1281,13 @@
         <limits>
         <list>
         <map>
-        <math.h>
+        <cmath>
         <ostream>
         <queue>
         <set>
         <sstream>
-        <stdint.h>
-        <stdlib.h>
+        <cstdint>
+        <cstdlib>
         <string>
         <tuple>
         <typeinfo>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/.ns3rc-template ns-3.46/build-support/.ns3rc-template
--- ns-3.45/build-support/.ns3rc-template	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/build-support/.ns3rc-template	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,21 @@
+# A list of the modules that will be enabled when ns-3 is run.
+# Modules that depend on the listed modules will be enabled also.
+#
+# All modules can be enabled by emptying the list.
+set(ns3rc_enabled_modules @ns3rc_enabled_modules@)
+
+# A list of the modules that will be disabled when ns-3 is run.
+# Modules that depend on the listed modules will be disabled also.
+#
+# If the list is empty, no module will be disabled.
+set(ns3rc_disabled_modules @ns3rc_disabled_modules@)
+
+# Set this equal to ON if you want examples to be run.
+set(ns3rc_examples_enabled @ns3rc_examples_enabled@)
+
+# Set this equal to ON if you want tests to be run.
+set(ns3rc_tests_enabled @ns3rc_tests_enabled@)
+
+# Override other ns-3 settings by setting their values below
+# Note: command-line settings will also be overridden.
+#set(NS3_LOG ON)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/build-support/test-clang17-stdlibcpp-map.cc ns-3.46/build-support/test-clang17-stdlibcpp-map.cc
--- ns-3.45/build-support/test-clang17-stdlibcpp-map.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/build-support/test-clang17-stdlibcpp-map.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,12 @@
+#include <iostream>
+#include <map>
+#include <tuple>
+
+int
+main()
+{
+    std::map<std::tuple<int, int>, int> testMap;
+    testMap[{1, 1}] = 2;
+    std::cout << testMap.at({1, 1}) << std::endl;
+    return 0;
+}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/CHANGES.md ns-3.46/CHANGES.md
--- ns-3.45/CHANGES.md	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/CHANGES.md	2025-10-01 18:46:49.000000000 -0700
@@ -12,6 +12,50 @@
 
 This file is a best-effort approach to solving this issue; we will do our best but can guarantee that there will be things that fall through the cracks, unfortunately. If you, as a user, can suggest improvements to this file based on your experience, please contribute a patch or drop us a note on ns-developers mailing list.
 
+## Changes from ns-3.45 to ns-3.46
+
+### New API
+
+* (spectrum) Added the base `WraparoundModel`, which is retrieved from the associated objects of a spectrum channel, and then used to wraparound the transmitter mobility model during transmissions.
+* (spectrum) Added the `HexagonalWraparoundModel`, which implements the wraparound for a hexagonal cell deployment, typical of cellular networks.
+* (wifi) Added a `StaticWifiSetupHelper` to (optionally) setup Wi-Fi devices (associations, block ack agreements, EMLSR mode) at simulation start time, without actually exchanging management frames over the air.
+to DisableScanning` attribute to `StaWifiMac` to disable channel scanning; it can be useful to set this attribute to false when a static setup is performed.
+* (wifi) Added a new `EarlyTxopEndDetect` attribute to `EhtFrameExchangeManager` to control whether the Duration/ID value of the frame being transmitted or received by a device shall be used to early detect the end of an ongoing TXOP (held by another device).
+* (wifi) Added a new `DisableScanning` attribute to `StaWifiMac` to disable channel scanning; it can be useful to set this attribute to false when a static setup is performed.
+
+### Changes to existing API
+
+The wimax module was removed and moved to the ns-3 App Store.
+
+* (antenna) Reformatted documentation.
+* (documentation) Improve models documentation look and feel.
+* (internet) Added check for longest prefix match in GlobalRouting.
+* (lr-wpan) Debloat MAC PD-DATA.indication and reduce packet copies.
+* (zigbee) Added group table.
+* (zigbee) Added Groupcast (Multicast) support.
+* (zigbee) Added basic APS layer support.
+* (mobility) Mobility models now implement a Copy() function.
+* (propagation) MatrixPropagationLossModels are now associated per NodeId, and not per mobility model objects.
+* (propagation) Removed ThreeGppPropagationLossModel prologue function, added temporarily for ns-3.45 wraparound support.
+* (spectrum) MobilityModels associated to devices are not passed to receptor in SpectrumChannel. A virtual mobility model object, created from a copy and subject to wraparound is passed in its place.
+* (spectrum) SpectrumSignalParameters now includes an entry for the transmitter virtual mobility model.
+* (zigbee) Several callback type definitions were moved from global to class scope, for the ZigbeeAps and ZigbeeNwk classes.
+
+### Changes to build system
+
+* Raised minimum C++ version from C++20 to C++23.
+* Raised minimum CMake version from 3.13 to 3.20.
+* Raised minimum Clang version from 11 to 17.
+* Raised minimum GCC version from 10.1 to 11.0.
+* Added support for ClangCL compiler (part of MSVC tools).
+* Added ``GENERATE_EXPORT_HEADER`` flag to the CMake ``build_lib`` macro. It will generate a ``ns3/module-export.h`` header file, which defines a C++ macro``MODULE_EXPORT``. The macro must be used when declaring a class with static member variables, or a global variable exported by a library.
+
+### Changed behavior
+
+* (internet) ArpCache::Flush() and NdiscCache::Flush() no longer remove autogenerated entries.
+* (internet) The Ipv[4,6]RawSocket now reflects the Linux implementation, meaning that fragmented packets are reassembled (fragments are not anymore received by the socket), and packets that are simply forwarded are not received by the socket either (fixes #809).
+* (wifi) WiFi backoffs are now reset only if PHY went to sleep or off for more than a threshold, improving performance and compliance with standards.
+
 ## Changes from ns-3.44 to ns-3.45
 
 ### New API
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/.clang-format ns-3.46/.clang-format
--- ns-3.45/.clang-format	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/.clang-format	2025-10-01 18:46:32.000000000 -0700
@@ -4,12 +4,11 @@
 
 AllowAllArgumentsOnNextLine: false
 AllowAllParametersOfDeclarationOnNextLine: false
-AlwaysBreakAfterReturnType: TopLevelDefinitions
-AlwaysBreakTemplateDeclarations: Yes
 BinPackArguments: false
 BinPackParameters: false
+BreakAfterReturnType: TopLevelDefinitions
+BreakTemplateDeclarations: Yes
 ColumnLimit: 100
-DeriveLineEnding: false
 IncludeBlocks: Regroup
 IncludeCategories:
   - Regex: '^(<|")ns3/'
@@ -22,7 +21,12 @@
     Priority: 1
     SortPriority: 0
 InsertBraces: true
-KeepEmptyLinesAtTheStartOfBlocks: false
+InsertNewlineAtEOF: true
+KeepEmptyLines:
+  AtEndOfFile: false
+  AtStartOfBlock: false
+  AtStartOfFile: false
+LineEnding: LF
 PackConstructorInitializers: Never
 PointerAlignment: Left
 QualifierAlignment: Left
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/CMakeLists.txt ns-3.46/CMakeLists.txt
--- ns-3.45/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -1,19 +1,19 @@
 # ##############################################################################
 # Required CMake version            #
 # ##############################################################################
-cmake_minimum_required(VERSION 3.13..3.13)
+cmake_minimum_required(VERSION 3.20..3.20)
 
 # ##############################################################################
 # Project name                        #
 # ##############################################################################
-project(NS3 CXX C)
+project(NS3 CXX)
 
 file(STRINGS VERSION NS3_VER)
 
 # minimum compiler versions
-set(AppleClang_MinVersion 13.1.6)
-set(Clang_MinVersion 11.0.0)
-set(GNU_MinVersion 10.1.0)
+set(AppleClang_MinVersion 15.0.0)
+set(Clang_MinVersion 17.0.0)
+set(GNU_MinVersion 11.0.0)
 
 # common options
 option(NS3_ASSERT "Enable assert on failure" OFF)
@@ -101,7 +101,7 @@
     CACHE STRING "List of modules to enable (e.g. core;network;internet)"
 )
 set(NS3_DISABLED_MODULES "" CACHE STRING
-                                  "List of modules to disable (e.g. lte;wimax)"
+                                  "List of modules to disable (e.g. lte;wifi)"
 )
 
 # Filter in the modules from which examples and tests will be built
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/contrib/.gitignore ns-3.46/contrib/.gitignore
--- ns-3.45/contrib/.gitignore	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/contrib/.gitignore	1969-12-31 16:00:00.000000000 -0800
@@ -1,5 +0,0 @@
-# Ignore everything by default, contrib sources are coming from other places
-*
-
-# Include specific files that should be tracked by Git
-!.gitignore
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/CONTRIBUTING.md ns-3.46/CONTRIBUTING.md
--- ns-3.45/CONTRIBUTING.md	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/CONTRIBUTING.md	2025-10-01 18:46:32.000000000 -0700
@@ -286,4 +286,3 @@
 | `visualizer` | Any issue related to this module |
 | `wave module` | Any issue related to this module |
 | `wifi` | Any issue related to this module |
-| `wimax` | Any issue related to this module |
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/figures/README ns-3.46/doc/contributing/figures/README
--- ns-3.45/doc/contributing/figures/README	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/contributing/figures/README	1969-12-31 16:00:00.000000000 -0800
@@ -1,18 +0,0 @@
-Please write image files in a vector graphics format, when possible, and
-generate the .png and .pdf versions on the fly (see ../Makefile).  
-
-The currently supported tool is dia.  xfig could be added similarly
-if someone wants to add it.  The main requirement for adding another format
-is that the tool to edit it is freely available and that a cron script can 
-autogenerate the pdf and png from the figure source.  Tgif (.obj) files
-were once used but the file conversions require a valid X display to 
-be running, and are therefore to be avoided since our code server 
-does not run such a server.  Tgif pdf conversions were also cumbersome.
-
-Store the .dia versions in git, but not the .png or .pdfs.  
-If the figure is not available in a vector graphics format, store both
-a .png and a .pdf version in this directory.
-
-If you add a source (.dia) file here, remember to add it to
-the list of figure sources in the Makefile in the directory above
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/Makefile ns-3.46/doc/contributing/Makefile
--- ns-3.45/doc/contributing/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/contributing/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,23 +1,11 @@
 # Makefile for Sphinx documentation
 #
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
+include $(CURDIR)/../sphinx/defines.mk
 
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
 
 # Additional variables for figures, not sphinx default:
-DIA = dia
-EPSTOPDF = epstopdf
 FIGURES = source/figures
 IMAGES_EPS = \
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/source/best-practices.rst ns-3.46/doc/contributing/source/best-practices.rst
--- ns-3.45/doc/contributing/source/best-practices.rst	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/doc/contributing/source/best-practices.rst	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,98 @@
+.. include:: replace.txt
+.. heading hierarchy:
+   ------------- Chapter
+   ************* Section (#.#)
+   ============= Subsection (#.#.#)
+   ############# Paragraph (no number)
+
+.. _Best practices:
+
+Best practices
+--------------
+
+When writing code to be contributed to the |ns3| open source project, we
+recommend following the best practices listed below.
+These practices apply to different phases of software development and testing,
+and are organized according to the typical application lifecycle.
+
+Development phase
+*****************
+
+Refactor-or-die: Preliminary refactoring before introducing functional changes
+==============================================================================
+
+As presented in Mikhail Matrosov's "Refactor or die" talk in CppCon 2017 [`1`_], mixing refactoring and functional
+changes is a bad practice.
+
+It is considered a bad practice because refactoring may involve a lot
+of different files, classes, API changes to accommodate new parameters, for example.
+If a functional change is mixed in between, there is a higher
+probability of introducing a bug. This results in more code to inspect and debug
+to isolate and fix the bug. Which translates to unproductive work to isolate and
+fix the bug, which results in extra hours, working on weekends, etc, etc.
+
+The figure below depicts the scope differences in refactoring and functional changes.
+
+.. figure:: figures/cppcon2017-refactorOrDie-scope.png
+    :align: center
+
+    Impact of different scope changes (inverted triangle), and scopes affected
+    by refactoring and functional changes. [`1`_]
+
+This is why refactoring should be done as a preliminary step,
+before functional changes. This will drastically reduce the number
+of lines of code which may have introduced a potential bug,
+saving development/maintenance time in the long run.
+
+The figure below depicts the effects of mixed refactoring AND functional changes (left orange rectangle),
+versus the preliminary refactoring (right green rectangle) PLUS functional changes (right orange rectangle).
+
+.. figure:: figures/cppcon2017-refactorOrDie-probabilityOfBug.png
+    :align: center
+
+    Assume the existence of a bug kills you. If you mix functional and refactoring changes, the number
+    of lines potentially containing a bug increases. As such, the probability of dying is unnecessarily
+    augmented. If you do not mix these changes, the probability of dying is significantly reduced. [`1`_]
+
+Compile-or-die: Individual commit compilation and testing
+#########################################################
+
+Since preliminary refactoring is not always trivial, due to the potentially unknown requirements,
+it is very unlikely to completely avoid mixing refactoring and functional changes.
+However, these changes can and should be separated before merging them upstream.
+
+This can be achieved through commit history rewriting, which can also introduce new bugs,
+if commits are not properly rewritten.
+
+A suggested practice is to at least compile and run tests for every single commit
+in the branch before merging it. This can be accomplished by checking out each commit,
+hard-resetting to that commit, reconfiguring the project and running test.py.
+
+This can be done automatically using `./ns3 --compile-or-die base_commit head_commit`.
+
+Note: ALWAYS back up your ns-3 directory and sync your local branches with the remote server.
+
+.. sourcecode:: console
+
+    ~ns-3-dev/$ ./ns3 --compile-or-die 757a2bfc2abb5f3584593609434c40e5ac678e8e 5a30398332d70646279285a2ef8997cea0ed9e43
+    Compile-or-die with commits: ['757a2bfc2abb5f3584593609434c40e5ac678e8e', '5a30398332d70646279285a2ef8997cea0ed9e43']
+            Testing commit 757a2bfc2abb5f3584593609434c40e5ac678e8e
+            Testing commit 5a30398332d70646279285a2ef8997cea0ed9e43
+
+In case there are uncommitted changes, the script won't continue to prevent potential data loss.
+In case there is no associated branch with the current git head, a backup branch will be created
+to prevent data loss.
+Then it will create a new temporary test branch, that will be used to checkout and test each
+commit between base and head commits.
+
+If there is no error message, all commits succeed. Which only means there is no issue preventing
+compilation or causing one of the existing tests to fail. That is, we have anecdotal evidence that
+refactoring was done correctly.
+
+Two branches are created automatically: the current HEAD is tagged as ``compileOrDieBackup`` if not currently tagged,
+and the commit being currently tested is tagged as ``compileOrDieTest``. These won't be cleaned automatically to
+prevent potential data loss. So users should verify and delete tags manually.
+
+.. _1:
+
+[1] Mikhail Matrosov. Refactor or die. CppCon 2017. Available in `YouTube <https://youtu.be/fzmjXK9JZ9o>`_.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/source/coding-style.rst ns-3.46/doc/contributing/source/coding-style.rst
--- ns-3.45/doc/contributing/source/coding-style.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/contributing/source/coding-style.rst	2025-10-01 18:46:32.000000000 -0700
@@ -29,9 +29,37 @@
 Clang-format installation
 =========================
 
-Clang-format can be installed using your OS's package manager. Please note that you
-should install one of the supported versions of clang-format, which are listed in the
-following section.
+Clang-format can be installed using one of two methods.
+Please note that you should install one of the supported versions of clang-format,
+which are listed in the ``RELEASE_NOTES.md`` file.
+
+The first method is to install clang-format using the package manager available in the
+Linux distribution (e.g., Ubuntu's ``apt``).
+For example, in Ubuntu 24.04, clang-format 20 can be installed with the following command:
+
+.. sourcecode:: console
+
+  sudo apt install clang-format-20
+
+If the package manager does not provide one of the clang-format versions supported by |ns3|,
+users can install clang-format using Python's pip tool.
+
+The following command will install the latest version of clang-format:
+
+.. sourcecode:: console
+
+  pip3 install clang-format
+
+To install a specific version of clang-format, use the following command:
+
+.. sourcecode:: console
+
+  pip3 install clang-format==<version_number>
+
+where ``<version_number>`` is something like ``20.1.8`` (MAJOR.MINOR.PATCH).
+
+Starting with Python 3.11, pip requires users to either create a virtual environment (venv)
+or add the ``--break-system-packages`` flag to the installation commands above.
 
 Supported versions of clang-format
 ==================================
@@ -40,14 +68,8 @@
 newer versions of clang-format might produce different outputs compared to
 previous versions.
 
-The following list contains the set of clang-format versions that are verified
-to produce consistent output among themselves.
-
-* clang-format-19
-* clang-format-18
-* clang-format-17
-* clang-format-16
-* clang-format-15
+The list of clang-format versions that are verified to produce consistent output
+among themselves are listed in the ``RELEASE_NOTES.md`` document.
 
 Integration with IDEs
 =====================
@@ -57,10 +79,11 @@
 
 Please refer to the documentation of your IDE for more information.
 Some examples of IDE integration are provided in
-`clang-format documentation <https://clang.llvm.org/docs/ClangFormat.html>`_
+`clang-format documentation <https://clang.llvm.org/docs/ClangFormat.html>`_.
 
-As an example, VS Code can be configured to automatically format code on save, on paste
-and on type by enabling the following settings:
+As an example, VS Code's `C/C++ extension <https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools>`_
+contains the latest clang-format binary.
+VS Code can be configured to automatically format code on save, on paste and on type by enabling the following settings:
 
 .. sourcecode:: json
 
@@ -1911,73 +1934,79 @@
 Markdown Lint
 *************
 
-.. _Markdownlint: https://github.com/markdownlint/markdownlint
-.. _Markdownlint Rules: https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md
-.. _Markdownlint Configuration Style File: https://github.com/markdownlint/markdownlint/blob/main/docs/creating_styles.md
-.. _Markdownlint Docker Hub: https://hub.docker.com/r/markdownlint/markdownlint
-.. _Markdownlint Docker Instructions: https://github.com/markdownlint/markdownlint/tree/main/tools/docker
-.. _Markdownlint VS Code Extension: https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
+.. _MarkdownLint: https://github.com/DavidAnson/MarkdownLint
+.. _MarkdownLint Rules: https://github.com/DavidAnson/MarkdownLint/blob/main/doc/Rules.md
+.. _MarkdownLint Installation: https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#installation
+.. _MarkdownLint Configuration File: https://github.com/DavidAnson/MarkdownLint/blob/main/schema/.MarkdownLint.yaml
+.. _MarkdownLint Docker: https://github.com/igorshubovych/MarkdownLint-cli/pkgs/container/MarkdownLint-cli
+.. _MarkdownLint VS Code Extension: https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-MarkdownLint
 
-|ns3| uses `Markdownlint`_ as a linter of Markdown files.
+|ns3| uses `MarkdownLint`_ as a linter of Markdown files.
 This linter checks if Markdown files follow a set of defined rules, in order to encourage
 standardization and consistency of Markdown files across parsers.
 It also ensures that Markdown files are correctly interpreted and rendered.
 
-Markdownlint detects linting issues, but it can not fix them automatically.
-The issues must be fixed manually.
+MarkdownLint detects linting issues and can fix most of them automatically.
+Some issues may need to be manually fixed.
 
-Markdownlint configuration
+MarkdownLint configuration
 ==========================
 
-Markdownlint's settings are saved in the file ``.mdl_style.rb``.
-This file is defined in `Markdownlint Configuration Style File`_, which explains how to
-customize the tool to enable / disable rules or customize its parameters.
+MarkdownLint's settings are saved in the file ``.markdownlint.yml``.
+This schema of this file is defined in `MarkdownLint Configuration File`_,
+which explains how to customize the tool to enable / disable rules or customize its parameters.
 
-The list of Markdown rules supported by Markdownlint is available in `Markdownlint Rules`_.
+The list of Markdown rules supported by MarkdownLint is available in `MarkdownLint Rules`_.
 
-Install and Run Markdownlint
+Install and Run MarkdownLint
 ============================
 
-Markdownlint is written in Ruby. To run Markdownlint, either use the official
-Markdownlint Docker image or install Ruby and Markdownlint.
+MarkdownLint is written in NodeJS. To run MarkdownLint, either use the official
+MarkdownLint Docker image, install it natively in macOS via Homebrew,
+or install MarkdownLint with NodeJS / npm.
 
-Run Markdownlint with Docker image
+Run MarkdownLint with Docker image
 ##################################
 
-Markdownlint has an official Docker image in `Markdownlint Docker Hub`_ with the tool
+MarkdownLint has an official Docker image in `MarkdownLint Docker`_ with the tool
 and all dependencies installed.
-The instructions to use the Docker image are available in `Markdownlint Docker Instructions`_.
 
-To run Markdownlint in a Docker container, use the following command:
+To run MarkdownLint in a Docker container, use the following command:
 
 .. sourcecode:: console
 
-  docker run -v .:/data markdownlint/markdownlint -s .mdl_style.rb .
+  # Check all Markdown files in the current directory and subdirectories
+  docker run --rm -v $PWD:/workdir ghcr.io/igorshubovych/markdownlint-cli:latest . [--fix]
 
-Install and Run Markdownlint with Ruby
-######################################
+  # Check specific Markdown file
+  docker run --rm -v $PWD:/workdir ghcr.io/igorshubovych/markdownlint-cli:latest PATH_TO_FILE [--fix]
 
-To install Markdownlint natively, you need to have Ruby installed in your system.
-Check the installation instructions in the Ruby's official documentation.
+If the ``fix`` flag is used, the tool tries to automatically fix the detected issues.
+Otherwise, it only reports the issues found.
 
-After installing Ruby in your system, install Markdownlint using the following command:
+Install and Run MarkdownLint natively
+#####################################
 
-.. sourcecode:: console
+To install MarkdownLint natively, either on macOS via Homebrew or using NodeJS / npm,
+follow the instructions available in `MarkdownLint Installation`_.
 
-  gem install mdl
-
-To run Markdownlint and check Markdown files for linting issues, run Markdownlint
-using the following command:
+To run MarkdownLint, use the following command:
 
 .. sourcecode:: console
 
-  mdl -s .mdl_style.rb .
+  # Check all Markdown files in the current directory and subdirectories
+  markdownlint-cli . [--fix]
+
+  # Check specific Markdown file
+  markdownlint-cli PATH_TO_FILE [--fix]
 
 VS Code Extension
 =================
 
-For VS Code users, the `Markdownlint VS Code Extension`_ extension is available in the marketplace.
-This extension is inspired in `Markdownlint`_ and follows the same set of rules.
+For VS Code users, the `MarkdownLint VS Code Extension`_ extension is available in the marketplace.
+This extension uses the same engine and respects the configuration file.
 
-The Markdownlint extension automatically analyzes files open in the editor and provides inline hints
+The MarkdownLint extension automatically analyzes files open in the editor and provides inline hints
 when issues are detected. It can automatically fix most issues related with formatting.
+As explained in the "Integration with IDEs" section, VS Code can be configured to automatically
+format code when saving, editing or pasting code.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/source/conf.py ns-3.46/doc/contributing/source/conf.py
--- ns-3.45/doc/contributing/source/conf.py	2025-06-01 20:35:04.000000000 -0700
+++ ns-3.46/doc/contributing/source/conf.py	2025-10-01 18:46:49.000000000 -0700
@@ -49,9 +49,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = "ns-3.45"
+version = "ns-3.46"
 # The full version, including alpha/beta/rc tags.
-release = "ns-3.45"
+release = "ns-3.46"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/source/index.rst ns-3.46/doc/contributing/source/index.rst
--- ns-3.45/doc/contributing/source/index.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/contributing/source/index.rst	2025-10-01 18:46:32.000000000 -0700
@@ -32,3 +32,4 @@
    models
    external
    coding-style
+   best-practices
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/contributing/source/models.rst ns-3.46/doc/contributing/source/models.rst
--- ns-3.45/doc/contributing/source/models.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/contributing/source/models.rst	2025-10-01 18:46:32.000000000 -0700
@@ -337,7 +337,7 @@
 
 Examples
 ~~~~~~~~
-For many submissions, it will be important to include at least one example that exercises the new code, so the reviewer understands how it is intended to be used. For final submission, please consider to add as many examples as you can that will help new users of your code. The <tt>samples/</tt> and <tt>examples/</tt> directories are places for these files.
+For many submissions, it will be important to include at least one example that exercises the new code, so the reviewer understands how it is intended to be used. For final submission, please consider to add as many examples as you can that will help new users of your code. The ``samples/`` and ``examples/`` directories are places for these files.
 
 Tests
 ~~~~~
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/doxygen.conf ns-3.46/doc/doxygen.conf
--- ns-3.45/doc/doxygen.conf	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/doxygen.conf	2025-10-01 18:46:32.000000000 -0700
@@ -2299,12 +2299,10 @@
                          ATTRIBUTE_VALUE_IMPLEMENT_WITH_NAME \
                          NS_UNUSED_GLOBAL \
                          NS_DEPRECATED \
+                         NS_DEPRECATED_3_46 \
                          NS_DEPRECATED_3_45 \
                          NS_DEPRECATED_3_44 \
-                         NS_DEPRECATED_3_43 \
-                         NS_DEPRECATED_3_42 \
-                         NS_DEPRECATED_3_41 \
-                         NS_DEPRECATED_3_40
+                         NS_DEPRECATED_3_43
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
 # remove all references to function-like macros that are alone on a line, have
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/installation/Makefile ns-3.46/doc/installation/Makefile
--- ns-3.45/doc/installation/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/installation/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,23 +1,11 @@
 # Makefile for Sphinx documentation
 #
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
+include $(CURDIR)/../sphinx/defines.mk
 
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
 
 # Additional variables for figures, not sphinx default:
-DIA = dia
-EPSTOPDF = epstopdf
 FIGURES = source/figures
 IMAGES_EPS = \
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/installation/source/conf.py ns-3.46/doc/installation/source/conf.py
--- ns-3.45/doc/installation/source/conf.py	2025-06-01 20:35:04.000000000 -0700
+++ ns-3.46/doc/installation/source/conf.py	2025-10-01 18:46:49.000000000 -0700
@@ -49,9 +49,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = "ns-3.45"
+version = "ns-3.46"
 # The full version, including alpha/beta/rc tags.
-release = "ns-3.45"
+release = "ns-3.46"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/installation/source/linux.rst ns-3.46/doc/installation/source/linux.rst
--- ns-3.45/doc/installation/source/linux.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/installation/source/linux.rst	2025-10-01 18:46:32.000000000 -0700
@@ -21,8 +21,10 @@
 Requirements
 ************
 
-The minimum supported version of Ubuntu is Ubuntu 18.04 LTS (as long as a modern compiler
-version such as g++ version 9 or later is added).
+The minimum supported version of Ubuntu is Ubuntu 22.04 LTS.  Older versions may also be
+suitable as long as the C++ compiler version is relatively recent.  As of the ns-3.46
+release, g++ version 11 or later is required (or clang++ version 17 or later).
+Older ns-3 releases may work with older versions of g++; check the RELEASE_NOTES.md file.
 
 +--------------------+---------------------------------------------------------------------+
 | **ns-3 Version**   | **apt Packages**                                                    |
@@ -34,10 +36,6 @@
 | 3.29 and earlier   | ``g++ python2``                                                     |
 +--------------------+---------------------------------------------------------------------+
 
-.. note::
-  As of July 2023 (ns-3.39 release and later), the minimum g++ version is g++-9.
-  Older ns-3 releases may work with older versions of g++; check the RELEASE_NOTES.
-
 Recommended
 ***********
 
@@ -58,7 +56,18 @@
   installed using apt.
 
 .. note::
-  clang-format-14 through clang-format-16 version is required.
+  Different versions of ns-3 use different versions of clang-format, resulting in
+  slightly different formatting decisions.  The ``check-style-clang-format.py``
+  file enforces a minimum and maximum major version of clang-format with which the
+  current codebase is compatible.  Since the ns-3.46 release, please consult the
+  ``RELEASE_NOTES.md`` file for the currently supported versions.
+  For some additional information about installing and using clang-format, please see the
+  `ns-3 coding style section <https://www.nsnam.org/docs/contributing/html/coding-style.html#clang-format>`_
+  on clang-format.
+
+.. note::
+  Different versions of ns-3 use different versions of clang-tidy.  Since the ns-3.46
+  release, see the ``RELEASE_NOTES.md`` file for the currently supported versions.
 
 Optional
 ********
@@ -104,9 +113,13 @@
 ===============
 
 Python requires `Cppyy, <https://cppyy.readthedocs.io/en/latest/installation.html>` and specifically,
-version 3.1.2 is the latest version known to work with ns-3 at this time.
+version 3.5.0 is the latest version known to work with ns-3 at this time.
+
+ns-3.45 and newer::
+
+  python3 -m pip install --user cppyy==3.5.0
 
-ns-3.42 and newer::
+ns-3.42-3.44::
 
   python3 -m pip install --user cppyy==3.1.2
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/installation/source/quick-start.rst ns-3.46/doc/installation/source/quick-start.rst
--- ns-3.45/doc/installation/source/quick-start.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/installation/source/quick-start.rst	2025-10-01 18:46:32.000000000 -0700
@@ -139,7 +139,7 @@
   sixlowpan                 spectrum                  stats
   tap-bridge                test                      topology-read
   traffic-control           uan                       virtual-net-device
-  wifi                      wimax
+  wifi
 
   Modules that cannot be built:
   brite                     click                     mpi
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/Makefile ns-3.46/doc/manual/Makefile
--- ns-3.45/doc/manual/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,6 +1,4 @@
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
+include $(CURDIR)/../sphinx/defines.mk
 
 SRC = ../../src
 # Temporary source directory, for build
@@ -45,6 +43,7 @@
 	source/tracing.rst \
 	source/troubleshoot.rst \
 	source/utilities.rst \
+	source/working-with-cilicon.rst \
 	source/working-with-cmake.rst \
 	source/working-with-docker.rst \
 	source/working-with-git.rst \
@@ -64,7 +63,8 @@
 # documentation formats (html, latex...) the following formats are supported:
 #  1) a single .dia file (preferred option, because it can be edited)
 #  2) a single .eps file
-#  3) both a .pdf and .png file
+#  3) a single .png file
+#  4) both a .pdf and .png file
 
 SOURCEFIGS = \
     figures/software-organization.dia \
@@ -139,15 +139,7 @@
 	@$(EPSTOPDF) $< -o=$@ >/dev/null
 	@if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
 
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCETEMP)
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/attributes.rst ns-3.46/doc/manual/source/attributes.rst
--- ns-3.45/doc/manual/source/attributes.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/attributes.rst	2025-10-01 18:46:32.000000000 -0700
@@ -788,12 +788,20 @@
 checking *when the attribute is used* (*cf*. ``NS_ASSERT_MSG``
 or ``NS_ABORT_MSG``).
 
-In general, the attribute code to assign values to the underlying class member
-variables is executed after an object is constructed. But what if you need the
-values assigned before the constructor body executes, because you need them in
-the logic of the constructor? There is a way to do this, used for example in the
-class :cpp:class:`ConfigStore`: call :cpp:func:`ObjectBase::ConstructSelf()` as
-follows::
+For classes deriving from the :cpp:class:`Object` class, the attribute code to assign initial
+values to the underlying class member variables is executed after an object is constructed.
+Therefore, you cannot access the values assigned to the attributes of an object from within
+its constructor. Instead, you can override :cpp:func:`ObjectBase::NotifyConstructionCompleted()`
+and access the values assigned to the attributes of the object from within that function.
+A practical example of how this is used can be found in the ns-3 class :cpp:class:`RttEstimator`
+in the `internet` module.
+
+For classes deriving directly from :cpp:class:`ObjectBase`, it is instead needed to explicitly
+call :cpp:func:`ObjectBase::ConstructSelf()` to assign initial values to the class attributes.
+Such a call can be made in the class constructor, in which case the values assigned to the
+attributes are accessible from within its constructor. There are not many examples of this usage
+in the ns-3 codebase because most classes with attributes typically derive from :cpp:class:`Object`.
+One example is the :cpp:class:`ConfigStore` class, whose constructor is shown as follows::
 
     ConfigStore::ConfigStore()
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/conf.py ns-3.46/doc/manual/source/conf.py
--- ns-3.45/doc/manual/source/conf.py	2025-06-01 20:35:04.000000000 -0700
+++ ns-3.46/doc/manual/source/conf.py	2025-10-01 18:46:49.000000000 -0700
@@ -74,9 +74,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = "ns-3.45"
+version = "ns-3.46"
 # The full version, including alpha/beta/rc tags.
-release = "ns-3.45"
+release = "ns-3.46"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/develop.rst ns-3.46/doc/manual/source/develop.rst
--- ns-3.45/doc/manual/source/develop.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/develop.rst	2025-10-01 18:46:32.000000000 -0700
@@ -18,3 +18,4 @@
    profiling
    working-with-gitlab-ci-local
    working-with-docker
+   working-with-cilicon
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/documentation.rst ns-3.46/doc/manual/source/documentation.rst
--- ns-3.45/doc/manual/source/documentation.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/documentation.rst	2025-10-01 18:46:32.000000000 -0700
@@ -403,7 +403,6 @@
     Count Directory
     ----- ----------------------------------
     3414 src/lte/model
-    1532 src/wimax/model
      825 src/lte/test
     ....
        1 src/applications/test
@@ -434,7 +433,6 @@
      272 src/core/model/simulator.h
      221 src/netanim/model/animation-interface.h
     ....
-       1 src/wimax/model/ul-job.cc
     ----------------------------------------
        771 files with warnings
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/enable-tests.rst ns-3.46/doc/manual/source/enable-tests.rst
--- ns-3.45/doc/manual/source/enable-tests.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/enable-tests.rst	2025-10-01 18:46:32.000000000 -0700
@@ -12,40 +12,11 @@
 How to enable/disable examples and tests in |ns3|
 *************************************************
 
-There are 3 ways to enable/disable examples and tests in |ns3|:
+There are 2 ways to enable/disable examples and tests in |ns3|:
 
-#. Using build.py when |ns3| is built for the first time
 #. Using ns3 once |ns3| has been built
 #. Using the |ns3| configuration file once |ns3| has been built
 
-Enable/disable examples and tests using build.py
-++++++++++++++++++++++++++++++++++++++++++++++++
-
-You can use build.py to enable/disable examples and tests when |ns3| is built for the first time.
-
-By default, examples and tests are not built in |ns3|.
-
-From the ns-3-allinone directory, you can build |ns3| without any
-examples or tests simply by doing: ::
-
-  $ ./build.py
-
-Running test.py in the top level |ns3| directory now will cause no examples or tests to be run:
-
-.. sourcecode:: text
-
-  0 of 0 tests passed (0 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors)
-
-If you would like build |ns3| with examples and tests, then do the following from the ns-3-allinone directory: ::
-
-  $ ./build.py --enable-examples --enable-tests
-
-Running test.py in the top level |ns3| directory will cause all of the examples and tests to be run:
-
-.. sourcecode:: text
-
-  170 of 170 tests passed (170 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors)
-
 Enable/disable examples and tests using ns3
 +++++++++++++++++++++++++++++++++++++++++++
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/events.rst ns-3.46/doc/manual/source/events.rst
--- ns-3.45/doc/manual/source/events.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/events.rst	2025-10-01 18:46:32.000000000 -0700
@@ -370,6 +370,64 @@
 In the case of writing it is easy to choose the output unit, different
 from the resolution unit.
 
+Here are examples of common usage:
+
+.. sourcecode:: cpp
+
+    Time t1 = MilliSeconds(1500); // 1.5 s = 1500 ms
+    Time t2 = MicroSeconds(500);  // 500 microseconds
+    Time t3 = t1 + t2;            // arithmetic
+    Time t4 = t3 * 2;             // multiplication
+
+    if (t4 > Seconds(3))
+    {
+        std::cout << "t4 is greater than 3 seconds\n";
+    }
+
+    double ms = t4.GetMilliSeconds(); // convert to double in ms
+
+    std::cout << t4.As(Time::MS) << "\n"; // stream with specific unit
+
+.. note::
+
+   When using floating-point values with constructors like ``Seconds(1.5)``,
+   users should be aware that values smaller than the current resolution
+   will be rounded. For example, if the resolution is set to nanoseconds,
+   values like ``Seconds(1e-10)`` will be rounded to zero.
+   Consider inspecting ``Time::SetResolution()`` and using methods like
+   ``GetNanoSeconds()`` to understand how sub-resolution values behave in practice.
+
+When calling ``Time::SetResolution()``, there is a trade-off between
+the precision of time measurements and the maximum simulation time
+span that can be represented. Finer resolutions (like femtoseconds)
+allow for more precise timing but reduce the maximum representable
+duration.
+
+.. list-table::
+  :header-rows: 1
+  :widths: 25 25 50
+
+  * - Resolution Unit
+    - Smallest Step
+    - Approximate Max Time Span
+  * - Seconds
+    - 1 s
+    - ~2.9 × 10¹¹ years
+  * - Milliseconds
+    - 1 ms
+    - ~2.9 × 10⁸ years
+  * - Microseconds
+    - 1 µs
+    - ~2.9 × 10⁵ years
+  * - Nanoseconds
+    - 1 ns
+    - ~292 years
+  * - Picoseconds
+    - 1 ps
+    - ~107 days
+  * - Femtoseconds
+    - 1 fs
+    - ~2.6 hours
 
 Scheduler
 *********
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/profiling.rst ns-3.46/doc/manual/source/profiling.rst
--- ns-3.45/doc/manual/source/profiling.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/profiling.rst	2025-10-01 18:46:32.000000000 -0700
@@ -172,7 +172,7 @@
   * The adopted solution in merge request `MR703`_ was to fix one of the schedulers that could produce the index value of -1,
     and updating the asserts to catch the illegal index value.
 
-* A wrong downcast in the Wimax module:
+* A wrong downcast in the wimax module (note: wimax is no longer a module within the ns-3 mainline):
 
   * The pointer was casted incorrectly to U16TlvValue instead of U8TvlValue, which could have different sizes in memory
     leading to the program reading the wrong memory address.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/test-framework.rst ns-3.46/doc/manual/source/test-framework.rst
--- ns-3.45/doc/manual/source/test-framework.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/test-framework.rst	2025-10-01 18:46:32.000000000 -0700
@@ -101,49 +101,50 @@
 
 .. sourcecode:: text
 
-  Usage: test.py [options]
+  usage: test.py [-h] [-b BUILDPATH] [-c CONSTRAIN] [-d] [-e EXAMPLE] [-u]
+                 [-f {QUICK,EXTENSIVE,TAKES_FOREVER} | -of {QUICK,EXTENSIVE,TAKES_FOREVER}]
+                 [-g] [-k] [-l] [-m] [-n] [-p PYEXAMPLE] [-r] [-s SUITE] [-t TEXT-FILE]
+                 [-v] [--verbose-failed] [-w HTML-FILE] [-x XML-FILE] [--nocolor]
+                 [--jobs PROCESS_LIMIT] [--rerun-failed]
 
-  Options:
+  options:
     -h, --help            show this help message and exit
-    -b BUILDPATH, --buildpath=BUILDPATH
-                          specify the path where ns-3 was built (defaults to the
-                          build directory for the current variant)
-    -c KIND, --constrain=KIND
+    -b, --buildpath BUILDPATH
+                          specify the path where ns-3 was built (defaults to the build
+                          directory for the current variant)
+    -c, --constrain CONSTRAIN
                           constrain the test-runner by kind of test
-    -e EXAMPLE, --example=EXAMPLE
-                          specify a single example to run (no relative path is
-                          needed)
     -d, --duration        print the duration of each test suite and example
-    -e EXAMPLE, --example=EXAMPLE
-                          specify a single example to run (no relative path is
-                          needed)
-    -u, --update-data     If examples use reference data files, get them to re-
-                          generate them
-    -f FULLNESS, --fullness=FULLNESS
-                          choose the duration of tests to run: QUICK, EXTENSIVE,
-                          or TAKES_FOREVER, where EXTENSIVE includes QUICK and
-                          TAKES_FOREVER includes QUICK and EXTENSIVE (only QUICK
-                          tests are run by default)
+    -e, --example EXAMPLE
+                          specify a single example to run (no relative path is needed)
+    -u, --update-data     If examples use reference data files, get them to re-generate
+                          them
+    -f, --fullness {QUICK,EXTENSIVE,TAKES_FOREVER}
+                          choose the duration of tests to run: QUICK, EXTENSIVE, or
+                          TAKES_FOREVER, where EXTENSIVE includes QUICK and TAKES_FOREVER
+                          includes QUICK and EXTENSIVE (only QUICK tests are run by
+                          default)
+    -of, --only-fullness {QUICK,EXTENSIVE,TAKES_FOREVER}
+                          choose the duration of tests to run: QUICK, EXTENSIVE, or
+                          TAKES_FOREVER (only tests marked with fullness will be executed)
     -g, --grind           run the test suites and examples using valgrind
     -k, --kinds           print the kinds of tests available
     -l, --list            print the list of known tests
-    -m, --multiple        report multiple failures from test suites and test
-                          cases
-    -n, --nobuild           do not run ns3 before starting testing
-    -p PYEXAMPLE, --pyexample=PYEXAMPLE
-                          specify a single python example to run (with relative
-                          path)
-    -r, --retain          retain all temporary files (which are normally
-                          deleted)
-    -s TEST-SUITE, --suite=TEST-SUITE
-                          specify a single test suite to run
-    -t TEXT-FILE, --text=TEXT-FILE
-                          write detailed test results into TEXT-FILE.txt
+    -m, --multiple        report multiple failures from test suites and test cases
+    -n, --no-build        do not build before starting testing
+    -p, --pyexample PYEXAMPLE
+                          specify a single python example to run (with relative path)
+    -r, --retain          retain all temporary files (which are normally deleted)
+    -s, --suite SUITE     specify a single test suite to run
+    -t, --text TEXT-FILE  write detailed test results into TEXT-FILE.txt
     -v, --verbose         print progress and informational messages
-    -w HTML-FILE, --web=HTML-FILE, --html=HTML-FILE
+    --verbose-failed      print progress and informational messages for failed jobs
+    -w, --web, --html HTML-FILE
                           write detailed test results into HTML-FILE.html
-    -x XML-FILE, --xml=XML-FILE
-                          write detailed test results into XML-FILE.xml
+    -x, --xml XML-FILE    write detailed test results into XML-FILE.xml
+    --nocolor             do not use colors in the standard output
+    --jobs PROCESS_LIMIT  limit number of worker threads
+    --rerun-failed        rerun failed tests
 
 If one specifies an optional output style, one can generate detailed descriptions
 of the tests and status.  Available styles are ``text`` and ``HTML``.
@@ -266,10 +267,6 @@
 
 .. sourcecode:: text
 
-  Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
-  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
-  'build' finished successfully (0.939s)
-
   Test Type    Test Name
   ---------    ---------
   performance  many-uniform-random-variables-one-get-value-call
@@ -281,10 +278,11 @@
   system       devices-mesh-flame-regression
   system       epc-gtpu
   ...
-  unit         wimax-phy-layer
-  unit         wimax-service-flow
-  unit         wimax-ss-mac-layer
-  unit         wimax-tlv
+  unit         wifi-primary-channels
+  unit         wifi-ru-allocation
+  unit         wifi-spectrum-wifi-phy
+  unit         wifi-transmit-mask
+  unit         wifi-txop
   example      adhoc-aloha-ideal-phy
   example      adhoc-aloha-ideal-phy-matrix-propagation-loss-model
   example      adhoc-aloha-ideal-phy-with-microwave-oven
@@ -337,6 +335,40 @@
 
   PASS: Example examples/udp/udp-echo
 
+You can also execute all instances of declared examples using different parameters,
+as defined in ``examples-to-run.py`` by including a star at the end of the example name.
+
+::
+
+  $ ./test.py --example=wifi-phy-configuration*
+
+results in that example being run with the following parameters:
+
+.. sourcecode:: text
+
+  [1/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=0
+  [2/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=8
+  [3/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=10
+  [4/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=12
+  [5/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=1
+  [6/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=13
+  [7/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=4
+  [8/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=3
+  [9/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=14
+  [10/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=5
+  [11/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=15
+  [12/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=6
+  [13/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=7
+  [14/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=11
+  [15/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=2
+  [16/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=9
+  [17/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=16
+  [18/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=19
+  [19/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=18
+  [20/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=17
+  [21/21] PASS: Example src/wifi/examples/wifi-phy-configuration --testCase=20
+  21 of 21 tests passed (21 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors)
+
 You can specify the directory where |ns3| was built using the
 ``--buildpath`` option as follows.
 
@@ -458,6 +490,12 @@
 Specifying TAKES_FOREVER will run tests in EXTENSIVE and QUICK categories.
 By default, only QUICK tests are ran.
 
+Alternatively, one can specify only-fullness option, which runs tests
+from just that particular category. This allows for tiered execution, both in
+time constrained jobs (starting from TAKES_FOREVER to give them more time,
+then EXTENSIVE, and then QUICK), or to progressively run more expensive tests
+(QUICK, then EXTENSIVE, then TAKES_FOREVER).
+
 As a rule of thumb, tests that must be run to ensure |ns3| coherence should be
 QUICK (i.e., take a few seconds). Tests that could be skipped, but are nice to do
 can be EXTENSIVE; these are tests that typically need minutes. TAKES_FOREVER is
@@ -540,6 +578,28 @@
 C++ program called ``test-runner`` to actually run the tests.  As discussed
 below, this ``test-runner`` can be a helpful way to debug tests.
 
+There are two options to control the scope of tests that are run:
+
+* ``--fullness`` (abbreviated ``-f``):  Runs all tests up to that classification
+   * ``./test.py`` (runs only QUICK)
+   * ``./test.py -f QUICK`` (runs only QUICK)
+   * ``./test.py -f EXTENSIVE`` (runs QUICK and EXTENSIVE)
+   * ``./test.py -f TAKES_FOREVER`` (runs QUICK, EXTENSIVE, and TAKES_FOREVER)
+
+* ``--only-fullness`` (abbreviated ``-of``):  Runs only tests of that classification
+
+   * ``./test.py -of QUICK`` (runs only QUICK)
+   * ``./test.py -of EXTENSIVE`` (runs only EXTENSIVE)
+   * ``./test.py -of TAKES_FOREVER`` (runs only TAKES_FOREVER)
+
+The change in test scope can be further controlled by selecting individual
+tests by using the ``-s`` option.  For example, the following command
+will cause all test cases of only one test suite to be executed:
+
+::
+
+  $ ./test.py -s wifi-primary-channels -f TAKES_FOREVER
+
 Debugging Tests
 ***************
 
@@ -564,34 +624,37 @@
 
 .. sourcecode:: text
 
-  Usage: /home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build/utils/ns3-dev-test-runner-debug [OPTIONS]
+  Usage: /mnt/c/tools/sources/ns-3-dev/build/utils/ns3-dev-test-runner-debug [OPTIONS]
 
   Options:
-  --help                 : print these options
-  --print-test-name-list : print the list of names of tests available
-  --list                 : an alias for --print-test-name-list
-  --print-test-types     : print the type of tests along with their names
-  --print-test-type-list : print the list of types of tests available
-  --print-temp-dir       : print name of temporary directory before running
-                           the tests
-  --test-type=TYPE       : process only tests of type TYPE
-  --test-name=NAME       : process only test whose name matches NAME
-  --suite=NAME           : an alias (here for compatibility reasons only)
-                           for --test-name=NAME
-  --assert-on-failure    : when a test fails, crash immediately (useful
-                           when running under a debugger
-  --stop-on-failure      : when a test fails, stop immediately
-  --fullness=FULLNESS    : choose the duration of tests to run: QUICK,
-                           EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE
-                           includes QUICK and TAKES_FOREVER includes
-                           QUICK and EXTENSIVE (only QUICK tests are
-                           run by default)
-  --verbose              : print details of test execution
-  --xml                  : format test run output as xml
-  --tempdir=DIR          : set temp dir for tests to store output files
-  --datadir=DIR          : set data dir for tests to read reference files
-  --out=FILE             : send test result to FILE instead of standard output
-  --append=FILE          : append test result to FILE instead of standard output
+    --help                   : print these options
+    --print-test-name-list   : print the list of names of tests available
+    --list                   : an alias for --print-test-name-list
+    --print-test-types       : print the type of tests along with their names
+    --print-test-type-list   : print the list of types of tests available
+    --print-temp-dir         : print name of temporary directory before running
+                               the tests
+    --test-type=TYPE         : process only tests of type TYPE
+    --test-name=NAME         : process only test whose name matches NAME
+    --suite=NAME             : an alias (here for compatibility reasons only)
+                               for --test-name=NAME
+    --assert-on-failure      : when a test fails, crash immediately (useful
+                               when running under a debugger
+    --stop-on-failure        : when a test fails, stop immediately
+    --fullness=FULLNESS      : choose the duration of tests to run: QUICK,
+                               EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE
+                               includes QUICK and TAKES_FOREVER includes
+                               QUICK and EXTENSIVE (only QUICK tests are
+                               run by default)
+    --only-fullness=FULLNESS : choose the duration of tests to run: QUICK,
+                               EXTENSIVE, TAKES_FOREVER (only tests marked
+                               with fullness will be executed)
+    --verbose                : print details of test execution
+    --xml                    : format test run output as xml
+    --tempdir=DIR            : set temp dir for tests to store output files
+    --datadir=DIR            : set data dir for tests to read reference files
+    --out=FILE               : send test result to FILE instead of standard output
+    --append=FILE            : append test result to FILE instead of standard output
 
 
 There are a number of things available to you which will be familiar to you if
@@ -741,6 +804,7 @@
 * Unit Tests
 * System Tests
 * Examples
+* Examples-as-Tests
 * Performance Tests
 
 This classification is exported from the TestSuite class.  This class is quite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/troubleshoot.rst ns-3.46/doc/manual/source/troubleshoot.rst
--- ns-3.45/doc/manual/source/troubleshoot.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/troubleshoot.rst	2025-10-01 18:46:32.000000000 -0700
@@ -28,7 +28,7 @@
     Compilation finished successfully
     Command ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] exited with code -11
 
-The error message says that the program terminated unsuccessfuly, but it is
+The error message says that the program terminated unsuccessfully, but it is
 not clear from this information what might be wrong. To examine more
 closely, try running it under the
 `gdb debugger <https://www.nsnam.org/wiki/HOWTO_use_gdb_to_debug_program_errors>`_:
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/working-with-cilicon.rst ns-3.46/doc/manual/source/working-with-cilicon.rst
--- ns-3.45/doc/manual/source/working-with-cilicon.rst	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/doc/manual/source/working-with-cilicon.rst	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,115 @@
+.. include:: replace.txt
+.. highlight:: bash
+
+.. _Working with Cilicon:
+
+Working with Cilicon
+--------------------
+
+.. _continuous integration (CI) : https://docs.gitlab.com/ee/ci/
+.. _Cilicon : https://github.com/traderepublic/Cilicon/
+.. _Cilicon releases : https://github.com/traderepublic/Cilicon/releases/
+
+The ns-3 project repository is currently hosted in GitLab, which includes
+`continuous integration (CI)`_ tools to automate build, tests, packaging and
+distribution of software. The CI works based on jobs, that are defined
+in YAML files and run inside containers.
+
+While we can run most Linux containers everywhere without much problem,
+that is not the case for Windows and MacOS. You can run gitlab-runner as a
+local user, taking proper precautions to avoid that user from escalating privileges,
+then taking over your own network and other systems on it.
+
+That is typically harder than just enforce network security, and virtualization-based security.
+GitLab doesn't offer a way to do that, other than their own runners, which cost up to 6x more
+than linux ones.
+Which is why Trade Republic created the `Cilicon`_ application for MacOS, which creates an ephemeral virtual
+machine, executes a gitlab job, then destroys the VM, and creates a fresh new one.
+
+To set it up, first go to System Settings->Energy and enable all options to prevent sleep, wake on
+network traffic, and restart after power failure (assuming the Mac will be used exclusively as a CI server).
+
+After this, download the latest release in `Cilicon releases`_.
+Put the application in Applications directory and start it. It will ask you to install MacOS virtualization framework.
+
+If you only have a single CI runner that you wish to run, follow their easy settings and create a
+``~/cilicon.yml`` file at the user directory containing:
+
+.. sourcecode:: yaml
+
+    source: oci://ghcr.io/cirruslabs/macos-runner:sequoia
+    provisioner:
+      type: gitlab
+      config:
+        gitlabURL: <GITLAB_INSTANCE_URL>
+        runnerToken: <RUNNER_TOKEN>
+
+If you have multiple CI runners that you wish to run from a single machine, one job at a time,
+you need a custom configuration file, first create a folder that will be shared with the VM.
+
+.. sourcecode:: console
+
+    mkdir /Users/nsnam/gitlab-ephemeral
+
+Then add your GitLab runner ``config.toml`` file there, for example, containing:
+
+.. sourcecode:: toml
+
+    concurrent = 1
+    check_interval = 0
+    connection_max_age = "15m0s"
+    shutdown_timeout = 0
+
+    [session_server]
+      session_timeout = 1800
+
+    [[runners]]
+      name = "MacOsRunnerForProjectA"
+      url = "https://gitlab.com/"
+      token = "<RUNNER_TOKEN_A>"
+      executor = "shell"
+      cleanup_policy = "always"
+
+    [[runners]]
+      name = "MacOsRunnerForProjectB"
+      url = "https://gitlab.com/"
+      token = "<RUNNER_TOKEN_B>"
+      executor = "shell"
+      cleanup_policy = "always"
+
+
+Then create a ``cilicon.yml`` file at the user directory containing:
+
+.. sourcecode:: yaml
+
+    source: oci://ghcr.io/cirruslabs/macos-sonoma-xcode:15
+    provisioner:
+      type: script
+      config:
+        run: |
+          cp /Volumes/My\ Shared\ Files/gitlab-runner/config.toml /Users/admin/.gitlab-runner/config.toml
+          gitlab-runner run
+    consoleDevices:
+      - tart-version-2
+    hardware:
+      ramGigabytes: 20
+      connectsToAudioDevice: false
+    directoryMounts:
+      - hostPath: /Users/nsnam/gitlab-ephemeral
+        guestFolder: gitlab-runner
+        readOnly: true
+
+Note: If you want to create a new VM for every CI job, replace ``gitlab-runner run``
+with ``gitlab-runner run-single``. Not very recommended, because it will hit SSD hard.
+And recent Macs have soldered storage.
+
+After configuring everything, execute Cilicon. It will setup MacOS virtualization framework, then fetch the VM image.
+It will then start the VM.
+
+At this point, MacOS will query you for being visible in network.
+You need to say yes, so the VM can access the shared directory.
+
+Otherwise, you need to either write the TOML with the cilicon.yml, or download it from a remote server.
+
+At this point, you should have your native MacOS runners fully working.
+Try starting a job and see if they respond via GitLab web interface.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/manual/source/working-with-cmake.rst ns-3.46/doc/manual/source/working-with-cmake.rst
--- ns-3.45/doc/manual/source/working-with-cmake.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/manual/source/working-with-cmake.rst	2025-10-01 18:46:32.000000000 -0700
@@ -122,7 +122,6 @@
   -- Detecting CXX compile features - done
   ...
   -- Processing src/wifi
-  -- Processing src/wimax
   -- ---- Summary of optional ns-3 features:
   Build profile                 : release
   Build directory               : /ns-3-dev/build
@@ -138,7 +137,7 @@
   bridge                    buildings                 config-store
   core                      csma                      csma-layout
   ...
-  wifi                      wimax
+  wifi
 
   Modules that cannot be built:
   brite                     click                     openflow
@@ -453,7 +452,6 @@
    │   │   ├── antenna
    │   │   ├── ...
    │   │   ├── wifi
-   │   │   └── wimax
    │   ├── third-party
    │   └── utils
    │       ├── perf
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/models/Makefile ns-3.46/doc/models/Makefile
--- ns-3.45/doc/models/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/models/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,6 +1,4 @@
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
+include $(CURDIR)/../sphinx/defines.mk
 
 SRC = ../../src
 # Temporary source directory, for build
@@ -18,10 +16,7 @@
 	source/network.rst \
 	source/emulation-overview.rst \
 	source/traffic-control.rst \
-	$(SRC)/antenna/doc/source/antenna.rst \
-	$(SRC)/antenna/doc/source/antenna-design.rst \
-	$(SRC)/antenna/doc/source/antenna-user.rst \
-	$(SRC)/antenna/doc/source/antenna-testing.rst \
+	$(SRC)/antenna/doc/antenna.rst \
 	$(SRC)/aodv/doc/aodv.rst \
 	$(SRC)/applications/doc/applications.rst \
 	$(SRC)/bridge/doc/bridge.rst \
@@ -78,7 +73,6 @@
 	$(SRC)/wifi/doc/source/wifi-testing.rst \
 	$(SRC)/wifi/doc/source/wifi-changelog.rst \
 	$(SRC)/wifi/doc/source/wifi-references.rst \
-	$(SRC)/wimax/doc/wimax.rst \
 	$(SRC)/uan/doc/uan.rst \
 	$(SRC)/topology-read/doc/topology.rst \
 	$(SRC)/traffic-control/doc/traffic-control-layer.rst \
@@ -107,12 +101,13 @@
 # documentation formats (html, latex...) the following formats are supported:
 #  1) a single .dia file (preferred option, because it can be edited)
 #  2) a single .eps file
-#  3) both a .pdf and .png file
+#  3) a single .png file
+#  4) both a .pdf and .png file
 SOURCEFIGS = \
 	figures/testbed.dia \
 	figures/emulated-channel.dia \
-	$(SRC)/antenna/doc/source/figures/antenna-coordinate-system.dia	\
-	$(SRC)/antenna/doc/source/figures/circular-antenna-pattern.png	\
+	$(SRC)/antenna/doc/figures/antenna-coordinate-system.dia	\
+	$(SRC)/antenna/doc/figures/circular-antenna-pattern.png	\
 	$(SRC)/applications/doc/http-embedded-object-size.png \
 	$(SRC)/applications/doc/http-main-object-size.png \
 	$(SRC)/applications/doc/http-num-of-embedded-objects.png \
@@ -128,6 +123,7 @@
 	$(SRC)/internet/doc/internet-node-recv.dia \
 	$(SRC)/internet/doc/routing.dia \
 	$(SRC)/internet/doc/routing-specialization.dia \
+	$(SRC)/internet/doc/global-routing-limitation.dia \
 	$(SRC)/internet/doc/figures/tcp-state-machine.png \
 	$(SRC)/internet/doc/figures/dctcp-10ms-50mbps-tcp-throughput.pdf \
 	$(SRC)/internet/doc/figures/dctcp-10ms-50mbps-tcp-throughput.png \
@@ -172,7 +168,6 @@
 	$(SRC)/wifi/doc/source/figures/spectrum-wifi-phy-multiple-interfaces.png \
 	$(SRC)/wifi/doc/source/figures/cca-channel-switching-multiple-interfaces.pdf \
 	$(SRC)/wifi/doc/source/figures/cca-channel-switching-multiple-interfaces.png \
-	$(SRC)/wimax/doc/WimaxArchitecture.dia \
 	$(SRC)/lte/doc/source/figures/epc-ctrl-arch.dia \
 	$(SRC)/lte/doc/source/figures/epc-data-flow-dl.dia \
 	$(SRC)/lte/doc/source/figures/epc-data-flow-dl-with-split.dia \
@@ -357,18 +352,21 @@
 	$(SRC)/spectrum/doc/two-ray-spectrum-loss-model-3gpp-radiation-pattern.png \
 	$(SRC)/spectrum/doc/two-ray-spectrum-loss-model-iso-radiation-pattern.png \
 	$(SRC)/spectrum/doc/three-gpp-gain-reference-gain-vs-fc.png \
+	$(SRC)/spectrum/doc/hexagonal-wraparound-cdf-comparison.png \
+	$(SRC)/spectrum/doc/hexagonal-wraparound-topology.png \
+	$(SRC)/spectrum/doc/hexagonal-wraparound-execution-and-median-thr.png \
 	$(SRC)/traffic-control/doc/classful-queue-disc.dia \
 	$(SRC)/traffic-control/doc/multi-queue-aware-queue-disc.dia \
 	$(SRC)/traffic-control/doc/figures/collision_prob.jpeg \
 	$(SRC)/traffic-control/doc/figures/overlapped.jpeg \
-	$(SRC)/lr-wpan/doc/lr-wpan-arch.dia \
-	$(SRC)/lr-wpan/doc/lr-wpan-assocSequence.dia \
-	$(SRC)/lr-wpan/doc/lr-wpan-data-example.dia \
-	$(SRC)/lr-wpan/doc/lr-wpan-phy.dia \
-	$(SRC)/lr-wpan/doc/lr-wpan-primitives.dia \
-	$(SRC)/lr-wpan/doc/802-15-4-ber.eps \
-	$(SRC)/lr-wpan/doc/802-15-4-per-sens.eps \
-	$(SRC)/lr-wpan/doc/802-15-4-psr-distance.eps \
+	$(SRC)/lr-wpan/doc/figures/lr-wpan-arch.dia \
+	$(SRC)/lr-wpan/doc/figures/lr-wpan-assocSequence.dia \
+	$(SRC)/lr-wpan/doc/figures/lr-wpan-data-example.dia \
+	$(SRC)/lr-wpan/doc/figures/lr-wpan-phy.dia \
+	$(SRC)/lr-wpan/doc/figures/lr-wpan-primitives.dia \
+	$(SRC)/lr-wpan/doc/figures/802-15-4-ber.eps \
+	$(SRC)/lr-wpan/doc/figures/802-15-4-per-sens.eps \
+	$(SRC)/lr-wpan/doc/figures/802-15-4-psr-distance.eps \
 	$(SRC)/flow-monitor/doc/figures/flowmonitorArq.dia \
 	$(SRC)/energy/doc/figures/dischargeCurve.png \
 	$(SRC)/energy/doc/figures/energyFramework.dia \
@@ -396,13 +394,13 @@
 	$(FIGURES)/internet-node-recv.eps \
 	$(FIGURES)/routing.eps \
 	$(FIGURES)/routing-specialization.eps \
+	$(FIGURES)/global-routing-limitation.eps \
 	$(FIGURES)/WifiArchitecture.eps \
 	$(FIGURES)/PhyEntityHierarchy.eps \
 	$(FIGURES)/WifiPpduHierarchy.eps \
 	$(FIGURES)/FemHierarchy.eps \
 	$(FIGURES)/wifi-phy-rx-trace-helper.eps \
 	$(FIGURES)/snir.eps \
-	$(FIGURES)/WimaxArchitecture.eps \
 	$(FIGURES)/epc-ctrl-arch.eps \
 	$(FIGURES)/epc-data-flow-dl.eps \
 	$(FIGURES)/epc-data-flow-dl-with-split.eps \
@@ -525,6 +523,7 @@
 $(FIGURES)/internet-node-recv.pdf_width = 5in
 $(FIGURES)/routing.pdf_width = 6in
 $(FIGURES)/routing-specialization.pdf_width = 5in
+$(FIGURES)/global-routing-limitation.pdf_width = 6in
 $(FIGURES)/snir.pdf_width = 3in
 $(FIGURES)/lte-interference-test-scenario.pdf_width = 3in
 $(FIGURES)/epc-ctrl-arch.pdf_width = 8cm
@@ -603,15 +602,7 @@
 	@$(EPSTOPDF) $< -o=$@ >/dev/null
 	@if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
 
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCETEMP)
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/models/source/conf.py ns-3.46/doc/models/source/conf.py
--- ns-3.45/doc/models/source/conf.py	2025-06-01 20:35:04.000000000 -0700
+++ ns-3.46/doc/models/source/conf.py	2025-10-01 18:46:49.000000000 -0700
@@ -74,9 +74,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = "ns-3.45"
+version = "ns-3.46"
 # The full version, including alpha/beta/rc tags.
-release = "ns-3.45"
+release = "ns-3.46"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/models/source/index.rst ns-3.46/doc/models/source/index.rst
--- ns-3.45/doc/models/source/index.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/models/source/index.rst	2025-10-01 18:46:32.000000000 -0700
@@ -61,5 +61,4 @@
    traffic-control
    uan
    wifi
-   wimax
    zigbee
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/ns3_html_theme/static/ns3_stylesheet.css ns-3.46/doc/ns3_html_theme/static/ns3_stylesheet.css
--- ns-3.45/doc/ns3_html_theme/static/ns3_stylesheet.css	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/ns3_html_theme/static/ns3_stylesheet.css	2025-10-01 18:46:32.000000000 -0700
@@ -1,5 +1,15 @@
 /* ns-3 changes to the default CSS from Doxygen and Sphinx */
 
+/* This size should match the height of the div.related (Navigation menu)
+   + titlearea.
+   Because these areas are "fixed" (sticky), addint this property
+   solves a scroll offset issue (Links in the sidebar point to the
+   correct position of the section anchors in the body.
+*/
+html {
+    scroll-padding-top: 96px;
+}
+
 body,
 table,
 div,
@@ -15,17 +25,50 @@
     font-weight: bold;
 }
 
-/* Sphinx headings */
-/*
-div.body h1,
-div.body h2,
+/* Sphinx body headings (All Section level headings in the body) */
+
+div.body {
+    margin-left: 20px; /*Controls the body area initial position after the default*/
+}
+
+div.body h1 {
+    font-weight: normal;
+    font-size: 39px;
+    color: #91A501;
+}
+
+div.body h2 {
+    color: #91A501;
+    font-weight: normal;
+    font-size: 28px;
+}
+
+div.body h3 {
+    color: #41531C;
+    font-weight: 700;
+    font-size: 18px;
+}
+
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-weight: normal;
+    font-style: italic;
+    font-size: 14px;
+}
+
 div.body h3,
 div.body h4,
 div.body h5,
 div.body h6 {
-  background-image: url('nav_f.png');
+    border-bottom: none;/* Remove horizontal line for subsections */
+    padding-bottom: 0;
+    margin-bottom: 0.5em;
+    margin-left: 0;
+    border-left: none;
+    padding-left: 0;
+    background: none;
 }
-*/
 
 /* Sphinx figure captions */
 p.caption {
@@ -41,12 +84,13 @@
     font-weight: normal;
 }
 
-/* Sphinx nav links bar (relbar) */
-/*
+/* Sphinx navigation links bar (relbar) */
 div.related {
-  background-image: url('tab_b.png')
+    position: sticky;
+    top: 56px; /* or 96px if your #titlearea + #ns3-menu is ~96px total */
+    z-index: 9999;
+    background-color: #E3E3E3;/*#f8f8f8; /* Prevent transparency when stuck */
 }
-*/
 
 div.related h3 {
     display: none;
@@ -72,15 +116,59 @@
     padding-right: 0px;
 }
 
-/* Sphinx side bar */
+
+div.sphinxsidebar {
+    width: 330px;
+}
+
+div.bodywrapper {
+    margin-left: 330px;
+}
+
+/* Enable independent vertical scrolling in sidebar */
 div.sphinxsidebar {
     font-size: 12px;
+    position: sticky;        /* keep sidebar visible on scroll */
+    top: 90px;               /* align with top of viewport (title area + div.related) */
+    max-height: 100vh;       /* full viewport height */
+    overflow-y: auto;        /* only vertical scrolling */
+    overflow-x: hidden;      /* no horizontal scroll */
+    z-index: 10;             /* ensure it stays above main content */
+
+    /* Hide scrollbar cross-browser */
+    scrollbar-width: none;          /* Firefox */
+    -ms-overflow-style: none;       /* IE/Edge */
+}
+
+div.sphinxsidebar::-webkit-scrollbar {
+    display: none;                  /* Chrome/Safari */
 }
 
 div.sphinxsidebar a {
     font-weight: normal;
 }
 
+/* Top-level (Module Title) */
+.sphinxsidebar .sphinxsidebarwrapper > div > ul > li > a {
+    color: #91A501 !important;
+    font-weight: bold;
+}
+
+/* Second-level (Sections) */
+.sphinxsidebar .sphinxsidebarwrapper > div > ul > li > ul > li > a {
+    color: #91A501 !important;
+}
+
+/* 3rd level (SubsubSections and deeper) */
+.sphinxsidebar .sphinxsidebarwrapper ul ul ul a {
+    color: #41531C !important;
+}
+
+
+/* Hide any subsection after the 3rd level*/
+.sphinxsidebar .sphinxsidebarwrapper ul ul ul ul {
+    display: none;
+}
 
 /* Title bar elements */
 
@@ -89,8 +177,8 @@
     background-repeat: repeat;
     border-bottom: 1px solid #5B5B5B;
     color: white;
-    position: relative;
-    /* Doxygen tab bar ("Main Page", "Related Pages"..) is at z: 9999 */
+    position: sticky;
+    top: 0;
     z-index: 10000;
 }
 
@@ -229,6 +317,15 @@
     /* don't add underline on hover */
 }
 
+/* Highlight small code blocks in the documentation */
+code.literal, span.literal {
+    background-color: #f0f0f0;
+    padding: 2px 4px;
+    border-radius: 3px;
+    font-family: monospace;
+    font-size: 90%;
+}
+
 /* Dark mode is not supported in Doxygen versions earlier than 1.9.6 */
 @media (prefers-color-scheme: dark) {
     a {
@@ -248,25 +345,43 @@
     div.sphinxsidebar h3,
     div.sphinxsidebar h4,
     div.sphinxsidebar h3 a {
-        color: ivory;
+        color: #b2beb5;
         background: #2f2f2f;
     }
 
-    div.related a,
-    div.sphinxsidebar a {
-        color: #cfde63;
-    }
+    div.body h3 {
+        color: #DFF9BA; /* #C5C7C0; */
+        font-weight: 700;
+        font-size: 18px;
+   }
+
+    /* 3rd level (SubsubSections and deeper) */
+    .sphinxsidebar .sphinxsidebarwrapper ul ul ul a {
+        color: #DFF9BA !important;
+   }
 
     div.sphinxsidebar input {
         background: #2c2d24;
     }
 
-    div.note {
-        background-color: unset;
+    /* Notes in the dark theme*/
+    div.note,
+    div.note p {
+        background-color: #404040;
     }
 
+    /*div.related a,
+    div.sphinxsidebar a {
+        color: #cfde63;
+    }*/
+
+    /* Sphinx navigation links bar (relbar) */
     div.related {
-        background-image: linear-gradient(to bottom, #66696a 0%, transparent 80%);
+        position: sticky;
+        top: 56px; /* or 96px if your #titlearea + #ns3-menu is ~96px total */
+        z-index: 9999;
+        background-color: #404040;/*#f8f8f8; /* Prevent transparency when stuck */
+        background-image: linear-gradient(to bottom, #404040 0%, transparent 80%);
     }
 
     th {
@@ -277,6 +392,8 @@
         background-color: transparent;
     }
 
+    /* Code blocks (highlight), ns-3 dark theme starts here */
+
     .highlight {
         background-color: #424e20;
     }
@@ -355,7 +472,7 @@
     }
 
     img {
-        background-color: #ceccca;
+        background-color: white;
         padding: 3px;
     }
 
@@ -370,4 +487,15 @@
     #nav-sync img {
         background-color: transparent;
     }
+
+    code.literal, span.literal {
+        color:#E3E3E3;
+        background-color: /*#6B5A39;*/ #424E20;
+        padding: 2px 4px;
+        border-radius: 3px;
+        font-family: monospace;
+        font-size: 90%;
+    }
 }
+
+
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/sphinx/defines.mk ns-3.46/doc/sphinx/defines.mk
--- ns-3.45/doc/sphinx/defines.mk	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/doc/sphinx/defines.mk	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,19 @@
+ifeq (, $(shell command -v magick))
+	CONVERT = convert -density 300
+else
+	CONVERT = magick -density 300
+endif
+
+DIA = dia
+DOT = dot
+EPSTOPDF = epstopdf
+
+# You can set these variables from the command line.
+SPHINXOPTS    = -W --keep-going
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/tutorial/Makefile ns-3.46/doc/tutorial/Makefile
--- ns-3.45/doc/tutorial/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/tutorial/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,23 +1,11 @@
 # Makefile for Sphinx documentation
 #
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
+include $(CURDIR)/../sphinx/defines.mk
 
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
 
 # Additional variables for figures, not sphinx default:
-DIA = dia
-EPSTOPDF = epstopdf
 FIGURES = source/figures
 IMAGES_EPS = \
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/tutorial/source/conf.py ns-3.46/doc/tutorial/source/conf.py
--- ns-3.45/doc/tutorial/source/conf.py	2025-06-01 20:35:04.000000000 -0700
+++ ns-3.46/doc/tutorial/source/conf.py	2025-10-01 18:46:49.000000000 -0700
@@ -71,9 +71,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = "ns-3.45"
+version = "ns-3.46"
 # The full version, including alpha/beta/rc tags.
-release = "ns-3.45"
+release = "ns-3.46"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/doc/tutorial/source/getting-started.rst ns-3.46/doc/tutorial/source/getting-started.rst
--- ns-3.45/doc/tutorial/source/getting-started.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/doc/tutorial/source/getting-started.rst	2025-10-01 18:46:32.000000000 -0700
@@ -105,6 +105,20 @@
 The process for downloading |ns3| via tarball is simple; you just
 have to pick a release, download it and uncompress it.
 
+We recommend downloading the most recent release (highest release
+number).  Prior to the ns-3.45 release, we offered one downloadable
+source code archive, called ``ns-allinone-3.nn.tar.bz2`` (where ``nn``
+stands for the release number), which contained the network animator
+NetAnim, the bake build tool and the ns-3 release.  Starting with
+ns-3.45, we offer two release archives:
+
+#.  ``ns-3.45.tar.bz2``: Contains only ns-3
+#.  ``ns-allinone-3.45.tar.bz2``: Contains ns-3 plus some compatible extension modules available in the `ns-3 App Store <https://apps.nsnam.org>`_
+
+We will focus on the first option above.  The instructions for the second
+one are basically the same, except that you will need to change into
+the ``ns-3.nn`` directory after unpacking it.
+
 Let's assume that you, as a user, wish to build |ns3| in a local
 directory called ``workspace``.
 If you adopt the ``workspace`` directory approach, you can
@@ -116,8 +130,8 @@
   $ cd
   $ mkdir workspace
   $ cd workspace
-  $ wget https://www.nsnam.org/release/ns-allinone-3.45.tar.bz2
-  $ tar xjf ns-allinone-3.45.tar.bz2
+  $ wget https://www.nsnam.org/release/ns-3.45.tar.bz2
+  $ tar xjf ns-3.45.tar.bz2
 
 Notice the use above of the ``wget`` utility, which is a command-line
 tool to fetch objects from the web; if you do not have this installed,
@@ -311,7 +325,6 @@
   -- Processing src/uan
   -- Processing src/virtual-net-device
   -- Processing src/wifi
-  -- Processing src/wimax
   -- ---- Summary of optional NS-3 features:
   Build profile                 : optimized
   Build directory               : /mnt/dev/tools/source/ns-3-dev/build
@@ -349,7 +362,7 @@
   sixlowpan                 spectrum                  stats
   tap-bridge                test                      topology-read
   traffic-control           uan                       virtual-net-device
-  wifi                      wimax
+  wifi
 
 
   Modules that cannot be built:
@@ -401,30 +414,6 @@
   $ ./ns3 show profile
   Build profile: debug
 
-The build.py script discussed above supports also the ``--enable-examples``
-and ``enable-tests`` arguments and passes them through to the ns-3
-configuration, but in general, does not directly support
-other ns3 options; for example, this will not work:
-
-.. sourcecode:: console
-
-  $ ./build.py --enable-asserts
-
-will result in:
-
-.. sourcecode:: console
-
-  build.py: error: no such option: --enable-asserts
-
-However, the special operator ``--`` can be used to pass additional
-configure options through to ns3, so instead of the above, the following will work:
-
-.. sourcecode:: console
-
-  $ ./build.py -- --enable-asserts
-
-as it generates the underlying command ``./ns3 configure --enable-asserts``.
-
 Here are a few more introductory tips about CMake.
 
 Handling build errors
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/channel-models/three-gpp-v2v-channel-example.cc ns-3.46/examples/channel-models/three-gpp-v2v-channel-example.cc
--- ns-3.45/examples/channel-models/three-gpp-v2v-channel-example.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/channel-models/three-gpp-v2v-channel-example.cc	2025-10-01 18:46:32.000000000 -0700
@@ -151,13 +151,10 @@
         NS_LOG_ERROR("Can't open file " << filename);
         return;
     }
-    uint32_t index = 0;
     for (auto it = BuildingList::Begin(); it != BuildingList::End(); ++it)
     {
-        ++index;
         Box box = (*it)->GetBoundaries();
-        outFile << "set object " << index << " rect from " << box.xMin << "," << box.yMin << " to "
-                << box.xMax << "," << box.yMax << std::endl;
+        outFile << box.xMin << " " << box.yMin << " " << box.xMax << " " << box.yMax << std::endl;
     }
 }
 
@@ -359,7 +356,7 @@
 
     for (int i = 0; i < simTime / timeRes; i++)
     {
-        ComputeSnrParams params{txMob, rxMob, txParams, noiseFigure, txAntenna, rxAntenna};
+        ComputeSnrParams params{txMob, rxMob, txParams->Copy(), noiseFigure, txAntenna, rxAntenna};
         Simulator::Schedule(timeRes * i, &ComputeSnr, params);
     }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/channel-models/three-gpp-v2v-channel-example.py ns-3.46/examples/channel-models/three-gpp-v2v-channel-example.py
--- ns-3.45/examples/channel-models/three-gpp-v2v-channel-example.py	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/examples/channel-models/three-gpp-v2v-channel-example.py	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,86 @@
+#!/bin/python3
+
+# Copyright (c) 2020, University of Padova, Dep. of Information Engineering, SIGNET lab
+# Copyright (c) 2025, Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+#
+# SPDX-License-Identifier: GPL-2.0-only
+
+import matplotlib.animation as animation
+import matplotlib.patches as patches
+import matplotlib.pyplot as plt
+
+#
+#  Plot the traces generated by three-gpp-v2v-channel-example
+#
+import pandas as pd
+
+# Load the data
+df = pd.read_csv("example-output.txt", sep=r"\s+", comment="#")
+df = df.iloc[::10, :]
+
+# Column indices (adjust if needed)
+TIME = 0
+TX_X = 1
+TX_Y = 2
+RX_X = 3
+RX_Y = 4
+SNR = 6
+
+# Create the figure and subplots
+fig, (ax_map, ax_snr) = plt.subplots(1, 2, figsize=(12, 6))
+
+# Map plot config
+ax_map.set_xlim(-25, 600)
+ax_map.set_ylim(-25, 1000)
+ax_map.set_xlabel("X [m]")
+ax_map.set_ylabel("Y [m]")
+ax_map.set_aspect("equal")
+tx_circle = patches.Circle((0, 0), 5, color="blue", alpha=0.35)
+rx_circle = patches.Circle((0, 0), 5, color="red", alpha=0.35)
+ax_map.add_patch(tx_circle)
+ax_map.add_patch(rx_circle)
+
+# SNR plot config
+ax_snr.set_xlim(0, 40)
+ax_snr.set_ylim(-20, 100)
+ax_snr.set_xlabel("Time [s]")
+ax_snr.set_ylabel("SNR [dB]")
+ax_snr.grid(True)
+(snr_line,) = ax_snr.plot([], [], "k-")
+
+buildings = pd.read_csv("buildings.txt", sep=r"\s+", comment="#", header=None)
+building_patches = []
+for idx, row in buildings.iterrows():
+    x0, y0, x1, y1 = row
+    width = x1 - x0
+    height = y1 - y0
+    rect = patches.Rectangle((x0, y0), width, height, color="gray", alpha=0.5)
+    ax_map.add_patch(rect)
+    building_patches.append(rect)
+
+
+# Animation update function
+def update(frame):
+    row = df.iloc[frame]
+    tx_circle.set_center((row.iloc[TX_X], row.iloc[TX_Y]))
+    rx_circle.set_center((row.iloc[RX_X], row.iloc[RX_Y]))
+    snr_line.set_data(df.iloc[: frame + 1, TIME], df.iloc[: frame + 1, SNR])
+    ax_map.set_title(f"Time = {row.iloc[TIME]:.1f} s")
+    return tx_circle, rx_circle, snr_line
+
+
+# Run animation
+ani = animation.FuncAnimation(fig, update, frames=len(df), interval=0.001, blit=False)
+
+# Save animation
+ani.save("map.gif", writer="pillow")
+
+# Save final SNR plot separately
+plt.figure()
+plt.plot(df.iloc[:, TIME], df.iloc[:, SNR], "k-")
+plt.xlabel("Time [s]")
+plt.ylabel("SNR [dB]")
+plt.grid(True)
+plt.xlim(0, 40)
+plt.ylim(-20, 100)
+plt.savefig("snr.png")
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/channel-models/three-gpp-v2v-channel-example.sh ns-3.46/examples/channel-models/three-gpp-v2v-channel-example.sh
--- ns-3.45/examples/channel-models/three-gpp-v2v-channel-example.sh	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/channel-models/three-gpp-v2v-channel-example.sh	1969-12-31 16:00:00.000000000 -0800
@@ -1,57 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2020, University of Padova, Dep. of Information Engineering, SIGNET lab
-#
-# SPDX-License-Identifier: GPL-2.0-only
-
-#
-#  Plot the traces generated by three-gpp-vehicular-channel-condition-model-example
-#
-
-cat >aa <<EOL
-set terminal gif animate delay 100
-set output 'map.gif'
-set view map
-set style fill transparent solid 0.5
-unset key
-set style fill  transparent solid 0.35 noborder
-set style circle radius 5
-
-do for [i=0:299] {
-  set multiplot layout 1,2
-    set zrange [i-1:i]
-    set xrange [-25:600]
-    set yrange [-25:1000]
-    set xlabel 'X [m]'
-    set ylabel 'Y [m]'
-    set xtics
-    set ytics
-    load 'buildings.txt'
-    splot 'example-output.txt' u 2:3:1 with circles lc rgb "blue", 'example-output.txt' u 4:5:1 with circles lc rgb "red"
-    set object 101 rect from -25,-25 to 1400,1000 fc rgb "white"
-    set xrange [i-0.001:i+0.001]
-    set yrange [i-0.001:i+0.001]
-    unset xlabel
-    unset ylabel
-    unset xtics
-    unset ytics
-    plot 'example-output.txt' using 1:1:1 with labels offset -10, 0, 'example-output.txt' using 1:1:6 with labels offset 10, 0
-    unset object 101
-  unset multiplot
-}
-
-reset
-set terminal png
-set output 'snr.png'
-set xlabel 'Time [s]'
-set ylabel 'SNR [dB]'
-set xtics
-set ytics
-set grid
-set xrange [0:40]
-set yrange [-20:100]
-plot 'example-output.txt' u 1:7 w l
-EOL
-gnuplot aa
-rm aa
-# rm out.txt
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/wireless/examples-to-run.py ns-3.46/examples/wireless/examples-to-run.py
--- ns-3.45/examples/wireless/examples-to-run.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/wireless/examples-to-run.py	2025-10-01 18:46:32.000000000 -0700
@@ -85,17 +85,17 @@
         "True",
     ),
     (
-        "wifi-vht-network --simulationTime=0.2s --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=620",
+        "wifi-vht-network --simulationTime=0.2s --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=630",
         "True",
         "True",
     ),
     (
-        "wifi-vht-network --simulationTime=0.2s --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=557",
+        "wifi-vht-network --simulationTime=0.2s --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=565",
         "True",
         "True",
     ),
     (
-        "wifi-vht-network --simulationTime=0.2s --useRts=0 --use80Plus80=1 --minExpectedThroughput=5 --maxExpectedThroughput=620",
+        "wifi-vht-network --simulationTime=0.2s --useRts=0 --use80Plus80=1 --minExpectedThroughput=5 --maxExpectedThroughput=630",
         "True",
         "True",
     ),
@@ -195,7 +195,7 @@
         "True",
     ),
     (
-        "wifi-eht-network --simulationTime=0.25s --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=8 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=50 --maxExpectedThroughput=550 --RngRun=3",
+        "wifi-eht-network --simulationTime=0.25s --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=8 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=50 --maxExpectedThroughput=550 --RngRun=6",
         "True",
         "True",
     ),
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/wireless/wifi-eht-network.cc ns-3.46/examples/wireless/wifi-eht-network.cc
--- ns-3.45/examples/wireless/wifi-eht-network.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/wireless/wifi-eht-network.cc	2025-10-01 18:46:32.000000000 -0700
@@ -18,6 +18,7 @@
 #include "ns3/log.h"
 #include "ns3/mobility-helper.h"
 #include "ns3/multi-model-spectrum-channel.h"
+#include "ns3/neighbor-cache-helper.h"
 #include "ns3/on-off-helper.h"
 #include "ns3/packet-sink-helper.h"
 #include "ns3/packet-sink.h"
@@ -28,8 +29,7 @@
 #include "ns3/udp-server.h"
 #include "ns3/uinteger.h"
 #include "ns3/wifi-acknowledgment.h"
-#include "ns3/yans-wifi-channel.h"
-#include "ns3/yans-wifi-helper.h"
+#include "ns3/wifi-static-setup-helper.h"
 
 #include <algorithm>
 #include <array>
@@ -148,6 +148,8 @@
     uint16_t auxPhyChWidth{20};
     bool auxPhyTxCapable{true};
     Time simulationTime{"10s"};
+    bool staticSetup{true};
+    auto clientAppStartTime = Seconds(1);
     meter_u distance{1.0};
     double frequency{5};  // whether the first link operates in the 2.4, 5 or 6 GHz
     double frequency2{0}; // whether the second link operates in the 2.4, 5 or 6 GHz (0 means no
@@ -170,6 +172,9 @@
     Time accessReqInterval{0};
 
     CommandLine cmd(__FILE__);
+    cmd.AddValue("staticSetup",
+                 "Whether devices are configured using the static setup helper",
+                 staticSetup);
     cmd.AddValue(
         "frequency",
         "Whether the first link operates in the 2.4, 5 or 6 GHz band (other values gets rejected)",
@@ -481,6 +486,8 @@
                 mac.SetType("ns3::ApWifiMac",
                             "EnableBeaconJitter",
                             BooleanValue(false),
+                            "BeaconGeneration",
+                            BooleanValue(!staticSetup),
                             "Ssid",
                             SsidValue(ssid));
                 apDevice = wifi.Install(phy, mac, wifiApNode);
@@ -509,6 +516,17 @@
                 mobility.Install(wifiApNode);
                 mobility.Install(wifiStaNodes);
 
+                if (staticSetup)
+                {
+                    /* static setup of association and BA agreements */
+                    auto apDev = DynamicCast<WifiNetDevice>(apDevice.Get(0));
+                    NS_ASSERT(apDev);
+                    WifiStaticSetupHelper::SetStaticAssociation(apDev, staDevices);
+                    WifiStaticSetupHelper::SetStaticEmlsr(apDev, staDevices);
+                    WifiStaticSetupHelper::SetStaticBlockAck(apDev, staDevices, {0});
+                    clientAppStartTime = MilliSeconds(1);
+                }
+
                 /* Internet stack*/
                 InternetStackHelper stack;
                 stack.Install(wifiApNode);
@@ -524,6 +542,13 @@
                 staNodeInterfaces = address.Assign(staDevices);
                 apNodeInterface = address.Assign(apDevice);
 
+                if (staticSetup)
+                {
+                    /* static setup of ARP cache */
+                    NeighborCacheHelper nbCache;
+                    nbCache.PopulateNeighborCache();
+                }
+
                 /* Setting applications */
                 ApplicationContainer serverApp;
                 auto serverNodes = downlink ? std::ref(wifiStaNodes) : std::ref(wifiApNode);
@@ -551,7 +576,7 @@
                     streamNumber += server.AssignStreams(serverNodes.get(), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
                     const auto packetInterval = payloadSize * 8.0 / maxLoad;
 
                     for (std::size_t i = 0; i < nStations; i++)
@@ -563,8 +588,8 @@
                         ApplicationContainer clientApp = client.Install(clientNodes.Get(i));
                         streamNumber += client.AssignStreams(clientNodes.Get(i), streamNumber);
 
-                        clientApp.Start(Seconds(1));
-                        clientApp.Stop(simulationTime + Seconds(1));
+                        clientApp.Start(clientAppStartTime);
+                        clientApp.Stop(simulationTime + clientAppStartTime);
                     }
                 }
                 else
@@ -577,7 +602,7 @@
                     streamNumber += packetSinkHelper.AssignStreams(serverNodes.get(), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
 
                     for (std::size_t i = 0; i < nStations; i++)
                     {
@@ -594,8 +619,8 @@
                         ApplicationContainer clientApp = onoff.Install(clientNodes.Get(i));
                         streamNumber += onoff.AssignStreams(clientNodes.Get(i), streamNumber);
 
-                        clientApp.Start(Seconds(1));
-                        clientApp.Stop(simulationTime + Seconds(1));
+                        clientApp.Start(clientAppStartTime);
+                        clientApp.Stop(simulationTime + clientAppStartTime);
                     }
                 }
 
@@ -604,17 +629,17 @@
 
                 if (tputInterval.IsStrictlyPositive())
                 {
-                    Simulator::Schedule(Seconds(1) + tputInterval,
+                    Simulator::Schedule(clientAppStartTime + tputInterval,
                                         &PrintIntermediateTput,
                                         cumulRxBytes,
                                         udp,
                                         serverApp,
                                         payloadSize,
                                         tputInterval,
-                                        simulationTime + Seconds(1));
+                                        simulationTime + clientAppStartTime);
                 }
 
-                Simulator::Stop(simulationTime + Seconds(1));
+                Simulator::Stop(simulationTime + clientAppStartTime);
                 Simulator::Run();
 
                 // When multiple stations are used, there are chances that association requests
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/wireless/wifi-he-network.cc ns-3.46/examples/wireless/wifi-he-network.cc
--- ns-3.45/examples/wireless/wifi-he-network.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/wireless/wifi-he-network.cc	2025-10-01 18:46:32.000000000 -0700
@@ -19,6 +19,7 @@
 #include "ns3/log.h"
 #include "ns3/mobility-helper.h"
 #include "ns3/multi-model-spectrum-channel.h"
+#include "ns3/neighbor-cache-helper.h"
 #include "ns3/on-off-helper.h"
 #include "ns3/packet-sink-helper.h"
 #include "ns3/packet-sink.h"
@@ -29,6 +30,7 @@
 #include "ns3/udp-server.h"
 #include "ns3/uinteger.h"
 #include "ns3/wifi-acknowledgment.h"
+#include "ns3/wifi-static-setup-helper.h"
 #include "ns3/yans-wifi-channel.h"
 #include "ns3/yans-wifi-helper.h"
 
@@ -66,6 +68,8 @@
     bool use80Plus80{false};
     bool useExtendedBlockAck{false};
     Time simulationTime{"10s"};
+    bool staticSetup{true};
+    auto clientAppStartTime = Seconds(1);
     meter_u distance{1.0};
     double frequency{5}; // whether 2.4, 5 or 6 GHz
     std::size_t nStations{1};
@@ -84,6 +88,9 @@
     Time accessReqInterval{0};
 
     CommandLine cmd(__FILE__);
+    cmd.AddValue("staticSetup",
+                 "Whether devices are configured using the static setup helper",
+                 staticSetup);
     cmd.AddValue("frequency",
                  "Whether working in the 2.4, 5 or 6 GHz band (other values gets rejected)",
                  frequency);
@@ -332,6 +339,8 @@
                     mac.SetType("ns3::ApWifiMac",
                                 "EnableBeaconJitter",
                                 BooleanValue(false),
+                                "BeaconGeneration",
+                                BooleanValue(!staticSetup),
                                 "Ssid",
                                 SsidValue(ssid));
                     apDevice = wifi.Install(phy, mac, wifiApNode);
@@ -376,6 +385,16 @@
                 mobility.Install(wifiApNode);
                 mobility.Install(wifiStaNodes);
 
+                if (staticSetup)
+                {
+                    /* static setup of association and BA agreements */
+                    auto apDev = DynamicCast<WifiNetDevice>(apDevice.Get(0));
+                    NS_ASSERT(apDev);
+                    WifiStaticSetupHelper::SetStaticAssociation(apDev, staDevices);
+                    WifiStaticSetupHelper::SetStaticBlockAck(apDev, staDevices, {0});
+                    clientAppStartTime = MilliSeconds(1);
+                }
+
                 /* Internet stack*/
                 InternetStackHelper stack;
                 stack.Install(wifiApNode);
@@ -391,6 +410,13 @@
                 staNodeInterfaces = address.Assign(staDevices);
                 apNodeInterface = address.Assign(apDevice);
 
+                if (staticSetup)
+                {
+                    /* static setup of ARP cache */
+                    NeighborCacheHelper nbCache;
+                    nbCache.PopulateNeighborCache();
+                }
+
                 /* Setting applications */
                 ApplicationContainer serverApp;
                 auto serverNodes = downlink ? std::ref(wifiStaNodes) : std::ref(wifiApNode);
@@ -415,7 +441,7 @@
                     streamNumber += server.AssignStreams(serverNodes.get(), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
                     const auto packetInterval = payloadSize * 8.0 / maxLoad;
 
                     for (std::size_t i = 0; i < nStations; i++)
@@ -427,8 +453,8 @@
                         ApplicationContainer clientApp = client.Install(clientNodes.Get(i));
                         streamNumber += client.AssignStreams(clientNodes.Get(i), streamNumber);
 
-                        clientApp.Start(Seconds(1));
-                        clientApp.Stop(simulationTime + Seconds(1));
+                        clientApp.Start(clientAppStartTime);
+                        clientApp.Stop(simulationTime + clientAppStartTime);
                     }
                 }
                 else
@@ -441,7 +467,7 @@
                     streamNumber += packetSinkHelper.AssignStreams(serverNodes.get(), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
 
                     for (std::size_t i = 0; i < nStations; i++)
                     {
@@ -458,14 +484,14 @@
                         ApplicationContainer clientApp = onoff.Install(clientNodes.Get(i));
                         streamNumber += onoff.AssignStreams(clientNodes.Get(i), streamNumber);
 
-                        clientApp.Start(Seconds(1));
-                        clientApp.Stop(simulationTime + Seconds(1));
+                        clientApp.Start(clientAppStartTime);
+                        clientApp.Stop(simulationTime + clientAppStartTime);
                     }
                 }
 
                 Simulator::Schedule(Seconds(0), &Ipv4GlobalRoutingHelper::PopulateRoutingTables);
 
-                Simulator::Stop(simulationTime + Seconds(1));
+                Simulator::Stop(simulationTime + clientAppStartTime);
                 Simulator::Run();
 
                 // When multiple stations are used, there are chances that association requests
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/wireless/wifi-ht-network.cc ns-3.46/examples/wireless/wifi-ht-network.cc
--- ns-3.45/examples/wireless/wifi-ht-network.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/wireless/wifi-ht-network.cc	2025-10-01 18:46:32.000000000 -0700
@@ -19,6 +19,7 @@
 #include "ns3/ipv4-global-routing-helper.h"
 #include "ns3/log.h"
 #include "ns3/mobility-helper.h"
+#include "ns3/neighbor-cache-helper.h"
 #include "ns3/on-off-helper.h"
 #include "ns3/packet-sink-helper.h"
 #include "ns3/packet-sink.h"
@@ -28,6 +29,7 @@
 #include "ns3/udp-client-server-helper.h"
 #include "ns3/udp-server.h"
 #include "ns3/uinteger.h"
+#include "ns3/wifi-static-setup-helper.h"
 #include "ns3/yans-wifi-channel.h"
 #include "ns3/yans-wifi-helper.h"
 
@@ -60,6 +62,8 @@
     bool udp{true};
     bool useRts{false};
     Time simulationTime{"10s"};
+    bool staticSetup{true};
+    auto clientAppStartTime = Seconds(1);
     meter_u distance{1.0};
     double frequency{5}; // whether 2.4 or 5 GHz
     std::string mcsStr;
@@ -70,6 +74,9 @@
     double maxExpectedThroughput{0.0};
 
     CommandLine cmd(__FILE__);
+    cmd.AddValue("staticSetup",
+                 "Whether devices are configured using the static setup helper",
+                 staticSetup);
     cmd.AddValue("frequency",
                  "Whether working in the 2.4 or 5.0 GHz band (other values gets rejected)",
                  frequency);
@@ -233,6 +240,8 @@
                 mac.SetType("ns3::ApWifiMac",
                             "EnableBeaconJitter",
                             BooleanValue(false),
+                            "BeaconGeneration",
+                            BooleanValue(!staticSetup),
                             "Ssid",
                             SsidValue(ssid));
 
@@ -256,6 +265,16 @@
                 mobility.Install(wifiApNode);
                 mobility.Install(wifiStaNode);
 
+                if (staticSetup)
+                {
+                    /* static setup of association and BA agreements */
+                    auto apDev = DynamicCast<WifiNetDevice>(apDevice.Get(0));
+                    NS_ASSERT(apDev);
+                    WifiStaticSetupHelper::SetStaticAssociation(apDev, staDevice);
+                    WifiStaticSetupHelper::SetStaticBlockAck(apDev, staDevice, {0});
+                    clientAppStartTime = MilliSeconds(1);
+                }
+
                 /* Internet stack*/
                 InternetStackHelper stack;
                 stack.Install(wifiApNode);
@@ -271,6 +290,13 @@
                 staNodeInterface = address.Assign(staDevice);
                 apNodeInterface = address.Assign(apDevice);
 
+                if (staticSetup)
+                {
+                    /* static setup of ARP cache */
+                    NeighborCacheHelper nbCache;
+                    nbCache.PopulateNeighborCache();
+                }
+
                 /* Setting applications */
                 const auto maxLoad = HtPhy::GetDataRate(mcs,
                                                         MHz_u{static_cast<double>(width)},
@@ -286,7 +312,7 @@
                     streamNumber += server.AssignStreams(wifiStaNode.Get(0), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
                     const auto packetInterval = payloadSize * 8.0 / maxLoad;
 
                     UdpClientHelper client(staNodeInterface.GetAddress(0), port);
@@ -296,8 +322,8 @@
                     ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
                     streamNumber += client.AssignStreams(wifiApNode.Get(0), streamNumber);
 
-                    clientApp.Start(Seconds(1));
-                    clientApp.Stop(simulationTime + Seconds(1));
+                    clientApp.Start(clientAppStartTime);
+                    clientApp.Stop(simulationTime + clientAppStartTime);
                 }
                 else
                 {
@@ -310,7 +336,7 @@
                         packetSinkHelper.AssignStreams(wifiStaNode.Get(0), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
 
                     OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
                     onoff.SetAttribute("OnTime",
@@ -325,13 +351,13 @@
                     ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
                     streamNumber += onoff.AssignStreams(wifiApNode.Get(0), streamNumber);
 
-                    clientApp.Start(Seconds(1));
-                    clientApp.Stop(simulationTime + Seconds(1));
+                    clientApp.Start(clientAppStartTime);
+                    clientApp.Stop(simulationTime + clientAppStartTime);
                 }
 
                 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
 
-                Simulator::Stop(simulationTime + Seconds(1));
+                Simulator::Stop(simulationTime + clientAppStartTime);
                 Simulator::Run();
 
                 auto rxBytes = 0.0;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/wireless/wifi-spatial-reuse.cc ns-3.46/examples/wireless/wifi-spatial-reuse.cc
--- ns-3.45/examples/wireless/wifi-spatial-reuse.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/wireless/wifi-spatial-reuse.cc	2025-10-01 18:46:32.000000000 -0700
@@ -351,11 +351,13 @@
         // to the Reset trace source on each STA.  Note that this trace connection
         // cannot be done through the Config path system, so pointers are used.
         auto deviceA = staDeviceA.Get(0)->GetObject<WifiNetDevice>();
-        auto hePhyA = DynamicCast<HePhy>(deviceA->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
+        auto hePhyA =
+            std::dynamic_pointer_cast<HePhy>(deviceA->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
         // Pass in the context string "1" to allow the trace to distinguish objects
         hePhyA->GetObssPdAlgorithm()->TraceConnect("Reset", "1", MakeCallback(&ResetTrace));
         auto deviceB = staDeviceB.Get(0)->GetObject<WifiNetDevice>();
-        auto hePhyB = DynamicCast<HePhy>(deviceB->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
+        auto hePhyB =
+            std::dynamic_pointer_cast<HePhy>(deviceB->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
         // Pass in the context string "2" to allow the trace to distinguish objects
         hePhyB->GetObssPdAlgorithm()->TraceConnect("Reset", "2", MakeCallback(&ResetTrace));
     }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/examples/wireless/wifi-vht-network.cc ns-3.46/examples/wireless/wifi-vht-network.cc
--- ns-3.45/examples/wireless/wifi-vht-network.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/examples/wireless/wifi-vht-network.cc	2025-10-01 18:46:32.000000000 -0700
@@ -17,6 +17,7 @@
 #include "ns3/log.h"
 #include "ns3/mobility-helper.h"
 #include "ns3/multi-model-spectrum-channel.h"
+#include "ns3/neighbor-cache-helper.h"
 #include "ns3/on-off-helper.h"
 #include "ns3/packet-sink-helper.h"
 #include "ns3/packet-sink.h"
@@ -27,6 +28,7 @@
 #include "ns3/udp-server.h"
 #include "ns3/uinteger.h"
 #include "ns3/vht-phy.h"
+#include "ns3/wifi-static-setup-helper.h"
 #include "ns3/yans-wifi-channel.h"
 #include "ns3/yans-wifi-helper.h"
 
@@ -61,6 +63,8 @@
     bool useRts{false};
     bool use80Plus80{false};
     Time simulationTime{"10s"};
+    bool staticSetup{true};
+    auto clientAppStartTime = Seconds(1);
     meter_u distance{1.0};
     std::string mcsStr;
     std::vector<uint64_t> mcsValues;
@@ -71,6 +75,9 @@
     double maxExpectedThroughput{0.0};
 
     CommandLine cmd(__FILE__);
+    cmd.AddValue("staticSetup",
+                 "Whether devices are configured using the static setup helper",
+                 staticSetup);
     cmd.AddValue("distance",
                  "Distance in meters between the station and the access point",
                  distance);
@@ -247,6 +254,8 @@
                     mac.SetType("ns3::ApWifiMac",
                                 "EnableBeaconJitter",
                                 BooleanValue(false),
+                                "BeaconGeneration",
+                                BooleanValue(!staticSetup),
                                 "Ssid",
                                 SsidValue(ssid));
                     apDevice = wifi.Install(phy, mac, wifiApNode);
@@ -289,6 +298,16 @@
                 mobility.Install(wifiApNode);
                 mobility.Install(wifiStaNode);
 
+                if (staticSetup)
+                {
+                    /* static setup of association and BA agreements */
+                    auto apDev = DynamicCast<WifiNetDevice>(apDevice.Get(0));
+                    NS_ASSERT(apDev);
+                    WifiStaticSetupHelper::SetStaticAssociation(apDev, staDevice);
+                    WifiStaticSetupHelper::SetStaticBlockAck(apDev, staDevice, {0});
+                    clientAppStartTime = MilliSeconds(1);
+                }
+
                 /* Internet stack*/
                 InternetStackHelper stack;
                 stack.Install(wifiApNode);
@@ -304,6 +323,13 @@
                 staNodeInterface = address.Assign(staDevice);
                 apNodeInterface = address.Assign(apDevice);
 
+                if (staticSetup)
+                {
+                    /* static setup of ARP cache */
+                    NeighborCacheHelper nbCache;
+                    nbCache.PopulateNeighborCache();
+                }
+
                 /* Setting applications */
                 const auto maxLoad = VhtPhy::GetDataRate(mcs,
                                                          MHz_u{static_cast<double>(width)},
@@ -319,7 +345,7 @@
                     streamNumber += server.AssignStreams(wifiStaNode.Get(0), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
                     const auto packetInterval = payloadSize * 8.0 / maxLoad;
 
                     UdpClientHelper client(staNodeInterface.GetAddress(0), port);
@@ -329,8 +355,8 @@
                     ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
                     streamNumber += client.AssignStreams(wifiApNode.Get(0), streamNumber);
 
-                    clientApp.Start(Seconds(1));
-                    clientApp.Stop(simulationTime + Seconds(1));
+                    clientApp.Start(clientAppStartTime);
+                    clientApp.Stop(simulationTime + clientAppStartTime);
                 }
                 else
                 {
@@ -343,7 +369,7 @@
                         packetSinkHelper.AssignStreams(wifiStaNode.Get(0), streamNumber);
 
                     serverApp.Start(Seconds(0));
-                    serverApp.Stop(simulationTime + Seconds(1));
+                    serverApp.Stop(simulationTime + clientAppStartTime);
 
                     OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
                     onoff.SetAttribute("OnTime",
@@ -358,13 +384,13 @@
                     ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
                     streamNumber += onoff.AssignStreams(wifiApNode.Get(0), streamNumber);
 
-                    clientApp.Start(Seconds(1));
-                    clientApp.Stop(simulationTime + Seconds(1));
+                    clientApp.Start(clientAppStartTime);
+                    clientApp.Stop(simulationTime + clientAppStartTime);
                 }
 
                 Ipv4GlobalRoutingHelper::PopulateRoutingTables();
 
-                Simulator::Stop(simulationTime + Seconds(1));
+                Simulator::Stop(simulationTime + clientAppStartTime);
                 Simulator::Run();
 
                 auto rxBytes = 0.0;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/.github/workflows/per_commit.yml ns-3.46/.github/workflows/per_commit.yml
--- ns-3.45/.github/workflows/per_commit.yml	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/.github/workflows/per_commit.yml	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,219 @@
+name: "CI"
+
+on: [push]
+jobs:
+  Ubuntu:
+    runs-on: ubuntu-latest
+    outputs:
+      cache_misses: ${{ env.cache_misses }}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install required packages
+        run: |
+          sudo apt-get update
+          sudo apt-get -y install apt-utils
+          sudo apt-get -y install git gcc g++ cmake python3 make ninja-build
+          sudo apt-get -y install tcpdump libgsl-dev libxml2-dev
+          sudo apt-get -y install curl unzip tar
+          sudo apt-get -y install ccache
+      - name: Get timestamp
+        id: time
+        run: python3 -c "from datetime import datetime; print('time='+datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))" >> $GITHUB_ENV
+      - name: Restore ccache
+        id: ccache
+        uses: actions/cache@v4
+        with:
+          path: .ccache
+          key: ubuntu-ci-${{env.time}}
+          restore-keys: ubuntu-ci-
+      - name: Setup ccache
+        run: |
+          ccache --set-config=cache_dir="$GITHUB_WORKSPACE/.ccache"
+          ccache --set-config=max_size=400M
+          ccache --set-config=compression=true
+          ccache -z
+      - name: Configure CMake
+        run: |
+          ./ns3 configure -d release --enable-asserts --enable-examples --enable-tests --disable-werror -G"Ninja"
+      - name: Build ns-3
+        run: |
+          ./ns3 build
+      - name: Print ccache statistics
+        id: ccache_results
+        run: |
+          ccache -s
+          python3 -c "import re, subprocess;print('cache_misses=%d' % int(re.findall('cache_miss(.*)', subprocess.check_output(['ccache', '--print-stats']).decode())[0]))" >> $GITHUB_ENV
+      - name: Run tests and examples
+        if: env.cache_misses != '0'
+        run: python3 test.py --no-build --verbose-failed
+
+  Codecov:
+    runs-on: ubuntu-latest
+    needs: Ubuntu
+    if: needs.Ubuntu.outputs.cache_misses != '0'
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install required packages
+        run: |
+          sudo apt-get update
+          sudo apt-get -y install apt-utils
+          sudo apt-get -y install git gcc g++ cmake python3 make ninja-build
+          sudo apt-get -y install tcpdump libgsl-dev libxml2-dev
+          sudo apt-get -y install curl unzip tar
+          sudo apt-get -y install ccache
+          sudo apt-get -y install lcov
+      - name: Get timestamp
+        id: time
+        run: python3 -c "from datetime import datetime; print('time='+datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))" >> $GITHUB_ENV
+      - name: Restore ccache
+        id: ccache
+        uses: actions/cache@v4
+        with:
+          path: .ccache
+          key: ubuntu-coverage-${{env.time}}
+          restore-keys: ubuntu-coverage-
+      - name: Setup ccache
+        run: |
+          ccache --set-config=cache_dir="$GITHUB_WORKSPACE/.ccache"
+          ccache --set-config=max_size=400M
+          ccache --set-config=compression=true
+          ccache -z
+      - name: Configure CMake
+        run: |
+          ./ns3 configure --enable-asserts --enable-examples --enable-tests --disable-werror --enable-gcov -G"Ninja"
+      - name: Build ns-3
+        run: |
+          ./ns3 build
+      - name: Print ccache statistics
+        id: ccache_results
+        run: |
+          ccache -s
+          python3 -c "import re, subprocess;print('cache_misses=%d' % int(re.findall('cache_miss(.*)', subprocess.check_output(['ccache', '--print-stats']).decode())[0]))" >> $GITHUB_ENV
+      - name: Generate coverage data and submit to codecov.io
+        if: env.cache_misses != '0'
+        run: |
+          ./ns3 build coverage_gcc
+          cd ./build/coverage
+          bash <(curl -s https://codecov.io/bash) -f ns3.info || echo "Codecov did not collect coverage reports"
+        env:
+          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+  Windows_MinGW:
+    runs-on: windows-latest
+    defaults:
+      run:
+        shell: msys2 {0}
+    steps:
+      - uses: actions/checkout@v4
+      - uses: msys2/setup-msys2@v2
+      - name: Install required msys2/mingw64 packages
+        run: |
+          pacman -S --noconfirm \
+          unzip \
+          tar \
+          mingw-w64-x86_64-curl \
+          mingw-w64-x86_64-binutils \
+          mingw-w64-x86_64-cmake \
+          mingw-w64-x86_64-gcc \
+          mingw-w64-x86_64-ninja \
+          mingw-w64-x86_64-python \
+          mingw-w64-x86_64-ccache \
+          mingw-w64-x86_64-gsl \
+          mingw-w64-x86_64-libxml2 \
+          mingw-w64-x86_64-lld \
+          mingw-w64-x86_64-sed
+          pacman --noconfirm -Scc
+      - name: Get timestamp
+        id: time
+        run: python3 -c "from datetime import datetime; print('time='+datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))" >> $GITHUB_ENV
+      - name: Restore ccache
+        id: ccache
+        uses: actions/cache@v4
+        with:
+          path: .ccache
+          key: msys2-${{env.time}}
+          restore-keys: msys2-
+      - name: Setup ccache
+        run: |
+          ccache --set-config=cache_dir="$GITHUB_WORKSPACE/.ccache"
+          ccache --set-config=max_size=400M
+          ccache --set-config=compression=true
+          ccache -z
+      - name: Configure CMake
+        run: |
+          python3 ns3 configure -d release --enable-asserts --enable-examples --enable-tests --disable-werror -G"Ninja"
+      - name: Build ns-3
+        run: |
+          python3 ns3 build
+      - name: Print ccache statistics
+        id: ccache_results
+        run: |
+          ccache -s
+          python3 -c "import re, subprocess;print('cache_misses=%d' % int(re.findall('cache_miss(.*)', subprocess.check_output(['ccache', '--print-stats']).decode())[0]))" >> $GITHUB_ENV
+      - name: Run tests and examples
+        if: env.cache_misses != '0'
+        run: python3 test.py --no-build --verbose-failed
+
+  Mac_OS_X:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ macos-latest, macos-14 ]
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install required packages
+        run: |
+          brew uninstall cmake ninja
+          brew install ninja cmake ccache libxml2 gsl open-mpi #qt5
+      - name: Get timestamp
+        id: time
+        run: python3 -c "from datetime import datetime; print('time='+datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))" >> $GITHUB_ENV
+      - name: Restore ccache
+        id: ccache
+        uses: actions/cache@v4
+        with:
+          path: .ccache
+          key: osx_brew-ci-${{env.time}}
+          restore-keys: osx_brew-ci-
+      - name: Setup ccache
+        run: |
+          export PATH=/usr/local/bin:$PATH #:/usr/local/opt/qt/bin
+          ccache --set-config=cache_dir="$GITHUB_WORKSPACE/.ccache"
+          ccache --set-config=max_size=400M
+          ccache --set-config=compression=true
+          ccache -z
+      - name: Configure CMake
+        run: |
+          export PATH=/usr/local/bin:$PATH #:/usr/local/opt/qt/bin
+          ./ns3 configure -d release --enable-asserts --enable-examples --enable-tests --disable-werror -G"Ninja"
+      - name: Build ns-3
+        run: |
+          export PATH="$PATH" #:/usr/local/opt/qt/bin
+          ./ns3 build
+      - name: Print ccache statistics
+        id: ccache_results
+        run: |
+          ccache -s
+          python3 -c "import re, subprocess;print('cache_misses=%d' % int(re.findall('cache_miss(.*)', subprocess.check_output(['ccache', '--print-stats']).decode())[0]))" >> $GITHUB_ENV
+      - name: Run tests and examples
+        if: env.cache_misses != '0'
+        run: ./test.py --no-build --verbose-failed
+  Windows_Visual_Studio:
+    runs-on: windows-latest
+    defaults:
+      run:
+        shell: cmd
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v5
+      - name: Configure CMake
+        run: |
+          %comspec% /k ""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat""
+          python ns3 configure --enable-tests --enable-examples --enable-asserts -d release -- -G"Visual Studio 17 2022" -A x64 -T ClangCL
+      - name: Build ns-3
+        run: |
+          %comspec% /k ""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat""
+          python ns3 build
+      - name: Run tests and examples
+        run: |
+          set PATH=%CD%\build;%PATH%
+          python .\test.py --no-build --verbose-failed
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/.markdownlint.yml ns-3.46/.markdownlint.yml
--- ns-3.45/.markdownlint.yml	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/.markdownlint.yml	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,20 @@
+# Markdownlint Rules
+
+# Configuration file schema:
+# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
+
+# Markdown lint rules:
+#   Individual rules: https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md
+#   Tags: https://github.com/DavidAnson/markdownlint#tags
+
+# Markdownlint CLI usage:
+# https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#usage
+#
+# Example with Docker:
+#   docker run -v $PWD:/workdir ghcr.io/igorshubovych/markdownlint-cli:latest . [--fix]
+
+default: true
+
+descriptive-link-text: false # MD059
+line-length: false # MD013
+no-duplicate-heading: false # MD024
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/ns3 ns-3.46/ns3
--- ns-3.45/ns3	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/ns3	2025-10-01 18:46:32.000000000 -0700
@@ -26,6 +26,11 @@
 path_sep = ";" if ";" in os.environ["PATH"] else ":"
 path_variable = "$PATH" if path_sep == ":" else "%PATH%"
 
+try:
+    TERMINAL_WIDTH = os.get_terminal_size().columns
+except OSError:
+    TERMINAL_WIDTH = 80  # assume 80 columns when grepping
+
 
 # Prints everything in the print_buffer on exit
 def exit_handler(dry_run):
@@ -107,6 +112,19 @@
         default=None,
         dest="main_help",
     )
+    parser.add_argument(
+        "--compile-or-die",
+        help=(
+            "Build and test each individual commit between a base and an head commits.\n"
+            "This is especially useful when preparing MRs or rewriting git history, and ensuring refactor-or-die "
+            "principle is being followed"
+        ),
+        action="store",
+        nargs=2,
+        type=str,
+        default=[None, None],
+        metavar="compile_or_die",
+    )
     parser_help = sub_parser.add_parser("help", help="Print a summary of available commands")
     parser_help.add_argument(
         "help", help="Print a summary of available commands", action="store_true", default=False
@@ -166,7 +184,11 @@
     )
 
     parser_configure.add_argument(
-        "--cxx-standard", help="Compile NS-3 with the given C++ standard", type=str, default=None
+        "--cxx-standard",
+        help="Compile NS-3 with the given C++ standard",
+        type=str,
+        default=None,
+        choices=["23", "26"],
     )
 
     # On-Off options
@@ -218,7 +240,7 @@
     )
     parser_configure.add_argument(
         "--disable-modules",
-        help='List of modules not to build (e.g. "lte;wimax")',
+        help='List of modules not to build (e.g. "lte;wifi")',
         action="store",
         type=str,
         default=None,
@@ -520,7 +542,7 @@
             if custom_exit in e.message:
                 error_message = f"Exiting due to {e.message[e.message.index(custom_exit):]}"
         # Format error message to better fit the terminal width
-        print("\n".join(textwrap.wrap(error_message, width=os.get_terminal_size().columns)))
+        print("\n".join(textwrap.wrap(error_message, width=TERMINAL_WIDTH)))
         exit(1)
 
     # If run doesn't have a target, print the help message of the run parser
@@ -1179,8 +1201,6 @@
     current_settings.extend(re.findall("(CMAKE_GENERATOR):.*=(.*)", contents))  # extract generator
     current_settings.extend(re.findall("(CMAKE_CXX_COMPILER):.*=(.*)", contents))  # C++ compiler
     current_settings.extend(re.findall("(CMAKE_CXX_FLAGS):.*=(.*)", contents))  # C++ flags
-    current_settings.extend(re.findall("(CMAKE_C_COMPILER):.*=(.*)", contents))  # C compiler
-    current_settings.extend(re.findall("(CMAKE_C_FLAGS):.*=(.*)", contents))  # C flags
     current_settings.extend(
         re.findall("(CMAKE_INSTALL_PREFIX):.*=(.*)", contents)
     )  # installation directory
@@ -1505,12 +1525,12 @@
             # running mpi on the CI?
             if target_to_run in ["mpiexec", "mpirun"] and os.getenv("MPI_CI"):
                 if shutil.which("ompi_info"):
-                    target_args = ["--oversubscribe"] + target_args
                     try:
                         subprocess.check_call([target_to_run, "--allow-run-as-root", "dir"])
                         target_args = ["--allow-run-as-root"] + target_args
                     except subprocess.CalledProcessError:
                         pass
+                    target_args = ["--oversubscribe"] + target_args
 
     program_arguments = [*debugging_software, target_to_run, *target_args]
 
@@ -1571,11 +1591,7 @@
     def list_to_table(targets_list: list) -> str:
         # Set column width and check how much is space is left at the end
         columnwidth = 30
-        try:
-            terminal_width = os.get_terminal_size().columns
-        except OSError:
-            terminal_width = 80  # assume 80 columns when grepping
-        dead_space = terminal_width % columnwidth
+        dead_space = TERMINAL_WIDTH % columnwidth
 
         # Filter the targets with names longer than the column width
         large_items = list(filter(lambda x: len(x) >= columnwidth, targets_list))
@@ -1589,7 +1605,7 @@
             current_end = len(output)
             # If the terminal width minus the written columns is smaller than the dead space,
             # we add a new line and start counting the width of the new line from it
-            if terminal_width - (current_end - prev_new_line) < dead_space:
+            if TERMINAL_WIDTH - (current_end - prev_new_line) < dead_space:
                 prev_new_line = len(output)
                 output += "\n"
             # After the new line or space, add the item plus some spacing
@@ -1655,6 +1671,121 @@
         exit(0)
 
 
+def compile_or_die(base_commit, head_commit):
+    try:
+        import git.exc
+        from git import Repo
+    except ImportError:
+        raise Exception("Missing pip package 'GitPython'.")
+
+    if shutil.which("git") is None:
+        raise Exception("Missing program 'git'.")
+
+    # Load ns-3 and module git repositories
+    NS3_DIR = os.path.abspath(os.path.dirname(__file__))
+    SRC_DIR = os.path.join(NS3_DIR, "src")
+    CONTRIB_DIR = os.path.join(NS3_DIR, "contrib")
+    git_repos_dirs = [NS3_DIR]
+    git_repos_dirs.extend(map(lambda x: os.path.join(SRC_DIR, x), os.listdir(SRC_DIR)))
+    git_repos_dirs.extend(map(lambda x: os.path.join(CONTRIB_DIR, x), os.listdir(CONTRIB_DIR)))
+    git_repos_dirs = list(filter(lambda x: os.path.isdir(x), git_repos_dirs))
+    git_repos_dirs = list(filter(lambda x: os.path.exists(os.path.join(x, ".git")), git_repos_dirs))
+    git_repos = []
+    for repo_dir in git_repos_dirs:
+        try:
+            git_repos.append(Repo(repo_dir))
+        except Exception as e:
+            raise Exception(f"Failed to load git repository in {repo_dir}: {e}")
+
+    # Check which particular repo we are testing (contain both base and top commits)
+    tested_repo = None
+    commits = None
+    for git_repo in git_repos:
+        commits = list(git_repo.iter_commits(all=True))
+        base_commit_object = list(filter(lambda x: x.hexsha == base_commit, commits))
+        head_commit_object = list(filter(lambda x: x.hexsha == head_commit, commits))
+        if base_commit_object and head_commit_object:
+            tested_repo = git_repo
+            break
+
+    if not tested_repo:
+        raise Exception("Base and head commits were not found in any of the git repositories")
+
+    # Filter commits we want to test
+    commits_sha = list(map(lambda x: x.hexsha, commits))
+    commits = commits[commits_sha.index(head_commit) : commits_sha.index(base_commit) + 1]
+
+    # Check if there are uncommitted changes, that will be lost if we proceed
+    diff = tested_repo.git.diff()
+    if diff:
+        print(
+            "Interrupted compile-or-die testing to prevent data loss."
+            "Uncommitted changes were found. Commit them or remove them before proceeding."
+        )
+        exit(-1)
+
+    # Check if head commit has a branch attached to it
+    branches_with_head_commit = list(
+        filter(
+            lambda x: x.commit.hexsha == head_commit and x.name != "compileOrDieTest",
+            list(tested_repo.branches),
+        )
+    )
+    if not branches_with_head_commit:
+        # If not, then create one (compileOrDieBackup), otherwise we could lose data
+        compile_or_die_backup_branch = list(
+            filter(lambda x: x.name == "compileOrDieBackup", list(tested_repo.branches))
+        )
+        if not compile_or_die_backup_branch:
+            # If the backup branch does not exist, we can safely create it
+            tested_repo.create_head("compileOrDieBackup", commits[0]).checkout()
+        else:
+            # If the backup branch already exist, we actually need to check if there
+            # is another branch attached to it, otherwise we could lose data
+            branches_of_backup = list(
+                filter(
+                    lambda x: x.commit.hexsha == compile_or_die_backup_branch.commit.hexsha,
+                    list(tested_repo.branches),
+                )
+            )
+            if len(branches_of_backup) == 1:
+                print(
+                    "Interrupted compile-or-die testing to prevent data loss."
+                    "Make sure the head commit of the compileOrDieBackup branch has a second branch attached to it."
+                )
+                exit(-1)
+            compile_or_die_backup_branch[0].set_commit(commits[0])
+            compile_or_die_backup_branch[0].checkout()
+            compile_or_die_backup_branch[0].repo.git.reset("--hard")
+
+    # Checkout the test branch
+    compile_or_die_test_branch = tested_repo.create_head("compileOrDieTest")
+
+    # Reset the test branch to a specific commit, then hard reset it
+    # From oldest to newest
+    commits = list(reversed(commits))
+    print(f"Compile-or-die with commits: {list(map(lambda x: x.hexsha, commits))}")
+    for commit in commits:
+        print(f"\tTesting commit {commit.hexsha}")
+        compile_or_die_test_branch.set_commit(commit)
+        compile_or_die_test_branch.checkout()
+        compile_or_die_test_branch.repo.git.reset("--hard")
+        try:
+            ret = subprocess.run(
+                [sys.executable, "./test.py", "--verbose-failed"],
+                cwd=ns3_path,
+                capture_output=True,
+                shell=False,
+            )
+            if ret.returncode != 0:
+                print("\t\t" + ret.stdout.decode().replace("\n", "\n\t\t"))
+        except Exception as e:
+            tested_repo.checkout("compileOrDieBackup")  # Revert to head commit
+            print(f"Failed compile-or-die testing in commit {commit}")
+            exit(1)
+    exit(0)
+
+
 # Debugging this with PyCharm is a no no. It refuses to work hanging indefinitely
 def sudo_command(command: list, password: str):
     # Run command and feed the sudo password
@@ -1878,6 +2009,10 @@
     if ns3_modules is None:
         project_not_configured()
 
+    # Entry point for compile-or-die
+    if args.compile_or_die[0] and args.compile_or_die[1]:
+        compile_or_die(*args.compile_or_die)
+
     # We could also replace the "ns3-" prefix used in .lock-ns3 with the "lib" prefix currently used in cmake
     ns3_modules = [module.replace("ns3-", "") for module in ns3_modules]
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/.ns3.supp ns-3.46/.ns3.supp
--- ns-3.45/.ns3.supp	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/.ns3.supp	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,10 @@
+# This is the valgrind suppression file for ns-3.
+
+# libucs is included by openMPI. Added Feb 2024.
+# Errors generated by openucx 1.15.0-2
+{
+   ignore_libucs_init_memory_leak
+   Memcheck:Leak
+   ...
+   obj:*/libucs.so.*
+}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/RELEASE_NOTES.md ns-3.46/RELEASE_NOTES.md
--- ns-3.45/RELEASE_NOTES.md	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/RELEASE_NOTES.md	2025-10-01 18:46:49.000000000 -0700
@@ -12,6 +12,59 @@
 and references prefixed by '!' refer to a
 [GitLab.com merge request](https://gitlab.com/nsnam/ns-3-dev/-/merge_requests) number.
 
+## Release 3.46
+
+This release is available from:
+<https://www.nsnam.org/release/ns-3.46.tar.bz2>
+
+### Supported platforms
+
+This release is intended to work on systems with the following minimal
+requirements (Note: not all ns-3 features are available on all systems):
+
+- g++-11.1 or later, or LLVM/clang++-17 or later
+- Python 3.8 or later
+- CMake 3.20 or later
+- (macOS only) Xcode 16.2 or later
+- (Windows only) Msys2/MinGW64, Msys2/UCRT64 and ClangCL/MSVC toolchains, or WSL2
+
+Note that the minimum C++ compiler versions have increased since the last release.
+
+The version of clang-format enforced by the check-style-clang-format.py script for
+this release is version 20 only; the previous ns-3 release was compatible with versions 15-19.
+
+Version 20 of the clang-tidy linter is now supported and recommended, although versions 15-19
+are still compatible.
+
+Python API requires [Cppyy](https://cppyy.readthedocs.io/en/latest/installation.html) and has only
+been tested on Linux. As of this release, the latest known version to work with ns-3 is cppyy==3.5.0.
+
+### New user-visible features
+
+ns-3 has switched to the C++23 standard by default.
+
+The wimax module was removed and moved to the ns-3 App Store.
+
+- (antenna) !2516 - Reformatted documentation
+- (documentation) !2519 - Improve models documentation look and feel
+- (core) A stacktrace will now be printed on fatal errors in supported platforms.
+- (zigbee) !2512 - Added Groupcast (Multicast) support
+- (zigbee) Added basic APS layer support
+- (spectrum) !2452 - Added new wraparound model support for spectrum channels, and the hexagonal wraparound model, typical of cellular deployments
+
+### Bugs fixed
+
+- (examples) #1146 - Fixed three-gpp-v2v-channel-example to prevent pathloss from being incorrectly accumulated over time
+- (internet) #851 - NeighborCacheHelper entries are no longer removed due to LinkUp events
+- (internet) #809 - Fixed IPv4,6 Raw Socket fragmentation issue
+- (internet) #1251 - Added check for longest prefix match in GlobalRouting
+- (stats) #295 - Added 100 ms timeout for sqlite3 operations to prevent hangs
+- (wifi) !2524 - Fix corrupted radiotap header when EHT is used.
+- (wifi) Block transmission on other EMLSR links as soon as it is detected that the main PHY is receiving an A-MPDU, to prevent that the EMLSR client starts an UL TXOP before the end of the A-MPDU
+- (wifi) EMLSR clients can switch to listening operations when receiving the MAC header of a broadcast frame that is not a Trigger Frame nor a Multi-STA BA
+- (wifi) Immediate channel access should not be postponed by a backoff slot if channel access is requested at a slot boundary
+- (wifi) Reset backoffs only if PHY went to sleep or off for more than a threshold
+
 ## Release 3.45
 
 This release is available from:
@@ -52,6 +105,7 @@
 
 - (bindings) #1187 - Fix library filtering to skip non-ns-3 libraries with "ns3" in their names.
 - (flow-monitor) #1202 - Create XML file in text mode
+- (internet) !2486 - Fix #809 - Ping for v4,v6 works now if fragmentation occurs.
 - (mobility) !2397 - Fix Rectangle::GetClosestSideOrCorner. It could assign the incorrect side when the checked position was outside the rectangle.
 - (wifi) #2368 - Fix various issues related to Content Channels and RU allocation. Fixes mostly covers cases where OFDMA is used with central 26 tones, where a single user is being assigned the whole PPDU bandwidth or where a RU is larger than 20 MHz.
 - (wifi) Various fixes to the EMLSR model have been made
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/scratch/CMakeLists.txt ns-3.46/scratch/CMakeLists.txt
--- ns-3.45/scratch/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/scratch/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -40,17 +40,7 @@
   string(REPLACE "/" "_" scratch_dirname "${scratch_dirname}")
 
   # Get source name
-  if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0")
-    get_filename_component(scratch_name ${scratch_src} NAME_WLE)
-  else()
-    get_filename_component(scratch_name ${scratch_src} NAME)
-    string(FIND "${scratch_name}" "." ext_position REVERSE)
-    if(${ext_position} EQUAL -1)
-      message(FATAL_ERROR "Source file has no extension: ${scratch_src}")
-    else()
-      string(SUBSTRING "${scratch_name}" 0 ${ext_position} scratch_name)
-    endif()
-  endif()
+  get_filename_component(scratch_name ${scratch_src} NAME_WLE)
 
   set(target_prefix scratch_)
   if(scratch_dirname)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/antenna.rst ns-3.46/src/antenna/doc/antenna.rst
--- ns-3.45/src/antenna/doc/antenna.rst	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/antenna/doc/antenna.rst	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,334 @@
+.. include:: replace.txt
+.. highlight:: cpp
+.. highlight:: bash
+
+Antenna
+=======
+
+The Antenna module provides:
+
+- A class ``Angles`` and utility functions to deal with angles.
+- A base class ``AntennaModel`` that provides an interface for the modeling of the radiation pattern of an antenna with a set of classes derived from this base class, each models the radiation pattern of different types of antennas.
+- A base class ``PhasedArrayModel`` that provides a flexible interface for modeling a number of Phase Antenna Array (PAA) models.
+- A class ``UniformPlanarArray`` derived from this base class, implementing a Uniform Planar Array (UPA) supporting both rectangular and linear lattices.
+
+ The antenna model can be used with all the wireless technologies and physical layer models that support it.
+ Currently, this includes the physical layer models based on the ``SpectrumPhy`` class. Please refer to the documentation of each of these models for details.
+
+Scope and Limitations
+---------------------
+
+Not present.
+
+Angles
+------
+
+The Angles class holds information about an angle in 3D space using spherical coordinates in radian units.
+Specifically, it uses the azimuth-inclination convention, where
+
+* Inclination is the angle between the zenith direction (positive z-axis) and the desired direction. It is included in the range [0, pi] radians.
+* Azimuth is the signed angle measured from the positive x-axis, where a positive direction goes towards the positive y-axis. It is included in the range [-pi, pi) radians.
+
+Multiple constructors are present, supporting the most common ways to encode information on a direction.
+A static boolean variable allows the user to decide whether angles should be printed in radian or degree units.
+
+A number of angle-related utilities are offered, such as radians/degree conversions, for both scalars and vectors, and angle wrapping.
+
+AntennaModel
+------------
+
+The AntennaModel uses the coordinate system adopted in [:ref:`1<antennaRef1>`] and
+depicted in Figure :ref:`fig-antenna-coordinate-system`. This system
+is obtained by translating the Cartesian coordinate system used by the
+ns-3 MobilityModel into the new origin :math:`o` which is the location
+of the antenna, and then transforming the coordinates of every generic
+point :math:`p` of the space from Cartesian coordinates
+:math:`(x,y,z)` into spherical coordinates
+:math:`(r, \theta,\phi)`.
+
+The antenna model neglects the radial component :math:`r`, and
+only considers the angle components :math:`(\theta, \phi)`. An antenna
+radiation pattern is then expressed as a mathematical function
+:math:`g(\theta, \phi) \longrightarrow \mathcal{R}` that returns the
+gain (in dB) for each possible direction of
+transmission/reception. All angles are expressed in radians.
+
+
+.. _fig-antenna-coordinate-system:
+
+.. figure:: figures/antenna-coordinate-system.*
+   :align: center
+
+   Coordinate system of the AntennaModel
+
+The ``AntennaModel`` is used to implement a subset of derived classes that represents different radiation patterns of a single antenna.
+
+The current models supported are:
+
+- Isotropic Antenna Model
+- Cosine Antenna Model
+- Parabolic Antenna Model
+- Three Gpp Antenna Model
+
+
+**Isotropic Antenna Model**
+
+This is the simplest antenna model. This antenna radiation pattern model provides the same gain (0 dB) for all directions.
+This is implemented in the ``IsotropicAntennaModel`` class.
+
+**Cosine Antenna Model**
+
+This is the cosine model described in [:ref:`2<antennaRef2>`]: the antenna gain is
+determined as:
+
+.. math::
+
+  g(\phi, \theta) = \cos^{n} \left(\frac{\phi - \phi_{0}}{2}  \right)
+
+where :math:`\phi_{0}` is the azimuthal orientation of the antenna
+(i.e., its direction of maximum gain) and the exponential
+
+.. math::
+
+  n = -\frac{3}{20 \log_{10} \left( \cos \frac{\phi_{3dB}}{4} \right)}
+
+determines the desired 3dB beamwidth :math:`\phi_{3dB}`. Note that
+this radiation pattern is independent of the inclination angle
+:math:`\theta`.
+
+A major difference between the model of [:ref:`2<antennaRef2>`] and the one
+implemented in the class CosineAntennaModel is that only the element
+factor (i.e., what described by the above formulas) is considered. In
+fact, [:ref:`2<antennaRef2>`] also considered an additional antenna array
+factor. The reason why the latter is excluded is that we expect that
+the average user would desire to specify a given beamwidth exactly,
+without adding an array factor at a latter stage which would in
+practice alter the effective beamwidth of the resulting radiation
+pattern.
+
+This is implemented in the ``CosineAntennaModel`` class.
+
+.. _ParabolicAntennaModel:
+
+**Parabolic Antenna Model**
+
+This model is based on the parabolic approximation of the main lobe radiation pattern. It is often
+used in the context of cellular system to model the radiation pattern of a cell sector, see for
+instance [:ref:`3<antennaRef3>`] and [:ref:`4<antennaRef4>`]. The antenna gain in dB is determined as:
+
+.. math::
+
+  g_{dB}(\phi, \theta) = -\min \left( 12 \left(\frac{\phi  - \phi_{0}}{\phi_{3dB}} \right)^2, A_{max} \right)
+
+where :math:`\phi_{0}` is the azimuthal orientation of the antenna
+(i.e., its direction of maximum gain), :math:`\phi_{3dB}` is its 3 dB
+beamwidth, and :math:`A_{max}` is the maximum attenuation in dB of the
+antenna. Note that this radiation pattern is independent of the inclination angle
+:math:`\theta`.
+
+This is implemented in the ``ParabolicAntennaModel`` class.
+
+**Three Gpp Antenna Model**
+
+This model implements the antenna element described in [:ref:`5<antennaRef5>`].
+Parameters are fixed from the technical report, thus no attributes nor setters are provided.
+The model is largely based on the :ref:`Parabolic Antenna Model<ParabolicAntennaModel>`.
+
+Phased Array Model
+------------------
+
+The class ``PhasedArrayModel`` has been created with flexibility in mind.
+It abstracts the basic idea of a Phased Antenna Array (PAA) by removing any constraint on the
+position of each element, and instead generalizes the concept of steering and beamforming vectors,
+solely based on the generalized location of the antenna elements.
+For details on Phased Array Antennas see for instance [:ref:`6<antennaRef6>`].
+
+Derived classes must implement the following functions:
+
+* ``GetNumElems``: returns the number of antenna elements
+* ``GetElementLocation``: returns the location of the antenna element with the specified index, normalized with respect to the wavelength
+* ``GetElementFieldPattern``: returns the horizontal and vertical components of the antenna element field pattern at the specified direction. Same polarization (configurable) for all antenna elements of the array is considered.
+
+The class ``PhasedArrayModel`` also assumes that all antenna elements are equal, a typical key assumption which allows to model the PAA field pattern as the sum of the array factor, given by the geometry of the location of the antenna elements, and the element field pattern.
+Any class derived from ``AntennaModel`` is a valid antenna element for the ``PhasedArrayModel``, allowing for a great flexibility of the framework.
+
+.. _3gpp-antenna-model:
+
+Uniform Planar Array (UPA)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The class UniformPlanarArray is a generic implementation of Uniform Planar Arrays (UPAs),
+supporting rectangular and linear regular lattices.
+It closely follows the implementation described in the 3GPP TR 38.901 [:ref:`7<antennaRef7>`],
+considering only a single panel, i.e., :math:`N_{g} = M_{g} = 1`.
+
+By default, the antenna array is orthogonal to the x-axis, pointing towards the positive
+direction, but the orientation can be changed through the attributes ``BearingAngle``,
+which adjusts the azimuth angle, and ``DowntiltAngle``, which adjusts the elevation angle.
+The slant angle is instead fixed and assumed to be 0.
+
+The number of antenna elements in the vertical and horizontal directions can be configured
+through the attributes ``NumRows`` and ``NumColumns``, while the spacing between the horizontal
+and vertical elements can be configured through the attributes ``AntennaHorizontalSpacing``
+and ``AntennaVerticalSpacing``.
+
+UniformPlannarArray supports the concept of antenna ports following the sub-array partition
+model for TXRU virtualization, as described in Section 5.2.2 of 3GPP TR 36.897 [:ref:`8<antennaRef8>`].
+The number of antenna ports in vertical and horizontal directions can be configured through
+the attributes ``NumVerticalPorts`` and ``NumHorizontalPorts``, respectively. For example,
+if ``NumRows`` and ``NumColumns`` are configured to 2 and 4, and the number of
+``NumVerticalPorts`` and ``NumHorizontalPorts`` to 1 and 2, then the antenna elements belonging
+to the first two columns of the antenna array will belong to the first antenna port,
+and the third and the fourth columns will belong to the second antenna port. Note that
+``NumRows`` and ``NumColumns`` must be a multiple of ``NumVerticalPorts`` and ``NumHorizontalPorts``,
+respectively.
+
+Whether the antenna is dual-polarized or not is configured through the attribute
+``IsDualPolarized``. In case the antenna array is dual polarized, the total number
+of antenna elements is doubled and the two polarizations are overlapped in space.
+The polarization slant angle of the antenna elements belonging to the first polarization
+are configured through the attribute ``PolSlantAngle``; while the antenna elements of
+the second polarization have the polarization slant angle minus 90 degrees,
+as described in [:ref:`7<antennaRef7>`] (i.e., :math:`{\zeta}`).
+
+Circular Aperture Antenna Model
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The class ``CircularApertureAntennaModel`` implements the radiation pattern described in [:ref:`7<antennaRef7>`].
+Specifically, the latter represents parabolic antennas, i.e., antennas which are typically used
+for achieving long range communications such as earth-to-satellite links.
+The default boresight orientation is parallel to the positive z-axis, and it can be tuned by
+using the ``AntennaInclination`` and ``AntennaAzimuth`` parameters.
+This implementation provides an exact characterization of the antenna field pattern, by leveraging
+the standard library Bessel functions implementation introduced with C++17.
+Accordingly, the antenna gain :math:`G` at an angle :math:`\theta` from the boresight main beam
+is evaluated as:
+
+.. math::
+   G \cdot 4\left | \frac{J_{1}\left ( k\cdot a\cdot sin\theta \right )}{k\cdot a\cdot sin\theta} \right
+   |^{2}\;\;\;\;\; for\; 0<\left | \theta \right |\leq 90^{\circ} \\
+   G \cdot 1\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; for\; \theta=0
+
+where :math:`J_{1}()` is the Bessel function of the first kind and first order, and :math:`a` is
+the radius of the antenna's circular aperture.
+The parameter :math:`k` is equal to :math:`k=\frac{2\pi f}{x}`, where :math:`f` is the carrier
+frequency, and :math:`c` is the speed of light in vacuum.
+The parameters :math:`G` (in logarithmic scale), :math:`a` and :math:`f` can be configured by using
+the attributes ``AntennaMaxGainDb``, ``AntennaCircularApertureRadius`` and ``OperatingFrequency``, respectively.
+This type of antennas features a symmetric radiation pattern, meaning that a single angle, measured
+from the boresight direction, is sufficient to characterize the radiation strength along a given direction.
+
+.. _fig-circular-antenna-pattern:
+
+.. figure:: figures/circular-antenna-pattern.png
+   :align: center
+
+   Circular aperture antenna radiation pattern with :math:`G =` 38.5 dB and :math:`a =` 10 :math:`\frac{c}{f}.`
+
+Usage
+-----
+
+Not present.
+
+Helpers
+~~~~~~~
+
+Not present
+
+Attributes
+~~~~~~~~~~
+
+Not present.
+
+Traces
+~~~~~~
+
+Not present.
+
+Examples and Tests
+------------------
+
+In this section we describe the test suites included with the antenna
+module that verify its correct functionality.
+
+
+- ``test-angles.cc``: The unit test suite ``angles`` verifies that the Angles class is
+  constructed properly by correct conversion from 3D Cartesian
+  coordinates according to the available methods (construction from a
+  single vector and from a pair of vectors). For each method, several
+  test cases are provided that compare the values :math:`(\phi, \theta)`
+  determined by the constructor to known reference values. The test
+  passes if for each case the values are equal to the reference up to a
+  tolerance of :math:`10^{-10}` which accounts for numerical errors.
+
+- ``test-degree-radians.cc``: The unit test suite ``degrees-radians`` verifies that the methods
+  ``DegreesToRadians`` and ``RadiansToDegrees`` work properly by
+  comparing with known reference values in a number of test
+  cases. Each test case passes if the comparison is equal up to a
+  tolerance of :math:`10^{-10}` which accounts for numerical errors.
+
+- ``test-isotropic-antenna.cc``: The unit test suite ``isotropic-antenna-model`` checks that the
+  ``IsotropicAntennaModel`` class works properly, i.e., returns always a
+  0dB gain regardless of the direction.
+
+- ``test-cosine-antenna.cc``: The unit test suite ``cosine-antenna-model`` checks that the
+  ``CosineAntennaModel`` class works properly. Several test cases are
+  provided that check for the antenna gain value calculated at different
+  directions and for different values of the orientation, the reference
+  gain and the beamwidth. The reference gain is calculated by hand. Each
+  test case passes if the reference gain in dB is equal to the value returned
+  by ``CosineAntennaModel`` within a tolerance of 0.001, which accounts
+  for the approximation done for the calculation of the reference
+  values.
+
+- ``test-parabolic-antenna.cc``: The unit test suite ``parabolic-antenna-model`` checks that the
+  ``ParabolicAntennaModel`` class works properly. Several test cases are
+  provided that check for the antenna gain value calculated at different
+  directions and for different values of the orientation, the maximum attenuation
+  and the beamwidth. The reference gain is calculated by hand. Each
+  test case passes if the reference gain in dB is equal to the value returned
+  by ``ParabolicAntennaModel`` within a tolerance of 0.001, which accounts
+  for the approximation done for the calculation of the reference
+  values.
+
+
+Validation
+----------
+
+Validation has been performed as described in each antenna test.
+
+References
+----------
+
+.. _antennaRef1:
+
+[1] C.A. Balanis, "Antenna Theory - Analysis and Design",  Wiley, 2nd Ed.
+
+.. _antennaRef2:
+
+[2] Li Chunjian, "Efficient Antenna Patterns for Three-Sector WCDMA Systems", Master of Science Thesis, Chalmers University of Technology, Göteborg, Sweden, 2003.
+
+.. _antennaRef3:
+
+[3] 3GPP TSG RAN WG4 (Radio) Meeting #51, R4-092042, Simulation assumptions and parameters for FDD HeNB RF requirements.
+
+.. _antennaRef4:
+
+[`4 <https://dl.acm.org/doi/abs/10.1145/1234161.1234186>`_] George Calcev and Matt Dillon, "Antenna Tilt Control in CDMA Networks", in Proc. of the 2nd Annual International Wireless Internet Conference (WICON), 2006.
+
+.. _antennaRef5:
+
+[5] 3GPP. 2018. TR 38.901, Study on channel model for frequencies from 0.5 to 100 GHz, V15.0.0. (2018-06).
+
+.. _antennaRef6:
+
+[6] Robert J. Mailloux, "Phased Array Antenna Handbook", Artech House, 2nd Ed.
+
+.. _antennaRef7:
+
+[`7 <https://hscc.csie.ncu.edu.tw/38811.pdf>`_] 3GPP. 2018. TR 38.811, Study on New Radio (NR) to support non-terrestrial networks, V15.4.0. (2020-09).
+
+.. _antennaRef8:
+
+[`8 <https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2580>`_] 3GPP. 2015. TR 36.897. Study on elevation beamforming / Full-Dimension (FD) Multiple Input Multiple Output (MIMO) for LTE. V13.0.0. (2015-06).
+
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/Makefile ns-3.46/src/antenna/doc/Makefile
--- ns-3.45/src/antenna/doc/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/Makefile	1969-12-31 16:00:00.000000000 -0800
@@ -1,179 +0,0 @@
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
-
-SOURCE = source
-FIGURES = $(SOURCE)/figures
-
-# specify figures from which .png and .pdf figures need to be
-# generated (all dia and eps figures)
-IMAGES_EPS = ${FIGURES}/antenna-coordinate-system.eps
-
-# specify figures for build process (all eps figures)
-GRAPHS_EPS =
-
-# rescale pdf figures as necessary
-$(FIGURES)/antenna-coordinate-system.pdf_width = 3in
-
-IMAGES_PNG = ${IMAGES_EPS:.eps=.png}
-IMAGES_PDF = ${IMAGES_EPS:.eps=.pdf}
-
-IMAGES = $(IMAGES_EPS) $(IMAGES_PNG) $(IMAGES_PDF)
-
-RESCALE = ../../../utils/rescale-pdf.sh
-
-%.eps : %.dia; $(DIA) -t eps $< -e $@
-%.png : %.dia; $(DIA) -t png $< -e $@
-%.png : %.eps; $(CONVERT) $< $@
-%.pdf : %.eps
-	$(EPSTOPDF) $< -o=$@
-	@if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
-
-GRAPHS_PNG = ${GRAPHS_EPS:.eps=.png}
-GRAPHS_PDF = ${GRAPHS_EPS:.eps=.pdf}
-
-GRAPHS = $(GRAPHS_EPS) $(GRAPHS_PNG) $(GRAPHS_PDF)
-
-%.png : %.eps; $(CONVERT) $< $@
-%.pdf : %.eps
-	$(EPSTOPDF) $< -o=$@
-	@if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
-
-help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  html       to make standalone HTML files"
-	@echo "  dirhtml    to make HTML files named index.html in directories"
-	@echo "  singlehtml to make a single large HTML file"
-	@echo "  pickle     to make pickle files"
-	@echo "  json       to make JSON files"
-	@echo "  htmlhelp   to make HTML files and a HTML help project"
-	@echo "  qthelp     to make HTML files and a qthelp project"
-	@echo "  devhelp    to make HTML files and a Devhelp project"
-	@echo "  epub       to make an epub"
-	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
-	@echo "  text       to make text files"
-	@echo "  man        to make manual pages"
-	@echo "  changes    to make an overview of all changed/added/deprecated items"
-	@echo "  linkcheck  to check all external links for integrity"
-	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
-
-clean:
-	-rm -rf $(BUILDDIR)/*
-	-rm -f $(IMAGES_PNG)
-	-rm -f $(IMAGES_PDF)
-	-rm -f $(GRAPHS_PNG)
-	-rm -f $(GRAPHS_PDF)
-
-frag: pickle
-	@if test ! -d $(BUILDDIR)/frag; then mkdir $(BUILDDIR)/frag; fi
-	pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle  > navigation.xml && popd
-	cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag
-
-html:  $(IMAGES) ${GRAPHS}
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:  $(IMAGES)
-	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:  $(IMAGES)
-	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
-	@echo
-	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:  $(IMAGES)
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files."
-
-json:  $(IMAGES)
-	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
-	@echo
-	@echo "Build finished; now you can process the JSON files."
-
-htmlhelp:  $(IMAGES)
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:  $(IMAGES)
-	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
-	@echo
-	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
-	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ns-3.qhcp"
-	@echo "To view the help file:"
-	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ns-3.qhc"
-
-devhelp:  $(IMAGES)
-	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
-	@echo
-	@echo "Build finished."
-	@echo "To view the help file:"
-	@echo "# mkdir -p $$HOME/.local/share/devhelp/ns-3"
-	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ns-3"
-	@echo "# devhelp"
-
-epub:  $(IMAGES)
-	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
-	@echo
-	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:  $(IMAGES) ${GRAPHS}
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
-	@echo "Run \`make' in that directory to run these through (pdf)latex" \
-	      "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:  $(IMAGES) ${GRAPHS}
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-	@echo "Running LaTeX files through pdflatex..."
-	make -C $(BUILDDIR)/latex all-pdf
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:  $(IMAGES)
-	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
-	@echo
-	@echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:  $(IMAGES)
-	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
-	@echo
-	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-changes:  $(IMAGES)
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
-	@echo
-	@echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:  $(IMAGEs)
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:  $(IMAGES)
-	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
-	@echo "Testing of doctests in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/doctest/output.txt."
-
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/antenna-design.rst ns-3.46/src/antenna/doc/source/antenna-design.rst
--- ns-3.45/src/antenna/doc/source/antenna-design.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/antenna-design.rst	1969-12-31 16:00:00.000000000 -0800
@@ -1,252 +0,0 @@
-.. include:: replace.txt
-
-
-++++++++++++++++++++
-Design documentation
-++++++++++++++++++++
-
---------
-Overview
---------
-
-The Antenna module provides:
-
- #. a class (Angles) and utility functions to deal with angles
- #. a base class (AntennaModel) that provides an interface for the modeling of the radiation pattern of an antenna;
- #. a set of classes derived from this base class that each models the radiation pattern of different types of antennas;
- #. a base class (PhasedArrayModel) that provides a flexible interface for modeling a number of Phase Antenna Array (PAA) models
- #. a class (UniformPlanarArray) derived from this base class, implementing a Uniform Planar Array (UPA) supporting both rectangular and linear lattices
-
-
-------
-Angles
-------
-
-The Angles class holds information about an angle in 3D space using spherical coordinates in radian units.
-Specifically, it uses the azimuth-inclination convention, where
-
-* Inclination is the angle between the zenith direction (positive z-axis) and the desired direction. It is included in the range [0, pi] radians.
-* Azimuth is the signed angle measured from the positive x-axis, where a positive direction goes towards the positive y-axis. It is included in the range [-pi, pi) radians.
-
-Multiple constructors are present, supporting the most common ways to encode information on a direction.
-A static boolean variable allows the user to decide whether angles should be printed in radian or degree units.
-
-A number of angle-related utilities are offered, such as radians/degree conversions, for both scalars and vectors, and angle wrapping.
-
-
-------------
-AntennaModel
-------------
-
-The AntennaModel uses the coordinate system adopted in [Balanis]_ and
-depicted in Figure :ref:`fig-antenna-coordinate-system`. This system
-is obtained by translating the Cartesian coordinate system used by the
-ns-3 MobilityModel into the new origin :math:`o` which is the location
-of the antenna, and then transforming the coordinates of every generic
-point :math:`p` of the space from Cartesian coordinates
-:math:`(x,y,z)` into spherical coordinates
-:math:`(r, \theta,\phi)`.
-The antenna model neglects the radial component :math:`r`, and
-only considers the angle components :math:`(\theta, \phi)`. An antenna
-radiation pattern is then expressed as a mathematical function
-:math:`g(\theta, \phi) \longrightarrow \mathcal{R}` that returns the
-gain (in dB) for each possible direction of
-transmission/reception. All angles are expressed in radians.
-
-
-.. _fig-antenna-coordinate-system:
-
-.. figure:: figures/antenna-coordinate-system.*
-   :align: center
-
-   Coordinate system of the AntennaModel
-
----------------------
-Single antenna models
----------------------
-
-In this section we describe the antenna radiation pattern models that
-are included within the antenna module.
-
-
-IsotropicAntennaModel
-+++++++++++++++++++++
-
-This antenna radiation pattern model provides a unitary gain (0 dB)
-for all direction.
-
-
-
-CosineAntennaModel
-++++++++++++++++++
-
-This is the cosine model described in [Chunjian]_: the antenna gain is
-determined as:
-
-.. math::
-
-  g(\phi, \theta) = \cos^{n} \left(\frac{\phi - \phi_{0}}{2}  \right)
-
-where :math:`\phi_{0}` is the azimuthal orientation of the antenna
-(i.e., its direction of maximum gain) and the exponential
-
-.. math::
-
-  n = -\frac{3}{20 \log_{10} \left( \cos \frac{\phi_{3dB}}{4} \right)}
-
-determines the desired 3dB beamwidth :math:`\phi_{3dB}`. Note that
-this radiation pattern is independent of the inclination angle
-:math:`\theta`.
-
-A major difference between the model of [Chunjian]_ and the one
-implemented in the class CosineAntennaModel is that only the element
-factor (i.e., what described by the above formulas) is considered. In
-fact, [Chunjian]_ also considered an additional antenna array
-factor. The reason why the latter is excluded is that we expect that
-the average user would desire to specify a given beamwidth exactly,
-without adding an array factor at a latter stage which would in
-practice alter the effective beamwidth of the resulting radiation
-pattern.
-
-
-
-ParabolicAntennaModel
-+++++++++++++++++++++
-
-This model is based on the parabolic approximation of the main lobe radiation pattern. It is often
-used in the context of cellular system to model the radiation pattern of a cell sector, see for
-instance [R4-092042a]_ and [Calcev]_. The antenna gain in dB is determined as:
-
-.. math::
-
-  g_{dB}(\phi, \theta) = -\min \left( 12 \left(\frac{\phi  - \phi_{0}}{\phi_{3dB}} \right)^2, A_{max} \right)
-
-where :math:`\phi_{0}` is the azimuthal orientation of the antenna
-(i.e., its direction of maximum gain), :math:`\phi_{3dB}` is its 3 dB
-beamwidth, and :math:`A_{max}` is the maximum attenuation in dB of the
-antenna. Note that this radiation pattern is independent of the inclination angle
-:math:`\theta`.
-
-
-
-ThreeGppAntennaModel
-++++++++++++++++++++
-
-This model implements the antenna element described in [38901]_.
-Parameters are fixed from the technical report, thus no attributes nor setters are provided.
-The model is largely based on the `ParabolicAntennaModel`_.
-
-------------------
-Phased Array Model
-------------------
-
-The class PhasedArrayModel has been created with flexibility in mind.
-It abstracts the basic idea of a Phased Antenna Array (PAA) by removing any constraint on the
-position of each element, and instead generalizes the concept of steering and beamforming vectors,
-solely based on the generalized location of the antenna elements.
-For details on Phased Array Antennas see for instance [Mailloux]_.
-
-Derived classes must implement the following functions:
-
-* GetNumElems: returns the number of antenna elements
-* GetElementLocation: returns the location of the antenna element with the specified index, normalized with respect to the wavelength
-* GetElementFieldPattern: returns the horizontal and vertical components of the antenna element field pattern at the specified direction. Same polarization (configurable) for all antenna elements of the array is considered.
-
-The class PhasedArrayModel also assumes that all antenna elements are equal, a typical key assumption which allows to model the PAA field pattern as the sum of the array factor, given by the geometry of the location of the antenna elements, and the element field pattern.
-Any class derived from AntennaModel is a valid antenna element for the PhasedArrayModel, allowing for a great flexibility of the framework.
-
-.. _3gpp-antenna-model:
-
-UniformPlanarArray
-++++++++++++++++++
-
-The class UniformPlanarArray is a generic implementation of Uniform Planar Arrays (UPAs),
-supporting rectangular and linear regular lattices.
-It closely follows the implementation described in the 3GPP TR 38.901 [38901]_,
-considering only a single panel, i.e., :math:`N_{g} = M_{g} = 1`.
-
-By default, the antenna array is orthogonal to the x-axis, pointing towards the positive
-direction, but the orientation can be changed through the attributes "BearingAngle",
-which adjusts the azimuth angle, and "DowntiltAngle", which adjusts the elevation angle.
-The slant angle is instead fixed and assumed to be 0.
-
-The number of antenna elements in the vertical and horizontal directions can be configured
-through the attributes "NumRows" and "NumColumns", while the spacing between the horizontal
-and vertical elements can be configured through the attributes "AntennaHorizontalSpacing"
-and "AntennaVerticalSpacing".
-
-UniformPlannarArray supports the concept of antenna ports following the sub-array partition
-model for TXRU virtualization, as described in Section 5.2.2 of 3GPP TR 36.897 [3GPP_TR36897]_.
-The number of antenna ports in vertical and horizontal directions can be configured through
-the attributes "NumVerticalPorts" and "NumHorizontalPorts", respectively. For example,
-if "NumRows" and "NumColumns" are configured to 2 and 4, and the number of
-"NumVerticalPorts" and "NumHorizontalPorts" to 1 and 2, then the antenna elements belonging
-to the first two columns of the antenna array will belong to the first antenna port,
-and the third and the fourth columns will belong to the second antenna port. Note that
-"NumRows" and "NumColumns" must be a multiple of "NumVerticalPorts" and "NumHorizontalPorts",
-respectively.
-
-Whether the antenna is dual-polarized or not is configured through the attribute
-"IsDualPolarized". In case the antenna array is dual polarized, the total number
-of antenna elements is doubled and the two polarizations are overlapped in space.
-The polarization slant angle of the antenna elements belonging to the first polarization
-are configured through the attribute "PolSlantAngle"; while the antenna elements of
-the second polarization have the polarization slant angle minus 90 degrees,
-as described in [38901]_ (i.e., :math:`{\zeta}`).
-
-CircularApertureAntennaModel
-++++++++++++++++++++++++++++
-
-The class CircularApertureAntennaModel implements the radiation pattern described in [38811]_.
-Specifically, the latter represents parabolic antennas, i.e., antennas which are typically used
-for achieving long range communications such as earth-to-satellite links.
-The default boresight orientation is parallel to the positive z-axis, and it can be tuned by
-using the AntennaInclination and AntennaAzimuth parameters.
-This implementation provides an exact characterization of the antenna field pattern, by leveraging
-the standard library Bessel functions implementation introduced with C++17.
-Accordingly, the antenna gain :math:`G` at an angle :math:`\theta` from the boresight main beam
-is evaluated as:
-
-.. math::
-   G \cdot 4\left | \frac{J_{1}\left ( k\cdot a\cdot sin\theta \right )}{k\cdot a\cdot sin\theta} \right
-   |^{2}\;\;\;\;\; for\; 0<\left | \theta \right |\leq 90^{\circ} \\
-   G \cdot 1\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; for\; \theta=0
-
-where :math:`J_{1}()` is the Bessel function of the first kind and first order, and :math:`a` is
-the radius of the antenna's circular aperture.
-The parameter :math:`k` is equal to :math:`k=\frac{2\pi f}{x}`, where :math:`f` is the carrier
-frequency, and :math:`c` is the speed of light in vacuum.
-The parameters :math:`G` (in logarithmic scale), :math:`a` and :math:`f` can be configured by using
-the attributes "AntennaMaxGainDb", "AntennaCircularApertureRadius" and "OperatingFrequency", respectively.
-This type of antennas features a symmetric radiation pattern, meaning that a single angle, measured
-from the boresight direction, is sufficient to characterize the radiation strength along a given direction.
-
-.. _fig-circular-antenna-pattern:
-
-.. figure:: figures/circular-antenna-pattern.png
-   :align: center
-
-   Circular aperture antenna radiation pattern with :math:`G =` 38.5 dB and :math:`a =` 10 :math:`\frac{c}{f}.`
-
-
-.. [Balanis] C.A. Balanis, "Antenna Theory - Analysis and Design",  Wiley, 2nd Ed.
-
-.. [Chunjian] Li Chunjian, "Efficient Antenna Patterns for
-   Three-Sector WCDMA Systems", Master of Science Thesis, Chalmers
-   University of Technology, Göteborg, Sweden, 2003
-
-.. [Calcev] George Calcev and Matt Dillon, "Antenna Tilt Control in
-   CDMA Networks", in Proc. of the 2nd Annual International Wireless
-   Internet Conference (WICON), 2006
-
-.. [R4-092042a]  3GPP TSG RAN WG4 (Radio) Meeting #51, R4-092042, Simulation
-   assumptions and parameters for FDD HeNB RF requirements.
-
-.. [38901] 3GPP. 2018. TR 38.901, Study on channel model for frequencies from 0.5 to 100 GHz, V15.0.0. (2018-06).
-
-.. [38811] 3GPP. 2018. TR 38.811, Study on New Radio (NR) to support non-terrestrial networks, V15.4.0. (2020-09).
-
-.. [Mailloux] Robert J. Mailloux, "Phased Array Antenna Handbook", Artech House, 2nd Ed.
-
-.. [3GPP_TR36897] 3GPP. 2015. TR 36.897. Study on elevation beamforming / Full-Dimension (FD)
-   Multiple Input Multiple Output (MIMO) for LTE. V13.0.0. (2015-06)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/antenna.rst ns-3.46/src/antenna/doc/source/antenna.rst
--- ns-3.45/src/antenna/doc/source/antenna.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/antenna.rst	1969-12-31 16:00:00.000000000 -0800
@@ -1,17 +0,0 @@
-
-#####################################################
-Antenna Module
-#####################################################
-
-
-
-
-.. toctree::
-
-    antenna-design
-    antenna-user
-    antenna-testing
-
-
-
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/antenna-testing.rst ns-3.46/src/antenna/doc/source/antenna-testing.rst
--- ns-3.45/src/antenna/doc/source/antenna-testing.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/antenna-testing.rst	1969-12-31 16:00:00.000000000 -0800
@@ -1,76 +0,0 @@
-+++++++++++++++++++++++++++++++++++++
- Testing Documentation
-+++++++++++++++++++++++++++++++++++++
-
-In this section we describe the test suites included with the antenna
-module that verify its correct functionality.
-
-
-Angles
-------
-
-The unit test suite ``angles`` verifies that the Angles class is
-constructed properly by correct conversion from 3D Cartesian
-coordinates according to the available methods (construction from a
-single vector and from a pair of vectors). For each method, several
-test cases are provided that compare the values :math:`(\phi, \theta)`
-determined by the constructor to known reference values. The test
-passes if for each case the values are equal to the reference up to a
-tolerance of :math:`10^{-10}` which accounts for numerical errors.
-
-
-DegreesToRadians
-----------------
-
-The unit test suite ``degrees-radians`` verifies that the methods
-``DegreesToRadians`` and ``RadiansToDegrees`` work properly by
-comparing with known reference values in a number of test
-cases. Each test case passes if the comparison is equal up to a
-tolerance of :math:`10^{-10}` which accounts for numerical errors.
-
-
-
-IsotropicAntennaModel
----------------------
-
-The unit test suite ``isotropic-antenna-model`` checks that the
-``IsotropicAntennaModel`` class works properly, i.e., returns always a
-0dB gain regardless of the direction.
-
-
-
-CosineAntennaModel
-------------------
-
-The unit test suite ``cosine-antenna-model`` checks that the
-``CosineAntennaModel`` class works properly. Several test cases are
-provided that check for the antenna gain value calculated at different
-directions and for different values of the orientation, the reference
-gain and the beamwidth. The reference gain is calculated by hand. Each
-test case passes if the reference gain in dB is equal to the value returned
-by ``CosineAntennaModel`` within a tolerance of 0.001, which accounts
-for the approximation done for the calculation of the reference
-values.
-
-
-
-ParabolicAntennaModel
----------------------
-
-The unit test suite ``parabolic-antenna-model`` checks that the
-``ParabolicAntennaModel`` class works properly. Several test cases are
-provided that check for the antenna gain value calculated at different
-directions and for different values of the orientation, the maximum attenuation
-and the beamwidth. The reference gain is calculated by hand. Each
-test case passes if the reference gain in dB is equal to the value returned
-by ``ParabolicAntennaModel`` within a tolerance of 0.001, which accounts
-for the approximation done for the calculation of the reference
-values.
-
-
-
-
-
-
-
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/antenna-user.rst ns-3.46/src/antenna/doc/source/antenna-user.rst
--- ns-3.45/src/antenna/doc/source/antenna-user.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/antenna-user.rst	1969-12-31 16:00:00.000000000 -0800
@@ -1,16 +0,0 @@
-.. include:: replace.txt
-
-
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  User Documentation
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-The antenna modeled can be used with all the wireless technologies and
-physical layer models that support it. Currently, this includes
-the physical layer models based on the SpectrumPhy. Please refer to
-the documentation of each of these models for details.
-
-
-
-
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/conf.py ns-3.46/src/antenna/doc/source/conf.py
--- ns-3.45/src/antenna/doc/source/conf.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/conf.py	1969-12-31 16:00:00.000000000 -0800
@@ -1,219 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ns-3 documentation build configuration file, created by
-# sphinx-quickstart on Tue Dec 14 09:00:39 2010.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import os
-import sys
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-# sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ["sphinx.ext.imgmath"]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ["_templates"]
-
-# The suffix of source filenames.
-source_suffix = ".rst"
-
-# The encoding of source files.
-# source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = "index"
-
-# General information about the project.
-project = "LENA"
-copyright = "2011-2012, CTTC"
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = "ns-3-dev"
-# The full version, including alpha/beta/rc tags.
-release = "ns-3-dev"
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-# language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-# today = ''
-# Else, today_fmt is used as the format for a strftime call.
-# today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = []
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-# default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-# add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-# add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-# show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = "sphinx"
-
-# A list of ignored prefixes for module index sorting.
-# modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-html_theme = "default"
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-# html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-# html_theme_path = []
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-# html_title = None
-
-# A shorter title for the navigation bar.  Default is the same as html_title.
-# html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-# html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-# html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-# html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-# html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-# html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-# html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-# html_additional_pages = {}
-
-# If false, no module index is generated.
-# html_domain_indices = True
-
-# If false, no index is generated.
-# html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-# html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-# html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-# html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-# html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.  The value of this option must be the
-# base URL from which the finished HTML is served.
-# html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-# html_file_suffix = None
-
-# Output file base name for HTML help builder.
-# htmlhelp_basename = 'ns-3doc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-# The paper size ('letter' or 'a4').
-# latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-# latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
-    (
-        "antenna",
-        "antenna.tex",
-        "Antenna Module Documentation",
-        "Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)",
-        "manual",
-    ),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-# latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-# latex_use_parts = False
-
-# If true, show page references after internal links.
-# latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-# latex_show_urls = False
-
-# Additional stuff for the LaTeX preamble.
-# latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-# latex_appendices = []
-
-# If false, no module index is generated.
-# latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [("index", "ns-3-model-library", "ns-3 Model Library", ["ns-3 project"], 1)]
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/index.rst ns-3.46/src/antenna/doc/source/index.rst
--- ns-3.45/src/antenna/doc/source/index.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/index.rst	1969-12-31 16:00:00.000000000 -0800
@@ -1,17 +0,0 @@
-
-#####################################################
-Antenna Module
-#####################################################
-
-
-
-
-.. toctree::
-
-    antenna-design
-    antenna-user
-    antenna-testing
-
-
-
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/doc/source/replace.txt ns-3.46/src/antenna/doc/source/replace.txt
--- ns-3.45/src/antenna/doc/source/replace.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/doc/source/replace.txt	1969-12-31 16:00:00.000000000 -0800
@@ -1,3 +0,0 @@
-.. |ns3| replace:: *ns-3*
-
-.. |ns2| replace:: *ns-2*
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/examples/adjacency-matrix-example.cc ns-3.46/src/antenna/examples/adjacency-matrix-example.cc
--- ns-3.45/src/antenna/examples/adjacency-matrix-example.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/examples/adjacency-matrix-example.cc	2025-10-01 18:46:32.000000000 -0700
@@ -98,7 +98,7 @@
                 }
                 else
                 {
-                    routeMap[{i, j}] = {(int)i};
+                    routeMap[{i, j}] = std::vector<int>{(int)i};
                 }
             }
         }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/antenna/model/circular-aperture-antenna-model.cc ns-3.46/src/antenna/model/circular-aperture-antenna-model.cc
--- ns-3.45/src/antenna/model/circular-aperture-antenna-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/antenna/model/circular-aperture-antenna-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -20,7 +20,7 @@
 #include "ns3/double.h"
 #include "ns3/log.h"
 
-#include <math.h>
+#include <cmath>
 
 /**
  * @file
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/aodv/model/aodv-routing-protocol.cc ns-3.46/src/aodv/model/aodv-routing-protocol.cc
--- ns-3.45/src/aodv/model/aodv-routing-protocol.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/aodv/model/aodv-routing-protocol.cc	2025-10-01 18:46:32.000000000 -0700
@@ -13,11 +13,6 @@
  * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
  *          Pavel Boyko <boyko@iitp.ru>
  */
-#define NS_LOG_APPEND_CONTEXT                                                                      \
-    if (m_ipv4)                                                                                    \
-    {                                                                                              \
-        std::clog << "[node " << m_ipv4->GetObject<Node>()->GetId() << "] ";                       \
-    }
 
 #include "aodv-routing-protocol.h"
 
@@ -38,6 +33,13 @@
 #include <algorithm>
 #include <limits>
 
+#undef NS_LOG_APPEND_CONTEXT
+#define NS_LOG_APPEND_CONTEXT                                                                      \
+    if (m_ipv4)                                                                                    \
+    {                                                                                              \
+        std::clog << "[node " << m_ipv4->GetObject<Node>()->GetId() << "] ";                       \
+    }
+
 namespace ns3
 {
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/applications/model/three-gpp-http-variables.cc ns-3.46/src/applications/model/three-gpp-http-variables.cc
--- ns-3.45/src/applications/model/three-gpp-http-variables.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/applications/model/three-gpp-http-variables.cc	2025-10-01 18:46:32.000000000 -0700
@@ -13,7 +13,7 @@
 #include "ns3/log.h"
 #include "ns3/uinteger.h"
 
-#include <math.h>
+#include <cmath>
 
 NS_LOG_COMPONENT_DEFINE("ThreeGppHttpVariables");
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/brite/doc/brite.rst ns-3.46/src/brite/doc/brite.rst
--- ns-3.45/src/brite/doc/brite.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/brite/doc/brite.rst	2025-10-01 18:46:32.000000000 -0700
@@ -87,17 +87,18 @@
 
 The first step is to download and build the ns-3 specific BRITE repository::
 
-  $ hg clone http://code.nsnam.org/BRITE
+  $ git clone https://gitlab.com/nsnam/BRITE.git
   $ cd BRITE
+  $ mkdir build && cd build
+  $ cmake ..
   $ make
 
-This will build BRITE and create a library, libbrite.so, within the BRITE
-directory.
+This will build a library, libbrite.so, within the BRITE/build subdirectory.
 
 Once BRITE has been built successfully, we proceed to configure ns-3 with
 BRITE support. Change to your ns-3 directory::
 
-  $ ./ns3 configure --with-brite=/your/path/to/brite/source --enable-examples
+  $ ./ns3 configure --with-brite=/your/path/to/BRITE --enable-examples
 
 Make sure it says 'enabled' beside 'BRITE Integration'. If it does not, then
 something has gone wrong. Either you have forgotten to build BRITE first
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/doc/Makefile ns-3.46/src/buildings/doc/Makefile
--- ns-3.45/src/buildings/doc/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/doc/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,6 +1,4 @@
-EPSTOPDF = epstopdf
-DIA = dia
-CONVERT = convert -density 300
+include $(CURDIR)/../../../doc/sphinx/defines.mk
 
 SOURCE = source
 FIGURES = $(SOURCE)/figures
@@ -39,15 +37,7 @@
 	$(EPSTOPDF) $< -o=$@
 	@if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
 
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/doc/source/buildings-design.rst ns-3.46/src/buildings/doc/source/buildings-design.rst
--- ns-3.45/src/buildings/doc/source/buildings-design.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/doc/source/buildings-design.rst	2025-10-01 18:46:32.000000000 -0700
@@ -19,7 +19,7 @@
  #. a channel condition model (``BuildingsChannelConditionModel``) which determined the LOS/NLOS channel condition based on the ``Building`` objects deployed in the scenario.
  #. hybrid channel condition models (``ThreeGppV2vUrbanChannelConditionModel`` and ``ThreeGppV2vHighwayChannelConditionModel``) specifically designed to model vehicular environments (more information can be found in the :ref:`documentation of the propagation module <sec-3gpp-v2v-ch-cond>`)
 
-The models have been designed with LTE in mind, though their implementation is in fact independent from any LTE-specific code, and can be used with other ns-3 wireless technologies as well (e.g., wifi, wimax).
+The models have been designed with LTE in mind, though their implementation is in fact independent from any LTE-specific code, and can be used with other ns-3 wireless technologies as well (e.g., wifi).
 
 The ``HybridBuildingsPropagationLossModel`` pathloss model included is obtained through a combination of several well known pathloss models in order to mimic different environmental scenarios such as urban, suburban and open areas. Moreover, the model considers both outdoor and indoor indoor and outdoor communication has to be included since HeNB might be installed either within building and either outside. In case of indoor communication, the model has to consider also the type of building in outdoor <-> indoor communication according to some general criteria such as the wall penetration losses of the common materials; moreover it includes some general configuration for the internal walls in indoor communications.
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/doc/source/buildings-user.rst ns-3.46/src/buildings/doc/source/buildings-user.rst
--- ns-3.45/src/buildings/doc/source/buildings-user.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/doc/source/buildings-user.rst	2025-10-01 18:46:32.000000000 -0700
@@ -184,7 +184,7 @@
 After you placed buildings and nodes in a simulation, you can use a
 building-aware pathloss model in a simulation exactly in the same way
 you would use any regular path loss model. How to do this is specific
-for the wireless module that you are considering (lte, wifi, wimax,
+for the wireless module that you are considering (lte, wifi,
 etc.), so please refer to the documentation of that model for specific
 instructions.
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/model/buildings-channel-condition-model.cc ns-3.46/src/buildings/model/buildings-channel-condition-model.cc
--- ns-3.45/src/buildings/model/buildings-channel-condition-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/model/buildings-channel-condition-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -181,4 +181,4 @@
     return 0;
 }
 
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/model/random-walk-2d-outdoor-mobility-model.h ns-3.46/src/buildings/model/random-walk-2d-outdoor-mobility-model.h
--- ns-3.45/src/buildings/model/random-walk-2d-outdoor-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/model/random-walk-2d-outdoor-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -61,6 +61,12 @@
         MODE_TIME
     };
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<RandomWalk2dOutdoorMobilityModel>(*this);
+    }
+
   private:
     /**
      * @brief Performs the rebound of the node if it reaches a boundary
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/model/three-gpp-v2v-channel-condition-model.cc ns-3.46/src/buildings/model/three-gpp-v2v-channel-condition-model.cc
--- ns-3.45/src/buildings/model/three-gpp-v2v-channel-condition-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/model/three-gpp-v2v-channel-condition-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -202,4 +202,4 @@
     return cond;
 }
 
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/test/buildings-channel-condition-model-test.cc ns-3.46/src/buildings/test/buildings-channel-condition-model-test.cc
--- ns-3.45/src/buildings/test/buildings-channel-condition-model-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/test/buildings-channel-condition-model-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -104,7 +104,7 @@
 
     Ptr<BuildingsChannelConditionModel> condModel = CreateObject<BuildingsChannelConditionModel>();
 
-    Ptr<Building> building = Create<Building>();
+    auto building = CreateObject<Building>();
     building->SetNRoomsX(1);
     building->SetNRoomsY(1);
     building->SetNFloors(1);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/test/buildings-penetration-loss-pathloss-test.cc ns-3.46/src/buildings/test/buildings-penetration-loss-pathloss-test.cc
--- ns-3.45/src/buildings/test/buildings-penetration-loss-pathloss-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/test/buildings-penetration-loss-pathloss-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -174,7 +174,7 @@
     // create the factory for the propagation loss model
     ObjectFactory propModelFactory;
 
-    Ptr<Building> building = Create<Building>();
+    auto building = CreateObject<Building>();
     building->SetExtWallsType(Building::ExtWallsType_t::ConcreteWithWindows);
     building->SetNRoomsX(1);
     building->SetNRoomsY(1);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc ns-3.46/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc
--- ns-3.45/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -136,7 +136,7 @@
     Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel>();
     nodes.Get(1)->AggregateObject(b);
 
-    Ptr<Building> building = Create<Building>();
+    auto building = CreateObject<Building>();
     building->SetNRoomsX(1);
     building->SetNRoomsY(1);
     building->SetNFloors(1);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/click/model/ipv4-l3-click-protocol.cc ns-3.46/src/click/model/ipv4-l3-click-protocol.cc
--- ns-3.45/src/click/model/ipv4-l3-click-protocol.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/click/model/ipv4-l3-click-protocol.cc	2025-10-01 18:46:32.000000000 -0700
@@ -274,18 +274,6 @@
 }
 
 void
-Ipv4L3ClickProtocol::SetWeakEsModel(bool model)
-{
-    m_strongEndSystemModel = !model;
-}
-
-bool
-Ipv4L3ClickProtocol::GetWeakEsModel() const
-{
-    return !m_strongEndSystemModel;
-}
-
-void
 Ipv4L3ClickProtocol::SetStrongEndSystemModel(bool model)
 {
     m_strongEndSystemModel = model;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/click/model/ipv4-l3-click-protocol.h ns-3.46/src/click/model/ipv4-l3-click-protocol.h
--- ns-3.45/src/click/model/ipv4-l3-click-protocol.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/click/model/ipv4-l3-click-protocol.h	2025-10-01 18:46:32.000000000 -0700
@@ -257,13 +257,6 @@
     void SetIpForward(bool forward) override;
     bool GetIpForward() const override;
 
-    /** @copydoc Ipv4::SetWeakEsModel */
-    NS_DEPRECATED_3_41("Use SetStrongEndSystemModel instead")
-    void SetWeakEsModel(bool model) override;
-    /** @copydoc Ipv4::GetWeakEsModel */
-    NS_DEPRECATED_3_41("Use GetStrongEndSystemModel instead")
-    bool GetWeakEsModel() const override;
-
     void SetStrongEndSystemModel(bool model) override;
     bool GetStrongEndSystemModel() const override;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/config-store/model/display-functions.h ns-3.46/src/config-store/model/display-functions.h
--- ns-3.45/src/config-store/model/display-functions.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/config-store/model/display-functions.h	2025-10-01 18:46:32.000000000 -0700
@@ -228,6 +228,6 @@
                                              GtkTreePath* path,
                                              GtkTreeIter* iter,
                                              gpointer data);
-} // end namespace ns3
+} // namespace ns3
 
 #endif
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/config-store/model/model-node-creator.cc ns-3.46/src/config-store/model/model-node-creator.cc
--- ns-3.45/src/config-store/model/model-node-creator.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/config-store/model/model-node-creator.cc	2025-10-01 18:46:32.000000000 -0700
@@ -127,4 +127,4 @@
     g_free(iter);
     m_iters.pop_back();
 }
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/config-store/model/model-typeid-creator.cc ns-3.46/src/config-store/model/model-typeid-creator.cc
--- ns-3.45/src/config-store/model/model-typeid-creator.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/config-store/model/model-typeid-creator.cc	2025-10-01 18:46:32.000000000 -0700
@@ -71,4 +71,4 @@
 {
     Remove();
 }
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/CMakeLists.txt ns-3.46/src/core/CMakeLists.txt
--- ns-3.45/src/core/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -349,4 +349,5 @@
   HEADER_FILES ${header_files}
   LIBRARIES_TO_LINK ${libraries_to_link}
   TEST_SOURCES ${test_sources}
+  GENERATE_EXPORT_HEADER
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/examples/empirical-random-variable-example.cc ns-3.46/src/core/examples/empirical-random-variable-example.cc
--- ns-3.45/src/core/examples/empirical-random-variable-example.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/examples/empirical-random-variable-example.cc	2025-10-01 18:46:32.000000000 -0700
@@ -200,14 +200,14 @@
     // Create the ERV in sampling mode
     Ptr<EmpiricalRandomVariable> erv = CreateObject<EmpiricalRandomVariable>();
 
-    //                          // Expectation for bin
-    erv->CDF(0.0, 0.0 / 15.0);  // 0
-    erv->CDF(0.2, 1.0 / 15.0);  // 0.2 1/15  =  2/150
-    erv->CDF(0.4, 3.0 / 15.0);  // 0.4 2/15  =  8/150
-    erv->CDF(0.6, 4.0 / 15.0);  // 0.6 1/15  =  6/150
-    erv->CDF(0.8, 7.0 / 15.0);  // 0.8 3/15  = 24/150
-    erv->CDF(1.0, 9.0 / 15.0);  // 1.0 2/15  = 20/150
-    erv->CDF(1.0, 15.0 / 15.0); // 1.0 6/15  = 60/150  <avg> = 120/150 = 0.8
+    //                         // Expectation for bin
+    erv->CDF(0.0, 0.0);        // 0
+    erv->CDF(0.2, 1.0 / 15.0); // 0.2 1/15  =  2/150
+    erv->CDF(0.4, 3.0 / 15.0); // 0.4 2/15  =  8/150
+    erv->CDF(0.6, 4.0 / 15.0); // 0.6 1/15  =  6/150
+    erv->CDF(0.8, 7.0 / 15.0); // 0.8 3/15  = 24/150
+    erv->CDF(1.0, 9.0 / 15.0); // 1.0 2/15  = 20/150
+    erv->CDF(1.0, 1.0);        // 1.0 6/15  = 60/150  <avg> = 120/150 = 0.8
 
     if (single)
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/examples/main-ptr.cc ns-3.46/src/core/examples/main-ptr.cc
--- ns-3.45/src/core/examples/main-ptr.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/examples/main-ptr.cc	2025-10-01 18:46:32.000000000 -0700
@@ -26,6 +26,12 @@
 class PtrExample : public Object
 {
   public:
+    /**
+     * @brief Get the type ID.
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId();
+
     /** Constructor. */
     PtrExample();
     /** Destructor. */
@@ -34,6 +40,16 @@
     void Method();
 };
 
+NS_OBJECT_ENSURE_REGISTERED(PtrExample);
+
+TypeId
+PtrExample::GetTypeId()
+{
+    static TypeId tid =
+        TypeId("ns3::PtrExample").SetParent<Object>().SetGroupName("Core").HideFromDocumentation();
+    return tid;
+}
+
 PtrExample::PtrExample()
 {
     std::cout << "PtrExample constructor" << std::endl;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/examples/main-random-variable-stream.cc ns-3.46/src/core/examples/main-random-variable-stream.cc
--- ns-3.45/src/core/examples/main-random-variable-stream.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/examples/main-random-variable-stream.cc	2025-10-01 18:46:32.000000000 -0700
@@ -268,12 +268,12 @@
         plot.AppendExtra("set xrange [*:*]");
 
         auto x = CreateObject<EmpiricalRandomVariable>();
-        x->CDF(0.0, 0.0 / 15.0);
+        x->CDF(0.0, 0.0);
         x->CDF(0.2, 1.0 / 15.0);
         x->CDF(0.4, 3.0 / 15.0);
         x->CDF(0.6, 6.0 / 15.0);
         x->CDF(0.8, 10.0 / 15.0);
-        x->CDF(1.0, 15.0 / 15.0);
+        x->CDF(1.0, 1.0);
 
         plot.AddDataset(
             Histogram(x, probes, precision, "EmpiricalRandomVariable (Sampling)", true));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/helper/csv-reader.h ns-3.46/src/core/helper/csv-reader.h
--- ns-3.45/src/core/helper/csv-reader.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/helper/csv-reader.h	2025-10-01 18:46:32.000000000 -0700
@@ -408,6 +408,6 @@
     return GetValueAs(std::move(cell), value);
 }
 
-} //  namespace ns3
+} // namespace ns3
 
 #endif //  NS3_CSV_READER_H_
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/attribute-accessor-helper.h ns-3.46/src/core/model/attribute-accessor-helper.h
--- ns-3.45/src/core/model/attribute-accessor-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/attribute-accessor-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -233,12 +233,9 @@
  * @param [in]  memberVariable  The address of the data member.
  * @returns The AttributeAccessor.
  */
-// clang-format off
-// Clang-format guard needed for versions <= 18
 template <typename V, typename T, typename U>
 inline Ptr<const AttributeAccessor>
 DoMakeAccessorHelperOne(U T::* memberVariable)
-// clang-format on
 {
     /* AttributeAccessor implementation for a class member variable. */
     class MemberVariable : public AccessorHelper<T, V>
@@ -248,10 +245,7 @@
          * Construct from a class data member address.
          * @param [in] memberVariable The class data member address.
          */
-        // clang-format off
-        // Clang-format guard needed for versions <= 18
         MemberVariable(U T::* memberVariable)
-            // clang-format on
             : AccessorHelper<T, V>(),
               m_memberVariable(memberVariable)
         {
@@ -286,10 +280,7 @@
             return true;
         }
 
-        // clang-format off
-        // Clang-format guard needed for versions <= 18
         U T::* m_memberVariable; // Address of the class data member.
-        // clang-format on
     };
 
     return Ptr<const AttributeAccessor>(new MemberVariable(memberVariable), false);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/boolean.cc ns-3.46/src/core/model/boolean.cc
--- ns-3.45/src/core/model/boolean.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/boolean.cc	2025-10-01 18:46:32.000000000 -0700
@@ -47,7 +47,8 @@
     return m_value;
 }
 
-BooleanValue::operator bool() const
+BooleanValue::
+operator bool() const
 {
     return m_value;
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/cairo-wideint.c ns-3.46/src/core/model/cairo-wideint.c
--- ns-3.45/src/core/model/cairo-wideint.c	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/cairo-wideint.c	2025-10-01 18:46:32.000000000 -0700
@@ -45,7 +45,14 @@
 
 #if HAVE_UINT64_T
 
-const char * cairo_impl64 = "uint64_t";
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char *
+cairo_impl64()
+{
+    return "uint64_t";
+}
 
 #define _cairo_uint32s_to_uint64(h,l) ((uint64_t) (h) << 32 | (l))
 
@@ -61,7 +68,14 @@
 
 #else
 
-const char * cairo_impl64 = "uint32_t";
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char *
+cairo_impl64()
+{
+    return "uint32_t";
+}
 
 cairo_uint64_t
 _cairo_uint32_to_uint64 (uint32_t i)
@@ -329,7 +343,14 @@
 
 #if HAVE_UINT128_T
 
-const char * cairo_impl128 = "uint128_t";
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char *
+cairo_impl128()
+{
+    return "uint128_t";
+}
 
 cairo_uquorem128_t
 _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den)
@@ -343,7 +364,14 @@
 
 #else
 
-const char * cairo_impl128 = "cairo_uint64_t";
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char *
+cairo_impl128()
+{
+    return "cairo_uint64_t";
+}
 
 cairo_uint128_t
 _cairo_uint32_to_uint128 (uint32_t i)
@@ -550,7 +578,7 @@
 }
 
 cairo_uint128_t
-_cairo_uint128_rsa (cairo_int128_t a, int shift)
+_cairo_uint128_rsa (cairo_uint128_t a, int shift)
 {
     if (shift >= 64)
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/cairo-wideint-private.h ns-3.46/src/core/model/cairo-wideint-private.h
--- ns-3.45/src/core/model/cairo-wideint-private.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/cairo-wideint-private.h	2025-10-01 18:46:32.000000000 -0700
@@ -51,45 +51,7 @@
 // extern const char * cairo_impl64;
 // extern const char * cairo_impl128;
 
-/*for compatibility with MacOS and Cygwin*/
-#ifndef HAVE_STDINT_H
-#ifdef __APPLE__
-#define HAVE_STDINT_H 1
-#elif defined(WIN32)
-#define HAVE_STDINT_H 1
-#endif
-#endif
-
-#if   HAVE_STDINT_H
-# include <stdint.h>
-#elif HAVE_INTTYPES_H
-# include <inttypes.h>
-#elif HAVE_SYS_INT_TYPES_H
-# include <sys/int_types.h>
-#elif defined(_MSC_VER)
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-# ifndef HAVE_UINT64_T
-#  define HAVE_UINT64_T 1
-# endif
-# ifndef INT16_MIN
-#  define INT16_MIN     (-32767-1)
-# endif
-# ifndef INT16_MAX
-#  define INT16_MAX     (32767)
-# endif
-# ifndef UINT16_MAX
-#  define UINT16_MAX    (65535)
-# endif
-#else
-#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
-#endif
+#include <cstdint> // PDB
 
 #ifdef __cplusplus
 extern "C" {
@@ -108,7 +70,10 @@
 
 #if !HAVE_UINT64_T
 
-extern const char * cairo_impl64;
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char * cairo_impl64();
 
 typedef struct _cairo_uint64 {
   uint32_t    lo, hi;
@@ -149,7 +114,10 @@
 
 #else
 
-extern const char * cairo_impl64;
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char * cairo_impl64();
 
 typedef uint64_t    cairo_uint64_t;
 typedef int64_t     cairo_int64_t;
@@ -231,7 +199,10 @@
 
 #if !HAVE_UINT128_T
 
-extern const char * cairo_impl128;
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char * cairo_impl128();
 
 typedef struct cairo_uint128 {
   cairo_uint64_t      lo, hi;
@@ -276,7 +247,10 @@
 
 #else   /* !HAVE_UINT128_T */
 
-extern const char * cairo_impl128;
+//PDB original string literal causes access violation on Windows when accessed
+// by binaries that link to core, e.g. tests
+// Substitute function call
+const char * cairo_impl128();
 
 typedef uint128_t       cairo_uint128_t;
 typedef int128_t        cairo_int128_t;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/deprecated.h ns-3.46/src/core/model/deprecated.h
--- ns-3.45/src/core/model/deprecated.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/deprecated.h	2025-10-01 18:46:32.000000000 -0700
@@ -85,6 +85,13 @@
 
 /**
  * @ingroup deprecation
+ * @def NS_DEPRECATED_3_46
+ * Tag for things deprecated in version ns-3.46.
+ */
+#define NS_DEPRECATED_3_46(msg) NS_DEPRECATED("Deprecated in ns-3.46: " msg)
+
+/**
+ * @ingroup deprecation
  * @def NS_DEPRECATED_3_45
  * Tag for things deprecated in version ns-3.45.
  */
@@ -104,25 +111,4 @@
  */
 #define NS_DEPRECATED_3_43(msg) NS_DEPRECATED("Deprecated in ns-3.43: " msg)
 
-/**
- * @ingroup deprecation
- * @def NS_DEPRECATED_3_42
- * Tag for things deprecated in version ns-3.42.
- */
-#define NS_DEPRECATED_3_42(msg) NS_DEPRECATED("Deprecated in ns-3.42: " msg)
-
-/**
- * @ingroup deprecation
- * @def NS_DEPRECATED_3_41
- * Tag for things deprecated in version ns-3.41.
- */
-#define NS_DEPRECATED_3_41(msg) NS_DEPRECATED("Deprecated in ns-3.41: " msg)
-
-/**
- * @ingroup deprecation
- * @def NS_DEPRECATED_3_40
- * Tag for things deprecated in version ns-3.40.
- */
-#define NS_DEPRECATED_3_40(msg) NS_DEPRECATED("Deprecated in ns-3.40: " msg)
-
 #endif /* NS3_DEPRECATED_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/environment-variable.cc ns-3.46/src/core/model/environment-variable.cc
--- ns-3.45/src/core/model/environment-variable.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/environment-variable.cc	2025-10-01 18:46:32.000000000 -0700
@@ -11,9 +11,9 @@
 #include "string.h"
 
 #include <cstdlib>  // std::getenv
+#include <cstdlib>  // Global functions setenv, unsetenv
 #include <cstring>  // strlen
 #include <iostream> // clog
-#include <stdlib.h> // Global functions setenv, unsetenv
 
 /**
  * @file
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/event-id.cc ns-3.46/src/core/model/event-id.cc
--- ns-3.45/src/core/model/event-id.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/event-id.cc	2025-10-01 18:46:32.000000000 -0700
@@ -68,12 +68,6 @@
     return !IsExpired();
 }
 
-bool
-EventId::IsRunning() const
-{
-    return IsPending();
-}
-
 EventImpl*
 EventId::PeekEventImpl() const
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/event-id.h ns-3.46/src/core/model/event-id.h
--- ns-3.45/src/core/model/event-id.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/event-id.h	2025-10-01 18:46:32.000000000 -0700
@@ -8,7 +8,6 @@
 #ifndef EVENT_ID_H
 #define EVENT_ID_H
 
-#include "deprecated.h"
 #include "event-impl.h"
 #include "ptr.h"
 
@@ -93,14 +92,6 @@
      */
     bool IsPending() const;
 
-    /**
-     * This method is syntactic sugar for !IsExpired().
-     *
-     * @returns \c true if the event has not expired, \c false otherwise.
-     */
-    NS_DEPRECATED_3_42("Use IsPending instead")
-    bool IsRunning() const;
-
   public:
     /**
      * @name Scheduler Helpers.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/fatal-error.h ns-3.46/src/core/model/fatal-error.h
--- ns-3.45/src/core/model/fatal-error.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/fatal-error.h	2025-10-01 18:46:32.000000000 -0700
@@ -17,6 +17,23 @@
 #include <iostream>
 #include <string_view>
 
+// If stacktrace is available, print it on fatal errors
+#ifdef STACKTRACE_LIBRARY_IS_LINKED
+#include <stacktrace>
+/**
+ * @brief Macro prints the current stack trace to standard error.
+ *
+ * This macro is defined only if the stacktrace library is linked.
+ */
+
+#define PRINT_STACKTRACE std::cerr << std::stacktrace::current() << std::endl
+#else
+/**
+ * @brief Macro does nothing if stacktrace library is not available.
+ */
+#define PRINT_STACKTRACE
+#endif
+
 /**
  * @file
  * @ingroup fatal
@@ -84,6 +101,7 @@
         if (fatal)                                                                                 \
         {                                                                                          \
             std::cerr << ns3::NS_FATAL_MSG << std::endl;                                           \
+            PRINT_STACKTRACE;                                                                      \
             std::terminate();                                                                      \
         }                                                                                          \
     } while (false)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/hash-fnv.cc ns-3.46/src/core/model/hash-fnv.cc
--- ns-3.45/src/core/model/hash-fnv.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/hash-fnv.cc	2025-10-01 18:46:32.000000000 -0700
@@ -22,7 +22,7 @@
 
 #include "log.h"
 
-#include <stdlib.h>
+#include <cstdlib>
 #include <sys/types.h>
 
 /**
@@ -347,7 +347,7 @@
  * Share and Enjoy!	:-)
  */
 
-//#include <stdlib.h>    //PDB
+//#include <cstdlib>    //PDB
 //#include "fnv.h"       //PDB
 
 
@@ -495,7 +495,7 @@
  * Share and Enjoy!	:-)
  */
 
-//#include <stdlib.h>    //PDB
+//#include <cstdlib>    //PDB
 //#include "fnv.h"       //PDB
 
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/int64x64-cairo.cc ns-3.46/src/core/model/int64x64-cairo.cc
--- ns-3.45/src/core/model/int64x64-cairo.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/int64x64-cairo.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1,3 +1,4 @@
+// NOLINTBEGIN
 /*
  * Copyright (c) 2006 INRIA
  *
@@ -228,3 +229,4 @@
 } // namespace ns3
 
 #endif /* INT64X64_CAIRO_H */
+// NOLINTEND
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/int64x64-cairo.h ns-3.46/src/core/model/int64x64-cairo.h
--- ns-3.45/src/core/model/int64x64-cairo.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/int64x64-cairo.h	2025-10-01 18:46:32.000000000 -0700
@@ -1,3 +1,4 @@
+// NOLINTBEGIN
 /*
  * Copyright (c) 2010 INRIA
  *
@@ -435,3 +436,4 @@
 
 #endif /* defined(INT64X64_USE_CAIRO) && !defined(PYTHON_SCAN) */
 #endif /* INT64X64_CAIRO_H */
+// NOLINTEND
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/int64x64.cc ns-3.46/src/core/model/int64x64.cc
--- ns-3.45/src/core/model/int64x64.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/int64x64.cc	2025-10-01 18:46:32.000000000 -0700
@@ -9,11 +9,11 @@
 #include "assert.h"
 #include "log.h"
 
+#include <cstdint>
 #include <iomanip> // showpos
 #include <iostream>
 #include <limits>
 #include <sstream>
-#include <stdint.h>
 
 /**
  * @file
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/log.cc ns-3.46/src/core/model/log.cc
--- ns-3.45/src/core/model/log.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/log.cc	2025-10-01 18:46:32.000000000 -0700
@@ -233,13 +233,6 @@
 }
 
 bool
-LogComponent::IsEnabled(const LogLevel level) const
-{
-    //  LogComponentEnableEnvVar ();
-    return level & m_levels;
-}
-
-bool
 LogComponent::IsNoneEnabled() const
 {
     return m_levels == 0;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/log.h ns-3.46/src/core/model/log.h
--- ns-3.45/src/core/model/log.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/log.h	2025-10-01 18:46:32.000000000 -0700
@@ -326,13 +326,22 @@
      *                  functions which help implement the logging facility.
      */
     LogComponent(const std::string& name, const std::string& file, const LogLevel mask = LOG_NONE);
+
     /**
      * Check if this LogComponent is enabled for \c level
      *
      * @param [in] level The level to check for.
      * @return \c true if we are enabled at \c level.
+     *
+     * @internal
+     * This function is defined in the header to enable inlining for better performance. See:
+     * https://gitlab.com/nsnam/ns-3-dev/-/merge_requests/2448#note_2527898962
      */
-    bool IsEnabled(const LogLevel level) const;
+    bool IsEnabled(const LogLevel level) const
+    {
+        return level & m_levels;
+    }
+
     /**
      * Check if all levels are disabled.
      *
@@ -478,6 +487,10 @@
         // Use + unary operator to cast uint8_t / int8_t to uint32_t / int32_t, respectively
         m_os << +param;
     }
+    else if constexpr (std::is_pointer_v<T>)
+    {
+        m_os << static_cast<const void*>(&param);
+    }
     else
     {
         m_os << param;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/matrix-array.cc ns-3.46/src/core/model/matrix-array.cc
--- ns-3.45/src/core/model/matrix-array.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/matrix-array.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,9 +15,16 @@
 #pragma GCC diagnostic ignored "-Wclass-memaccess"
 #pragma GCC diagnostic ignored "-Wunused-variable"
 #endif
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
 
 #include <Eigen/Dense>
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
 #if defined(__GNUC__) && !defined(__clang__)
 #pragma GCC diagnostic pop
 #endif
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/nstime.h ns-3.46/src/core/model/nstime.h
--- ns-3.45/src/core/model/nstime.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/nstime.h	2025-10-01 18:46:32.000000000 -0700
@@ -15,6 +15,8 @@
 #include "int64x64.h"
 #include "type-name.h"
 
+#include "ns3/core-export.h"
+
 #include <cmath>
 #include <limits>
 #include <ostream>
@@ -90,7 +92,7 @@
  * if you use picoseconds is 2^64 ps = 2^24 s = 7 months, whereas,
  * had you used nanoseconds, you could have run for 584 years.
  */
-class Time
+class CORE_EXPORT Time
 {
   public:
     /**
@@ -127,7 +129,7 @@
     inline Time()
         : m_data()
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -141,7 +143,7 @@
     inline Time(const Time& o)
         : m_data(o.m_data)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -155,7 +157,7 @@
     Time(Time&& o)
         : m_data(o.m_data)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -174,7 +176,7 @@
     explicit inline Time(double v)
         : m_data(llround(v))
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -183,7 +185,7 @@
     explicit inline Time(int v)
         : m_data(v)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -192,7 +194,7 @@
     explicit inline Time(long int v)
         : m_data(v)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -201,7 +203,7 @@
     explicit inline Time(long long int v)
         : m_data(v)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -210,7 +212,7 @@
     explicit inline Time(unsigned int v)
         : m_data(v)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -219,7 +221,7 @@
     explicit inline Time(unsigned long int v)
         : m_data(v)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -228,7 +230,7 @@
     explicit inline Time(unsigned long long int v)
         : m_data(v)
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -237,7 +239,7 @@
     explicit inline Time(const int64x64_t& v)
         : m_data(v.Round())
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Mark(this);
         }
@@ -291,7 +293,7 @@
     /** Destructor */
     ~Time()
     {
-        if (g_markingTimes)
+        if (MarkingTimes())
         {
             Clear(this);
         }
@@ -746,6 +748,21 @@
      */
     static MarkedTimes* g_markingTimes;
 
+    /**
+     *  Null check for g_markingTimes from outside time.cc
+     *
+     *  @return \c true if g_markingTimes is not null
+     *
+     *  @internal
+     *
+     *  The inline Time ctors need to check if g_markingTimes is allocated
+     *  before calling Mark(). Likewise, the dtor also needs to check before
+     *  calling Clear(). On Windows, attempting to access g_markingTimes
+     *  directly from outside the compilation unit is an access violation so
+     *  this method is provided to work around that limitation.
+     */
+    static bool MarkingTimes();
+
   public:
     /**
      *  Function to force static initialization of Time.
@@ -867,6 +884,13 @@
 } // namespace TracedValueCallback
 
 /**
+ * Force static initialization order of Time in each compilation unit.
+ * This is internal to the Time implementation.
+ * @relates Time
+ */
+static bool g_TimeStaticInit [[maybe_unused]] = Time::StaticInit();
+
+/**
  * Equality operator for Time.
  * @param [in] lhs The first value
  * @param [in] rhs The second value
@@ -1510,27 +1534,6 @@
  */
 TYPENAMEGET_DEFINE(Time);
 
-/**
- * @ingroup time
- *
- * @brief Helper class to force static initialization
- * of Time in each compilation unit, ensuring it is
- * initialized before usage.
- * This is internal to the Time implementation.
- * @relates Time
- */
-class TimeInitializationHelper
-{
-  public:
-    /** Default constructor calls Time::StaticInit */
-    TimeInitializationHelper()
-    {
-        Time::StaticInit();
-    }
-};
-
-static TimeInitializationHelper g_timeInitHelper; ///< Instance of Time static initialization helper
-
 } // namespace ns3
 
 #endif /* TIME_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/object-base.cc ns-3.46/src/core/model/object-base.cc
--- ns-3.45/src/core/model/object-base.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/object-base.cc	2025-10-01 18:46:32.000000000 -0700
@@ -83,6 +83,19 @@
     // loop over the inheritance tree back to the Object base class.
     NS_LOG_FUNCTION(this << &attributes);
     TypeId tid = GetInstanceTypeId();
+    TypeId objectTid;
+    // the TypeId of a class derived from Object is initialized to "ns3::Object"; for a class
+    // deriving from Object, check that this function is called after that the correct TypeId is set
+    // to ensure that the attributes of the class are initialized
+    NS_ABORT_MSG_IF(TypeId::LookupByNameFailSafe("ns3::Object", &objectTid) && tid == objectTid,
+                    "ObjectBase::ConstructSelf() has been called on an object of a class derived "
+                    "from the Object class, but the TypeId is still set to ns3::Object.\n"
+                    "This is known to happen in two cases:\n"
+                    "- ObjectBase::ConstructSelf() is called in the class constructor; in this "
+                    "case, override ObjectBase::NotifyConstructionCompleted() to access the "
+                    "initial values of the object attributes as soon as object construction is "
+                    "completed (see issue #1249)\n"
+                    "- the class deriving from Object does not define a static GetTypeId() method");
     do // Do this tid and all parents
     {
         // loop over all attributes in object type
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/object-map.h ns-3.46/src/core/model/object-map.h
--- ns-3.45/src/core/model/object-map.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/object-map.h	2025-10-01 18:46:32.000000000 -0700
@@ -33,11 +33,8 @@
  * MakeAccessorHelper implementation for ObjectVector.
  * @copydetails ns3::DoMakeAccessorHelperOne(U T::*)
  */
-// clang-format off
-// Clang-format guard needed for versions <= 18
 template <typename T, typename U>
 Ptr<const AttributeAccessor> MakeObjectMapAccessor(U T::* memberVariable);
-// clang-format on
 
 // Documentation generated by print-introspected-doxygen.cc
 template <typename T>
@@ -63,12 +60,9 @@
  *  Implementation of the templates declared above.
  ***************************************************************/
 
-// clang-format off
-// Clang-format guard needed for versions <= 18
 template <typename T, typename U>
 Ptr<const AttributeAccessor>
 MakeObjectMapAccessor(U T::* memberVector)
-// clang-format on
 {
     struct MemberStdContainer : public ObjectPtrContainerAccessor
     {
@@ -104,10 +98,7 @@
             return nullptr;
         }
 
-        // clang-format off
-        // Clang-format guard needed for versions <= 18
         U T::* m_memberVector;
-        // clang-format on
     }* spec = new MemberStdContainer();
 
     spec->m_memberVector = memberVector;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/object-vector.h ns-3.46/src/core/model/object-vector.h
--- ns-3.45/src/core/model/object-vector.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/object-vector.h	2025-10-01 18:46:32.000000000 -0700
@@ -33,11 +33,8 @@
  * MakeAccessorHelper implementation for ObjectVector.
  * @copydetails ns3::DoMakeAccessorHelperOne(U T::*)
  */
-// clang-format off
-// Clang-format guard needed for versions <= 18
 template <typename T, typename U>
 Ptr<const AttributeAccessor> MakeObjectVectorAccessor(U T::* memberVariable);
-// clang-format on
 
 // Documentation generated by print-introspected-doxygen.cc
 template <typename T>
@@ -63,12 +60,9 @@
  *  Implementation of the templates declared above.
  ***************************************************************/
 
-// clang-format off
-// Clang-format guard needed for versions <= 18
 template <typename T, typename U>
 Ptr<const AttributeAccessor>
 MakeObjectVectorAccessor(U T::* memberVector)
-// clang-format on
 {
     struct MemberStdContainer : public ObjectPtrContainerAccessor
     {
@@ -104,10 +98,7 @@
             return nullptr;
         }
 
-        // clang-format off
-        // Clang-format guard needed for versions <= 18
         U T::* m_memberVector;
-        // clang-format on
     }* spec = new MemberStdContainer();
 
     spec->m_memberVector = memberVector;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/pointer.h ns-3.46/src/core/model/pointer.h
--- ns-3.45/src/core/model/pointer.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/pointer.h	2025-10-01 18:46:32.000000000 -0700
@@ -227,7 +227,8 @@
 }
 
 template <typename T>
-PointerValue::operator Ptr<T>() const
+PointerValue::
+operator Ptr<T>() const
 {
     return Get<T>();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/ptr.h ns-3.46/src/core/model/ptr.h
--- ns-3.45/src/core/model/ptr.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/ptr.h	2025-10-01 18:46:32.000000000 -0700
@@ -13,6 +13,7 @@
 
 #include <iostream>
 #include <stdint.h>
+#include <type_traits>
 
 /**
  * @file
@@ -427,6 +428,8 @@
 namespace ns3
 {
 
+class Object;
+
 /*************************************************
  *  friend non-member function implementations
  ************************************************/
@@ -435,6 +438,8 @@
 Ptr<T>
 Create(Ts&&... args)
 {
+    static_assert(!std::is_base_of_v<Object, T>,
+                  "Use CreateObject() instead of Create() for Object subclasses");
     return Ptr<T>(new T(std::forward<Ts>(args)...), false);
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/random-variable-stream.cc ns-3.46/src/core/model/random-variable-stream.cc
--- ns-3.45/src/core/model/random-variable-stream.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/random-variable-stream.cc	2025-10-01 18:46:32.000000000 -0700
@@ -652,8 +652,6 @@
 
 NS_OBJECT_ENSURE_REGISTERED(NormalRandomVariable);
 
-const double NormalRandomVariable::INFINITE_VALUE = 1e307;
-
 TypeId
 NormalRandomVariable::GetTypeId()
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/random-variable-stream.h ns-3.46/src/core/model/random-variable-stream.h
--- ns-3.45/src/core/model/random-variable-stream.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/random-variable-stream.h	2025-10-01 18:46:32.000000000 -0700
@@ -19,6 +19,7 @@
 #include "object.h"
 #include "type-id.h"
 
+#include <limits>
 #include <map>
 #include <stdint.h>
 
@@ -978,8 +979,8 @@
 class NormalRandomVariable : public RandomVariableStream
 {
   public:
-    /** Large constant to bound the range. */
-    static const double INFINITE_VALUE;
+    /// Large constant to bound the range.
+    static constexpr double INFINITE_VALUE = std::numeric_limits<double>::max();
 
     /**
      * @brief Register this type.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/rng-stream.cc ns-3.46/src/core/model/rng-stream.cc
--- ns-3.45/src/core/model/rng-stream.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/rng-stream.cc	2025-10-01 18:46:32.000000000 -0700
@@ -98,7 +98,7 @@
  * \param [in] s Second multiplicative argument.
  * \param [in] c Additive argument.
  * \param [in] m Modulus.
- * \returns <tt>(a*s +c) MOD m</tt>
+ * \returns ``(a*s +c) MOD m``
  */
 double MultModM (double a, double s, double c, double m)
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/test.cc ns-3.46/src/core/model/test.cc
--- ns-3.45/src/core/model/test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -224,12 +224,12 @@
      *
      * @param [in] testName Include a specific test by name.
      * @param [in] testType Include all tests of give type.
-     * @param [in] maximumTestDuration Restrict to tests shorter than this.
+     * @param [in] filteredTestDuration Restrict tests that match these durations.
      * @returns The list of tests matching the filter constraints.
      */
     std::list<TestCase*> FilterTests(std::string testName,
                                      TestSuite::Type testType,
-                                     TestCase::Duration maximumTestDuration);
+                                     std::vector<TestCase::Duration> filteredTestDuration);
 
     /** Container type for the test. */
     typedef std::vector<TestSuite*> TestSuiteVector;
@@ -752,33 +752,39 @@
         << "Usage: " << program_name << " [OPTIONS]" << std::endl
         << std::endl
         << "Options: " << std::endl
-        << "  --help                 : print these options" << std::endl
-        << "  --print-test-name-list : print the list of names of tests available" << std::endl
-        << "  --list                 : an alias for --print-test-name-list" << std::endl
-        << "  --print-test-types     : print the type of tests along with their names" << std::endl
-        << "  --print-test-type-list : print the list of types of tests available" << std::endl
-        << "  --print-temp-dir       : print name of temporary directory before running "
+        << "  --help                   : print these options" << std::endl
+        << "  --print-test-name-list   : print the list of names of tests available" << std::endl
+        << "  --list                   : an alias for --print-test-name-list" << std::endl
+        << "  --print-test-types       : print the type of tests along with their names"
         << std::endl
-        << "                           the tests" << std::endl
-        << "  --test-type=TYPE       : process only tests of type TYPE" << std::endl
-        << "  --test-name=NAME       : process only test whose name matches NAME" << std::endl
-        << "  --suite=NAME           : an alias (here for compatibility reasons only) " << std::endl
-        << "                           for --test-name=NAME" << std::endl
-        << "  --assert-on-failure    : when a test fails, crash immediately (useful" << std::endl
-        << "                           when running under a debugger" << std::endl
-        << "  --stop-on-failure      : when a test fails, stop immediately" << std::endl
-        << "  --fullness=FULLNESS    : choose the duration of tests to run: QUICK, " << std::endl
-        << "                           EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
-        << "                           includes QUICK and TAKES_FOREVER includes " << std::endl
-        << "                           QUICK and EXTENSIVE (only QUICK tests are " << std::endl
-        << "                           run by default)" << std::endl
-        << "  --verbose              : print details of test execution" << std::endl
-        << "  --xml                  : format test run output as xml" << std::endl
-        << "  --tempdir=DIR          : set temp dir for tests to store output files" << std::endl
-        << "  --datadir=DIR          : set data dir for tests to read reference files" << std::endl
-        << "  --out=FILE             : send test result to FILE instead of standard output"
+        << "  --print-test-type-list   : print the list of types of tests available" << std::endl
+        << "  --print-temp-dir         : print name of temporary directory before running "
         << std::endl
-        << "  --append=FILE          : append test result to FILE instead of standard output"
+        << "                             the tests" << std::endl
+        << "  --test-type=TYPE         : process only tests of type TYPE" << std::endl
+        << "  --test-name=NAME         : process only test whose name matches NAME" << std::endl
+        << "  --suite=NAME             : an alias (here for compatibility reasons only) "
+        << std::endl
+        << "                             for --test-name=NAME" << std::endl
+        << "  --assert-on-failure      : when a test fails, crash immediately (useful" << std::endl
+        << "                             when running under a debugger" << std::endl
+        << "  --stop-on-failure        : when a test fails, stop immediately" << std::endl
+        << "  --fullness=FULLNESS      : choose the duration of tests to run: QUICK, " << std::endl
+        << "                             EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
+        << "                             includes QUICK and TAKES_FOREVER includes " << std::endl
+        << "                             QUICK and EXTENSIVE (only QUICK tests are " << std::endl
+        << "                             run by default)" << std::endl
+        << "  --only-fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
+        << "                             EXTENSIVE, TAKES_FOREVER (only tests marked " << std::endl
+        << "                             with fullness will be executed)" << std::endl
+        << "  --verbose                : print details of test execution" << std::endl
+        << "  --xml                    : format test run output as xml" << std::endl
+        << "  --tempdir=DIR            : set temp dir for tests to store output files" << std::endl
+        << "  --datadir=DIR            : set data dir for tests to read reference files"
+        << std::endl
+        << "  --out=FILE               : send test result to FILE instead of standard output"
+        << std::endl
+        << "  --append=FILE            : append test result to FILE instead of standard output"
         << std::endl;
 }
 
@@ -790,11 +796,11 @@
     NS_LOG_FUNCTION(this << &begin << &end << printTestType);
     std::map<TestSuite::Type, std::string> label;
 
-    label[TestSuite::Type::ALL] = "all          ";
-    label[TestSuite::Type::UNIT] = "unit         ";
-    label[TestSuite::Type::SYSTEM] = "system       ";
-    label[TestSuite::Type::EXAMPLE] = "example      ";
-    label[TestSuite::Type::PERFORMANCE] = "performance  ";
+    label[TestSuite::Type::ALL] = "all                  ";
+    label[TestSuite::Type::UNIT] = "unit                 ";
+    label[TestSuite::Type::SYSTEM] = "system               ";
+    label[TestSuite::Type::EXAMPLE] = "example-as-test      ";
+    label[TestSuite::Type::PERFORMANCE] = "performance          ";
 
     for (auto i = begin; i != end; ++i)
     {
@@ -812,22 +818,24 @@
 TestRunnerImpl::PrintTestTypeList() const
 {
     NS_LOG_FUNCTION(this);
-    std::cout << "  core:        Run all TestSuite-based tests (exclude examples)" << std::endl;
-    std::cout << "  example:     Examples (to see if example programs run successfully)"
-              << std::endl;
-    std::cout
-        << "  performance: Performance Tests (check to see if the system is as fast as expected)"
-        << std::endl;
-    std::cout << "  system:      System Tests (spans modules to check integration of modules)"
-              << std::endl;
-    std::cout << "  unit:        Unit Tests (within modules to check basic functionality)"
+    std::cout << "  core:            Run all TestSuite-based tests (exclude examples)" << std::endl
+              << "  example:         Examples (to see if example programs run successfully)"
+              << std::endl
+              << "  example-as-test: Examples (which are tested against reference outputs)"
+              << std::endl
+              << "  performance:     Performance Tests (check to see if the system is as fast as "
+                 "expected)"
+              << std::endl
+              << "  system:          System Tests (spans modules to check integration of modules)"
+              << std::endl
+              << "  unit:            Unit Tests (within modules to check basic functionality)"
               << std::endl;
 }
 
 std::list<TestCase*>
 TestRunnerImpl::FilterTests(std::string testName,
                             TestSuite::Type testType,
-                            TestCase::Duration maximumTestDuration)
+                            std::vector<TestCase::Duration> filteredTestDuration)
 {
     NS_LOG_FUNCTION(this << testName << testType);
     std::list<TestCase*> tests;
@@ -852,7 +860,10 @@
 
             // If this test case takes longer than the maximum test
             // duration that should be run, then don't run it.
-            if (testCase->m_duration > maximumTestDuration)
+            auto it = std::find(filteredTestDuration.begin(),
+                                filteredTestDuration.end(),
+                                testCase->m_duration);
+            if (it == filteredTestDuration.end())
             {
                 // Free this test case's memory.
                 delete *j;
@@ -882,13 +893,14 @@
     std::string testTypeString = "";
     std::string out = "";
     std::string fullness = "";
+    std::string onlyFullness = "";
     bool xml = false;
     bool append = false;
     bool printTempDir = false;
     bool printTestTypeList = false;
     bool printTestNameList = false;
     bool printTestTypeAndName = false;
-    TestCase::Duration maximumTestDuration = TestCase::Duration::QUICK;
+    std::vector<TestCase::Duration> filteredTestDuration{TestCase::Duration::QUICK};
     char* progname = argv[0];
 
     char** argi = argv;
@@ -962,15 +974,17 @@
             // Set the maximum test length allowed.
             if (fullness == "QUICK")
             {
-                maximumTestDuration = TestCase::Duration::QUICK;
+                filteredTestDuration = {TestCase::Duration::QUICK};
             }
             else if (fullness == "EXTENSIVE")
             {
-                maximumTestDuration = TestCase::Duration::EXTENSIVE;
+                filteredTestDuration = {TestCase::Duration::QUICK, TestCase::Duration::EXTENSIVE};
             }
             else if (fullness == "TAKES_FOREVER")
             {
-                maximumTestDuration = TestCase::Duration::TAKES_FOREVER;
+                filteredTestDuration = {TestCase::Duration::QUICK,
+                                        TestCase::Duration::EXTENSIVE,
+                                        TestCase::Duration::TAKES_FOREVER};
             }
             else
             {
@@ -979,6 +993,30 @@
                 return 3;
             }
         }
+        else if (arg.find("--only-fullness=") != std::string::npos)
+        {
+            onlyFullness = arg.substr(arg.find_first_of('=') + 1);
+
+            // Set the maximum test length allowed.
+            if (onlyFullness == "QUICK")
+            {
+                filteredTestDuration = {TestCase::Duration::QUICK};
+            }
+            else if (onlyFullness == "EXTENSIVE")
+            {
+                filteredTestDuration = {TestCase::Duration::EXTENSIVE};
+            }
+            else if (onlyFullness == "TAKES_FOREVER")
+            {
+                filteredTestDuration = {TestCase::Duration::TAKES_FOREVER};
+            }
+            else
+            {
+                // Wrong fullness option
+                PrintHelp(progname);
+                return 4;
+            }
+        }
         else
         {
             // Print the help if arg == "--help" or arg is an un-recognized command-line argument
@@ -1015,7 +1053,15 @@
         return 1;
     }
 
-    std::list<TestCase*> tests = FilterTests(testName, testType, maximumTestDuration);
+    if (!fullness.empty() && !onlyFullness.empty())
+    {
+        std::cout << "Invalid simultaneous use of '--fullness' and '--only-fullness'. "
+                  << "Use only one of them." << std::endl;
+        PrintHelp(progname);
+        return 5;
+    }
+
+    std::list<TestCase*> tests = FilterTests(testName, testType, filteredTestDuration);
 
     if (m_tempDir.empty())
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/test.h ns-3.46/src/core/model/test.h
--- ns-3.45/src/core/model/test.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/test.h	2025-10-01 18:46:32.000000000 -0700
@@ -7,7 +7,6 @@
 #ifndef NS3_TEST_H
 #define NS3_TEST_H
 
-#include "deprecated.h"
 #include "system-wall-clock-ms.h"
 
 #include <fstream>
@@ -1058,22 +1057,6 @@
     };
 
     /**
-     * Deprecated test duration simple enums.
-     *
-     * Use the `TestCase::Duration` enum class symbols instead.
-     * @{
-     */
-    NS_DEPRECATED_3_42("Use Duration::QUICK instead")
-    static constexpr auto QUICK = Duration::QUICK;
-    NS_DEPRECATED_3_42("Use Duration::EXTENSIVE instead")
-    static constexpr auto EXTENSIVE = Duration::EXTENSIVE;
-    NS_DEPRECATED_3_42("Use Duration::TAKES_FOREVER instead")
-    static constexpr auto TAKES_FOREVER = Duration::TAKES_FOREVER;
-
-    using TestDuration NS_DEPRECATED_3_42("Use Duration instead") = Duration;
-    /**@}*/
-
-    /**
      *  Destructor
      */
     virtual ~TestCase();
@@ -1280,24 +1263,6 @@
     };
 
     /**
-     * Deprecated test type simple enums.
-     *
-     * Use the `TestSuite::Type` enum class symbols instead.
-     * @{
-     */
-    NS_DEPRECATED_3_42("Use Type::ALL instead")
-    static constexpr auto ALL = Type::ALL;
-    NS_DEPRECATED_3_42("Use Type::UNIT instead")
-    static constexpr auto UNIT = Type::UNIT;
-    NS_DEPRECATED_3_42("Use Type::SYSTEM instead")
-    static constexpr auto SYSTEM = Type::SYSTEM;
-    NS_DEPRECATED_3_42("Use Type::EXAMPLE instead")
-    static constexpr auto EXAMPLE = Type::EXAMPLE;
-    NS_DEPRECATED_3_42("Use Type::PERFORMANCE instead")
-    static constexpr auto PERFORMANCE = Type::PERFORMANCE;
-    /**@}*/
-
-    /**
      * @brief Construct a new test suite.
      *
      * @param [in] name The name of the test suite.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/time.cc ns-3.46/src/core/model/time.cc
--- ns-3.45/src/core/model/time.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/time.cc	2025-10-01 18:46:32.000000000 -0700
@@ -181,7 +181,7 @@
         *this = Time::FromDouble(v, Time::S);
     }
 
-    if (g_markingTimes)
+    if (MarkingTimes())
     {
         Mark(this);
     }
@@ -280,6 +280,12 @@
     resolution->unit = unit;
 }
 
+bool
+Time::MarkingTimes()
+{
+    return (g_markingTimes != nullptr);
+}
+
 // static
 void
 Time::ClearMarkedTimes()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/traced-value.h ns-3.46/src/core/model/traced-value.h
--- ns-3.45/src/core/model/traced-value.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/traced-value.h	2025-10-01 18:46:32.000000000 -0700
@@ -501,13 +501,10 @@
  * @returns The result of doing the operator on
  *     the underlying values.
  */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator+(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() + rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x+x");
     return TracedValue<decltype(lhs.Get() + rhs.Get())>(lhs.Get() + rhs.Get());
@@ -532,13 +529,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator-(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() - rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x-x");
     return TracedValue<decltype(lhs.Get() - rhs.Get())>(lhs.Get() - rhs.Get());
@@ -563,13 +557,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator*(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() * rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x*x");
     return TracedValue<decltype(lhs.Get() * rhs.Get())>(lhs.Get() * rhs.Get());
@@ -594,13 +585,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator/(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() / rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x/x");
     return TracedValue<decltype(lhs.Get() / rhs.Get())>(lhs.Get() / rhs.Get());
@@ -625,13 +613,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator%(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() % rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x%x");
     return TracedValue<decltype(lhs.Get() % rhs.Get())>(lhs.Get() % rhs.Get());
@@ -656,13 +641,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator^(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() ^ rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x^x");
     return TracedValue<decltype(lhs.Get() ^ rhs.Get())>(lhs.Get() ^ rhs.Get());
@@ -687,13 +669,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator|(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() | rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x|x");
     return TracedValue<decltype(lhs.Get() | rhs.Get())>(lhs.Get() | rhs.Get());
@@ -718,13 +697,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator&(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() & rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x&x");
     return TracedValue<decltype(lhs.Get() & rhs.Get())>(lhs.Get() & rhs.Get());
@@ -749,13 +725,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator<<(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() << rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x<<x");
     return TracedValue<decltype(lhs.Get() << rhs.Get())>(lhs.Get() << rhs.Get());
@@ -780,13 +753,10 @@
 }
 
 /** @copydoc operator+(const TracedValue<T>&lhs,const TracedValue<U>&rhs) */
-// clang-format off
-// Clang-format guard needed for version 18 only
 template <typename T, typename U>
 auto
 operator>>(const TracedValue<T>& lhs, const TracedValue<U>& rhs)
     -> TracedValue<decltype(lhs.Get() >> rhs.Get())>
-// clang-format on
 {
     TRACED_VALUE_DEBUG("x>>x");
     return TracedValue<decltype(lhs.Get() >> rhs.Get())>(lhs.Get() >> rhs.Get());
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/trace-source-accessor.h ns-3.46/src/core/model/trace-source-accessor.h
--- ns-3.45/src/core/model/trace-source-accessor.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/trace-source-accessor.h	2025-10-01 18:46:32.000000000 -0700
@@ -136,12 +136,9 @@
  * @param [in] a The underlying data value.
  * @returns The TraceSourceAccessor
  */
-// clang-format off
-// Clang-format guard needed for versions <= 18
 template <typename T, typename SOURCE>
 Ptr<const TraceSourceAccessor>
 DoMakeTraceSourceAccessor(SOURCE T::* a)
-// clang-format on
 {
     struct Accessor : public TraceSourceAccessor
     {
@@ -189,10 +186,7 @@
             return true;
         }
 
-        // clang-format off
-        // Clang-format guard needed for versions <= 18
         SOURCE T::* m_source;
-        // clang-format on
     }* accessor = new Accessor();
 
     accessor->m_source = a;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/unix-fd-reader.cc ns-3.46/src/core/model/unix-fd-reader.cc
--- ns-3.45/src/core/model/unix-fd-reader.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/unix-fd-reader.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2010 The Boeing Company
  *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/version.cache ns-3.46/src/core/model/version.cache
--- ns-3.45/src/core/model/version.cache	2025-06-01 20:35:16.000000000 -0700
+++ ns-3.46/src/core/model/version.cache	2025-10-01 18:47:01.000000000 -0700
@@ -1,10 +1,10 @@
-CLOSEST_TAG = '"ns-3.45"'
-VERSION_COMMIT_HASH = '"g4059af204"'
+CLOSEST_TAG = '"ns-3.46"'
+VERSION_COMMIT_HASH = '"gea50b72ab"'
 VERSION_DIRTY_FLAG = '0'
 VERSION_MAJOR = '3'
-VERSION_MINOR = '45'
+VERSION_MINOR = '46'
 VERSION_PATCH = '0'
 VERSION_RELEASE_CANDIDATE = '""'
-VERSION_TAG = '"ns-3.45"'
+VERSION_TAG = '"ns-3.46"'
 VERSION_TAG_DISTANCE = '0'
 VERSION_BUILD_PROFILE = 'default'
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/model/version.h ns-3.46/src/core/model/version.h
--- ns-3.45/src/core/model/version.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/model/version.h	2025-10-01 18:46:32.000000000 -0700
@@ -91,7 +91,7 @@
 {
   public:
     /**
-     * Returns the ns-3 version tag of the closest ancestor commit.
+     * Returns the ns-3 version tag of the closest ancestor commit prefixed with ns-3.
      *
      * The format of the tag is
      * @verbatim ns3-<major>.<minor>[.patch] \endverbatim
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/test/attribute-test-suite.cc ns-3.46/src/core/test/attribute-test-suite.cc
--- ns-3.45/src/core/test/attribute-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/test/attribute-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1880,7 +1880,7 @@
     // Now, lets create an Object of type Derived and set the local Ptr to point
     // to that object.  We can then set the PointerValue Attribute to that Ptr.
     //
-    derived = Create<Derived>();
+    derived = CreateObject<Derived>();
     bool ok = p->SetAttributeFailSafe("Pointer", PointerValue(derived));
     NS_TEST_ASSERT_MSG_EQ(ok,
                           true,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/test/callback-test-suite.cc ns-3.46/src/core/test/callback-test-suite.cc
--- ns-3.45/src/core/test/callback-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/test/callback-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1013,25 +1013,20 @@
  * Test function - does nothing.
  * @{
  */
-
-// clang-format off
-
-void TestFZero() {}
-void TestFOne(int) {}
-void TestFTwo(int, int) {}
-void TestFThree(int, int, int) {}
-void TestFFour(int, int, int, int) {}
-void TestFFive(int, int, int, int, int) {}
-void TestFSix(int, int, int, int, int, int) {}
-
-void TestFROne(int&) {}
-void TestFRTwo(int&, int&) {}
-void TestFRThree(int&, int&, int&) {}
-void TestFRFour(int&, int&, int&, int&) {}
-void TestFRFive(int&, int&, int&, int&, int&) {}
-void TestFRSix(int&, int&, int&, int&, int&, int&) {}
-
-// clang-format on
+void TestFZero() {};
+void TestFOne(int) {};
+void TestFTwo(int, int) {};
+void TestFThree(int, int, int) {};
+void TestFFour(int, int, int, int) {};
+void TestFFive(int, int, int, int, int) {};
+void TestFSix(int, int, int, int, int, int) {};
+
+void TestFROne(int&) {};
+void TestFRTwo(int&, int&) {};
+void TestFRThree(int&, int&, int&) {};
+void TestFRFour(int&, int&, int&, int&) {};
+void TestFRFive(int&, int&, int&, int&, int&) {};
+void TestFRSix(int&, int&, int&, int&, int&, int&) {};
 
 /** @} */
 
@@ -1080,25 +1075,20 @@
      * Test function - does nothing.
      * @{
      */
-
-    // clang-format off
-
-    void TestZero() {}
-    void TestOne(int) {}
-    void TestTwo(int, int) {}
-    void TestThree(int, int, int) {}
-    void TestFour(int, int, int, int) {}
-    void TestFive(int, int, int, int, int) {}
-    void TestSix(int, int, int, int, int, int) {}
-    void TestCZero() const  {}
-    void TestCOne(int) const  {}
-    void TestCTwo(int, int) const  {}
-    void TestCThree(int, int, int) const  {}
-    void TestCFour(int, int, int, int) const  {}
-    void TestCFive(int, int, int, int, int) const  {}
-    void TestCSix(int, int, int, int, int, int) const  {}
-
-    // clang-format on
+    void TestZero() {};
+    void TestOne(int) {};
+    void TestTwo(int, int) {};
+    void TestThree(int, int, int) {};
+    void TestFour(int, int, int, int) {};
+    void TestFive(int, int, int, int, int) {};
+    void TestSix(int, int, int, int, int, int) {};
+    void TestCZero() const {};
+    void TestCOne(int) const {};
+    void TestCTwo(int, int) const {};
+    void TestCThree(int, int, int) const {};
+    void TestCFour(int, int, int, int) const {};
+    void TestCFive(int, int, int, int, int) const {};
+    void TestCSix(int, int, int, int, int, int) const {};
 
     /** @} */
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/test/int64x64-test-suite.cc ns-3.46/src/core/test/int64x64-test-suite.cc
--- ns-3.45/src/core/test/int64x64-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/test/int64x64-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -805,66 +805,66 @@
 
     // NOLINTBEGIN(misc-redundant-expression)
     // clang-format off
-  Check(                 1ULL, "+0.0000000000000000000542");
-  Check(                 2ULL, "+0.0000000000000000001084");
-  Check(                 3ULL, "+0.0000000000000000001626");
-  Check(                 4ULL, "+0.0000000000000000002168");
-  Check(                 5ULL, "+0.0000000000000000002710");
-  Check(                 6ULL, "+0.0000000000000000003253");
-  Check(                 7ULL, "+0.0000000000000000003795");
-  Check(                 8ULL, "+0.0000000000000000004337");
-  Check(                 9ULL, "+0.0000000000000000004879");
-  Check(               0xAULL, "+0.0000000000000000005421");
-  Check(               0xFULL, "+0.0000000000000000008132");
-  Check(              0xF0ULL, "+0.0000000000000000130104");
-  Check(             0xF00ULL, "+0.0000000000000002081668");
-  Check(            0xF000ULL, "+0.0000000000000033306691");
-  Check(           0xF0000ULL, "+0.0000000000000532907052");
-  Check(          0xF00000ULL, "+0.0000000000008526512829");
-  Check(         0xF000000ULL, "+0.0000000000136424205266");
-  Check(        0xF0000000ULL, "+0.0000000002182787284255");
-  Check(       0xF00000000ULL, "+0.0000000034924596548080");
-  Check(      0xF000000000ULL, "+0.0000000558793544769287");
-  Check(     0xF0000000000ULL, "+0.0000008940696716308594");
-  Check(    0xF00000000000ULL, "+0.0000143051147460937500");
-  Check(   0xF000000000000ULL, "+0.0002288818359375000000");
-  Check(  0xF0000000000000ULL, "+0.0036621093750000000000");
-  Check( 0xF00000000000000ULL, "+0.0585937500000000000000");
-  std::cout << std::endl;
-  Check(0x7FFFFFFFFFFFFFFDULL, "+0.4999999999999999998374", tolerance);
-  Check(0x7FFFFFFFFFFFFFFEULL, "+0.4999999999999999998916", tolerance);
-  Check(0x7FFFFFFFFFFFFFFFULL, "+0.4999999999999999999458", tolerance);
-  Check(0x8000000000000000ULL, "+0.5000000000000000000000");
-  Check(0x8000000000000001ULL, "+0.5000000000000000000542", tolerance);
-  Check(0x8000000000000002ULL, "+0.5000000000000000001084", tolerance);
-  Check(0x8000000000000003ULL, "+0.5000000000000000001626", tolerance);
-  std::cout << std::endl;
-  Check(0xF000000000000000ULL, "+0.9375000000000000000000");
-  Check(0xFF00000000000000ULL, "+0.9960937500000000000000");
-  Check(0xFFF0000000000000ULL, "+0.9997558593750000000000");
-  Check(0xFFFF000000000000ULL, "+0.9999847412109375000000");
-  Check(0xFFFFF00000000000ULL, "+0.9999990463256835937500");
-  Check(0xFFFFFF0000000000ULL, "+0.9999999403953552246094");
-  Check(0xFFFFFFF000000000ULL, "+0.9999999962747097015381");
-  Check(0xFFFFFFFF00000000ULL, "+0.9999999997671693563461");
-  Check(0xFFFFFFFFF0000000ULL, "+0.9999999999854480847716");
-  Check(0xFFFFFFFFFF000000ULL, "+0.9999999999990905052982");
-  Check(0xFFFFFFFFFFF00000ULL, "+0.9999999999999431565811");
-  Check(0xFFFFFFFFFFFF0000ULL, "+0.9999999999999964472863");
-  Check(0xFFFFFFFFFFFFF000ULL, "+0.9999999999999997779554");
-  Check(0xFFFFFFFFFFFFFF00ULL, "+0.9999999999999999861222");
-  Check(0xFFFFFFFFFFFFFFF0ULL, "+0.9999999999999999991326");
-  Check(0xFFFFFFFFFFFFFFF5ULL, "+0.9999999999999999994037", tolerance);
-  Check(0xFFFFFFFFFFFFFFF6ULL, "+0.9999999999999999994579", tolerance);
-  Check(0xFFFFFFFFFFFFFFF7ULL, "+0.9999999999999999995121", tolerance);
-  Check(0xFFFFFFFFFFFFFFF8ULL, "+0.9999999999999999995663", tolerance);
-  Check(0xFFFFFFFFFFFFFFF9ULL, "+0.9999999999999999996205", tolerance);
-  Check(0xFFFFFFFFFFFFFFFAULL, "+0.9999999999999999996747", tolerance);
-  Check(0xFFFFFFFFFFFFFFFBULL, "+0.9999999999999999997289", tolerance);
-  Check(0xFFFFFFFFFFFFFFFCULL, "+0.9999999999999999997832", tolerance);
-  Check(0xFFFFFFFFFFFFFFFDULL, "+0.9999999999999999998374", tolerance);
-  Check(0xFFFFFFFFFFFFFFFEULL, "+0.9999999999999999998916", tolerance);
-  Check(0xFFFFFFFFFFFFFFFFULL, "+0.9999999999999999999458", tolerance);
+    Check(                 1ULL, "+0.0000000000000000000542");
+    Check(                 2ULL, "+0.0000000000000000001084");
+    Check(                 3ULL, "+0.0000000000000000001626");
+    Check(                 4ULL, "+0.0000000000000000002168");
+    Check(                 5ULL, "+0.0000000000000000002710");
+    Check(                 6ULL, "+0.0000000000000000003253");
+    Check(                 7ULL, "+0.0000000000000000003795");
+    Check(                 8ULL, "+0.0000000000000000004337");
+    Check(                 9ULL, "+0.0000000000000000004879");
+    Check(               0xAULL, "+0.0000000000000000005421");
+    Check(               0xFULL, "+0.0000000000000000008132");
+    Check(              0xF0ULL, "+0.0000000000000000130104");
+    Check(             0xF00ULL, "+0.0000000000000002081668");
+    Check(            0xF000ULL, "+0.0000000000000033306691");
+    Check(           0xF0000ULL, "+0.0000000000000532907052");
+    Check(          0xF00000ULL, "+0.0000000000008526512829");
+    Check(         0xF000000ULL, "+0.0000000000136424205266");
+    Check(        0xF0000000ULL, "+0.0000000002182787284255");
+    Check(       0xF00000000ULL, "+0.0000000034924596548080");
+    Check(      0xF000000000ULL, "+0.0000000558793544769287");
+    Check(     0xF0000000000ULL, "+0.0000008940696716308594");
+    Check(    0xF00000000000ULL, "+0.0000143051147460937500");
+    Check(   0xF000000000000ULL, "+0.0002288818359375000000");
+    Check(  0xF0000000000000ULL, "+0.0036621093750000000000");
+    Check( 0xF00000000000000ULL, "+0.0585937500000000000000");
+    std::cout << std::endl;
+    Check(0x7FFFFFFFFFFFFFFDULL, "+0.4999999999999999998374", tolerance);
+    Check(0x7FFFFFFFFFFFFFFEULL, "+0.4999999999999999998916", tolerance);
+    Check(0x7FFFFFFFFFFFFFFFULL, "+0.4999999999999999999458", tolerance);
+    Check(0x8000000000000000ULL, "+0.5000000000000000000000");
+    Check(0x8000000000000001ULL, "+0.5000000000000000000542", tolerance);
+    Check(0x8000000000000002ULL, "+0.5000000000000000001084", tolerance);
+    Check(0x8000000000000003ULL, "+0.5000000000000000001626", tolerance);
+    std::cout << std::endl;
+    Check(0xF000000000000000ULL, "+0.9375000000000000000000");
+    Check(0xFF00000000000000ULL, "+0.9960937500000000000000");
+    Check(0xFFF0000000000000ULL, "+0.9997558593750000000000");
+    Check(0xFFFF000000000000ULL, "+0.9999847412109375000000");
+    Check(0xFFFFF00000000000ULL, "+0.9999990463256835937500");
+    Check(0xFFFFFF0000000000ULL, "+0.9999999403953552246094");
+    Check(0xFFFFFFF000000000ULL, "+0.9999999962747097015381");
+    Check(0xFFFFFFFF00000000ULL, "+0.9999999997671693563461");
+    Check(0xFFFFFFFFF0000000ULL, "+0.9999999999854480847716");
+    Check(0xFFFFFFFFFF000000ULL, "+0.9999999999990905052982");
+    Check(0xFFFFFFFFFFF00000ULL, "+0.9999999999999431565811");
+    Check(0xFFFFFFFFFFFF0000ULL, "+0.9999999999999964472863");
+    Check(0xFFFFFFFFFFFFF000ULL, "+0.9999999999999997779554");
+    Check(0xFFFFFFFFFFFFFF00ULL, "+0.9999999999999999861222");
+    Check(0xFFFFFFFFFFFFFFF0ULL, "+0.9999999999999999991326");
+    Check(0xFFFFFFFFFFFFFFF5ULL, "+0.9999999999999999994037", tolerance);
+    Check(0xFFFFFFFFFFFFFFF6ULL, "+0.9999999999999999994579", tolerance);
+    Check(0xFFFFFFFFFFFFFFF7ULL, "+0.9999999999999999995121", tolerance);
+    Check(0xFFFFFFFFFFFFFFF8ULL, "+0.9999999999999999995663", tolerance);
+    Check(0xFFFFFFFFFFFFFFF9ULL, "+0.9999999999999999996205", tolerance);
+    Check(0xFFFFFFFFFFFFFFFAULL, "+0.9999999999999999996747", tolerance);
+    Check(0xFFFFFFFFFFFFFFFBULL, "+0.9999999999999999997289", tolerance);
+    Check(0xFFFFFFFFFFFFFFFCULL, "+0.9999999999999999997832", tolerance);
+    Check(0xFFFFFFFFFFFFFFFDULL, "+0.9999999999999999998374", tolerance);
+    Check(0xFFFFFFFFFFFFFFFEULL, "+0.9999999999999999998916", tolerance);
+    Check(0xFFFFFFFFFFFFFFFFULL, "+0.9999999999999999999458", tolerance);
     // clang-format on
     // NOLINTEND(misc-redundant-expression)
 }
@@ -1152,6 +1152,7 @@
      *
      * This will lie in the closed interval [0, 64]
      */
+    // NOLINTNEXTLINE(misc-redundant-expression)
     static constexpr int MISS_MANT_DIG = std::max(0, 64 - LDBL_MANT_DIG);
 
     /**
@@ -1540,8 +1541,8 @@
     std::cout << std::endl;
 
 #if defined(INT64X64_USE_CAIRO) && !defined(PYTHON_SCAN)
-    std::cout << "cairo_impl64:  " << cairo_impl64 << std::endl;
-    std::cout << "cairo_impl128: " << cairo_impl128 << std::endl;
+    std::cout << "cairo_impl64:  " << cairo_impl64() << std::endl;
+    std::cout << "cairo_impl128: " << cairo_impl128() << std::endl;
 #endif
 
     if (RUNNING_WITH_LIMITED_PRECISION != 0)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/test/matrix-array-test-suite.cc ns-3.46/src/core/test/matrix-array-test-suite.cc
--- ns-3.45/src/core/test/matrix-array-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/test/matrix-array-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -487,34 +487,34 @@
     }
     // clang-format off
     std::valarray<int> multiPageMatrixValues{
-            // page 0: identity matrix
-            1, 0, 0,
-            0, 1, 0,
-            0, 0, 1,
-            // page 1: permutation matrix
-            0, 0, 1,
-            0, 1, 0,
-            1, 0, 0,
-            // page 2: random matrix
-            1, 4, 6,
-            0, 2, 5,
-            7, 0, 3,
-            // page 3: upper triangular
-            5, -9, 2,
-            0, -4, -10,
-            0, 0, -3,
-            // page 4: lower triangular
-            -7, 0, 0,
-            -1, -9, 0,
-            -5, 6, -5,
-            // page 5: zero diagonal
-            0, 1, 2,
-            1, 0, 1,
-            2, 1, 0,
-            // page 6: zero bidiagonal
-            0, 1, 0,
-            1, 0, 1,
-            0, 1, 0
+        // page 0: identity matrix
+        1, 0, 0,
+        0, 1, 0,
+        0, 0, 1,
+        // page 1: permutation matrix
+        0, 0, 1,
+        0, 1, 0,
+        1, 0, 0,
+        // page 2: random matrix
+        1, 4, 6,
+        0, 2, 5,
+        7, 0, 3,
+        // page 3: upper triangular
+        5, -9, 2,
+        0, -4, -10,
+        0, 0, -3,
+        // page 4: lower triangular
+        -7, 0, 0,
+        -1, -9, 0,
+        -5, 6, -5,
+        // page 5: zero diagonal
+        0, 1, 2,
+        1, 0, 1,
+        2, 1, 0,
+        // page 6: zero bidiagonal
+        0, 1, 0,
+        1, 0, 1,
+        0, 1, 0
     };
     // clang-format on
     std::valarray<T> castMultiPageMatrixValues(multiPageMatrixValues.size());
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/test/simulator-test-suite.cc ns-3.46/src/core/test/simulator-test-suite.cc
--- ns-3.45/src/core/test/simulator-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/test/simulator-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -235,45 +235,39 @@
      *
      * @{
      */
-
-    // clang-format off
-
-    void bar0() {}
-    void bar1(int) {}
-    void bar2(int, int) {}
-    void bar3(int, int, int) {}
-    void bar4(int, int, int, int) {}
-    void bar5(int, int, int, int, int) {}
-    void baz1(int&) {}
-    void baz2(int&, int&) {}
-    void baz3(int&, int&, int&) {}
-    void baz4(int&, int&, int&, int&) {}
-    void baz5(int&, int&, int&, int&, int&) {}
-    void cbaz1(const int&) {}
-    void cbaz2(const int&, const int&) {}
-    void cbaz3(const int&, const int&, const int&) {}
-    void cbaz4(const int&, const int&, const int&, const int&) {}
-    void cbaz5(const int&, const int&, const int&, const int&, const int&) {}
-
-    void bar0c() const {}
-    void bar1c(int) const {}
-    void bar2c(int, int) const {}
-    void bar3c(int, int, int) const {}
-    void bar4c(int, int, int, int) const {}
-    void bar5c(int, int, int, int, int) const {}
-    void baz1c(int&) const {}
-    void baz2c(int&, int&) const {}
-    void baz3c(int&, int&, int&) const {}
-    void baz4c(int&, int&, int&, int&) const {}
-    void baz5c(int&, int&, int&, int&, int&) const {}
-    void cbaz1c(const int&) const {}
-    void cbaz2c(const int&, const int&) const {}
-    void cbaz3c(const int&, const int&, const int&) const {}
-    void cbaz4c(const int&, const int&, const int&, const int&) const {}
-    void cbaz5c(const int&, const int&, const int&, const int&, const int&) const {}
-
-    // clang-format on
-
+    void bar0() {};
+    void bar1(int) {};
+    void bar2(int, int) {};
+    void bar3(int, int, int) {};
+    void bar4(int, int, int, int) {};
+    void bar5(int, int, int, int, int) {};
+    void baz1(int&) {};
+    void baz2(int&, int&) {};
+    void baz3(int&, int&, int&) {};
+    void baz4(int&, int&, int&, int&) {};
+    void baz5(int&, int&, int&, int&, int&) {};
+    void cbaz1(const int&) {};
+    void cbaz2(const int&, const int&) {};
+    void cbaz3(const int&, const int&, const int&) {};
+    void cbaz4(const int&, const int&, const int&, const int&) {};
+    void cbaz5(const int&, const int&, const int&, const int&, const int&) {};
+
+    void bar0c() const {};
+    void bar1c(int) const {};
+    void bar2c(int, int) const {};
+    void bar3c(int, int, int) const {};
+    void bar4c(int, int, int, int) const {};
+    void bar5c(int, int, int, int, int) const {};
+    void baz1c(int&) const {};
+    void baz2c(int&, int&) const {};
+    void baz3c(int&, int&, int&) const {};
+    void baz4c(int&, int&, int&, int&) const {};
+    void baz5c(int&, int&, int&, int&, int&) const {};
+    void cbaz1c(const int&) const {};
+    void cbaz2c(const int&, const int&) const {};
+    void cbaz3c(const int&, const int&, const int&) const {};
+    void cbaz4c(const int&, const int&, const int&, const int&) const {};
+    void cbaz5c(const int&, const int&, const int&, const int&, const int&) const {};
     /** @} */
 };
 
@@ -282,27 +276,22 @@
  *
  * @{
  */
-
-// clang-format off
-
-static void foo0() {}
-static void foo1(int) {}
-static void foo2(int, int) {}
-static void foo3(int, int, int) {}
-static void foo4(int, int, int, int) {}
-static void foo5(int, int, int, int, int) {}
-static void ber1(int&) {}
-static void ber2(int&, int&) {}
-static void ber3(int&, int&, int&) {}
-static void ber4(int&, int&, int&, int&) {}
-static void ber5(int&, int&, int&, int&, int&) {}
-static void cber1(const int&) {}
-static void cber2(const int&, const int&) {}
-static void cber3(const int&, const int&, const int&) {}
-static void cber4(const int&, const int&, const int&, const int&) {}
-static void cber5(const int&, const int&, const int&, const int&, const int&) {}
-
-// clang-format on
+static void foo0() {};
+static void foo1(int) {};
+static void foo2(int, int) {};
+static void foo3(int, int, int) {};
+static void foo4(int, int, int, int) {};
+static void foo5(int, int, int, int, int) {};
+static void ber1(int&) {};
+static void ber2(int&, int&) {};
+static void ber3(int&, int&, int&) {};
+static void ber4(int&, int&, int&, int&) {};
+static void ber5(int&, int&, int&, int&, int&) {};
+static void cber1(const int&) {};
+static void cber2(const int&, const int&) {};
+static void cber3(const int&, const int&, const int&) {};
+static void cber4(const int&, const int&, const int&, const int&) {};
+static void cber5(const int&, const int&, const int&, const int&, const int&) {};
 
 /** @} */
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/core/test/timer-test-suite.cc ns-3.46/src/core/test/timer-test-suite.cc
--- ns-3.45/src/core/test/timer-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/core/test/timer-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -23,26 +23,20 @@
 
 namespace
 {
-
-// clang-format off
-
 /// Function with one int parameter.
-void bari(int) {}
+void bari(int) {};
 /// Function with two int parameters.
-void bar2i(int, int) {}
+void bar2i(int, int) {};
 /// Function with three int parameters.
-void bar3i(int, int, int) {}
+void bar3i(int, int, int) {};
 /// Function with four int parameters.
-void bar4i(int, int, int, int) {}
+void bar4i(int, int, int, int) {};
 /// Function with five int parameters.
-void bar5i(int, int, int, int, int) {}
+void bar5i(int, int, int, int, int) {};
 /// Function with one const int reference parameter.
-void barcir(const int&) {}
+void barcir(const int&) {};
 /// Function with one int reference parameter.
-void barir(int&) {}
-
-// clang-format on
-
+void barir(int&) {};
 } // anonymous namespace
 
 using namespace ns3;
@@ -110,30 +104,26 @@
     void DoRun() override;
     void DoTeardown() override;
 
-    // clang-format off
-
     /// Member function with one int parameter.
-    void bazi(int) {}
+    void bazi(int) {};
     /// Member function with two int parameters.
-    void baz2i(int, int) {}
+    void baz2i(int, int) {};
     /// Member function with three int parameters.
-    void baz3i(int, int, int) {}
+    void baz3i(int, int, int) {};
     /// Member function with four int parameters.
-    void baz4i(int, int, int, int) {}
+    void baz4i(int, int, int, int) {};
     /// Member function with five int parameters.
-    void baz5i(int, int, int, int, int) {}
+    void baz5i(int, int, int, int, int) {};
     /// Member function with six int parameters.
-    void baz6i(int, int, int, int, int, int) {}
+    void baz6i(int, int, int, int, int, int) {};
     /// Member function with one const int reference parameter.
-    void bazcir(const int&) {}
+    void bazcir(const int&) {};
     /// Member function with one int reference parameter.
-    void bazir(int&) {}
+    void bazir(int&) {};
     /// Member function with one int pointer parameter.
-    void bazip(int*) {}
+    void bazip(int*) {};
     /// Member function with one const int pointer parameter.
-    void bazcip(const int*) {}
-
-    // clang-format on
+    void bazcip(const int*) {};
 };
 
 TimerTemplateTestCase::TimerTemplateTestCase()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/csma/model/backoff.h ns-3.46/src/csma/model/backoff.h
--- ns-3.45/src/csma/model/backoff.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/csma/model/backoff.h	2025-10-01 18:46:32.000000000 -0700
@@ -105,7 +105,7 @@
 
   private:
     /**
-     * Number of times that the transmitter has tried to unsuccessfuly transmit the current packet.
+     * Number of times that the transmitter has tried to unsuccessfully transmit the current packet.
      */
     uint32_t m_numBackoffRetries;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/CMakeLists.txt ns-3.46/src/energy/CMakeLists.txt
--- ns-3.45/src/energy/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -17,7 +17,6 @@
     model/energy-harvester.cc
     model/energy-source.cc
     model/generic-battery-model.cc
-    model/li-ion-energy-source.cc
     model/rv-battery-model.cc
     model/simple-device-energy-model.cc
   HEADER_FILES
@@ -37,10 +36,9 @@
     model/energy-harvester.h
     model/energy-source.h
     model/generic-battery-model.h
-    model/li-ion-energy-source.h
     model/rv-battery-model.h
     model/simple-device-energy-model.h
   LIBRARIES_TO_LINK ${libnetwork}
   TEST_SOURCES test/basic-energy-harvester-test.cc
-               test/li-ion-energy-source-test.cc
+               test/generic-battery-test.cc
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/examples/CMakeLists.txt ns-3.46/src/energy/examples/CMakeLists.txt
--- ns-3.45/src/energy/examples/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/examples/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -18,13 +18,6 @@
 )
 
 build_lib_example(
-  NAME li-ion-energy-source-example
-  SOURCE_FILES li-ion-energy-source-example.cc
-  LIBRARIES_TO_LINK ${libcore}
-                    ${libenergy}
-)
-
-build_lib_example(
   NAME rv-battery-model-test
   SOURCE_FILES rv-battery-model-test.cc
   LIBRARIES_TO_LINK
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/examples/li-ion-energy-source-example.cc ns-3.46/src/energy/examples/li-ion-energy-source-example.cc
--- ns-3.45/src/energy/examples/li-ion-energy-source-example.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/examples/li-ion-energy-source-example.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2010 Andrea Sacco
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Andrea Sacco <andrea.sacco85@gmail.com>
- */
-
-#include "ns3/command-line.h"
-#include "ns3/energy-source-container.h"
-#include "ns3/li-ion-energy-source.h"
-#include "ns3/log.h"
-#include "ns3/simple-device-energy-model.h"
-#include "ns3/simulator.h"
-
-using namespace ns3;
-using namespace ns3::energy;
-
-/**
- * In this simple example, we show how to create and drain energy from a
- * LiIonEnergySource.
- * We make a series of discharge calls to the energy source class with
- * different current drain and duration until all the energy is depleted
- * from the cell.
- *
- * Every 20 seconds it is printed out the actual cell voltage to verify
- * that it follows the discharge curve of the datasheet [1].
- *
- * At the end of the example it is verified that after the energy depletion
- * call, the cell voltage is below the threshold voltage.
- *
- * References:
- * [1] Panasonic CGR18650DA Datasheet,
- * http://www.panasonic.com/industrial/includes/pdf/Panasonic_LiIon_CGR18650DA.pdf
- */
-
-// NS_DEPRECATED_3_43() - tag for future removal
-// LiIonEnergySource was deprecated in commit
-// https://gitlab.com/nsnam/ns-3-dev/-/commit/086913b0
-//
-// The new battery model is illustrated in
-// `src/energy/examples/generic-battery-discharge-example.cc`
-
-NS_WARNING_PUSH_DEPRECATED;
-
-static void
-PrintCellInfo(Ptr<LiIonEnergySource> es)
-{
-    NS_WARNING_POP;
-    std::cout << "At " << Simulator::Now().As(Time::S)
-              << " Cell voltage: " << es->GetSupplyVoltage()
-              << " V Remaining Capacity: " << es->GetRemainingEnergy() / (3.6 * 3600) << " Ah"
-              << std::endl;
-
-    if (!Simulator::IsFinished())
-    {
-        Simulator::Schedule(Seconds(20), &PrintCellInfo, es);
-    }
-}
-
-int
-main(int argc, char** argv)
-{
-    CommandLine cmd(__FILE__);
-    cmd.Parse(argc, argv);
-
-    // uncomment below to see the energy consumption details
-    // LogComponentEnable ("LiIonEnergySource", LOG_LEVEL_DEBUG);
-
-    Ptr<Node> node = CreateObject<Node>();
-
-    Ptr<SimpleDeviceEnergyModel> sem = CreateObject<SimpleDeviceEnergyModel>();
-    Ptr<EnergySourceContainer> esCont = CreateObject<EnergySourceContainer>();
-    NS_WARNING_PUSH_DEPRECATED;
-    Ptr<LiIonEnergySource> es = CreateObject<LiIonEnergySource>();
-    NS_WARNING_POP;
-    esCont->Add(es);
-    es->SetNode(node);
-    sem->SetEnergySource(es);
-    es->AppendDeviceEnergyModel(sem);
-    sem->SetNode(node);
-    node->AggregateObject(esCont);
-
-    Time now = Simulator::Now();
-
-    // discharge at 2.33 A for 1700 seconds
-    sem->SetCurrentA(2.33);
-    now += Seconds(1701);
-
-    // discharge at 4.66 A for 628 seconds
-    Simulator::Schedule(now, &SimpleDeviceEnergyModel::SetCurrentA, sem, 4.66);
-    now += Seconds(600);
-
-    PrintCellInfo(es);
-
-    Simulator::Stop(now);
-    Simulator::Run();
-    Simulator::Destroy();
-
-    // the cell voltage should be under 3.3v
-    DoubleValue v;
-    es->GetAttribute("ThresholdVoltage", v);
-    NS_ASSERT(es->GetSupplyVoltage() <= v.Get());
-
-    return 0;
-}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/model/li-ion-energy-source.cc ns-3.46/src/energy/model/li-ion-energy-source.cc
--- ns-3.45/src/energy/model/li-ion-energy-source.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/model/li-ion-energy-source.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,312 +0,0 @@
-/*
- * Copyright (c) 2010 Andrea Sacco
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Andrea Sacco <andrea.sacco85@gmail.com>
- */
-
-#include "li-ion-energy-source.h"
-
-#include "ns3/assert.h"
-#include "ns3/double.h"
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/trace-source-accessor.h"
-
-#include <cmath>
-
-namespace ns3
-{
-namespace energy
-{
-
-NS_LOG_COMPONENT_DEFINE("LiIonEnergySource");
-NS_OBJECT_ENSURE_REGISTERED(LiIonEnergySource);
-
-TypeId
-LiIonEnergySource::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::energy::LiIonEnergySource")
-            .AddDeprecatedName("ns3::LiIonEnergySource")
-            .SetParent<EnergySource>()
-            .SetGroupName("Energy")
-            .AddConstructor<LiIonEnergySource>()
-            .AddAttribute("LiIonEnergySourceInitialEnergyJ",
-                          "Initial energy stored in basic energy source.",
-                          DoubleValue(31752.0), // in Joules
-                          MakeDoubleAccessor(&LiIonEnergySource::SetInitialEnergy,
-                                             &LiIonEnergySource::GetInitialEnergy),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("LiIonEnergyLowBatteryThreshold",
-                          "Low battery threshold for LiIon energy source.",
-                          DoubleValue(0.10), // as a fraction of the initial energy
-                          MakeDoubleAccessor(&LiIonEnergySource::m_lowBatteryTh),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("InitialCellVoltage",
-                          "Initial (maximum) voltage of the cell (fully charged).",
-                          DoubleValue(4.05), // in Volts
-                          MakeDoubleAccessor(&LiIonEnergySource::SetInitialSupplyVoltage,
-                                             &LiIonEnergySource::GetSupplyVoltage),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("NominalCellVoltage",
-                          "Nominal voltage of the cell.",
-                          DoubleValue(3.6), // in Volts
-                          MakeDoubleAccessor(&LiIonEnergySource::m_eNom),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("ExpCellVoltage",
-                          "Cell voltage at the end of the exponential zone.",
-                          DoubleValue(3.6), // in Volts
-                          MakeDoubleAccessor(&LiIonEnergySource::m_eExp),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("RatedCapacity",
-                          "Rated capacity of the cell.",
-                          DoubleValue(2.45), // in Ah
-                          MakeDoubleAccessor(&LiIonEnergySource::m_qRated),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("NomCapacity",
-                          "Cell capacity at the end of the nominal zone.",
-                          DoubleValue(1.1), // in Ah
-                          MakeDoubleAccessor(&LiIonEnergySource::m_qNom),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("ExpCapacity",
-                          "Cell Capacity at the end of the exponential zone.",
-                          DoubleValue(1.2), // in Ah
-                          MakeDoubleAccessor(&LiIonEnergySource::m_qExp),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("InternalResistance",
-                          "Internal resistance of the cell",
-                          DoubleValue(0.083), // in Ohms
-                          MakeDoubleAccessor(&LiIonEnergySource::m_internalResistance),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("TypCurrent",
-                          "Typical discharge current used to fit the curves",
-                          DoubleValue(2.33), // in A
-                          MakeDoubleAccessor(&LiIonEnergySource::m_typCurrent),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("ThresholdVoltage",
-                          "Minimum threshold voltage to consider the battery depleted.",
-                          DoubleValue(3.3), // in Volts
-                          MakeDoubleAccessor(&LiIonEnergySource::m_minVoltTh),
-                          MakeDoubleChecker<double>())
-            .AddAttribute("PeriodicEnergyUpdateInterval",
-                          "Time between two consecutive periodic energy updates.",
-                          TimeValue(Seconds(1)),
-                          MakeTimeAccessor(&LiIonEnergySource::SetEnergyUpdateInterval,
-                                           &LiIonEnergySource::GetEnergyUpdateInterval),
-                          MakeTimeChecker())
-            .AddTraceSource("RemainingEnergy",
-                            "Remaining energy at BasicEnergySource.",
-                            MakeTraceSourceAccessor(&LiIonEnergySource::m_remainingEnergyJ),
-                            "ns3::TracedValueCallback::Double");
-    return tid;
-}
-
-LiIonEnergySource::LiIonEnergySource()
-    : m_drainedCapacity(0.0),
-      m_lastUpdateTime()
-{
-    NS_LOG_FUNCTION(this);
-}
-
-LiIonEnergySource::~LiIonEnergySource()
-{
-    NS_LOG_FUNCTION(this);
-}
-
-void
-LiIonEnergySource::SetInitialEnergy(double initialEnergyJ)
-{
-    NS_LOG_FUNCTION(this << initialEnergyJ);
-    NS_ASSERT(initialEnergyJ >= 0);
-    m_initialEnergyJ = initialEnergyJ;
-    // set remaining energy to be initial energy
-    m_remainingEnergyJ = m_initialEnergyJ;
-}
-
-double
-LiIonEnergySource::GetInitialEnergy() const
-{
-    NS_LOG_FUNCTION(this);
-    return m_initialEnergyJ;
-}
-
-void
-LiIonEnergySource::SetInitialSupplyVoltage(double supplyVoltageV)
-{
-    NS_LOG_FUNCTION(this << supplyVoltageV);
-    m_eFull = supplyVoltageV;
-    m_supplyVoltageV = supplyVoltageV;
-}
-
-double
-LiIonEnergySource::GetSupplyVoltage() const
-{
-    NS_LOG_FUNCTION(this);
-    return m_supplyVoltageV;
-}
-
-void
-LiIonEnergySource::SetEnergyUpdateInterval(Time interval)
-{
-    NS_LOG_FUNCTION(this << interval);
-    m_energyUpdateInterval = interval;
-}
-
-Time
-LiIonEnergySource::GetEnergyUpdateInterval() const
-{
-    NS_LOG_FUNCTION(this);
-    return m_energyUpdateInterval;
-}
-
-double
-LiIonEnergySource::GetRemainingEnergy()
-{
-    NS_LOG_FUNCTION(this);
-    // update energy source to get the latest remaining energy.
-    UpdateEnergySource();
-    return m_remainingEnergyJ;
-}
-
-double
-LiIonEnergySource::GetEnergyFraction()
-{
-    NS_LOG_FUNCTION(this);
-    // update energy source to get the latest remaining energy.
-    UpdateEnergySource();
-    return m_remainingEnergyJ / m_initialEnergyJ;
-}
-
-void
-LiIonEnergySource::DecreaseRemainingEnergy(double energyJ)
-{
-    NS_LOG_FUNCTION(this << energyJ);
-    NS_ASSERT(energyJ >= 0);
-    m_remainingEnergyJ -= energyJ;
-
-    // check if remaining energy is 0
-    if (m_supplyVoltageV <= m_minVoltTh)
-    {
-        HandleEnergyDrainedEvent();
-    }
-}
-
-void
-LiIonEnergySource::IncreaseRemainingEnergy(double energyJ)
-{
-    NS_LOG_FUNCTION(this << energyJ);
-    NS_ASSERT(energyJ >= 0);
-    m_remainingEnergyJ += energyJ;
-}
-
-void
-LiIonEnergySource::UpdateEnergySource()
-{
-    NS_LOG_FUNCTION(this);
-    NS_LOG_DEBUG("LiIonEnergySource:Updating remaining energy at node #" << GetNode()->GetId());
-
-    // do not update if simulation has finished
-    if (Simulator::IsFinished())
-    {
-        return;
-    }
-
-    m_energyUpdateEvent.Cancel();
-
-    CalculateRemainingEnergy();
-
-    m_lastUpdateTime = Simulator::Now();
-
-    if (m_remainingEnergyJ <= m_lowBatteryTh * m_initialEnergyJ)
-    {
-        HandleEnergyDrainedEvent();
-        return; // stop periodic update
-    }
-
-    m_energyUpdateEvent =
-        Simulator::Schedule(m_energyUpdateInterval, &LiIonEnergySource::UpdateEnergySource, this);
-}
-
-/*
- * Private functions start here.
- */
-void
-LiIonEnergySource::DoInitialize()
-{
-    NS_LOG_FUNCTION(this);
-    UpdateEnergySource(); // start periodic update
-}
-
-void
-LiIonEnergySource::DoDispose()
-{
-    NS_LOG_FUNCTION(this);
-    BreakDeviceEnergyModelRefCycle(); // break reference cycle
-}
-
-void
-LiIonEnergySource::HandleEnergyDrainedEvent()
-{
-    NS_LOG_FUNCTION(this);
-    NS_LOG_DEBUG("LiIonEnergySource:Energy depleted at node #" << GetNode()->GetId());
-    NotifyEnergyDrained(); // notify DeviceEnergyModel objects
-}
-
-void
-LiIonEnergySource::CalculateRemainingEnergy()
-{
-    NS_LOG_FUNCTION(this);
-    double totalCurrentA = CalculateTotalCurrent();
-    Time duration = Simulator::Now() - m_lastUpdateTime;
-    NS_ASSERT(duration.GetSeconds() >= 0);
-    // energy = current * voltage * time
-    double energyToDecreaseJ = totalCurrentA * m_supplyVoltageV * duration.GetSeconds();
-
-    if (m_remainingEnergyJ < energyToDecreaseJ)
-    {
-        m_remainingEnergyJ = 0; // energy never goes below 0
-    }
-    else
-    {
-        m_remainingEnergyJ -= energyToDecreaseJ;
-    }
-
-    m_drainedCapacity += (totalCurrentA * duration).GetHours();
-    // update the supply voltage
-    m_supplyVoltageV = GetVoltage(totalCurrentA);
-    NS_LOG_DEBUG("LiIonEnergySource:Remaining energy = " << m_remainingEnergyJ);
-}
-
-double
-LiIonEnergySource::GetVoltage(double i) const
-{
-    NS_LOG_FUNCTION(this << i);
-
-    // integral of i in dt, drained capacity in Ah
-    double it = m_drainedCapacity;
-
-    // empirical factors
-    double A = m_eFull - m_eExp;
-    double B = 3 / m_qExp;
-
-    // slope of the polarization curve
-    double K = std::abs((m_eFull - m_eNom + A * (std::exp(-B * m_qNom) - 1)) * (m_qRated - m_qNom) /
-                        m_qNom);
-
-    // constant voltage
-    double E0 = m_eFull + K + m_internalResistance * m_typCurrent - A;
-
-    double E = E0 - K * m_qRated / (m_qRated - it) + A * std::exp(-B * it);
-
-    // cell voltage
-    double V = E - m_internalResistance * i;
-
-    NS_LOG_DEBUG("Voltage: " << V << " with E: " << E);
-
-    return V;
-}
-
-} // namespace energy
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/model/li-ion-energy-source.h ns-3.46/src/energy/model/li-ion-energy-source.h
--- ns-3.45/src/energy/model/li-ion-energy-source.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/model/li-ion-energy-source.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2010 Andrea Sacco
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Andrea Sacco <andrea.sacco85@gmail.com>
- */
-
-#ifndef LI_ION_ENERGY_SOURCE_H
-#define LI_ION_ENERGY_SOURCE_H
-
-#include "energy-source.h"
-
-#include "ns3/deprecated.h"
-#include "ns3/event-id.h"
-#include "ns3/nstime.h"
-#include "ns3/traced-value.h"
-
-namespace ns3
-{
-namespace energy
-{
-
-/**
- * @ingroup energy
- * @brief Model a generic Lithium Ion Battery basing on [1][2].
- *
- * The model can be fitted to any type of Li-Ion Battery, simply changing the
- * model parameters.
- * The default values are fitted for the Panasonic CGR18650DA Li-Ion Battery [3].
- *
- * The energy is drained as defined from the EnergySource interface but, this class
- * consider the non-linear behaviour of Li-Ion cell. Each time energy is drained from
- * the cell, the class evaluates the discharge curve to get the actual cell's voltage,
- * accordingly to State of Charge (SOC) and current's drain.
- *
- * If the actual voltage of the cell goes below the minimum threshold voltage, the
- * cell is considered depleted and the energy drained event fired up.
- *
- *
- * The model requires several parameters to approximates the discharge curves:
- * - InitialCellVoltage, maximum voltage of the fully charged cell
- * - NominalCellVoltage, nominal cell's voltage, is used to determine the end of the
- *   nominal zone.
- * - ExpCellVoltage, cell's voltage at the end of the exponential zone
- * - RatedCapacity, rated capacity of the cell, in Ah
- * - NomCapacity, cell's capacity at the end of the nominal zone, in Ah
- * - ExpCapacity, cell's capacity at the end of the exponential zone, in Ah
- * - InternalResistance, internal resistance of the cell, in Ohms
- * - TypCurrent, typical discharge current value, used during the fitting process, in Ah
- * - ThresholdVoltage, minimum threshold voltage below which the cell is considered
- *   depleted
- *
- * For a complete reference of the energy source model and model's fitting please refer
- * to <a href="http://www.nsnam.org/wiki/GSOC2010UANFramework">UAN Framework</a>
- * page and <a href="http://www.nsnam.org/wiki/Li-Ion_model_fitting">Li-Ion model
- * fitting</a> page.
- *
- * References:
- * [1] C. M. Shepherd, "Design of Primary and Secondary Cells - Part 3. Battery discharge equation,"
- * U.S. Naval Research Laboratory, 1963 [2] Tremblay, O.; Dessaint, L.-A.; Dekkiche, A.-I., "A
- * Generic Battery Model for the Dynamic Simulation of Hybrid Electric Vehicles," Ecole de
- * Technologie Superieure, Universite du Quebec, 2007 [3]
- * http://www.panasonic.com/industrial/includes/pdf/Panasonic_LiIon_CGR18650DA.pdf
-
- */
-// clang-format off
-class
-NS_DEPRECATED_3_40("The LiIonEnergySource was deprecated in ns-3.40 "
-                   "in favor of GenericBatteryModel, and will be removed "
-                   "in a future release.")
-LiIonEnergySource : public EnergySource
-// clang-format on
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return The object TypeId.
-     */
-    static TypeId GetTypeId();
-    LiIonEnergySource();
-    ~LiIonEnergySource() override;
-
-    /**
-     * @return Initial energy stored in energy source, in Joules.
-     *
-     * Implements GetInitialEnergy.
-     */
-    double GetInitialEnergy() const override;
-
-    /**
-     * @param initialEnergyJ Initial energy, in Joules
-     *
-     * Implements SetInitialEnergy. Note that initial energy is assumed to be set
-     * before simulation starts and is set only once per simulation.
-     */
-    void SetInitialEnergy(double initialEnergyJ);
-
-    /**
-     * @returns Supply voltage at the energy source.
-     *
-     * Implements GetSupplyVoltage.
-     */
-    double GetSupplyVoltage() const override;
-
-    /**
-     * @param supplyVoltageV Initial Supply voltage at the energy source, in Volts.
-     *
-     * Sets the initial supply voltage of the energy source.
-     * To be called only once.
-     */
-    void SetInitialSupplyVoltage(double supplyVoltageV);
-
-    /**
-     * @return Remaining energy in energy source, in Joules
-     *
-     * Implements GetRemainingEnergy.
-     */
-    double GetRemainingEnergy() override;
-
-    /**
-     * @returns Energy fraction.
-     *
-     * Implements GetEnergyFraction.
-     */
-    double GetEnergyFraction() override;
-
-    /**
-     * @param energyJ Amount of energy (in Joules) to decrease from energy source.
-     *
-     * Implements DecreaseRemainingEnergy.
-     */
-    NS_DEPRECATED_3_40("Use GenericBatteryModel instead")
-    virtual void DecreaseRemainingEnergy(double energyJ);
-
-    /**
-     * @param energyJ Amount of energy (in Joules) to increase from energy source.
-     *
-     * Implements IncreaseRemainingEnergy.
-     */
-    NS_DEPRECATED_3_40("Use GenericBatteryModel instead")
-    virtual void IncreaseRemainingEnergy(double energyJ);
-
-    /**
-     * Implements UpdateEnergySource.
-     */
-    void UpdateEnergySource() override;
-
-    /**
-     * @param interval Energy update interval.
-     *
-     * This function sets the interval between each energy update.
-     */
-    void SetEnergyUpdateInterval(Time interval);
-
-    /**
-     * @returns The interval between each energy update.
-     */
-    Time GetEnergyUpdateInterval() const;
-
-  private:
-    void DoInitialize() override;
-    void DoDispose() override;
-
-    /**
-     * Handles the remaining energy going to zero event. This function notifies
-     * all the energy models aggregated to the node about the energy being
-     * depleted. Each energy model is then responsible for its own handler.
-     */
-    void HandleEnergyDrainedEvent();
-
-    /**
-     * Calculates remaining energy. This function uses the total current from all
-     * device models to calculate the amount of energy to decrease. The energy to
-     * decrease is given by:
-     *    energy to decrease = total current * supply voltage * time duration
-     * This function subtracts the calculated energy to decrease from remaining
-     * energy.
-     */
-    void CalculateRemainingEnergy();
-
-    /**
-     * Get the cell voltage in function of the discharge current.
-     * It consider different discharge curves for different discharge currents
-     * and the remaining energy of the cell.
-     *
-     * @param current the actual discharge current value.
-     * @return the cell voltage
-     */
-    double GetVoltage(double current) const;
-
-  private:
-    double m_initialEnergyJ;                //!< initial energy, in Joules
-    TracedValue<double> m_remainingEnergyJ; //!< remaining energy, in Joules
-    double m_drainedCapacity;               //!< capacity drained from the cell, in Ah
-    double m_supplyVoltageV;                //!< actual voltage of the cell
-    double m_lowBatteryTh;       //!< low battery threshold, as a fraction of the initial energy
-    EventId m_energyUpdateEvent; //!< energy update event
-    Time m_lastUpdateTime;       //!< last update time
-    Time m_energyUpdateInterval; //!< energy update interval
-    double m_eFull;              //!< initial voltage of the cell, in Volts
-    double m_eNom;               //!< nominal voltage of the cell, in Volts
-    double m_eExp;               //!< cell voltage at the end of the exponential zone, in Volts
-    double m_internalResistance; //!< internal resistance of the cell, in Ohms
-    double m_qRated;             //!< rated capacity of the cell, in Ah
-    double m_qNom;               //!< cell capacity at the end of the nominal zone, in Ah
-    double m_qExp;               //!< capacity value at the end of the exponential zone, in Ah
-    double m_typCurrent;         //!< typical discharge current used to fit the curves
-    double m_minVoltTh;          //!< minimum threshold voltage to consider the battery depleted
-};
-
-} // namespace energy
-} // namespace ns3
-
-#endif /* LI_ION_ENERGY_SOURCE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/test/basic-energy-harvester-test.cc ns-3.46/src/energy/test/basic-energy-harvester-test.cc
--- ns-3.45/src/energy/test/basic-energy-harvester-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/test/basic-energy-harvester-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -77,8 +77,6 @@
     harvester->SetNode(node);
     harvester->SetEnergySource(source);
 
-    Time now = Simulator::Now();
-
     /*
      * The energy harvester will recharge the energy source for m_timeS seconds.
      */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/test/examples-to-run.py ns-3.46/src/energy/test/examples-to-run.py
--- ns-3.45/src/energy/test/examples-to-run.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/test/examples-to-run.py	2025-10-01 18:46:32.000000000 -0700
@@ -7,7 +7,6 @@
 #
 # See test.py for more information.
 cpp_examples = [
-    ("li-ion-energy-source", "True", "True"),
     ("rv-battery-model-test", "True", "True"),
     ("basic-energy-model-test", "True", "True"),
 ]
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/test/generic-battery-test.cc ns-3.46/src/energy/test/generic-battery-test.cc
--- ns-3.45/src/energy/test/generic-battery-test.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/energy/test/generic-battery-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ * Based on the works of Andrea Sacco (2010)
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/energy-module.h"
+
+using namespace ns3;
+using namespace ns3::energy;
+
+/**
+ * @ingroup energy-tests
+ *
+ * @brief Discharge a battery test
+ */
+class DischargeBatteryTestCase : public TestCase
+{
+  public:
+    DischargeBatteryTestCase();
+
+    void DoRun() override;
+
+    Ptr<Node> m_node; //!< Node to aggregate the source to.
+};
+
+DischargeBatteryTestCase::DischargeBatteryTestCase()
+    : TestCase("Discharge a Li-Ion Panasonic CGR18650DA battery")
+{
+}
+
+void
+DischargeBatteryTestCase::DoRun()
+{
+    // This test demonstrates that the battery reach its cutoff voltage in a little less than 1
+    // hour. When discharged with a constant current of 2.33 A (Equivalent to 1C).
+    // Note: The cutoff voltage is only reached within this time for the specified battery
+    // (PANASONIC CGR18650DA Li-Ion).
+
+    Ptr<Node> node = CreateObject<Node>();
+    GenericBatteryModelHelper batteryHelper;
+    Ptr<GenericBatteryModel> batteryModel =
+        DynamicCast<GenericBatteryModel>(batteryHelper.Install(node, PANASONIC_CGR18650DA_LION));
+
+    Ptr<SimpleDeviceEnergyModel> consumptionEnergyModel = CreateObject<SimpleDeviceEnergyModel>();
+    consumptionEnergyModel->SetEnergySource(batteryModel);
+    batteryModel->AppendDeviceEnergyModel(consumptionEnergyModel);
+    consumptionEnergyModel->SetNode(node);
+
+    // Needed to initialize battery model
+    batteryModel->UpdateEnergySource();
+
+    // Discharge the battery with a constant current of 2.33 A (1C)
+    consumptionEnergyModel->SetCurrentA(2.33);
+
+    Simulator::Stop(Seconds(3459));
+    Simulator::Run();
+
+    NS_TEST_ASSERT_MSG_EQ_TOL(batteryModel->GetSupplyVoltage(),
+                              3.0,
+                              1.0e-2,
+                              "Cutoff voltage not reached");
+    node->Dispose();
+    consumptionEnergyModel->Dispose();
+    batteryModel->Dispose();
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup energy-tests
+ *
+ * @brief Generic battery TestSuite
+ */
+class GenericBatteryTestSuite : public TestSuite
+{
+  public:
+    GenericBatteryTestSuite();
+};
+
+GenericBatteryTestSuite::GenericBatteryTestSuite()
+    : TestSuite("generic-battery-test", Type::UNIT)
+{
+    AddTestCase(new DischargeBatteryTestCase, TestCase::Duration::QUICK);
+}
+
+/// create an instance of the test suite
+static GenericBatteryTestSuite g_genericBatteryTestSuite;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/energy/test/li-ion-energy-source-test.cc ns-3.46/src/energy/test/li-ion-energy-source-test.cc
--- ns-3.45/src/energy/test/li-ion-energy-source-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/energy/test/li-ion-energy-source-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2010 Andrea Sacco
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Andrea Sacco <andrea.sacco85@gmail.com>
- */
-
-#include "ns3/li-ion-energy-source.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/simple-device-energy-model.h"
-#include "ns3/simulator.h"
-#include "ns3/test.h"
-
-using namespace ns3;
-using namespace ns3::energy;
-
-// NS_DEPRECATED_3_43() - tag for future removal
-// LiIonEnergySource was deprecated in commit
-// https://gitlab.com/nsnam/ns-3-dev/-/commit/086913b0
-//
-// The new battery model is illustrated in
-// `src/energy/examples/generic-battery-discharge-example.cc`
-//
-// A GenericBatteryModelTestCase is being developed in MR 2181
-// https://gitlab.com/nsnam/ns-3-dev/-/merge_requests/2181
-// which will be in
-// `src/energy/test/generic-battery-model-test.cc`
-
-NS_LOG_COMPONENT_DEFINE("LiIonEnergySourceTestSuite");
-
-/**
- * @ingroup energy-tests
- *
- * @brief LiIon battery Test
- */
-class LiIonEnergyTestCase : public TestCase
-{
-  public:
-    LiIonEnergyTestCase();
-    ~LiIonEnergyTestCase() override;
-
-    void DoRun() override;
-
-    Ptr<Node> m_node; //!< Node to aggreagte the source to.
-};
-
-LiIonEnergyTestCase::LiIonEnergyTestCase()
-    : TestCase("Li-Ion energy source test case")
-{
-}
-
-LiIonEnergyTestCase::~LiIonEnergyTestCase()
-{
-    m_node = nullptr;
-}
-
-void
-LiIonEnergyTestCase::DoRun()
-{
-    m_node = CreateObject<Node>();
-
-    Ptr<SimpleDeviceEnergyModel> sem = CreateObject<SimpleDeviceEnergyModel>();
-
-    NS_WARNING_PUSH_DEPRECATED;
-    Ptr<LiIonEnergySource> es = CreateObject<LiIonEnergySource>();
-    NS_WARNING_POP;
-
-    es->SetNode(m_node);
-    sem->SetEnergySource(es);
-    es->AppendDeviceEnergyModel(sem);
-    m_node->AggregateObject(es);
-
-    Time now = Simulator::Now();
-
-    // discharge at 2.33 A for 1700 seconds
-    sem->SetCurrentA(2.33);
-    now += Seconds(1701);
-
-    Simulator::Stop(now);
-    Simulator::Run();
-    Simulator::Destroy();
-
-    NS_TEST_ASSERT_MSG_EQ_TOL(es->GetSupplyVoltage(), 3.6, 1.0e-3, "Incorrect consumed energy!");
-}
-
-/**
- * @ingroup energy-tests
- *
- * @brief LiIon battery TestSuite
- */
-class LiIonEnergySourceTestSuite : public TestSuite
-{
-  public:
-    LiIonEnergySourceTestSuite();
-};
-
-LiIonEnergySourceTestSuite::LiIonEnergySourceTestSuite()
-    : TestSuite("li-ion-energy-source", Type::UNIT)
-{
-    AddTestCase(new LiIonEnergyTestCase, TestCase::Duration::QUICK);
-}
-
-/// create an instance of the test suite
-static LiIonEnergySourceTestSuite g_liIonEnergySourceTestSuite;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/CMakeLists.txt ns-3.46/src/fd-net-device/CMakeLists.txt
--- ns-3.45/src/fd-net-device/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -1,26 +1,26 @@
 set(module_enabled_features) # modulegen_customizations consumes this list
 
-check_include_file(
+check_include_file_cxx(
   net/ethernet.h
   HAVE_NET_ETHERNET_H
 )
-check_include_file(
+check_include_file_cxx(
   netpacket/packet.h
   HAVE_PACKET_H
 )
-check_include_file(
+check_include_file_cxx(
   net/if.h
   HAVE_IF_NETS_H
 )
-check_include_file(
+check_include_file_cxx(
   linux/if_tun.h
   HAVE_IF_TUN_H
 )
-check_include_file(
+check_include_file_cxx(
   net/netmap_user.h
   HAVE_NETMAP_USER_H
 )
-check_include_file(
+check_include_file_cxx(
   sys/ioctl.h
   HAVE_SYS_IOCTL_H
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/helper/creator-utils.cc ns-3.46/src/fd-net-device/helper/creator-utils.cc
--- ns-3.45/src/fd-net-device/helper/creator-utils.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/helper/creator-utils.cc	2025-10-01 18:46:32.000000000 -0700
@@ -9,6 +9,7 @@
 #include "encode-decode.h"
 
 #include <arpa/inet.h>
+#include <cstdlib>
 #include <cstring>
 #include <errno.h>
 #include <iomanip>
@@ -17,7 +18,6 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <sstream>
-#include <stdlib.h>
 #include <string>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/helper/emu-fd-net-device-helper.cc ns-3.46/src/fd-net-device/helper/emu-fd-net-device-helper.cc
--- ns-3.45/src/fd-net-device/helper/emu-fd-net-device-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/helper/emu-fd-net-device-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -19,6 +19,7 @@
 #include "ns3/trace-helper.h"
 
 #include <arpa/inet.h>
+#include <cstdlib>
 #include <errno.h>
 #include <iomanip>
 #include <iostream>
@@ -28,7 +29,6 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netpacket/packet.h>
-#include <stdlib.h>
 #include <string.h>
 #include <string>
 #include <sys/ioctl.h>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/helper/encode-decode.cc ns-3.46/src/fd-net-device/helper/encode-decode.cc
--- ns-3.45/src/fd-net-device/helper/encode-decode.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/helper/encode-decode.cc	2025-10-01 18:46:32.000000000 -0700
@@ -4,10 +4,10 @@
  * SPDX-License-Identifier: GPL-2.0-only
  */
 
+#include <cstdint>
 #include <iomanip>
 #include <iostream>
 #include <sstream>
-#include <stdint.h>
 #include <string>
 
 namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/helper/raw-sock-creator.cc ns-3.46/src/fd-net-device/helper/raw-sock-creator.cc
--- ns-3.45/src/fd-net-device/helper/raw-sock-creator.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/helper/raw-sock-creator.cc	2025-10-01 18:46:32.000000000 -0700
@@ -7,6 +7,7 @@
 #include "creator-utils.h"
 
 #include <arpa/inet.h>
+#include <cstdlib>
 #include <errno.h>
 #include <iomanip>
 #include <iostream>
@@ -15,7 +16,6 @@
 #include <netinet/in.h>
 #include <netpacket/packet.h>
 #include <sstream>
-#include <stdlib.h>
 #include <string>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/helper/tap-device-creator.cc ns-3.46/src/fd-net-device/helper/tap-device-creator.cc
--- ns-3.45/src/fd-net-device/helper/tap-device-creator.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/helper/tap-device-creator.cc	2025-10-01 18:46:32.000000000 -0700
@@ -9,6 +9,8 @@
 #include "ns3/mac48-address.h"
 
 #include <arpa/inet.h>
+#include <cstdint>
+#include <cstdlib>
 #include <cstring>
 #include <errno.h>
 #include <fcntl.h>
@@ -19,8 +21,6 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #include <sstream>
-#include <stdint.h>
-#include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/fd-net-device/helper/tap-fd-net-device-helper.cc ns-3.46/src/fd-net-device/helper/tap-fd-net-device-helper.cc
--- ns-3.45/src/fd-net-device/helper/tap-fd-net-device-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/fd-net-device/helper/tap-fd-net-device-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -19,6 +19,7 @@
 #include "ns3/trace-helper.h"
 
 #include <arpa/inet.h>
+#include <cstdlib>
 #include <errno.h>
 #include <iomanip>
 #include <iostream>
@@ -28,7 +29,6 @@
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netpacket/packet.h>
-#include <stdlib.h>
 #include <string.h>
 #include <string>
 #include <sys/ioctl.h>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/flow-monitor/helper/flow-monitor-helper.cc ns-3.46/src/flow-monitor/helper/flow-monitor-helper.cc
--- ns-3.45/src/flow-monitor/helper/flow-monitor-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/flow-monitor/helper/flow-monitor-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -85,15 +85,16 @@
     Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol>();
     if (ipv4)
     {
-        Ptr<Ipv4FlowProbe> probe =
-            Create<Ipv4FlowProbe>(monitor, DynamicCast<Ipv4FlowClassifier>(classifier), node);
+        auto probe =
+            CreateObject<Ipv4FlowProbe>(monitor, DynamicCast<Ipv4FlowClassifier>(classifier), node);
     }
     Ptr<FlowClassifier> classifier6 = GetClassifier6();
     Ptr<Ipv6L3Protocol> ipv6 = node->GetObject<Ipv6L3Protocol>();
     if (ipv6)
     {
-        Ptr<Ipv6FlowProbe> probe6 =
-            Create<Ipv6FlowProbe>(monitor, DynamicCast<Ipv6FlowClassifier>(classifier6), node);
+        auto probe6 = CreateObject<Ipv6FlowProbe>(monitor,
+                                                  DynamicCast<Ipv6FlowClassifier>(classifier6),
+                                                  node);
     }
     return m_flowMonitor;
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/doc/ipv4.rst ns-3.46/src/internet/doc/ipv4.rst
--- ns-3.45/src/internet/doc/ipv4.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/doc/ipv4.rst	2025-10-01 18:46:32.000000000 -0700
@@ -286,3 +286,8 @@
 
   NeighborCacheHelper neighborCache;
   neighborCache.PopulateNeighborCache(interfaces);    // interfaces is the Ipv4InterfaceContainer want to generate ARP caches
+
+Neighbor cache entries are not removed by calls to ``ArpCache::Flush()``,
+which may be called during the process of bringing IPv4 interfaces up
+or down.  Instead, to remove them, users must call
+``ArpCache::RemoveAutoGenerated()``.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/doc/ipv6.rst ns-3.46/src/internet/doc/ipv6.rst
--- ns-3.45/src/internet/doc/ipv6.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/doc/ipv6.rst	2025-10-01 18:46:32.000000000 -0700
@@ -523,3 +523,8 @@
 
   NeighborCacheHelper neighborCache;
   neighborCache.PopulateNeighborCache(interfaces);    // interfaces is the Ipv6InterfaceContainer want to generate ARP caches
+
+Neighbor cache entries are not removed by calls to ``NdiscCache::Flush()``,
+which may be called during the process of bringing IPv6 interfaces up
+or down.  Instead, to remove them, users must call
+``NdiscCache::RemoveAutoGenerated()``.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/doc/routing-overview.rst ns-3.46/src/internet/doc/routing-overview.rst
--- ns-3.45/src/internet/doc/routing-overview.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/doc/routing-overview.rst	2025-10-01 18:46:32.000000000 -0700
@@ -285,6 +285,33 @@
 fed into the OSPF shortest path computation logic. The Ipv4 API
 is finally used to populate the routes themselves.
 
+Limitations
+~~~~~~~~~~~
+
+The following are the known limitations of the GlobalRouting implementation:
+
+#. When calculating routes for networks using GlobalRouting,
+   if multiple exit Interfaces are present from the root node to a network,
+   then Packets may travel an extra hop to reach their destination in that network.
+   Clarifying this further, the following is the generalized conditions:
+
+    #. Assume that there is a network (e.g., 10.1.2.0/24) and the network has 2 (or more) routers (2 egress points, or more).
+    #. Assume that a node has 2 (or more) equal-cost paths toward said network.
+    #. Assume that multiple IP addresses with that network prefix are present on one or more interfaces.
+
+   This will mean that, to reach the internal interfaces of the "other" router(s), the packets will
+   do one unnecessary hop, passing through the designated router, and discarding the (shorter) path
+   leading directly to the destination.
+
+   .. _Global-Routing-Limitation:
+
+   .. figure:: figures/global-routing-limitation.*
+
+#. Although adding Multiple IP addresses on the same interface
+   and Equal Cost Multi Path are both supported individually,
+   the combination of both is not fully supported and may lead to unexpected results
+   and in some specific cases routing loops.
+   This limitation is tracked in issue #1242 of the issue tracker.
 
 RIP and RIPng
 +++++++++++++
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/helper/internet-trace-helper.cc ns-3.46/src/internet/helper/internet-trace-helper.cc
--- ns-3.45/src/internet/helper/internet-trace-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/helper/internet-trace-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,8 +15,8 @@
 #include "ns3/pcap-file-wrapper.h"
 #include "ns3/ptr.h"
 
+#include <cstdint>
 #include <fstream>
-#include <stdint.h>
 #include <string>
 
 namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/arp-cache.cc ns-3.46/src/internet/model/arp-cache.cc
--- ns-3.45/src/internet/model/arp-cache.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/arp-cache.cc	2025-10-01 18:46:32.000000000 -0700
@@ -88,7 +88,11 @@
 ArpCache::DoDispose()
 {
     NS_LOG_FUNCTION(this);
-    Flush();
+    for (auto& iter : m_arpCache)
+    {
+        delete iter.second; /* delete the pointer ArpCache::Entry */
+    }
+    m_arpCache.clear();
     m_device = nullptr;
     m_interface = nullptr;
     if (!m_waitReplyTimer.IsPending())
@@ -234,11 +238,19 @@
 ArpCache::Flush()
 {
     NS_LOG_FUNCTION(this);
-    for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
+    for (auto i = m_arpCache.begin(); i != m_arpCache.end();)
     {
-        delete (*i).second;
+        if (!i->second->IsAutoGenerated())
+        {
+            i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
+            delete i->second;
+            i = m_arpCache.erase(i);
+        }
+        else
+        {
+            i++;
+        }
     }
-    m_arpCache.erase(m_arpCache.begin(), m_arpCache.end());
     if (m_waitReplyTimer.IsPending())
     {
         NS_LOG_LOGIC("Stopping WaitReplyTimer at " << Simulator::Now().GetSeconds()
@@ -301,10 +313,12 @@
         {
             i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
             delete i->second;
-            m_arpCache.erase(i++);
-            continue;
+            i = m_arpCache.erase(i);
+        }
+        else
+        {
+            i++;
         }
-        i++;
     }
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/arp-cache.h ns-3.46/src/internet/model/arp-cache.h
--- ns-3.45/src/internet/model/arp-cache.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/arp-cache.h	2025-10-01 18:46:32.000000000 -0700
@@ -145,7 +145,12 @@
      */
     void Remove(ArpCache::Entry* entry);
     /**
-     * @brief Clear the ArpCache of all entries
+     * @brief Clear the ArpCache of all entries except auto-generated entries
+     *
+     * If you wish to remove all entries, including auto-generated entries,
+     * call this method and then also call RemoveAutoGeneratedEntries().
+     *
+     * @see RemoveAutoGenerated
      */
     void Flush();
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/global-route-manager.cc ns-3.46/src/internet/model/global-route-manager.cc
--- ns-3.45/src/internet/model/global-route-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/global-route-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -25,6 +25,8 @@
 //
 // ---------------------------------------------------------------------------
 
+uint32_t GlobalRouteManager::routerId = 0;
+
 void
 GlobalRouteManager::DeleteGlobalRoutes()
 {
@@ -50,8 +52,13 @@
 GlobalRouteManager::AllocateRouterId()
 {
     NS_LOG_FUNCTION_NOARGS();
-    static uint32_t routerId = 0;
     return routerId++;
 }
 
+void
+GlobalRouteManager::ResetRouterId()
+{
+    routerId = 0;
+}
+
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/global-route-manager.h ns-3.46/src/internet/model/global-route-manager.h
--- ns-3.45/src/internet/model/global-route-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/global-route-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -59,6 +59,16 @@
      * per-node forwarding tables
      */
     static void InitializeRoutes();
+
+    /**
+     * @brief Reset the router ID counter to zero. This should only be called by tests to reset the
+     * router ID counter between simulations within the same program. This function should not be
+     * called In typical simulations or when using the GlobalRouting helper.
+     */
+    static void ResetRouterId();
+
+  private:
+    static uint32_t routerId; //!< Router ID counter
 };
 
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/global-route-manager-impl.cc ns-3.46/src/internet/model/global-route-manager-impl.cc
--- ns-3.45/src/internet/model/global-route-manager-impl.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/global-route-manager-impl.cc	2025-10-01 18:46:32.000000000 -0700
@@ -104,6 +104,7 @@
     {
         NS_LOG_LOGIC("Setting m_vertexType to VertexRouter");
         m_vertexType = SPFVertex::VertexRouter;
+        m_node = lsa->GetNode();
     }
     else if (lsa->GetLSType() == GlobalRoutingLSA::NetworkLSA)
     {
@@ -405,6 +406,12 @@
     this->SetVertexProcessed(false);
 }
 
+Ptr<Node>
+SPFVertex::GetNode() const
+{
+    return m_node;
+}
+
 // ---------------------------------------------------------------------------
 //
 // GlobalRouteManagerLSDB Implementation
@@ -1098,7 +1105,7 @@
         }
         else
         {
-            w->SetRootExitDirection(v->GetRootExitDirection());
+            w->InheritAllRootExitDirections(v);
         }
     }
     else
@@ -1529,37 +1536,30 @@
 
     NS_LOG_LOGIC("Vertex ID = " << routerId);
     //
-    // We need to walk the list of nodes looking for the one that has the router
-    // ID corresponding to the root vertex.  This is the one we're going to write
-    // the routing information to.
+    // The node we need to add routes to is the node corresponding to the root vertex.
+    // This is the node for which we are building the routing table.
     //
-    for (auto i = NodeList::Begin(); i != NodeList::End(); i++)
-    {
-        Ptr<Node> node = *i;
-        //
-        // The router ID is accessible through the GlobalRouter interface, so we need
-        // to QI for that interface.  If there's no GlobalRouter interface, the node
-        // in question cannot be the router we want, so we continue.
-        //
-        Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
-
-        if (!rtr)
-        {
-            NS_LOG_LOGIC("No GlobalRouter interface on node " << node->GetId());
-            continue;
-        }
-        //
-        // If the router ID of the current node is equal to the router ID of the
-        // root of the SPF tree, then this node is the one for which we need to
-        // write the routing tables.
-        //
-        NS_LOG_LOGIC("Considering router " << rtr->GetRouterId());
-
-        if (rtr->GetRouterId() != routerId)
-        {
-            continue;
-        }
+    Ptr<Node> node = m_spfroot->GetNode();
 
+    if (!node)
+    {
+        NS_FATAL_ERROR("SPFAddASExternal():Can't find root node " << routerId);
+        return;
+    }
+    //
+    // The router ID is accessible through the GlobalRouter interface, so we need
+    // to QI for that interface.  If there's no GlobalRouter interface, the node
+    // in question cannot be the router we want, so we continue.
+    //
+    Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
+    NS_ASSERT_MSG(router, "No GlobalRouter interface on SPF root node " << node->GetId());
+    //
+    // If the router ID of the current node is equal to the router ID of the
+    // root of the SPF tree, then this node is the one for which we need to
+    // write the routing tables.
+    //
+    if (router->GetRouterId() == routerId)
+    {
         NS_LOG_LOGIC("Setting routes for node " << node->GetId());
         //
         // Routing information is updated using the Ipv4 interface.  We need to QI
@@ -1597,10 +1597,9 @@
         // which the packets should be send for forwarding.
         //
         Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
-        if (!router)
-        {
-            continue;
-        }
+
+        NS_ASSERT_MSG(router, "No GlobalRouter interface on node " << node->GetId());
+
         Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
         NS_ASSERT(gr);
         // walk through all next-hop-IPs and out-going-interfaces for reaching
@@ -1628,6 +1627,8 @@
         }
         return;
     }
+    // This should never happen. The RouterId and vertexId should match
+    NS_FATAL_ERROR("SPFIntraAddRouter(): routerId and vertex ID do not match");
 }
 
 // Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
@@ -1695,103 +1696,95 @@
 
     NS_LOG_LOGIC("Vertex ID = " << routerId);
     //
-    // We need to walk the list of nodes looking for the one that has the router
-    // ID corresponding to the root vertex.  This is the one we're going to write
-    // the routing information to.
+    // The node we need to add routes to is the node corresponding to the root vertex.
+    // This is the node for which we are building the routing table.
     //
-    for (auto i = NodeList::Begin(); i != NodeList::End(); i++)
+    Ptr<Node> node = m_spfroot->GetNode();
+    if (!node)
     {
-        Ptr<Node> node = *i;
+        NS_LOG_ERROR("SPFIntraAddStub():Can't find root node " << routerId);
+        return;
+    }
+    //
+    // The router ID is accessible through the GlobalRouter interface, so we need
+    // to QI for that interface.  If there's no GlobalRouter interface, the node
+    // in question cannot be the router we want, so we continue.
+    //
+    Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
+    NS_ASSERT_MSG(router, "No GlobalRouter interface on node " << node->GetId());
+    //
+    // If the router ID of the current node is equal to the router ID of the
+    // root of the SPF tree, then this node is the one for which we need to
+    // write the routing tables.
+    //
+    if (routerId == router->GetRouterId())
+    {
+        NS_LOG_LOGIC("Setting routes for node " << node->GetId());
         //
-        // The router ID is accessible through the GlobalRouter interface, so we need
-        // to QI for that interface.  If there's no GlobalRouter interface, the node
-        // in question cannot be the router we want, so we continue.
+        // Routing information is updated using the Ipv4 interface.  We need to QI
+        // for that interface.  If the node is acting as an IP version 4 router, it
+        // should absolutely have an Ipv4 interface.
         //
-        Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
-
-        if (!rtr)
-        {
-            NS_LOG_LOGIC("No GlobalRouter interface on node " << node->GetId());
-            continue;
-        }
+        Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
+        NS_ASSERT_MSG(ipv4,
+                      "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
+                      "QI for <Ipv4> interface failed");
+        //
+        // Get the Global Router Link State Advertisement from the vertex we're
+        // adding the routes to.  The LSA will have a number of attached Global Router
+        // Link Records corresponding to links off of that vertex / node.  We're going
+        // to be interested in the records corresponding to point-to-point links.
+        //
+        NS_ASSERT_MSG(v->GetLSA(),
+                      "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
+                      "Expected valid LSA in SPFVertex* v");
+        Ipv4Mask tempmask(l->GetLinkData().Get());
+        Ipv4Address tempip = l->GetLinkId();
+        tempip = tempip.CombineMask(tempmask);
+        //
+        // Here's why we did all of that work.  We're going to add a host route to the
+        // host address found in the m_linkData field of the point-to-point link
+        // record.  In the case of a point-to-point link, this is the local IP address
+        // of the node connected to the link.  Each of these point-to-point links
+        // will correspond to a local interface that has an IP address to which
+        // the node at the root of the SPF tree can send packets.  The vertex <v>
+        // (corresponding to the node that has these links and interfaces) has
+        // an m_nextHop address precalculated for us that is the address to which the
+        // root node should send packets to be forwarded to these IP addresses.
+        // Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
+        // which the packets should be send for forwarding.
         //
-        // If the router ID of the current node is equal to the router ID of the
-        // root of the SPF tree, then this node is the one for which we need to
-        // write the routing tables.
-        //
-        NS_LOG_LOGIC("Considering router " << rtr->GetRouterId());
-
-        if (rtr->GetRouterId() == routerId)
-        {
-            NS_LOG_LOGIC("Setting routes for node " << node->GetId());
-            //
-            // Routing information is updated using the Ipv4 interface.  We need to QI
-            // for that interface.  If the node is acting as an IP version 4 router, it
-            // should absolutely have an Ipv4 interface.
-            //
-            Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
-            NS_ASSERT_MSG(ipv4,
-                          "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
-                          "QI for <Ipv4> interface failed");
-            //
-            // Get the Global Router Link State Advertisement from the vertex we're
-            // adding the routes to.  The LSA will have a number of attached Global Router
-            // Link Records corresponding to links off of that vertex / node.  We're going
-            // to be interested in the records corresponding to point-to-point links.
-            //
-            NS_ASSERT_MSG(v->GetLSA(),
-                          "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
-                          "Expected valid LSA in SPFVertex* v");
-            Ipv4Mask tempmask(l->GetLinkData().Get());
-            Ipv4Address tempip = l->GetLinkId();
-            tempip = tempip.CombineMask(tempmask);
-            //
-            // Here's why we did all of that work.  We're going to add a host route to the
-            // host address found in the m_linkData field of the point-to-point link
-            // record.  In the case of a point-to-point link, this is the local IP address
-            // of the node connected to the link.  Each of these point-to-point links
-            // will correspond to a local interface that has an IP address to which
-            // the node at the root of the SPF tree can send packets.  The vertex <v>
-            // (corresponding to the node that has these links and interfaces) has
-            // an m_nextHop address precalculated for us that is the address to which the
-            // root node should send packets to be forwarded to these IP addresses.
-            // Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
-            // which the packets should be send for forwarding.
-            //
 
-            Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
-            if (!router)
+        Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
+
+        Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
+        NS_ASSERT(gr);
+        // walk through all next-hop-IPs and out-going-interfaces for reaching
+        // the stub network gateway 'v' from the root node
+        for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
+        {
+            SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
+            Ipv4Address nextHop = exit.first;
+            int32_t outIf = exit.second;
+            if (outIf >= 0)
             {
-                continue;
+                gr->AddNetworkRouteTo(tempip, tempmask, nextHop, outIf);
+                NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
+                                       << " add network route to " << tempip << " using next hop "
+                                       << nextHop << " via interface " << outIf);
             }
-            Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
-            NS_ASSERT(gr);
-            // walk through all next-hop-IPs and out-going-interfaces for reaching
-            // the stub network gateway 'v' from the root node
-            for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
+            else
             {
-                SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
-                Ipv4Address nextHop = exit.first;
-                int32_t outIf = exit.second;
-                if (outIf >= 0)
-                {
-                    gr->AddNetworkRouteTo(tempip, tempmask, nextHop, outIf);
-                    NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
-                                           << " add network route to " << tempip
-                                           << " using next hop " << nextHop << " via interface "
-                                           << outIf);
-                }
-                else
-                {
-                    NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
-                                           << " NOT able to add network route to " << tempip
-                                           << " using next hop " << nextHop
-                                           << " since outgoing interface id is negative");
-                }
+                NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
+                                       << " NOT able to add network route to " << tempip
+                                       << " using next hop " << nextHop
+                                       << " since outgoing interface id is negative");
             }
-            return;
         }
+        return;
     }
+    // This should never happen. The RouterId and vertex Id should match
+    NS_LOG_ERROR("SPFIntraAddStub(): routerId and vertex ID do not match");
 }
 
 //
@@ -1815,42 +1808,44 @@
     //
     Ipv4Address routerId = m_spfroot->GetVertexId();
     //
-    // Walk the list of nodes in the system looking for the one corresponding to
-    // the node at the root of the SPF tree.  This is the node for which we are
-    // building the routing table.
+    // The node we need to add routes to is the node corresponding to the root vertex.
+    // This is the node for which we are building the routing table.
     //
-    for (auto i = NodeList::Begin(); i != NodeList::End(); i++)
+    Ptr<Node> node = m_spfroot->GetNode();
+    if (!node)
     {
-        Ptr<Node> node = *i;
-
-        Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
         //
-        // If the node doesn't have a GlobalRouter interface it can't be the one
-        // we're interested in.
+        // Couldn't find it.
         //
-        if (!rtr)
-        {
-            continue;
-        }
+        NS_LOG_LOGIC("FindOutgoingInterfaceId():Can't find root node " << routerId);
+        return -1;
+    }
 
-        if (rtr->GetRouterId() == routerId)
-        {
-            //
-            // This is the node we're building the routing table for.  We're going to need
-            // the Ipv4 interface to look for the ipv4 interface index.  Since this node
-            // is participating in routing IP version 4 packets, it certainly must have
-            // an Ipv4 interface.
-            //
-            Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
-            NS_ASSERT_MSG(ipv4,
-                          "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
-                          "GetObject for <Ipv4> interface failed");
-            //
-            // Look through the interfaces on this node for one that has the IP address
-            // we're looking for.  If we find one, return the corresponding interface
-            // index, or -1 if not found.
-            //
-            int32_t interface = ipv4->GetInterfaceForPrefix(a, amask);
+    Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
+    NS_ASSERT_MSG(rtr, "No GlobalRouter interface on node " << node->GetId());
+    //
+    // If the node doesn't have a GlobalRouter interface it can't be the one
+    // we're interested in.
+    //
+
+    if (rtr->GetRouterId() == routerId)
+    {
+        //
+        // This is the node we're building the routing table for.  We're going to need
+        // the Ipv4 interface to look for the ipv4 interface index.  Since this node
+        // is participating in routing IP version 4 packets, it certainly must have
+        // an Ipv4 interface.
+        //
+        Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
+        NS_ASSERT_MSG(ipv4,
+                      "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
+                      "GetObject for <Ipv4> interface failed");
+        //
+        // Look through the interfaces on this node for one that has the IP address
+        // we're looking for.  If we find one, return the corresponding interface
+        // index, or -1 if not found.
+        //
+        int32_t interface = ipv4->GetInterfaceForPrefix(a, amask);
 
 #if 0
           if (interface < 0)
@@ -1859,13 +1854,10 @@
                               "Expected an interface associated with address a:" << a);
             }
 #endif
-            return interface;
-        }
+        return interface;
     }
-    //
-    // Couldn't find it.
-    //
-    NS_LOG_LOGIC("FindOutgoingInterfaceId():Can't find root node " << routerId);
+    // This should never happen. The RouterId and vertex Id should match
+    NS_FATAL_ERROR("SPFIntraAddRouter(): routerId and vertex ID do not match");
     return -1;
 }
 
@@ -1902,37 +1894,31 @@
 
     NS_LOG_LOGIC("Vertex ID = " << routerId);
     //
-    // We need to walk the list of nodes looking for the one that has the router
-    // ID corresponding to the root vertex.  This is the one we're going to write
-    // the routing information to.
+    // The node we need to add routes to is the node corresponding to the root vertex.
+    // This is the node for which we are building the routing table.
     //
-    for (auto i = NodeList::Begin(); i != NodeList::End(); i++)
+    Ptr<Node> node = m_spfroot->GetNode();
+    if (!node)
     {
-        Ptr<Node> node = *i;
-        //
-        // The router ID is accessible through the GlobalRouter interface, so we need
-        // to GetObject for that interface.  If there's no GlobalRouter interface,
-        // the node in question cannot be the router we want, so we continue.
-        //
-        Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
-
-        if (!rtr)
-        {
-            NS_LOG_LOGIC("No GlobalRouter interface on node " << node->GetId());
-            continue;
-        }
-        //
-        // If the router ID of the current node is equal to the router ID of the
-        // root of the SPF tree, then this node is the one for which we need to
-        // write the routing tables.
-        //
-        NS_LOG_LOGIC("Considering router " << rtr->GetRouterId());
+        NS_LOG_ERROR("SPFIntraAddRouter():Can't find root node " << routerId);
+        return;
+    }
 
-        if (rtr->GetRouterId() != routerId)
-        {
-            continue;
-        }
+    //
+    // The router ID is accessible through the GlobalRouter interface, so we need
+    // to GetObject for that interface.  If there's no GlobalRouter interface,
+    // the node in question cannot be the router we want, so we continue.
+    //
+    Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
+    NS_ASSERT_MSG(rtr, "No GlobalRouter interface on node " << node->GetId());
+    //
+    // If the router ID of the current node is equal to the router ID of the
+    // root of the SPF tree, then this node is the one for which we need to
+    // write the routing tables.
+    //
 
+    if (rtr->GetRouterId() == routerId)
+    {
         NS_LOG_LOGIC("Setting routes for node " << node->GetId());
         //
         // Routing information is updated using the Ipv4 interface.  We need to
@@ -2026,6 +2012,8 @@
         //
         return;
     }
+    // This should never happen. The RouterId and vertex Id should match
+    NS_FATAL_ERROR("SPFIntraAddRouter(): routerId and vertex ID do not match");
 }
 
 void
@@ -2045,91 +2033,88 @@
 
     NS_LOG_LOGIC("Vertex ID = " << routerId);
     //
-    // We need to walk the list of nodes looking for the one that has the router
-    // ID corresponding to the root vertex.  This is the one we're going to write
-    // the routing information to.
+    // The node we need to add routes to is the node corresponding to the root vertex.
+    // This is the node for which we are building the routing table.
     //
-    for (auto i = NodeList::Begin(); i != NodeList::End(); i++)
+    Ptr<Node> node = m_spfroot->GetNode();
+    if (!node)
     {
-        Ptr<Node> node = *i;
+        NS_LOG_ERROR("SPFIntraAddTransit():Can't find root node " << routerId);
+        return;
+    }
+
+    //
+    // The router ID is accessible through the GlobalRouter interface, so we need
+    // to GetObject for that interface.  If there's no GlobalRouter interface,
+    // the node in question cannot be the router we want, so we continue.
+    //
+    Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
+    NS_ASSERT_MSG(rtr, "No GlobalRouter interface on node " << node->GetId());
+    //
+    // If the router ID of the current node is equal to the router ID of the
+    // root of the SPF tree, then this node is the one for which we need to
+    // write the routing tables.
+    //
+
+    if (rtr->GetRouterId() == routerId)
+    {
+        NS_LOG_LOGIC("setting routes for node " << node->GetId());
         //
-        // The router ID is accessible through the GlobalRouter interface, so we need
-        // to GetObject for that interface.  If there's no GlobalRouter interface,
-        // the node in question cannot be the router we want, so we continue.
+        // Routing information is updated using the Ipv4 interface.  We need to
+        // GetObject for that interface.  If the node is acting as an IP version 4
+        // router, it should absolutely have an Ipv4 interface.
         //
-        Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter>();
-
-        if (!rtr)
-        {
-            NS_LOG_LOGIC("No GlobalRouter interface on node " << node->GetId());
-            continue;
-        }
+        Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
+        NS_ASSERT_MSG(ipv4,
+                      "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+                      "GetObject for <Ipv4> interface failed");
         //
-        // If the router ID of the current node is equal to the router ID of the
-        // root of the SPF tree, then this node is the one for which we need to
-        // write the routing tables.
-        //
-        NS_LOG_LOGIC("Considering router " << rtr->GetRouterId());
-
-        if (rtr->GetRouterId() == routerId)
-        {
-            NS_LOG_LOGIC("setting routes for node " << node->GetId());
-            //
-            // Routing information is updated using the Ipv4 interface.  We need to
-            // GetObject for that interface.  If the node is acting as an IP version 4
-            // router, it should absolutely have an Ipv4 interface.
-            //
-            Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
-            NS_ASSERT_MSG(ipv4,
-                          "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
-                          "GetObject for <Ipv4> interface failed");
-            //
-            // Get the Global Router Link State Advertisement from the vertex we're
-            // adding the routes to.  The LSA will have a number of attached Global Router
-            // Link Records corresponding to links off of that vertex / node.  We're going
-            // to be interested in the records corresponding to point-to-point links.
-            //
-            GlobalRoutingLSA* lsa = v->GetLSA();
-            NS_ASSERT_MSG(lsa,
-                          "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
-                          "Expected valid LSA in SPFVertex* v");
-            Ipv4Mask tempmask = lsa->GetNetworkLSANetworkMask();
-            Ipv4Address tempip = lsa->GetLinkStateId();
-            tempip = tempip.CombineMask(tempmask);
-            Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
-            if (!router)
+        // Get the Global Router Link State Advertisement from the vertex we're
+        // adding the routes to.  The LSA will have a number of attached Global Router
+        // Link Records corresponding to links off of that vertex / node.  We're going
+        // to be interested in the records corresponding to point-to-point links.
+        //
+        GlobalRoutingLSA* lsa = v->GetLSA();
+        NS_ASSERT_MSG(lsa,
+                      "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+                      "Expected valid LSA in SPFVertex* v");
+        Ipv4Mask tempmask = lsa->GetNetworkLSANetworkMask();
+        Ipv4Address tempip = lsa->GetLinkStateId();
+        tempip = tempip.CombineMask(tempmask);
+        Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
+        Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
+        NS_ASSERT(gr);
+        // walk through all available exit directions due to ECMP,
+        // and add host route for each of the exit direction toward
+        // the vertex 'v'
+        for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
+        {
+            SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
+            Ipv4Address nextHop = exit.first;
+            int32_t outIf = exit.second;
+
+            if (outIf >= 0)
             {
-                continue;
+                gr->AddNetworkRouteTo(tempip, tempmask, nextHop, outIf);
+                NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
+                                       << " add network route to " << tempip << " using next hop "
+                                       << nextHop << " via interface " << outIf);
             }
-            Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
-            NS_ASSERT(gr);
-            // walk through all available exit directions due to ECMP,
-            // and add host route for each of the exit direction toward
-            // the vertex 'v'
-            for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
+            else
             {
-                SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
-                Ipv4Address nextHop = exit.first;
-                int32_t outIf = exit.second;
-
-                if (outIf >= 0)
-                {
-                    gr->AddNetworkRouteTo(tempip, tempmask, nextHop, outIf);
-                    NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
-                                           << " add network route to " << tempip
-                                           << " using next hop " << nextHop << " via interface "
-                                           << outIf);
-                }
-                else
-                {
-                    NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
-                                           << " NOT able to add network route to " << tempip
-                                           << " using next hop " << nextHop
-                                           << " since outgoing interface id is negative " << outIf);
-                }
+                NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
+                                       << " NOT able to add network route to " << tempip
+                                       << " using next hop " << nextHop
+                                       << " since outgoing interface id is negative " << outIf);
             }
         }
+        //
+        // done adding routes for the root node.
+        //
+        return;
     }
+    // This should never happen. The RouterId and vertex Id should match
+    NS_FATAL_ERROR("SPFIntraAddTransit(): routerId and vertex ID do not match");
 }
 
 // Derived from quagga ospf_vertex_add_parents ()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/global-route-manager-impl.h ns-3.46/src/internet/model/global-route-manager-impl.h
--- ns-3.45/src/internet/model/global-route-manager-impl.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/global-route-manager-impl.h	2025-10-01 18:46:32.000000000 -0700
@@ -522,6 +522,12 @@
      */
     void ClearVertexProcessed();
 
+    /**
+     * @brief Get the node pointer corresponding to this Vertex
+     * @returns the node pointer corresponding to this Vertex
+     */
+    Ptr<Node> GetNode() const;
+
   private:
     VertexType m_vertexType;                        //!< Vertex type
     Ipv4Address m_vertexId;                         //!< Vertex ID
@@ -536,6 +542,7 @@
     ListOfSPFVertex_t m_children;                    //!< Children list
     bool m_vertexProcessed; //!< Flag to note whether vertex has been processed in stage two of SPF
                             //!< computation
+    Ptr<Node> m_node;       //!< node pointer corresponding to the this Vertex
 
     /**
      * @brief Stream insertion operator.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv4.cc ns-3.46/src/internet/model/ipv4.cc
--- ns-3.45/src/internet/model/ipv4.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv4.cc	2025-10-01 18:46:32.000000000 -0700
@@ -35,14 +35,6 @@
                 BooleanValue(true),
                 MakeBooleanAccessor(&Ipv4::SetIpForward, &Ipv4::GetIpForward),
                 MakeBooleanChecker())
-            .AddAttribute("WeakEsModel",
-                          "RFC1122 term for whether host accepts datagram with a dest. address on "
-                          "another interface",
-                          BooleanValue(true),
-                          MakeBooleanAccessor(&Ipv4::SetWeakEsModel, &Ipv4::GetWeakEsModel),
-                          MakeBooleanChecker(),
-                          TypeId::SupportLevel::DEPRECATED,
-                          "DEPRECATED since ns-3.41. Use the StrongEndSystemModel attribute.")
             .AddAttribute(
                 "StrongEndSystemModel",
                 "Reject packets for an address not configured on the interface they're "
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv4-global-routing.cc ns-3.46/src/internet/model/ipv4-global-routing.cc
--- ns-3.45/src/internet/model/ipv4-global-routing.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv4-global-routing.cc	2025-10-01 18:46:32.000000000 -0700
@@ -71,6 +71,15 @@
     NS_LOG_FUNCTION(this << dest << nextHop << interface);
     auto route = new Ipv4RoutingTableEntry();
     *route = Ipv4RoutingTableEntry::CreateHostRouteTo(dest, nextHop, interface);
+    for (auto routePointer : m_hostRoutes)
+    {
+        if (*routePointer == *route)
+        {
+            NS_LOG_LOGIC("Route already exists");
+            delete route;
+            return;
+        }
+    }
     m_hostRoutes.push_back(route);
 }
 
@@ -80,6 +89,15 @@
     NS_LOG_FUNCTION(this << dest << interface);
     auto route = new Ipv4RoutingTableEntry();
     *route = Ipv4RoutingTableEntry::CreateHostRouteTo(dest, interface);
+    for (auto routePointer : m_hostRoutes)
+    {
+        if (*routePointer == *route)
+        {
+            NS_LOG_LOGIC("Route already exists");
+            delete route;
+            return;
+        }
+    }
     m_hostRoutes.push_back(route);
 }
 
@@ -92,6 +110,15 @@
     NS_LOG_FUNCTION(this << network << networkMask << nextHop << interface);
     auto route = new Ipv4RoutingTableEntry();
     *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, nextHop, interface);
+    for (auto routePointer : m_networkRoutes)
+    {
+        if (*routePointer == *route)
+        {
+            NS_LOG_LOGIC("Route already exists");
+            delete route;
+            return;
+        }
+    }
     m_networkRoutes.push_back(route);
 }
 
@@ -101,6 +128,15 @@
     NS_LOG_FUNCTION(this << network << networkMask << interface);
     auto route = new Ipv4RoutingTableEntry();
     *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, interface);
+    for (auto routePointer : m_networkRoutes)
+    {
+        if (*routePointer == *route)
+        {
+            NS_LOG_LOGIC("Route already exists");
+            delete route;
+            return;
+        }
+    }
     m_networkRoutes.push_back(route);
 }
 
@@ -113,6 +149,15 @@
     NS_LOG_FUNCTION(this << network << networkMask << nextHop << interface);
     auto route = new Ipv4RoutingTableEntry();
     *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, nextHop, interface);
+    for (auto routePointer : m_ASexternalRoutes)
+    {
+        if (*routePointer == *route)
+        {
+            NS_LOG_LOGIC("Route already exists");
+            delete route;
+            return;
+        }
+    }
     m_ASexternalRoutes.push_back(route);
 }
 
@@ -147,9 +192,13 @@
     if (allRoutes.empty()) // if no host route is found
     {
         NS_LOG_LOGIC("Number of m_networkRoutes" << m_networkRoutes.size());
+        // store the length of the longest mask.
+        uint16_t longest_mask = 0;
         for (auto j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j++)
         {
             Ipv4Mask mask = (*j)->GetDestNetworkMask();
+            uint16_t masklen = mask.GetPrefixLength();
+
             Ipv4Address entry = (*j)->GetDestNetwork();
             if (mask.IsMatch(dest, entry))
             {
@@ -161,8 +210,23 @@
                         continue;
                     }
                 }
-                allRoutes.push_back(*j);
                 NS_LOG_LOGIC(allRoutes.size() << "Found global network route" << *j);
+                if (masklen < longest_mask) // Not interested if got shorter mask
+                {
+                    NS_LOG_LOGIC("Previous match longer, skipping");
+                    continue;
+                }
+                else if (masklen == longest_mask)
+                {
+                    NS_LOG_LOGIC("Equal mask length, adding this to the list");
+                    allRoutes.push_back(*j);
+                }
+                else
+                {
+                    NS_LOG_LOGIC("Longer mask length found, clearing the list and adding");
+                    allRoutes.clear();
+                    allRoutes.push_back(*j);
+                }
             }
         }
     }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv4.h ns-3.46/src/internet/model/ipv4.h
--- ns-3.45/src/internet/model/ipv4.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv4.h	2025-10-01 18:46:32.000000000 -0700
@@ -445,24 +445,6 @@
     virtual bool GetIpForward() const = 0;
 
     /**
-     * @brief Get the Weak Es Model status
-     *
-     * RFC1122 term for whether host accepts datagram with a dest. address on another interface
-     * @returns true for Weak Es Model activated
-     */
-    NS_DEPRECATED_3_41("Use GetStrongEndSystemModel instead")
-    virtual bool GetWeakEsModel() const = 0;
-
-    /**
-     * @brief Set or unset the Weak Es Model
-     *
-     * RFC1122 term for whether host accepts datagram with a dest. address on another interface
-     * @param model true for Weak Es Model
-     */
-    NS_DEPRECATED_3_41("Use SetStrongEndSystemModel instead")
-    virtual void SetWeakEsModel(bool model) = 0;
-
-    /**
      * @brief Set or unset the Strong End System Model
      *
      * RFC1122 term for whether host rejects datagram with a dest. address on another interface
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv4-l3-protocol.cc ns-3.46/src/internet/model/ipv4-l3-protocol.cc
--- ns-3.45/src/internet/model/ipv4-l3-protocol.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv4-l3-protocol.cc	2025-10-01 18:46:32.000000000 -0700
@@ -631,13 +631,6 @@
         }
     }
 
-    for (auto i = m_sockets.begin(); i != m_sockets.end(); ++i)
-    {
-        NS_LOG_LOGIC("Forwarding to raw socket");
-        Ptr<Ipv4RawSocketImpl> socket = *i;
-        socket->ForwardUp(packet, ipHeader, ipv4Interface);
-    }
-
     if (m_enableDpd && ipHeader.GetDestination().IsMulticast() && UpdateDuplicate(packet, ipHeader))
     {
         NS_LOG_LOGIC("Dropping received packet -- duplicate.");
@@ -1095,6 +1088,14 @@
 
     m_localDeliverTrace(ipHeader, p, iif);
 
+    Ptr<Ipv4Interface> ipv4Interface = GetInterface(iif);
+
+    for (auto& socket : m_sockets)
+    {
+        NS_LOG_INFO("Delivering to raw socket " << socket);
+        socket->ForwardUp(p, ipHeader, ipv4Interface);
+    }
+
     Ptr<IpL4Protocol> protocol = GetProtocol(ipHeader.GetProtocol(), iif);
     if (protocol)
     {
@@ -1401,19 +1402,6 @@
 }
 
 void
-Ipv4L3Protocol::SetWeakEsModel(bool model)
-{
-    NS_LOG_FUNCTION(this << model);
-    m_strongEndSystemModel = !model;
-}
-
-bool
-Ipv4L3Protocol::GetWeakEsModel() const
-{
-    return !m_strongEndSystemModel;
-}
-
-void
 Ipv4L3Protocol::SetStrongEndSystemModel(bool model)
 {
     NS_LOG_FUNCTION(this << model);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv4-l3-protocol.h ns-3.46/src/internet/model/ipv4-l3-protocol.h
--- ns-3.45/src/internet/model/ipv4-l3-protocol.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv4-l3-protocol.h	2025-10-01 18:46:32.000000000 -0700
@@ -289,13 +289,6 @@
     void SetIpForward(bool forward) override;
     bool GetIpForward() const override;
 
-    /** @copydoc Ipv4::SetWeakEsModel */
-    NS_DEPRECATED_3_41("Use SetStrongEndSystemModel instead")
-    void SetWeakEsModel(bool model) override;
-    /** @copydoc Ipv4::GetWeakEsModel */
-    NS_DEPRECATED_3_41("Use GetStrongEndSystemModel instead")
-    bool GetWeakEsModel() const override;
-
     void SetStrongEndSystemModel(bool model) override;
     bool GetStrongEndSystemModel() const override;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv4-packet-info-tag.cc ns-3.46/src/internet/model/ipv4-packet-info-tag.cc
--- ns-3.45/src/internet/model/ipv4-packet-info-tag.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv4-packet-info-tag.cc	2025-10-01 18:46:32.000000000 -0700
@@ -11,7 +11,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/log.h"
 
-#include <stdint.h>
+#include <cstdint>
 
 namespace ns3
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv6-autoconfigured-prefix.cc ns-3.46/src/internet/model/ipv6-autoconfigured-prefix.cc
--- ns-3.45/src/internet/model/ipv6-autoconfigured-prefix.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv6-autoconfigured-prefix.cc	2025-10-01 18:46:32.000000000 -0700
@@ -18,8 +18,18 @@
 
 NS_LOG_COMPONENT_DEFINE("Ipv6AutoconfiguredPrefix");
 
+NS_OBJECT_ENSURE_REGISTERED(Ipv6AutoconfiguredPrefix);
+
 uint32_t Ipv6AutoconfiguredPrefix::m_prefixId = 0;
 
+TypeId
+Ipv6AutoconfiguredPrefix::GetTypeId()
+{
+    static TypeId tid =
+        TypeId("ns3::Ipv6AutoconfiguredPrefix").SetParent<Object>().SetGroupName("Internet");
+    return tid;
+}
+
 Ipv6AutoconfiguredPrefix::Ipv6AutoconfiguredPrefix(Ptr<Node> node,
                                                    uint32_t interface,
                                                    Ipv6Address prefix,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv6-autoconfigured-prefix.h ns-3.46/src/internet/model/ipv6-autoconfigured-prefix.h
--- ns-3.45/src/internet/model/ipv6-autoconfigured-prefix.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv6-autoconfigured-prefix.h	2025-10-01 18:46:32.000000000 -0700
@@ -30,6 +30,12 @@
 {
   public:
     /**
+     * @brief Get the type ID.
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId();
+
+    /**
      * @brief Constructor.
      * @param node node
      * @param interface interface index
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv6-l3-protocol.cc ns-3.46/src/internet/model/ipv6-l3-protocol.cc
--- ns-3.45/src/internet/model/ipv6-l3-protocol.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv6-l3-protocol.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1048,13 +1048,6 @@
         }
     }
 
-    /* forward up to IPv6 raw sockets */
-    for (auto it = m_sockets.begin(); it != m_sockets.end(); ++it)
-    {
-        Ptr<Ipv6RawSocketImpl> socket = *it;
-        socket->ForwardUp(packet, hdr, device);
-    }
-
     Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
     Ptr<Ipv6Extension> ipv6Extension = nullptr;
     uint8_t nextHeader = hdr.GetNextHeader();
@@ -1442,6 +1435,7 @@
     bool isDropped = false;
     bool stopProcessing = false;
     DropReason dropReason;
+    Ptr<NetDevice> device = GetNetDevice(iif);
 
     // check for a malformed hop-by-hop extension
     // this is a common case when forging IPv6 raw packets
@@ -1534,6 +1528,12 @@
 
                 m_localDeliverTrace(newIpHeader, p, iif);
 
+                for (auto& socket : m_sockets)
+                {
+                    NS_LOG_INFO("Delivering to raw socket " << socket);
+                    socket->ForwardUp(p, newIpHeader, device);
+                }
+
                 IpL4Protocol::RxStatus status =
                     protocol->Receive(p, newIpHeader, GetInterface(iif));
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ipv6-packet-info-tag.cc ns-3.46/src/internet/model/ipv6-packet-info-tag.cc
--- ns-3.45/src/internet/model/ipv6-packet-info-tag.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ipv6-packet-info-tag.cc	2025-10-01 18:46:32.000000000 -0700
@@ -10,7 +10,7 @@
 
 #include "ns3/ipv6-address.h"
 
-#include <stdint.h>
+#include <cstdint>
 
 namespace ns3
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ndisc-cache.cc ns-3.46/src/internet/model/ndisc-cache.cc
--- ns-3.45/src/internet/model/ndisc-cache.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ndisc-cache.cc	2025-10-01 18:46:32.000000000 -0700
@@ -53,7 +53,11 @@
 NdiscCache::DoDispose()
 {
     NS_LOG_FUNCTION(this);
-    Flush();
+    for (auto& iter : m_ndCache)
+    {
+        delete iter.second; /* delete the pointer NdiscCache::Entry */
+    }
+    m_ndCache.clear();
     m_device = nullptr;
     m_interface = nullptr;
     m_icmpv6 = nullptr;
@@ -153,12 +157,19 @@
 {
     NS_LOG_FUNCTION(this);
 
-    for (auto i = m_ndCache.begin(); i != m_ndCache.end(); i++)
+    for (auto i = m_ndCache.begin(); i != m_ndCache.end();)
     {
-        delete (*i).second; /* delete the pointer NdiscCache::Entry */
+        if (!i->second->IsAutoGenerated())
+        {
+            i->second->ClearWaitingPacket();
+            delete i->second;
+            i = m_ndCache.erase(i);
+        }
+        else
+        {
+            i++;
+        }
     }
-
-    m_ndCache.erase(m_ndCache.begin(), m_ndCache.end());
 }
 
 void
@@ -712,10 +723,12 @@
         {
             i->second->ClearWaitingPacket();
             delete i->second;
-            m_ndCache.erase(i++);
-            continue;
+            i = m_ndCache.erase(i);
+        }
+        else
+        {
+            i++;
         }
-        i++;
     }
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/ndisc-cache.h ns-3.46/src/internet/model/ndisc-cache.h
--- ns-3.45/src/internet/model/ndisc-cache.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/ndisc-cache.h	2025-10-01 18:46:32.000000000 -0700
@@ -104,7 +104,12 @@
     void Remove(NdiscCache::Entry* entry);
 
     /**
-     * @brief Flush the cache.
+     * @brief Clear the cache of all entries except auto-generated entries
+     *
+     * If you wish to remove all entries, including auto-generated entries,
+     * call this method and then also call RemoveAutoGeneratedEntries().
+     *
+     * @see RemoveAutoGenerated
      */
     void Flush();
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/rtt-estimator.cc ns-3.46/src/internet/model/rtt-estimator.cc
--- ns-3.45/src/internet/model/rtt-estimator.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/rtt-estimator.cc	2025-10-01 18:46:32.000000000 -0700
@@ -63,12 +63,13 @@
     : m_nSamples(0)
 {
     NS_LOG_FUNCTION(this);
+}
 
-    // We need attributes initialized here, not later, so use the
-    // ConstructSelf() technique documented in the manual
-    ObjectBase::ConstructSelf(AttributeConstructionList());
+void
+RttEstimator::NotifyConstructionCompleted()
+{
+    NS_LOG_FUNCTION(this);
     m_estimatedRtt = m_initialEstimatedRtt;
-    m_estimatedVariation = Time(0);
     NS_LOG_DEBUG("Initialize m_estimatedRtt to " << m_estimatedRtt.GetSeconds() << " sec.");
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/rtt-estimator.h ns-3.46/src/internet/model/rtt-estimator.h
--- ns-3.45/src/internet/model/rtt-estimator.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/rtt-estimator.h	2025-10-01 18:46:32.000000000 -0700
@@ -89,6 +89,8 @@
     Time m_initialEstimatedRtt; //!< Initial RTT estimation
 
   protected:
+    void NotifyConstructionCompleted() override;
+
     Time m_estimatedRtt;       //!< Current estimate
     Time m_estimatedVariation; //!< Current estimate variation
     uint32_t m_nSamples;       //!< Number of samples
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/tcp-header.cc ns-3.46/src/internet/model/tcp-header.cc
--- ns-3.45/src/internet/model/tcp-header.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/tcp-header.cc	2025-10-01 18:46:32.000000000 -0700
@@ -14,8 +14,8 @@
 #include "ns3/buffer.h"
 #include "ns3/log.h"
 
+#include <cstdint>
 #include <iostream>
-#include <stdint.h>
 
 namespace ns3
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/tcp-socket-base.cc ns-3.46/src/internet/model/tcp-socket-base.cc
--- ns-3.45/src/internet/model/tcp-socket-base.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/tcp-socket-base.cc	2025-10-01 18:46:32.000000000 -0700
@@ -52,7 +52,7 @@
 #include "ns3/uinteger.h"
 
 #include <algorithm>
-#include <math.h>
+#include <cmath>
 
 namespace
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/model/win32-internet.h ns-3.46/src/internet/model/win32-internet.h
--- ns-3.45/src/internet/model/win32-internet.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/model/win32-internet.h	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 #ifndef WIN32_INTERNET_H
 #define WIN32_INTERNET_H
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/global-route-manager-impl-test-suite.cc ns-3.46/src/internet/test/global-route-manager-impl-test-suite.cc
--- ns-3.45/src/internet/test/global-route-manager-impl-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/global-route-manager-impl-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -6,19 +6,53 @@
  *
  * Authors:  Tom Henderson (tomhend@u.washington.edu)
  *
+ * Modified By: Shashwat Patni (shashwatpatni25@gmail.com)
+ *
  * Kunihiro Ishigura, Toshiaki Takada (GNU Zebra) are attributed authors
  * of the quagga 0.99.7/src/ospfd/ospf_spf.c code which was ported here
  */
 
 #include "ns3/candidate-queue.h"
+#include "ns3/config.h"
 #include "ns3/global-route-manager-impl.h"
+#include "ns3/internet-module.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/ipv4-global-routing.h"
+#include "ns3/network-module.h"
+#include "ns3/node-container.h"
+#include "ns3/rng-seed-manager.h"
+#include "ns3/simple-net-device-helper.h"
 #include "ns3/simulator.h"
 #include "ns3/test.h"
 
 #include <cstdlib> // for rand()
-
 using namespace ns3;
 
+NS_LOG_COMPONENT_DEFINE("GlobalRouteManagerImplTestSuite");
+
+//
+// This test suite is designed to check the Working of the GlobalRouteManagerImpl
+// For that reason, the tests in this suite manually build LSAs for each topology
+// we manually call DebugSPFCalculate() to fill routing tables of the node we are interested in.
+//
+//  TestCase 1: LinkRoutesTestCase
+//  This test case tests that:
+//  - GLobalRouteManagerLSDB stores the LSAs with key as the correct link state ID
+//  - GlobalRouteManagerImpl checks for stubnodes and computes default routes for them
+//  - HostRoutes are computed correctly for point-to-point links
+//
+//  TestCase 2: LanRoutesTestCase
+//  This test case tests that:
+//  - Network LSAs are handled by the GlobalRouteManagerImpl
+//  - GlobalRouteManagerImpl computes the routes correctly for a LAN topology
+//
+//  TestCase 3: RandomEcmpRoutesTestCase
+//  This test case tests that:
+//  - GlobalRouteManagerImpl computes ECMP routes correctly.
+//  - Those random routes are in fact used by the GlobalRouting protocol
+//
+
 /**
  * @ingroup internet
  * @ingroup tests
@@ -30,39 +64,60 @@
  *
  * @brief Global Route Manager Test
  */
-class GlobalRouteManagerImplTestCase : public TestCase
+class LinkRoutesTestCase : public TestCase
 {
   public:
-    GlobalRouteManagerImplTestCase();
+    LinkRoutesTestCase();
+    void DoSetup() override;
     void DoRun() override;
+
+  private:
+    /**
+     *@brief Builds the LSAs for the topology. These LSAs are manually created and inserted into the
+     * GlobalRouteManagerLSDB.Each node exports a router LSA.
+     */
+    void BuildLsa();
+
+    /**
+     *  @brief Checks the Routing Table Entries for the expected output.
+     * @param globalroutingprotocol The routing protocol for the node whose routing table is to be
+     * checked.
+     * @param dests The expected destinations.
+     * @param gws The expected gateways.
+     */
+    void CheckRoutes(Ptr<Ipv4GlobalRouting>& globalroutingprotocol,
+                     std::vector<Ipv4Address>& dests,
+                     std::vector<Ipv4Address>& gws);
+
+    NodeContainer nodes;                   //!< NodeContainer to hold the nodes in the topology
+    std::vector<GlobalRoutingLSA*> m_lsas; //!< The LSAs for the topology
 };
 
-GlobalRouteManagerImplTestCase::GlobalRouteManagerImplTestCase()
-    : TestCase("GlobalRouteManagerImplTestCase")
+LinkRoutesTestCase::LinkRoutesTestCase()
+    : TestCase("LinkRoutesTestCase")
 {
 }
 
 void
-GlobalRouteManagerImplTestCase::DoRun()
+LinkRoutesTestCase::CheckRoutes(Ptr<Ipv4GlobalRouting>& globalroutingprotocol,
+                                std::vector<Ipv4Address>& dests,
+                                std::vector<Ipv4Address>& gws)
 {
-    CandidateQueue candidate;
-
-    for (int i = 0; i < 100; ++i)
+    // check each individual Routing Table Entry for its destination and gateway
+    for (uint32_t i = 0; i < globalroutingprotocol->GetNRoutes(); i++)
     {
-        auto v = new SPFVertex;
-        v->SetDistanceFromRoot(std::rand() % 100);
-        candidate.Push(v);
-    }
-
-    for (int i = 0; i < 100; ++i)
-    {
-        SPFVertex* v = candidate.Pop();
-        delete v;
-        v = nullptr;
+        Ipv4RoutingTableEntry* route = globalroutingprotocol->GetRoute(i);
+        NS_LOG_DEBUG("dest " << route->GetDest() << " gw " << route->GetGateway());
+        NS_TEST_ASSERT_MSG_EQ(route->GetDest(), dests[i], "Error-- wrong destination");
+        NS_TEST_ASSERT_MSG_EQ(route->GetGateway(), gws[i], "Error-- wrong gateway");
     }
+}
 
-    // Build fake link state database; four routers (0-3), 3 point-to-point
-    // links
+void
+LinkRoutesTestCase::DoSetup()
+{
+    // Simple p2p links. n0,n1 and n3 are stub nodes
+    //
     //
     //   n0
     //      \ link 0
@@ -72,18 +127,56 @@
     //      / link 1
     //    n1
     //
-    //  link0:  10.1.1.1/30, 10.1.1.2/30
-    //  link1:  10.1.2.1/30, 10.1.2.2/30
-    //  link2:  10.1.3.1/30, 10.1.3.2/30
+    //  link0:  n0->10.1.1.1/30, n2-> 10.1.1.2/30
+    //  link1:  n1-> 10.1.2.1/30, n2->10.1.2.2/30
+    //  link2:  n2->10.1.3.1/30, n3-> 10.1.3.2/30
+    //
     //
+    //
+
+    nodes.Create(4);
+
+    Ipv4GlobalRoutingHelper globalhelper;
+    InternetStackHelper stack;
+    stack.SetRoutingHelper(globalhelper);
+    stack.Install(nodes);
+
+    SimpleNetDeviceHelper devHelper;
+    devHelper.SetNetDevicePointToPointMode(true);
+    Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d02 = devHelper.Install(nodes.Get(0), channel1);
+    d02.Add(devHelper.Install(nodes.Get(2), channel1));
+    Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d12 = devHelper.Install(nodes.Get(1), channel2);
+    d12.Add(devHelper.Install(nodes.Get(2), channel2));
+    Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d23 = devHelper.Install(nodes.Get(2), channel3);
+    d23.Add(devHelper.Install(nodes.Get(3), channel3));
+
+    // Assign IP addresses to the devices
+    Ipv4AddressHelper address;
+    address.SetBase("10.1.1.0", "255.255.255.252");
+    Ipv4InterfaceContainer i02 = address.Assign(d02);
+    address.SetBase("10.1.2.0", "255.255.255.252");
+    Ipv4InterfaceContainer i12 = address.Assign(d12);
+    address.SetBase("10.1.3.0", "255.255.255.252");
+    Ipv4InterfaceContainer i23 = address.Assign(d23);
+}
+
+void
+LinkRoutesTestCase::BuildLsa()
+{
+    // Manually build the link state database; four routers (0-3), 3 point-to-point
+    // links
+
     // Router 0
     auto lr0 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
-                                           "0.0.0.2",  // router ID 0.0.0.2
-                                           "10.1.1.1", // local ID
+                                           "0.0.0.2",  // link id -> router ID 0.0.0.2
+                                           "10.1.1.1", // link data -> Local IP address of router 0
                                            1);         // metric
 
     auto lr1 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
-                                           "10.1.1.1",
+                                           "10.1.1.2", // link id ->adjacent neighbor's IP address
                                            "255.255.255.252",
                                            1);
 
@@ -91,8 +184,10 @@
     lsa0->SetLSType(GlobalRoutingLSA::RouterLSA);
     lsa0->SetLinkStateId("0.0.0.0");
     lsa0->SetAdvertisingRouter("0.0.0.0");
+    lsa0->SetNode(nodes.Get(0));
     lsa0->AddLinkRecord(lr0);
     lsa0->AddLinkRecord(lr1);
+    m_lsas.push_back(lsa0);
 
     // Router 1
     auto lr2 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
@@ -101,7 +196,7 @@
                                            1);
 
     auto lr3 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
-                                           "10.1.2.1",
+                                           "10.1.2.2",
                                            "255.255.255.252",
                                            1);
 
@@ -111,6 +206,8 @@
     lsa1->SetAdvertisingRouter("0.0.0.1");
     lsa1->AddLinkRecord(lr2);
     lsa1->AddLinkRecord(lr3);
+    lsa1->SetNode(nodes.Get(1));
+    m_lsas.push_back(lsa1);
 
     // Router 2
     auto lr4 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
@@ -119,7 +216,7 @@
                                            1);
 
     auto lr5 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
-                                           "10.1.1.2",
+                                           "10.1.1.1",
                                            "255.255.255.252",
                                            1);
 
@@ -135,7 +232,7 @@
 
     auto lr8 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
                                            "0.0.0.3",
-                                           "10.1.3.2",
+                                           "10.1.3.1",
                                            1);
 
     auto lr9 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
@@ -153,15 +250,17 @@
     lsa2->AddLinkRecord(lr7);
     lsa2->AddLinkRecord(lr8);
     lsa2->AddLinkRecord(lr9);
+    lsa2->SetNode(nodes.Get(2));
+    m_lsas.push_back(lsa2);
 
     // Router 3
     auto lr10 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
                                             "0.0.0.2",
-                                            "10.1.2.1",
+                                            "10.1.3.2",
                                             1);
 
     auto lr11 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
-                                            "10.1.2.1",
+                                            "10.1.3.1",
                                             "255.255.255.252",
                                             1);
 
@@ -171,37 +270,674 @@
     lsa3->SetAdvertisingRouter("0.0.0.3");
     lsa3->AddLinkRecord(lr10);
     lsa3->AddLinkRecord(lr11);
+    lsa3->SetNode(nodes.Get(3));
+    m_lsas.push_back(lsa3);
+}
+
+void
+LinkRoutesTestCase::DoRun()
+{
+    //  This test is for checking the individual working of GlobalRouteManagerImpl
+    //  and GlobalRouteManagerLSDB, so we will not use the GlobalRoutingHelper
+    //  to create the routing tables, but instead we will manually create the LSAs
+    //  and insert them into the GlobalRouteManagerLSDB, and then use the
+    //  GlobalRouteManagerImpl to calculate the routes based on the LSDB.
+    //  This is a manual setup of the LSAs, which would normally be done by the
+    //  GlobalRoutingHelper.
+
+    BuildLsa();
 
     // Test the database
     auto srmlsdb = new GlobalRouteManagerLSDB();
-    srmlsdb->Insert(lsa0->GetLinkStateId(), lsa0);
-    srmlsdb->Insert(lsa1->GetLinkStateId(), lsa1);
-    srmlsdb->Insert(lsa2->GetLinkStateId(), lsa2);
-    srmlsdb->Insert(lsa3->GetLinkStateId(), lsa3);
-    NS_TEST_ASSERT_MSG_EQ(lsa2,
-                          srmlsdb->GetLSA(lsa2->GetLinkStateId()),
-                          "The Ipv4Address is not stored as the link state ID");
+    srmlsdb->Insert(m_lsas[0]->GetLinkStateId(), m_lsas[0]);
+    srmlsdb->Insert(m_lsas[1]->GetLinkStateId(), m_lsas[1]);
+    srmlsdb->Insert(m_lsas[2]->GetLinkStateId(), m_lsas[2]);
+    srmlsdb->Insert(m_lsas[3]->GetLinkStateId(), m_lsas[3]);
+
+    NS_TEST_ASSERT_MSG_EQ(
+        m_lsas[2],
+        srmlsdb->GetLSA(m_lsas[2]->GetLinkStateId()),
+        "The Ipv4Address is not stored as the link state ID"); // LSAs are mapped by router id as
+                                                               // key here we check that they are
+                                                               // indeed getting the right lsa for
+                                                               // the right key
 
     // next, calculate routes based on the manually created LSDB
     auto srm = new GlobalRouteManagerImpl();
     srm->DebugUseLsdb(srmlsdb); // manually add in an LSDB
-    // Note-- this will succeed without any nodes in the topology
-    // because the NodeList is empty
-    srm->DebugSPFCalculate(lsa0->GetLinkStateId()); // node n0
+
+    srm->DebugSPFCalculate(m_lsas[0]->GetLinkStateId()); // fill routing table for node n0
+
+    srm->DebugSPFCalculate(m_lsas[1]->GetLinkStateId()); // fill routing table for node n1
+
+    srm->DebugSPFCalculate(m_lsas[2]->GetLinkStateId()); // fill routing table for node n2
+
+    srm->DebugSPFCalculate(m_lsas[3]->GetLinkStateId()); // fill routing table for node n3
 
     Simulator::Run();
 
-    /// @todo here we should do some verification of the routes built
+    //-----------------Now the tests------------------
+    // Test 1: Check if the SPF calculate Sets default routes for Stub nodes
+    Ptr<Ipv4L3Protocol> ip0 = nodes.Get(0)->GetObject<Ipv4L3Protocol>();
+    NS_TEST_ASSERT_MSG_NE(ip0, nullptr, "Error-- no Ipv4 object at node 0");
+    Ptr<Ipv4RoutingProtocol> routing0 = ip0->GetRoutingProtocol();
+    NS_TEST_ASSERT_MSG_NE(routing0, nullptr, "Error-- no Ipv4 routing protocol object at node 0");
+    Ptr<Ipv4GlobalRouting> globalRouting0 = routing0->GetObject<Ipv4GlobalRouting>();
+    NS_TEST_ASSERT_MSG_NE(globalRouting0, nullptr, "Error-- no Ipv4GlobalRouting object at node 0");
+
+    // Check that the right number of entries are in the routing table
+    uint32_t nRoutes0 = globalRouting0->GetNRoutes();
+    NS_TEST_ASSERT_MSG_EQ(nRoutes0, 1, "Error-- default route not found for stub node");
+
+    Ipv4RoutingTableEntry* route = nullptr;
+    route = globalRouting0->GetRoute(0);
+    // the only route is the default route on this node
+    NS_TEST_ASSERT_MSG_EQ(route->GetDest(),
+                          Ipv4Address("0.0.0.0"),
+                          "Error-- wrong destination for default route");
+    NS_TEST_ASSERT_MSG_EQ(route->GetGateway(), Ipv4Address("10.1.1.2"), "Error-- wrong gateway");
+
+    // Test 2: Check if SPFCalculate sets the correct routes for node 2
+    Ptr<Ipv4L3Protocol> ip2 = nodes.Get(2)->GetObject<Ipv4L3Protocol>();
+    NS_TEST_ASSERT_MSG_NE(ip2, nullptr, "Error-- no Ipv4 object at node 2");
+    Ptr<Ipv4RoutingProtocol> routing2 = ip2->GetRoutingProtocol();
+    NS_TEST_ASSERT_MSG_NE(routing2, nullptr, "Error-- no Ipv4 routing protocol object at node 2");
+    Ptr<Ipv4GlobalRouting> globalRouting2 = routing2->GetObject<Ipv4GlobalRouting>();
+    NS_TEST_ASSERT_MSG_NE(globalRouting2, nullptr, "Error-- no Ipv4GlobalRouting object at node 2");
+
+    // check that the correct number of routes were built
+    uint32_t nRoutes2 = globalRouting2->GetNRoutes();
+    NS_LOG_DEBUG("LinkRoutesTest nRoutes2 " << nRoutes2);
+    NS_TEST_ASSERT_MSG_EQ(nRoutes2, 6, "Error--- Incorrect number of routes found on node 2");
+
+    // check that all the routes in the routing table are correct for node 2
+    std::vector<Ipv4Address> expecteddests;
+    std::vector<Ipv4Address> expectedgws;
+    expecteddests.emplace_back("10.1.1.1");
+    expecteddests.emplace_back("10.1.2.1");
+    expecteddests.emplace_back("10.1.3.2");
+    expecteddests.emplace_back("10.1.1.0");
+    expecteddests.emplace_back("10.1.2.0");
+    expecteddests.emplace_back("10.1.3.0");
+
+    expectedgws.emplace_back("10.1.1.1");
+    expectedgws.emplace_back("10.1.2.1");
+    expectedgws.emplace_back("10.1.3.2");
+    expectedgws.emplace_back("10.1.1.1");
+    expectedgws.emplace_back("10.1.2.1");
+    expectedgws.emplace_back("10.1.3.2");
+
+    CheckRoutes(globalRouting2, expecteddests, expectedgws);
 
+    Simulator::Run();
+
+    Simulator::Stop(Seconds(3));
     Simulator::Destroy();
 
     // This delete clears the srm, which deletes the LSDB, which clears
     // all of the LSAs, which each destroys the attached LinkRecords.
     delete srm;
+    // reset the router ID counter to zero so that it does not affect other tests
+    //  that may run after this one in the same program run.
+    GlobalRouteManager::ResetRouterId();
+}
+
+/**
+ * @ingroup internet-test
+ *
+ * @brief This test case is to check if NetworkRoutes are being built correctly, i.e if route
+ * computation works for a LAN Topology.
+ */
+class LanRoutesTestCase : public TestCase
+{
+  public:
+    LanRoutesTestCase();
+    void DoSetup() override;
+    void DoRun() override;
+
+  private:
+    /**
+     *@brief Builds the LSAs for the topology. These LSAs are manually created and inserted into the
+     * GlobalRouteManagerLSDB.Each node exports a router LSA. In addition,the designated router
+     * also Exports the Network LSA.
+     */
+    void BuildLsa();
+
+    NodeContainer nodes;                   //!< NodeContainer to hold the nodes in the topology
+    std::vector<GlobalRoutingLSA*> m_lsas; //!< The LSAs for the topology
+};
+
+LanRoutesTestCase::LanRoutesTestCase()
+    : TestCase("LanRoutesTestCase")
+{
+}
+
+void
+LanRoutesTestCase::DoSetup()
+{
+    // Simple Csma Network with three nodes
+    //
+    //      n0                       n1
+    //      |    (shared csma/cd)   |
+    //      -------------------------
+    //                |
+    //                n2
+    //
+    //       n0:10.1.1.1/29
+    //       n1:10.1.1.2/29
+    //       n2:10.1.1.3/29
+    nodes.Create(3);
+    Ipv4GlobalRoutingHelper globalhelper;
+    InternetStackHelper stack;
+    stack.SetRoutingHelper(globalhelper);
+    stack.Install(nodes);
+    SimpleNetDeviceHelper devHelper;
+    Ptr<SimpleChannel> channel = CreateObject<SimpleChannel>();
+    NetDeviceContainer d012 = devHelper.Install(nodes.Get(0), channel);
+    d012.Add(devHelper.Install(nodes.Get(1), channel));
+    d012.Add(devHelper.Install(nodes.Get(2), channel));
+
+    // assign IP addresses to the devices
+    Ipv4AddressHelper address;
+    address.SetBase("10.1.1.0", "255.255.255.248");
+    Ipv4InterfaceContainer i012 = address.Assign(d012);
+}
 
-    /// @todo Testing
-    // No testing has actually been done other than making sure that this code
-    // does not crash
+void
+LanRoutesTestCase::BuildLsa()
+{
+    // we manually create the link state database, we could have used BuildRoutingTables() but this
+    // way testing the GlobalRouteManagerImpl without the involvement of GLobalRouter makes it
+    // easier to debug each individually
+
+    // router 0
+    auto lr0 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::TransitNetwork,
+                                           "10.1.1.1",
+                                           "10.1.1.1",
+                                           1);
+    auto lsa0 = new GlobalRoutingLSA();
+    lsa0->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa0->AddLinkRecord(lr0);
+    lsa0->SetLinkStateId("0.0.0.0");
+    lsa0->SetAdvertisingRouter("0.0.0.0");
+    lsa0->SetNode(nodes.Get(0));
+    m_lsas.push_back(lsa0);
+
+    // router 1
+    auto lr1 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::TransitNetwork,
+                                           "10.1.1.1",
+                                           "10.1.1.2",
+                                           1);
+    auto lsa1 = new GlobalRoutingLSA();
+    lsa1->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa1->AddLinkRecord(lr1);
+    lsa1->SetLinkStateId("0.0.0.1");
+    lsa1->SetAdvertisingRouter("0.0.0.1");
+    lsa1->SetNode(nodes.Get(1));
+    m_lsas.push_back(lsa1);
+
+    // router 2
+    auto lr2 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::TransitNetwork,
+                                           "10.1.1.1",
+                                           "10.1.1.3",
+                                           1);
+    auto lsa2 = new GlobalRoutingLSA();
+    lsa2->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa2->AddLinkRecord(lr2);
+    lsa2->SetLinkStateId("0.0.0.2");
+    lsa2->SetAdvertisingRouter("0.0.0.2");
+    lsa2->SetNode(nodes.Get(2));
+    m_lsas.push_back(lsa2);
+
+    // router0 is the designated router for the LAN. it also exports the network LSA
+    auto lsa0network = new GlobalRoutingLSA();
+    lsa0network->SetLSType(GlobalRoutingLSA::NetworkLSA);
+    lsa0network->SetLinkStateId("10.1.1.1");
+    lsa0network->SetAdvertisingRouter("0.0.0.0");
+    lsa0network->AddAttachedRouter("10.1.1.1");
+    lsa0network->AddAttachedRouter("10.1.1.2");
+    lsa0network->AddAttachedRouter("10.1.1.3");
+    lsa0network->SetNetworkLSANetworkMask("255.255.255.248");
+    m_lsas.push_back(lsa0network); // note the index of the network lsa
+}
+
+void
+LanRoutesTestCase::DoRun()
+{
+    BuildLsa();
+    // insert the LSAs into the GlobalRouteManagerLSDB
+    auto srmlsdb = new GlobalRouteManagerLSDB();
+
+    srmlsdb->Insert(m_lsas[0]->GetLinkStateId(), m_lsas[0]);
+    srmlsdb->Insert(m_lsas[1]->GetLinkStateId(), m_lsas[1]);
+    srmlsdb->Insert(m_lsas[2]->GetLinkStateId(), m_lsas[2]);
+    srmlsdb->Insert(m_lsas[3]->GetLinkStateId(), m_lsas[3]);
+
+    // create the GlobalRouteManagerImpl
+    auto srm = new GlobalRouteManagerImpl();
+    srm->DebugUseLsdb(srmlsdb);
+
+    srm->DebugSPFCalculate(m_lsas[0]->GetLinkStateId()); // fill the routing table for node 0
+
+    // now the tests-----------------------
+
+    Ptr<Ipv4L3Protocol> ip0 = nodes.Get(0)->GetObject<Ipv4L3Protocol>();
+    NS_TEST_ASSERT_MSG_NE(ip0, nullptr, "Error-- no Ipv4 object at node 0");
+    Ptr<Ipv4RoutingProtocol> routing0 = ip0->GetRoutingProtocol();
+    NS_TEST_ASSERT_MSG_NE(routing0, nullptr, "Error-- no Ipv4 routing protocol object at node 0");
+    Ptr<Ipv4GlobalRouting> globalRouting0 = routing0->GetObject<Ipv4GlobalRouting>();
+    NS_TEST_ASSERT_MSG_NE(globalRouting0, nullptr, "Error-- no Ipv4GlobalRouting object at node 0");
+
+    // The only route to check is the network route
+    uint32_t nRoutes0 = globalRouting0->GetNRoutes();
+    NS_TEST_ASSERT_MSG_EQ(nRoutes0, 1, "Error-- Network route not found for node 0");
+    Ipv4RoutingTableEntry* route = globalRouting0->GetRoute(0);
+    NS_TEST_ASSERT_MSG_EQ(route->GetDest(),
+                          Ipv4Address("10.1.1.0"),
+                          "Error-- wrong destination for network route");
+    NS_TEST_ASSERT_MSG_EQ(route->GetGateway(),
+                          Ipv4Address("0.0.0.0"),
+                          "Error-- wrong gateway for network route");
+
+    Simulator::Run();
+
+    Simulator::Stop(Seconds(3));
+    Simulator::Destroy();
+    // This delete clears the srm, which deletes the LSDB, which clears
+    // all of the LSAs, which each destroys the attached LinkRecords.
+    delete srm;
+    GlobalRouteManager::ResetRouterId();
+}
+
+/**
+ * @ingroup internet-test
+ *
+ * @brief The purpose of this test is to check if Equal Cost MultiPath (ECMP) Routes are being built
+ * and used correctly.
+ */
+class RandomEcmpTestCase : public TestCase
+{
+  public:
+    RandomEcmpTestCase();
+
+    void DoSetup() override;
+    void DoRun() override;
+
+  private:
+    /**
+     *@brief Builds the LSAs for the topology. These LSAs are manually created and inserted into the
+     *       GlobalRouteManagerLSDB.Each node exports a router LSA.
+     */
+    void BuildLsa();
+
+    /**
+     * @brief Helper function that checks the output of the routing path
+     * and increments the corresponding route counter.
+     * @param route The routing path to check
+     */
+    void IncrementCount(Ptr<Ipv4Route>& route);
+    /**
+     * @brief function that checks the routing table entries for the expected output.
+     * @param globalroutingprotocol The routing protocol for the node whose routing table is to be
+     * checked.
+     * @param dests The expected destinations.
+     * @param gws The expected gateways.
+     */
+    void CheckRoutes(Ptr<Ipv4GlobalRouting>& globalroutingprotocol,
+                     std::vector<Ipv4Address>& dests,
+                     std::vector<Ipv4Address>& gws);
+    uint32_t route1 = 0; //!< Counter to keep track of the number of times route1 is used
+    uint32_t route2 = 0; //!< Counter to keep track of the number of times route2 is used
+    NodeContainer nodes; //!< NodeContainer to hold the nodes in the topology
+    std::vector<GlobalRoutingLSA*> m_lsas; //!< The LSAs for the topology
+};
+
+RandomEcmpTestCase::RandomEcmpTestCase()
+    : TestCase("RandomEcmpTestCase")
+{
+}
+
+void
+RandomEcmpTestCase::DoSetup()
+{
+    Config::SetDefault("ns3::Ipv4GlobalRouting::RandomEcmpRouting", BooleanValue(true));
+    /*
+    //   Creating a Simple topology with 4 nodes and 3 links
+    //
+    //
+    //
+    //          ------n1------
+    //         /              \
+    //        /                \
+    //       n0                n3
+    //        \                /
+    //         \              /
+    //          ------n2------
+    //
+    //    Link n0-n1: 10.1.1.1/30,10.1.1.2/30
+    //    Link n0-n2: 10.1.2.1/30,10.1.2.2/30
+    //    Link n1-n3: 10.1.3.1/30,10.1.3.2/30
+    //    Link n2-n3: 10.1.4.1/30,10.1.4.2/30
+    */
+    nodes.Create(4);
+
+    Ipv4GlobalRoutingHelper globalhelper;
+    InternetStackHelper stack;
+    stack.SetRoutingHelper(globalhelper);
+    stack.Install(nodes);
+    SimpleNetDeviceHelper devHelper;
+    devHelper.SetNetDevicePointToPointMode(true);
+    Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d01 = devHelper.Install(nodes.Get(0), channel1);
+    d01.Add(devHelper.Install(nodes.Get(1), channel1));
+    Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d23 = devHelper.Install(nodes.Get(2), channel2);
+    d23.Add(devHelper.Install(nodes.Get(3), channel2));
+    Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d02 = devHelper.Install(nodes.Get(0), channel3);
+    d02.Add(devHelper.Install(nodes.Get(2), channel3));
+    Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d13 = devHelper.Install(nodes.Get(1), channel4);
+    d13.Add(devHelper.Install(nodes.Get(3), channel4));
+
+    // Assign IP addresses to the devices
+    Ipv4AddressHelper address;
+    address.SetBase("10.1.1.0", "255.255.255.252");
+    Ipv4InterfaceContainer i01 = address.Assign(d01);
+
+    address.SetBase("10.1.2.0", "255.255.255.252");
+    Ipv4InterfaceContainer i02 = address.Assign(d02);
+
+    address.SetBase("10.1.3.0", "255.255.255.252");
+    Ipv4InterfaceContainer i13 = address.Assign(d13);
+
+    address.SetBase("10.1.4.0", "255.255.255.252");
+    Ipv4InterfaceContainer i23 = address.Assign(d23);
+}
+
+void
+RandomEcmpTestCase::CheckRoutes(Ptr<Ipv4GlobalRouting>& globalroutingprotocol,
+                                std::vector<Ipv4Address>& dests,
+                                std::vector<Ipv4Address>& gws)
+{
+    // check each individual routes destination and gateway
+    for (uint32_t i = 0; i < globalroutingprotocol->GetNRoutes(); i++)
+    {
+        Ipv4RoutingTableEntry* route = globalroutingprotocol->GetRoute(i);
+        NS_LOG_DEBUG("dest " << route->GetDest() << " gw " << route->GetGateway());
+        NS_TEST_ASSERT_MSG_EQ(route->GetDest(), dests[i], "Error-- wrong destination");
+        NS_TEST_ASSERT_MSG_EQ(route->GetGateway(), gws[i], "Error-- wrong gateway");
+    }
+}
+
+void
+RandomEcmpTestCase::IncrementCount(Ptr<Ipv4Route>& route)
+{
+    if (route->GetGateway() == Ipv4Address("10.1.1.2"))
+    {
+        route1++;
+    }
+    else if (route->GetGateway() == Ipv4Address("10.1.2.2"))
+    {
+        route2++;
+    }
+}
+
+void
+RandomEcmpTestCase::BuildLsa()
+{
+    // we manually create the link state database, we could have used BuildRoutingTables() but this
+    // way testing the GlobalRouteManagerImpl without the involvement of GLobalRouter makes it
+    // easier to debug each individually
+
+    // router 0
+    auto lr0 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                           "0.0.0.1",
+                                           "10.1.1.1",
+                                           1);
+    auto lr1 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                           "10.1.1.2",
+                                           "255.255.255.252",
+                                           1);
+
+    auto lr2 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                           "0.0.0.2",
+                                           "10.1.2.1",
+                                           1);
+    auto lr3 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                           "10.1.2.2",
+                                           "255.255.255.252",
+                                           1);
+
+    auto lsa0 = new GlobalRoutingLSA();
+    lsa0->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa0->SetStatus(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+    lsa0->SetLinkStateId("0.0.0.0");
+    lsa0->SetAdvertisingRouter("0.0.0.0");
+    lsa0->SetNode(nodes.Get(0));
+    lsa0->AddLinkRecord(lr0);
+    lsa0->AddLinkRecord(lr1);
+    lsa0->AddLinkRecord(lr2);
+    lsa0->AddLinkRecord(lr3);
+    m_lsas.push_back(lsa0);
+
+    // router 1
+    auto lr4 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                           "0.0.0.0",
+                                           "10.1.1.2",
+                                           1);
+    auto lr5 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                           "10.1.1.1",
+                                           "255.255.255.252",
+                                           1);
+
+    auto lr6 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                           "0.0.0.3",
+                                           "10.1.3.1",
+                                           1);
+    auto lr7 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                           "10.1.3.2",
+                                           "255.255.255.252",
+                                           1);
+
+    auto lsa1 = new GlobalRoutingLSA();
+    lsa1->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa1->SetStatus(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+    lsa1->SetLinkStateId("0.0.0.1");
+    lsa1->SetAdvertisingRouter("0.0.0.1");
+    lsa1->SetNode(nodes.Get(1));
+    lsa1->AddLinkRecord(lr4);
+    lsa1->AddLinkRecord(lr5);
+    lsa1->AddLinkRecord(lr6);
+    lsa1->AddLinkRecord(lr7);
+    m_lsas.push_back(lsa1);
+
+    // router 2
+    auto lr8 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                           "0.0.0.0",
+                                           "10.1.2.2",
+                                           1);
+    auto lr9 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                           "10.1.2.1",
+                                           "255.255.255.252",
+                                           1);
+    auto lr10 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                            "0.0.0.3",
+                                            "10.1.4.1",
+                                            1);
+    auto lr11 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                            "10.1.4.2",
+                                            "255.255.255.252",
+                                            1);
+
+    auto lsa2 = new GlobalRoutingLSA();
+    lsa2->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa2->SetStatus(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+    lsa2->SetLinkStateId("0.0.0.2");
+    lsa2->SetAdvertisingRouter("0.0.0.2");
+    lsa2->SetNode(nodes.Get(2));
+    lsa2->AddLinkRecord(lr8);
+    lsa2->AddLinkRecord(lr9);
+    lsa2->AddLinkRecord(lr10);
+    lsa2->AddLinkRecord(lr11);
+    m_lsas.push_back(lsa2);
+
+    // router 3
+    auto lr12 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                            "0.0.0.1",
+                                            "10.1.3.2",
+                                            1);
+    auto lr13 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                            "10.1.3.1",
+                                            "255.255.255.252",
+                                            1);
+    auto lr14 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::PointToPoint,
+                                            "0.0.0.2",
+                                            "10.1.4.2",
+                                            1);
+    auto lr15 = new GlobalRoutingLinkRecord(GlobalRoutingLinkRecord::StubNetwork,
+                                            "10.1.4.1",
+                                            "255.255.255.252",
+                                            1);
+
+    auto lsa3 = new GlobalRoutingLSA();
+    lsa3->SetLSType(GlobalRoutingLSA::RouterLSA);
+    lsa3->SetStatus(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+    lsa3->SetLinkStateId("0.0.0.3");
+    lsa3->SetAdvertisingRouter("0.0.0.3");
+    lsa3->SetNode(nodes.Get(3));
+    lsa3->AddLinkRecord(lr12);
+    lsa3->AddLinkRecord(lr13);
+    lsa3->AddLinkRecord(lr14);
+    lsa3->AddLinkRecord(lr15);
+    m_lsas.push_back(lsa3);
+}
+
+void
+RandomEcmpTestCase::DoRun()
+{
+    // We need a deterministic output to pass the test. So we set a fixed seed and run for our
+    // UniformRandomVariable
+    uint32_t oldseed = RngSeedManager::GetSeed();
+    uint32_t oldrun = RngSeedManager::GetRun();
+    RngSeedManager::SetSeed(1);
+    RngSeedManager::SetRun(1);
+
+    BuildLsa();
+
+    // insert the LSAs into the GlobalRouteManagerLSDB
+    auto srmlsdb = new GlobalRouteManagerLSDB();
+    srmlsdb->Insert(m_lsas[0]->GetLinkStateId(), m_lsas[0]);
+    srmlsdb->Insert(m_lsas[1]->GetLinkStateId(), m_lsas[1]);
+    srmlsdb->Insert(m_lsas[2]->GetLinkStateId(), m_lsas[2]);
+    srmlsdb->Insert(m_lsas[3]->GetLinkStateId(), m_lsas[3]);
+
+    // create the GlobalRouteManagerImpl
+    auto srm = new GlobalRouteManagerImpl();
+    srm->DebugUseLsdb(srmlsdb);
+
+    // we manually call the DebugSPFCalculate to fill the routing tables for node 0
+    srm->DebugSPFCalculate(m_lsas[0]->GetLinkStateId());
+
+    // now the tests-----------------------
+
+    Ptr<Ipv4L3Protocol> ip0 = nodes.Get(0)->GetObject<Ipv4L3Protocol>();
+    NS_TEST_ASSERT_MSG_NE(ip0, nullptr, "Error-- no Ipv4 object at node 0");
+    Ptr<Ipv4RoutingProtocol> routing0 = ip0->GetRoutingProtocol();
+    NS_TEST_ASSERT_MSG_NE(routing0, nullptr, "Error-- no Ipv4 routing protocol object at node 0");
+    Ptr<Ipv4GlobalRouting> globalRouting0 = routing0->GetObject<Ipv4GlobalRouting>();
+    NS_TEST_ASSERT_MSG_NE(globalRouting0, nullptr, "Error-- no Ipv4GlobalRouting object at node 0");
+
+    // assign streams to the UniformRandomVariable
+    globalRouting0->AssignStreams(0);
+    // check that the correct number of routes were built
+    uint32_t nRoutes0 = globalRouting0->GetNRoutes();
+    NS_TEST_ASSERT_MSG_EQ(nRoutes0, 14, "Error-- incorrect number of routes found on node 0");
+
+    // check that the routes are correct
+    std::vector<Ipv4Address> expectedDests;
+    std::vector<Ipv4Address> expectedNextHops;
+
+    // add all the expected destinations and gateways. This is pretty verbose
+    // Please Note: The order of the following line is important because we check the routing table
+    // entries in order. The test will fail if we reorder the vector entries.
+
+    // For Routing table of Node 0 we check the following Destinations and Gateways
+    expectedDests.emplace_back("10.1.1.2");
+    expectedDests.emplace_back("10.1.3.1");
+    expectedDests.emplace_back("10.1.2.2");
+    expectedDests.emplace_back("10.1.4.1");
+    expectedDests.emplace_back("10.1.3.2");
+    expectedDests.emplace_back("10.1.3.2");
+    expectedDests.emplace_back("10.1.4.2");
+    expectedDests.emplace_back("10.1.4.2");
+    expectedDests.emplace_back("10.1.1.0");
+    expectedDests.emplace_back("10.1.3.0");
+    expectedDests.emplace_back("10.1.3.0");
+    expectedDests.emplace_back("10.1.4.0");
+    expectedDests.emplace_back("10.1.4.0");
+    expectedDests.emplace_back("10.1.2.0");
+
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+    expectedNextHops.emplace_back("10.1.1.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+    expectedNextHops.emplace_back("10.1.2.2");
+
+    // Test 1: Check the Routing Table of Node 0
+    CheckRoutes(globalRouting0, expectedDests, expectedNextHops);
+
+    // Test 2: Check that the equal cost routes are being used at least once.
+    // we need to call RouteOutput() at node 0 and check the output
+    // route from the table. The thing to check here is that different equal cost routes are
+    // returned across different calls to this method.
+
+    Socket::SocketErrno errno_;
+    Ptr<NetDevice> oif(nullptr);
+    Ptr<Packet> packet = Create<Packet>();
+    Ipv4Header ipHeader;
+    ipHeader.SetSource(Ipv4Address("10.1.1.1"));
+    ipHeader.SetDestination(Ipv4Address("10.1.4.2"));
+
+    for (uint32_t i = 0; i < 10; i++)
+    {
+        Ptr<Ipv4Route> route = globalRouting0->RouteOutput(packet, ipHeader, oif, errno_);
+        IncrementCount(route);
+    }
+
+    Simulator::Run();
+
+    NS_TEST_ASSERT_MSG_GT_OR_EQ(
+        route1,
+        1,
+        "The routing path for node 0 to node 3 does not match the expected output, "
+        "Equal Cost MultiPath (ECMP) routes are not being used correctly");
+    NS_TEST_ASSERT_MSG_GT_OR_EQ(
+        route2,
+        1,
+        "The routing path for node 0 to node 3 does not match the expected output, "
+        "Equal Cost MultiPath (ECMP) routes are not being used correctly");
+
+    // end of test--------------------
+
+    Simulator::Stop(Seconds(5));
+
+    Simulator::Destroy();
+
+    RngSeedManager::SetSeed(oldseed);
+    RngSeedManager::SetRun(oldrun);
+    // This delete clears the srm, which deletes the LSDB, which clears
+    // all of the LSAs, which each destroys the attached LinkRecords.
+    delete srm;
 }
 
 /**
@@ -220,7 +956,9 @@
 GlobalRouteManagerImplTestSuite::GlobalRouteManagerImplTestSuite()
     : TestSuite("global-route-manager-impl", Type::UNIT)
 {
-    AddTestCase(new GlobalRouteManagerImplTestCase(), TestCase::Duration::QUICK);
+    AddTestCase(new LinkRoutesTestCase(), TestCase::Duration::QUICK);
+    AddTestCase(new LanRoutesTestCase(), TestCase::Duration::QUICK);
+    AddTestCase(new RandomEcmpTestCase(), TestCase::Duration::QUICK);
 }
 
 static GlobalRouteManagerImplTestSuite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/ipv4-global-routing-test-suite.cc ns-3.46/src/internet/test/ipv4-global-routing-test-suite.cc
--- ns-3.45/src/internet/test/ipv4-global-routing-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/ipv4-global-routing-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -5,11 +5,13 @@
 #include "ns3/boolean.h"
 #include "ns3/bridge-helper.h"
 #include "ns3/config.h"
+#include "ns3/global-route-manager.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/internet-stack-helper.h"
 #include "ns3/ipv4-address-helper.h"
 #include "ns3/ipv4-global-routing-helper.h"
 #include "ns3/ipv4-global-routing.h"
+#include "ns3/ipv4-interface.h"
 #include "ns3/ipv4-l3-protocol.h"
 #include "ns3/ipv4-packet-info-tag.h"
 #include "ns3/ipv4-routing-protocol.h"
@@ -31,7 +33,6 @@
 #include "ns3/uinteger.h"
 
 #include <vector>
-
 using namespace ns3;
 
 NS_LOG_COMPONENT_DEFINE("Ipv4GlobalRoutingTestSuite");
@@ -1279,6 +1280,489 @@
 /**
  * @ingroup internet-test
  *
+ * @brief This TestCase tests if ECMP Route Calculation works. It does not check the
+ * correctness of the routes.
+ */
+class EcmpRouteCalculationTestCase : public TestCase
+{
+  public:
+    EcmpRouteCalculationTestCase();
+    void DoSetup() override;
+    void DoRun() override;
+
+  private:
+    NodeContainer nodes; //!< Nodes used in the test.
+};
+
+EcmpRouteCalculationTestCase::EcmpRouteCalculationTestCase()
+    : TestCase("ECMP Route Calculation TestCase")
+{
+}
+
+void
+EcmpRouteCalculationTestCase::DoSetup()
+{
+    /*
+        This TestCase checks the resolution of issue #1243 in the issue tracker.
+        The problem was that Global Routing failed to calculate next hops when going from a
+        network vertex to a router vertex when ECMP Routes were involved.
+
+        //         Network Topology
+        //
+        //
+        //          ------n1------
+        //         /              \
+        //        /                \
+        //       n0                n3----n4----n5
+        //        \                /
+        //         \              /
+        //          ------n2------
+        //
+        //    Link n0-n1: 10.1.1.1/30,10.1.1.2/30
+        //    Link n0-n2: 10.1.2.1/30,10.1.2.2/30
+        //    Link n1-n3: 10.1.3.1/30,10.1.3.2/30
+        //    Link n2-n3: 10.1.4.1/30,10.1.4.2/30
+        //    Link n3-n4: 10.1.5.1/24,10.1.5.2/24
+        //    Link n4-n5: 10.1.6.1/24,10.1.6.2/24
+        //
+        //     Note: Link n4-n5 is a LAN LINK. All others are simple P2P links.
+    */
+
+    nodes.Create(6);
+
+    Ipv4GlobalRoutingHelper globalhelper;
+    InternetStackHelper stack;
+    stack.SetRoutingHelper(globalhelper);
+    stack.Install(nodes);
+    SimpleNetDeviceHelper devHelper;
+    devHelper.SetNetDevicePointToPointMode(true);
+
+    Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d01 = devHelper.Install(nodes.Get(0), channel1);
+    d01.Add(devHelper.Install(nodes.Get(1), channel1));
+
+    Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d23 = devHelper.Install(nodes.Get(2), channel2);
+    d23.Add(devHelper.Install(nodes.Get(3), channel2));
+
+    Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d02 = devHelper.Install(nodes.Get(0), channel3);
+    d02.Add(devHelper.Install(nodes.Get(2), channel3));
+
+    Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d34 = devHelper.Install(nodes.Get(3), channel4);
+    d34.Add(devHelper.Install(nodes.Get(4), channel4));
+
+    Ptr<SimpleChannel> channel5 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d13 = devHelper.Install(nodes.Get(1), channel5);
+    d13.Add(devHelper.Install(nodes.Get(3), channel5));
+
+    devHelper.SetNetDevicePointToPointMode(false);
+
+    Ptr<SimpleChannel> channel6 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d45 = devHelper.Install(nodes.Get(4), channel6);
+    d45.Add(devHelper.Install(nodes.Get(5), channel6));
+
+    // Assign IP addresses to the devices
+    Ipv4AddressHelper address;
+    address.SetBase("10.1.1.0", "255.255.255.252");
+    Ipv4InterfaceContainer i01 = address.Assign(d01);
+
+    address.SetBase("10.1.2.0", "255.255.255.252");
+    Ipv4InterfaceContainer i02 = address.Assign(d02);
+
+    address.SetBase("10.1.3.0", "255.255.255.252");
+    Ipv4InterfaceContainer i13 = address.Assign(d13);
+
+    address.SetBase("10.1.4.0", "255.255.255.224");
+    Ipv4InterfaceContainer i23 = address.Assign(d23);
+
+    address.SetBase("10.1.5.0", "255.255.255.0");
+    Ipv4InterfaceContainer i34 = address.Assign(d34);
+
+    address.SetBase("10.1.6.0", "255.255.255.0");
+    Ipv4InterfaceContainer i45 = address.Assign(d45);
+}
+
+void
+EcmpRouteCalculationTestCase::DoRun()
+{
+    // The purpose of this test is to make sure the code doesn't crash when calculating ECMP routes
+    // with a topology described in issue #1243. It does not look into the correctness of the
+    // routes. We have other tests to make sure the routes are correct.
+    Ipv4GlobalRoutingHelper::PopulateRoutingTables();
+
+    Simulator::Run();
+    Simulator::Stop(Seconds(2));
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup internet-test
+ *
+ * @brief TestCase to check calls to GlobalRoutingProtocol API. This TestCase Checks the output
+ * returned by the GlobalRoutingProtocol API to Ipv4L3 Layer.
+ */
+class GlobalRoutingProtocolTestCase : public TestCase
+{
+  public:
+    GlobalRoutingProtocolTestCase();
+    ~GlobalRoutingProtocolTestCase() override;
+
+  private:
+    void DoSetup() override;
+    void DoRun() override;
+    /**
+     * @brief Checks the Path taken by packets by calling RouteInput() and RouteOutput() APIs of
+     * GlobalRoutingProtocol. This mimics how Ipv4L3Protocol calls these APIs.
+     * @param pathNodes Vector of nodes in the path. This includes the source node,Intermediate
+     * nextHop nodes and the destination node.
+     * @param path Vector of Ipv4Addresses in the path. This includes the source egress IpAddress,
+     * destination ingress IpAddress and intermediate nextHop Node's ingress Ipaddress that we need
+     * to check.It does not include the egress addresses for intermediate nodes.
+     */
+    void CheckPath(std::vector<Ptr<Node>> pathNodes, std::vector<Ipv4Address> path);
+
+    /**
+     * @brief Callback function for RouteInput() API of GlobalRoutingProtocol.
+     * @param route Route to be used for forwarding
+     * @param packet Packet to be forwarded
+     * @param header IPv4 header of the packet
+     */
+    void MyUnicastCallback(Ptr<Ipv4Route> route,
+                           Ptr<const Packet> packet,
+                           const Ipv4Header& header);
+    /**
+     * @brief Callback function for RouteInput() API of GlobalRoutingProtocol.
+     * @param packet Packet to be locally delivered
+     * @param header IPv4 header of the packet
+     * @param iif Ingress Interface index
+     */
+    void MyLocalDeliverCallback(Ptr<const Packet> packet, const Ipv4Header& header, uint32_t iif);
+    /**
+     * @brief Callback function for RouteInput() API of GlobalRoutingProtocol.
+     * @param packet Packet to be locally delivered
+     * @param header IPv4 header of the packet
+     * @param errno_ Socket error number
+     */
+    void MyErrorCallback(Ptr<const Packet> packet,
+                         const Ipv4Header& header,
+                         Socket::SocketErrno errno_);
+
+    NodeContainer nodes;                                 //!< Nodes used in the test.
+    Ptr<Ipv4Route> m_lastRoute;                          //!< Route to be tested.
+    Ipv4RoutingProtocol::UnicastForwardCallback m_ucb;   ///< Unicast forward callback
+    Ipv4RoutingProtocol::MulticastForwardCallback m_mcb; ///< Multicast forward callback
+    Ipv4RoutingProtocol::LocalDeliverCallback m_lcb;     ///< Local delivery callback
+    Ipv4RoutingProtocol::ErrorCallback m_ecb;            ///< Error callback
+};
+
+// Signature: void (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header &header)
+void
+GlobalRoutingProtocolTestCase::MyUnicastCallback(Ptr<Ipv4Route> route,
+                                                 Ptr<const Packet> packet,
+                                                 const Ipv4Header& header)
+{
+    NS_LOG_DEBUG("Unicast Forward Callback called.");
+    m_lastRoute = route;
+}
+
+// Signature: void (Ptr<const Packet>, const Ipv4Header&, uint32_t)
+void
+GlobalRoutingProtocolTestCase::MyLocalDeliverCallback(Ptr<const Packet> packet,
+                                                      const Ipv4Header& header,
+                                                      uint32_t iif)
+{
+    NS_LOG_DEBUG("Local Deliver Callback called.");
+}
+
+// Signature: void (Ptr<const Packet>, const Ipv4Header&, Socket::SocketErrno)
+void
+GlobalRoutingProtocolTestCase::MyErrorCallback(Ptr<const Packet> packet,
+                                               const Ipv4Header& header,
+                                               Socket::SocketErrno errno_)
+{
+    NS_LOG_DEBUG("Error Callback called.");
+    // Fail the test if this callback is called
+    NS_TEST_ASSERT_MSG_EQ(1, 1, "Error Callback called in RouteInput");
+}
+
+GlobalRoutingProtocolTestCase::GlobalRoutingProtocolTestCase()
+    : TestCase("Test API calls to GlobalRoutingProtocol")
+{
+    m_ucb = MakeCallback(&GlobalRoutingProtocolTestCase::MyUnicastCallback, this);
+    m_lcb = MakeCallback(&GlobalRoutingProtocolTestCase::MyLocalDeliverCallback, this);
+    m_ecb = MakeCallback(&GlobalRoutingProtocolTestCase::MyErrorCallback, this);
+    // Multicast callback is not used in unicast test, can bind to null or dummy
+    Ipv4RoutingProtocol::MulticastForwardCallback mcb;
+}
+
+GlobalRoutingProtocolTestCase::~GlobalRoutingProtocolTestCase()
+{
+}
+
+void
+GlobalRoutingProtocolTestCase::CheckPath(std::vector<Ptr<Node>> pathNodes,
+                                         std::vector<Ipv4Address> path)
+{
+    uint32_t pathSize = path.size();
+
+    Ptr<Ipv4L3Protocol> ip = pathNodes[0]->GetObject<Ipv4L3Protocol>();
+    NS_TEST_ASSERT_MSG_NE(ip, nullptr, "Error-- no Ipv4 object at source node");
+    Ptr<Ipv4RoutingProtocol> routing = ip->GetRoutingProtocol();
+    NS_TEST_ASSERT_MSG_NE(routing,
+                          nullptr,
+                          "Error-- no Ipv4 routing protocol object at source node");
+    Ptr<Ipv4GlobalRouting> globalRouting = routing->GetObject<Ipv4GlobalRouting>();
+    NS_TEST_ASSERT_MSG_NE(globalRouting,
+                          nullptr,
+                          "Error-- no Ipv4GlobalRouting object at source node");
+
+    Socket::SocketErrno errno_;
+    Ptr<NetDevice> oif(nullptr);
+    Ptr<Packet> packet = Create<Packet>();
+    Ipv4Header ipHeader;
+    ipHeader.SetSource(path[0]);
+    ipHeader.SetDestination(path[pathSize - 1]);
+
+    // for the source node we need to call RouteOutput()
+    m_lastRoute = globalRouting->RouteOutput(packet, ipHeader, oif, errno_);
+    // for the rest of the nodes we need to call RouteInput()
+    for (uint32_t i = 1; i < pathSize; i++)
+    {
+        // for each iteration except the last one check that the UnicastForward Callback is called.
+        // For the last node that is the destination node LocalDelivery Callback will be called.
+        if (i != pathSize - 1)
+        {
+            NS_TEST_ASSERT_MSG_EQ(m_lastRoute->GetGateway(), path[i], "Error-- wrong gateway");
+        }
+
+        ip = pathNodes[i]->GetObject<Ipv4L3Protocol>();
+        NS_TEST_ASSERT_MSG_NE(ip, nullptr, "Error-- no Ipv4 object at node");
+        routing = ip->GetRoutingProtocol();
+        NS_TEST_ASSERT_MSG_NE(routing, nullptr, "Error-- no Ipv4 routing protocol object at node");
+        globalRouting = routing->GetObject<Ipv4GlobalRouting>();
+        NS_TEST_ASSERT_MSG_NE(globalRouting,
+                              nullptr,
+                              "Error-- no Ipv4GlobalRouting object at node");
+
+        Ptr<Ipv4Interface> interf = ip->GetInterface(ip->GetInterfaceForAddress(path[i]));
+        Ptr<NetDevice> idevice = interf->GetDevice();
+
+        // call RouteInput() for the next node in the path
+        globalRouting->RouteInput(packet, ipHeader, idevice, m_ucb, m_mcb, m_lcb, m_ecb);
+    }
+}
+
+void
+GlobalRoutingProtocolTestCase::DoSetup()
+{
+    /**
+     * This test case is designed to test the overall functionality of the GlobalRoutingProtocol.
+     * It tests the calls to the GlobalRoutingProtocol's RouteOutput() and RouteInput() APIs.
+     * It mimics how Ipv4L3Protocol calls these APIs. The topology covers most of the cases
+     * that are expected to be handled by the GlobalRoutingProtocol.
+     */
+
+    //
+    //
+    // Network topology
+    //
+    //  n0
+    //     \ p-p
+    //      \          (shared csma/cd)
+    //       n2 -------------------------n3
+    //      /            |        |
+    //     / p-p        n4        n5 ---------- n6-------n7----Bridge-n8--------n9
+    //   n1                             p-p     |              10.1.4.0/24
+    //   |                                      |
+    //   ----------------------------------------
+    //                p-p
+    //
+    //
+    //
+
+    nodes.Create(10);
+    NodeContainer n2345 = NodeContainer(nodes.Get(2), nodes.Get(3), nodes.Get(4), nodes.Get(5));
+
+    // We create the channels first without any IP addressing information
+    SimpleNetDeviceHelper devHelper;
+
+    devHelper.SetNetDevicePointToPointMode(true);
+
+    Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d0d2 = devHelper.Install(nodes.Get(0), channel1);
+    d0d2.Add(devHelper.Install(nodes.Get(2), channel1));
+
+    Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d1d6 = devHelper.Install(nodes.Get(1), channel2);
+    d1d6.Add(devHelper.Install(nodes.Get(6), channel2));
+
+    Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d1d2 = devHelper.Install(nodes.Get(1), channel3);
+    d1d2.Add(devHelper.Install(nodes.Get(2), channel3));
+
+    Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d5d6 = devHelper.Install(nodes.Get(5), channel4);
+    d5d6.Add(devHelper.Install(nodes.Get(6), channel4));
+
+    Ptr<SimpleChannel> channel5 = CreateObject<SimpleChannel>();
+    devHelper.SetNetDevicePointToPointMode(false);
+    NetDeviceContainer d6d7 = devHelper.Install(nodes.Get(6), channel5);
+    d6d7.Add(devHelper.Install(nodes.Get(7), channel5));
+
+    devHelper.SetNetDevicePointToPointMode(false);
+    NetDeviceContainer d2345 = devHelper.Install(n2345);
+
+    // handle the bridge
+    // connect node 7 to node 8(Switch)
+    Ptr<SimpleChannel> channel6 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d78 = devHelper.Install(nodes.Get(7), channel6);
+    d78.Add(devHelper.Install(nodes.Get(8), channel6));
+
+    // connect node 8(switch) to node 9
+    Ptr<SimpleChannel> channel7 = CreateObject<SimpleChannel>();
+    NetDeviceContainer d89 = devHelper.Install(nodes.Get(8), channel7);
+    d89.Add(devHelper.Install(nodes.Get(9), channel7));
+
+    NetDeviceContainer bridgeFacingDevices;
+    NetDeviceContainer switchDevices;
+    bridgeFacingDevices.Add(d78.Get(0));
+    switchDevices.Add(d78.Get(1));
+    bridgeFacingDevices.Add(d89.Get(1));
+    switchDevices.Add(d89.Get(0));
+
+    Ptr<Node> switchNode = nodes.Get(8);
+    BridgeHelper bridge;
+    bridge.Install(switchNode, switchDevices);
+
+    InternetStackHelper internet;
+    Ipv4GlobalRoutingHelper glbrouting;
+    internet.SetRoutingHelper(glbrouting);
+    internet.Install(nodes.Get(0));
+    internet.Install(nodes.Get(1));
+    internet.Install(nodes.Get(2));
+    internet.Install(nodes.Get(3));
+    internet.Install(nodes.Get(4));
+    internet.Install(nodes.Get(5));
+    internet.Install(nodes.Get(6));
+    internet.Install(nodes.Get(7));
+    // node 8 is a bridge node
+    internet.Install(nodes.Get(9));
+
+    // Later, we add IP addresses.
+    Ipv4AddressHelper ipv4;
+    ipv4.SetBase("10.1.1.0", "255.255.255.0");
+    Ipv4InterfaceContainer i0d2 = ipv4.Assign(d0d2);
+
+    ipv4.SetBase("10.1.2.0", "255.255.255.0");
+    Ipv4InterfaceContainer i1d2 = ipv4.Assign(d1d2);
+
+    ipv4.SetBase("10.1.3.0", "255.255.255.0");
+    Ipv4InterfaceContainer i5i6 = ipv4.Assign(d5d6);
+
+    ipv4.SetBase("10.250.1.0", "255.255.255.0");
+    Ipv4InterfaceContainer i2345 = ipv4.Assign(d2345);
+
+    ipv4.SetBase("172.16.1.0", "255.255.255.0");
+    Ipv4InterfaceContainer i1i6 = ipv4.Assign(d1d6);
+
+    ipv4.SetBase("10.1.4.0", "255.255.255.0");
+    Ipv4InterfaceContainer i67 = ipv4.Assign(d6d7);
+
+    ipv4.SetBase("10.1.5.0", "255.255.255.0");
+    Ipv4InterfaceContainer i79 = ipv4.Assign(bridgeFacingDevices);
+}
+
+void
+GlobalRoutingProtocolTestCase::DoRun()
+{
+    // Create router nodes, initialize routing database and set up the routing
+    // tables in the nodes.
+    GlobalRouteManager::ResetRouterId();
+
+    Ipv4GlobalRoutingHelper::PopulateRoutingTables();
+
+    // tests-------------------------
+    // test 1:check path from n0 to n6
+    // test 2:check path from n1 to n5
+    // test 3:check path from n1 to n9
+    // test 4:check path from n8 to n0
+
+    // Test 1: check path from n0 to n6
+    std::vector<Ipv4Address>
+        pathToCheck1; // includes the source egress destination ingress and intermediate next hops
+                      // addresses that we need to check.It does not include the egress addresses
+                      // for intermediate nodes.
+    pathToCheck1.emplace_back("10.1.1.1");
+    pathToCheck1.emplace_back("10.1.1.2");
+    pathToCheck1.emplace_back("10.1.2.1");
+    pathToCheck1.emplace_back("172.16.1.2");
+
+    std::vector<Ptr<Node>>
+        pathNodes1; // nodes in the path. Includes the source node and the destination node.
+    pathNodes1.push_back(nodes.Get(0));
+    pathNodes1.push_back(nodes.Get(2));
+    pathNodes1.push_back(nodes.Get(1));
+    pathNodes1.push_back(nodes.Get(6));
+
+    CheckPath(pathNodes1, pathToCheck1);
+
+    // Test 2:check path from n1 to n5
+    std::vector<Ipv4Address> pathToCheck2;
+    pathToCheck2.emplace_back("10.1.2.1");
+    pathToCheck2.emplace_back("10.1.2.2");
+    pathToCheck2.emplace_back("10.250.1.4");
+
+    std::vector<Ptr<Node>> pathNodes2;
+    pathNodes2.push_back(nodes.Get(1));
+    pathNodes2.push_back(nodes.Get(2));
+    pathNodes2.push_back(nodes.Get(5));
+
+    CheckPath(pathNodes2, pathToCheck2);
+
+    // Test 3:check path from n1 to n9
+    std::vector<Ipv4Address> pathToCheck3;
+    pathToCheck3.emplace_back("172.16.1.1");
+    pathToCheck3.emplace_back("172.16.1.2");
+    pathToCheck3.emplace_back("10.1.4.2");
+    pathToCheck3.emplace_back("10.1.5.2");
+
+    std::vector<Ptr<Node>> pathNodes3;
+    pathNodes3.push_back(nodes.Get(1));
+    pathNodes3.push_back(nodes.Get(6));
+    pathNodes3.push_back(nodes.Get(7));
+    pathNodes3.push_back(nodes.Get(9));
+
+    CheckPath(pathNodes3, pathToCheck3);
+
+    // Test 4:check path from n9 to n0
+    std::vector<Ipv4Address> pathToCheck4;
+    pathToCheck4.emplace_back("10.1.5.2");
+    pathToCheck4.emplace_back("10.1.5.1");
+    pathToCheck4.emplace_back("10.1.4.1");
+    pathToCheck4.emplace_back("10.1.3.1");
+    pathToCheck4.emplace_back("10.250.1.1");
+    pathToCheck4.emplace_back("10.1.1.1");
+
+    std::vector<Ptr<Node>> pathNodes4;
+    pathNodes4.push_back(nodes.Get(9));
+    pathNodes4.push_back(nodes.Get(7));
+    pathNodes4.push_back(nodes.Get(6));
+    pathNodes4.push_back(nodes.Get(5));
+    pathNodes4.push_back(nodes.Get(2));
+    pathNodes4.push_back(nodes.Get(0));
+
+    CheckPath(pathNodes4, pathToCheck4);
+
+    Simulator::Run();
+    Simulator::Stop(Seconds(10));
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup internet-test
+ *
  * @brief IPv4 GlobalRouting TestSuite
  */
 class Ipv4GlobalRoutingTestSuite : public TestSuite
@@ -1298,6 +1782,8 @@
     AddTestCase(new TwoBridgeTest, TestCase::Duration::QUICK);
     AddTestCase(new Ipv4DynamicGlobalRoutingTestCase, TestCase::Duration::QUICK);
     AddTestCase(new Ipv4GlobalRoutingSlash32TestCase, TestCase::Duration::QUICK);
+    AddTestCase(new EcmpRouteCalculationTestCase, TestCase::Duration::QUICK);
+    AddTestCase(new GlobalRoutingProtocolTestCase, TestCase::Duration::QUICK);
 }
 
 static Ipv4GlobalRoutingTestSuite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/ipv4-raw-test.cc ns-3.46/src/internet/test/ipv4-raw-test.cc
--- ns-3.45/src/internet/test/ipv4-raw-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/ipv4-raw-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -5,15 +5,19 @@
  *
  * Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
  */
-/**
+/*
  * This is the test code for ipv4-raw-socket-impl.cc.
  */
 
 #include "ns3/arp-l3-protocol.h"
 #include "ns3/boolean.h"
+#include "ns3/core-module.h"
+#include "ns3/error-model.h"
 #include "ns3/icmpv4-l4-protocol.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv4-global-routing-helper.h"
 #include "ns3/ipv4-l3-protocol.h"
 #include "ns3/ipv4-list-routing.h"
 #include "ns3/ipv4-raw-socket-factory.h"
@@ -27,7 +31,6 @@
 #include "ns3/socket-factory.h"
 #include "ns3/socket.h"
 #include "ns3/test.h"
-
 #ifdef __WIN32__
 #include "ns3/win32-internet.h"
 #else
@@ -41,6 +44,185 @@
 
 using namespace ns3;
 
+NS_LOG_COMPONENT_DEFINE("ipv4-raw-fragmentation-test");
+
+/**
+ * @ingroup internet-test
+ *
+ * @brief IPv4 Raw Socket Fragmentation Test
+ * Configuration : Two sockets. 1 sender, 1 receiver
+ *                 Sender socket sends packets in two epochs.
+ *                 In the first epoch, it sends payload of sizes {500, 1000, 5000, 10000,
+ *                 20000, 40000, 60000}.
+ *                 In the second epoch, it sends payload of sizes {5000, 10000, 20000,
+ *                 40000, 60000}. These are payloads of size greater than the MTU of
+ *                 the link.
+ *                 In the first epoch, there is no loss model.
+ *                 In the second epoch, the second fragment of the packet sent is dropped.
+ *
+ * Expected behaviour: In the first epoch: Receiver should receive only 1 packet and the size of
+ *                     the payload received should be equal to the size of the payload sent.
+ *                     No packets should have been dropped.
+ *                     In the second epoch: Receiver should not receive any packet. Only 1 packet
+ *                     should have been dropped at the physical layer.
+ */
+class Ipv4RawFragmentationTest : public TestCase
+{
+  public:
+    Ipv4RawFragmentationTest();
+    void DoRun() override;
+
+  private:
+    /**
+     * @brief Send data to the receiver
+     * @param s The sending socket.
+     * @param sz Size of the packet.
+     */
+    void SendPacket(Ptr<Socket> s, uint32_t sz);
+
+    /**
+     * @brief Receive callback
+     * @param s The receiving socket.
+     */
+    void RxCallback(Ptr<Socket> s);
+
+    /**
+     * @brief Packet dropped callback at Phy Rx.
+     * @param p Dropped packet.
+     */
+    void PhyRxDropCallback(Ptr<const Packet> p);
+
+    uint32_t m_rxCount{0};          //!< Received packet count
+    uint32_t m_rxPayloadSize{0};    //!< Received packet size
+    uint32_t m_droppedFragments{0}; //!< Number of dropped fragments
+};
+
+Ipv4RawFragmentationTest::Ipv4RawFragmentationTest()
+    : TestCase("IPv4 raw fragmentation, fragment‑loss test")
+{
+}
+
+void
+Ipv4RawFragmentationTest::RxCallback(Ptr<Socket> s)
+{
+    Ptr<Packet> p = s->Recv();
+    Ipv4Header h;
+    if (p->PeekHeader(h))
+    {
+        p->RemoveHeader(h);
+    }
+    m_rxCount++;
+    m_rxPayloadSize = p->GetSize();
+    NS_LOG_DEBUG("Receiver got " << m_rxPayloadSize << " bytes");
+}
+
+void
+Ipv4RawFragmentationTest::PhyRxDropCallback(Ptr<const Packet> p)
+{
+    ++m_droppedFragments;
+}
+
+void
+Ipv4RawFragmentationTest::SendPacket(Ptr<Socket> socket, uint32_t size)
+{
+    Address realTo = InetSocketAddress(Ipv4Address("10.0.1.1"), 0);
+    Ptr<Packet> p = Create<Packet>(size);
+    socket->SendTo(p, 0, realTo);
+    NS_LOG_DEBUG("Sender sent " << p->GetSize() << " bytes to 10.0.1.1");
+}
+
+void
+Ipv4RawFragmentationTest::DoRun()
+{
+    Ptr<Node> rxNode = CreateObject<Node>();
+    Ptr<Node> txNode = CreateObject<Node>();
+
+    NodeContainer nodes(rxNode, txNode);
+
+    SimpleNetDeviceHelper helperChannel;
+    helperChannel.SetNetDevicePointToPointMode(true);
+    NetDeviceContainer net = helperChannel.Install(nodes);
+
+    net.Get(1)->SetMtu(1000);
+
+    InternetStackHelper internet;
+    internet.Install(nodes);
+
+    Ptr<Ipv4> ipv4;
+    uint32_t netdev_idx;
+    Ipv4InterfaceAddress ipv4Addr;
+
+    ipv4 = rxNode->GetObject<Ipv4>();
+    netdev_idx = ipv4->AddInterface(net.Get(0));
+    ipv4Addr = Ipv4InterfaceAddress(Ipv4Address("10.0.1.1"), Ipv4Mask(0xffff0000U));
+    ipv4->AddAddress(netdev_idx, ipv4Addr);
+    ipv4->SetUp(netdev_idx);
+
+    ipv4 = txNode->GetObject<Ipv4>();
+    netdev_idx = ipv4->AddInterface(net.Get(1));
+    ipv4Addr = Ipv4InterfaceAddress(Ipv4Address("10.0.1.2"), Ipv4Mask(0xffff0000U));
+    ipv4->AddAddress(netdev_idx, ipv4Addr);
+    ipv4->SetUp(netdev_idx);
+
+    net.Get(0)->TraceConnectWithoutContext(
+        "PhyRxDrop",
+        MakeCallback(&Ipv4RawFragmentationTest::PhyRxDropCallback, this));
+
+    Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<Ipv4RawSocketFactory>();
+    Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket();
+    rxSocket->Bind(InetSocketAddress(Ipv4Address::GetAny(), 0));
+    rxSocket->SetRecvCallback(MakeCallback(&Ipv4RawFragmentationTest::RxCallback, this));
+
+    Ptr<SocketFactory> txSocketFactory = txNode->GetObject<Ipv4RawSocketFactory>();
+    Ptr<Socket> txSocket = txSocketFactory->CreateSocket();
+
+    // Contains both Fragmentable and Non-fragmentable payload sizes
+    std::vector<uint32_t> payloadSizes = {500, 1000, 5000, 10000, 20000, 40000, 60000};
+
+    for (auto sentPayloadSize : payloadSizes)
+    {
+        m_rxCount = 0;
+        m_droppedFragments = 0;
+        m_rxPayloadSize = 0;
+        Simulator::Schedule(Seconds(1.0),
+                            &Ipv4RawFragmentationTest::SendPacket,
+                            this,
+                            txSocket,
+                            sentPayloadSize);
+        Simulator::Run();
+
+        NS_TEST_EXPECT_MSG_EQ(m_rxCount, 1, "Packet should be reassembled and be delivered");
+        NS_TEST_EXPECT_MSG_EQ(m_rxPayloadSize,
+                              sentPayloadSize,
+                              "Reassembled payload size must match the payload size sent");
+        NS_TEST_EXPECT_MSG_EQ(m_droppedFragments, 0, "No fragment must have been dropped");
+    }
+
+    std::vector<uint32_t> fragmentablePayloadSizes = {5000, 10000, 20000, 40000, 60000};
+
+    for (auto sentPayloadSize : fragmentablePayloadSizes)
+    {
+        m_rxCount = 0;
+        m_droppedFragments = 0;
+        Ptr<ReceiveListErrorModel> errModel = CreateObject<ReceiveListErrorModel>();
+        errModel->SetList({1});
+
+        net.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(errModel));
+
+        Simulator::Schedule(Seconds(1.0),
+                            &Ipv4RawFragmentationTest::SendPacket,
+                            this,
+                            txSocket,
+                            sentPayloadSize);
+        Simulator::Run();
+
+        NS_TEST_EXPECT_MSG_EQ(m_rxCount, 0, "Packet must not have been delivered");
+
+        NS_TEST_EXPECT_MSG_EQ(m_droppedFragments, 1, "One fragment must have been dropped");
+    }
+    Simulator::Destroy();
+}
+
 /**
  * @ingroup internet-test
  *
@@ -370,6 +552,7 @@
         : TestSuite("ipv4-raw", Type::UNIT)
     {
         AddTestCase(new Ipv4RawSocketImplTest, TestCase::Duration::QUICK);
+        AddTestCase(new Ipv4RawFragmentationTest, TestCase::Duration::QUICK);
     }
 };
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/ipv6-raw-test.cc ns-3.46/src/internet/test/ipv6-raw-test.cc
--- ns-3.45/src/internet/test/ipv6-raw-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/ipv6-raw-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -5,11 +5,12 @@
  *
  * Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
  */
-/**
+/*
  * This is the test code for ipv6-raw-socket-impl.cc.
  */
 
 #include "ns3/boolean.h"
+#include "ns3/error-model.h"
 #include "ns3/icmpv6-l4-protocol.h"
 #include "ns3/inet6-socket-address.h"
 #include "ns3/internet-stack-helper.h"
@@ -21,6 +22,7 @@
 #include "ns3/log.h"
 #include "ns3/node-container.h"
 #include "ns3/node.h"
+#include "ns3/pointer.h"
 #include "ns3/simple-channel.h"
 #include "ns3/simple-net-device-helper.h"
 #include "ns3/simple-net-device.h"
@@ -43,6 +45,198 @@
 
 using namespace ns3;
 
+NS_LOG_COMPONENT_DEFINE("ipv6-raw-fragmentation-test");
+
+/**
+ * @ingroup internet-test
+ *
+ * @brief IPv6 Raw Socket Fragmentation Test
+ * Configuration : Two sockets. 1 sender, 1 receiver
+ *                 Sender socket sends packets in two epochs.
+ *                 In the first epoch, it sends payload of sizes {500, 1000, 5000, 10000,
+ *                 20000, 40000, 60000}.
+ *                 In the second epoch, it sends payload of sizes {5000, 10000, 20000,
+ *                 40000, 60000}. These are payloads of size greater than the MTU of
+ *                 the link.
+ *                 In the first epoch, there is no loss model.
+ *                 In the second epoch, the second fragment of the packet sent is dropped.
+ *
+ * Expected behaviour: In the first epoch: Receiver should receive only 1 packet and the size of
+ *                     the payload received should be equal to the size of the payload sent.
+ *                     No packets should have been dropped.
+ *                     In the second epoch: Receiver should not receive any packet. Only 1 packet
+ *                     should have been dropped at the physical layer.
+ */
+class Ipv6RawFragmentationTest : public TestCase
+{
+  public:
+    Ipv6RawFragmentationTest();
+    void DoRun() override;
+
+  private:
+    /**
+     * @brief         Send a packet
+     * @param socket  The sending socket
+     * @param dst     Destination IPv6 address.
+     * @param size    Size (bytes) of the payload to send.
+     */
+    void SendPacket(Ptr<Socket> socket, Ipv6Address dst, uint32_t size);
+
+    /**
+     * @brief Receive a packet
+     * @param socket Socket that received a packet
+     */
+    void RxCallback(Ptr<Socket> socket);
+
+    /**
+     * @brief Packet dropped callback at Phy Rx.
+     * @param p Dropped packet.
+     */
+    void PhyRxDropCallback(Ptr<const Packet> p);
+
+    uint32_t m_rxCount{0};          //!< Total count of packets received.
+    uint32_t m_rxPayloadSize{0};    //!< Size of the last packet received.
+    uint32_t m_droppedFragments{0}; //!< Number of dropped packets
+};
+
+Ipv6RawFragmentationTest::Ipv6RawFragmentationTest()
+    : TestCase("ipv6-raw-fragmentation-test")
+{
+}
+
+void
+Ipv6RawFragmentationTest::RxCallback(Ptr<Socket> socket)
+{
+    Ptr<Packet> p = socket->Recv(std::numeric_limits<uint32_t>::max(), 0);
+
+    Ipv6Header hdr;
+    if (p->PeekHeader(hdr))
+    {
+        p->RemoveHeader(hdr);
+    }
+
+    m_rxPayloadSize = p->GetSize();
+    m_rxCount++;
+    NS_LOG_DEBUG("Receiver got " << m_rxPayloadSize << " bytes");
+}
+
+void
+Ipv6RawFragmentationTest::SendPacket(Ptr<Socket> sock, Ipv6Address dst, uint32_t size)
+{
+    Ptr<Packet> p = Create<Packet>(size);
+    sock->SendTo(p, 0, Inet6SocketAddress(dst, 0));
+    NS_LOG_DEBUG("Sender sent " << p->GetSize() << " bytes to " << dst);
+}
+
+void
+Ipv6RawFragmentationTest::PhyRxDropCallback(Ptr<const Packet> /*p*/)
+{
+    ++m_droppedFragments;
+}
+
+void
+Ipv6RawFragmentationTest::DoRun()
+{
+    Ptr<Node> rxNode = CreateObject<Node>();
+    Ptr<Node> txNode = CreateObject<Node>();
+
+    SimpleNetDeviceHelper helper;
+    helper.SetNetDevicePointToPointMode(true);
+
+    Ptr<SimpleNetDevice> rxDev = DynamicCast<SimpleNetDevice>(helper.Install(rxNode).Get(0));
+    Ptr<SimpleNetDevice> txDev = DynamicCast<SimpleNetDevice>(helper.Install(txNode).Get(0));
+
+    txDev->SetMtu(1280); // Minimum MTU allowed for IPv6
+
+    rxDev->TraceConnectWithoutContext(
+        "PhyRxDrop",
+        MakeCallback(&Ipv6RawFragmentationTest::PhyRxDropCallback, this));
+
+    Ptr<SimpleChannel> ch = CreateObject<SimpleChannel>();
+    rxDev->SetChannel(ch);
+    txDev->SetChannel(ch);
+
+    InternetStackHelper stack;
+    stack.SetIpv4StackInstall(false);
+    stack.Install(NodeContainer(rxNode, txNode));
+
+    rxNode->GetObject<Icmpv6L4Protocol>()->SetAttribute("DAD", BooleanValue(false));
+    txNode->GetObject<Icmpv6L4Protocol>()->SetAttribute("DAD", BooleanValue(false));
+
+    Ptr<Ipv6> ipv6Rx = rxNode->GetObject<Ipv6>();
+    Ptr<Ipv6> ipv6Tx = txNode->GetObject<Ipv6>();
+
+    uint32_t ifRx = ipv6Rx->AddInterface(rxDev);
+    ipv6Rx->AddAddress(ifRx, Ipv6InterfaceAddress("2001:db8::1", Ipv6Prefix(64)));
+    ipv6Rx->SetUp(ifRx);
+
+    uint32_t ifTx = ipv6Tx->AddInterface(txDev);
+    ipv6Tx->AddAddress(ifTx, Ipv6InterfaceAddress("2001:db8::2", Ipv6Prefix(64)));
+    ipv6Tx->SetUp(ifTx);
+
+    const uint8_t proto = Ipv6Header::IPV6_ICMPV6;
+
+    Ptr<Socket> rxSock = rxNode->GetObject<Ipv6RawSocketFactory>()->CreateSocket();
+    rxSock->SetAttribute("Protocol", UintegerValue(proto));
+    rxSock->Bind(Inet6SocketAddress(Ipv6Address::GetAny(), 0));
+    rxSock->SetRecvCallback(MakeCallback(&Ipv6RawFragmentationTest::RxCallback, this));
+
+    Ptr<Socket> txSock = txNode->GetObject<Ipv6RawSocketFactory>()->CreateSocket();
+    txSock->SetAttribute("Protocol", UintegerValue(proto));
+
+    std::vector<uint32_t> payloadSizes = {500, 1000, 5000, 10000, 20000, 40000, 60000};
+
+    for (auto sentPayloadSize : payloadSizes)
+    {
+        m_rxCount = 0;
+        m_rxPayloadSize = 0;
+
+        Simulator::Schedule(Seconds(0.0),
+                            &Ipv6RawFragmentationTest::SendPacket,
+                            this,
+                            txSock,
+                            Ipv6Address("2001:db8::1"),
+                            sentPayloadSize);
+        Simulator::Stop(Seconds(1.0));
+        Simulator::Run();
+
+        NS_TEST_EXPECT_MSG_EQ(m_rxPayloadSize,
+                              sentPayloadSize,
+                              "Reassembled packet size should be the same as the packet size sent");
+
+        NS_TEST_EXPECT_MSG_EQ(m_rxCount, 1, "Only 1 packet should have been received");
+
+        NS_TEST_EXPECT_MSG_EQ(m_droppedFragments, 0, "No packets should have been dropped");
+    }
+
+    std::vector<uint32_t> fragmentablePayloadSizes = {5000, 10000, 20000, 40000, 60000};
+
+    for (auto sentPayloadSize : fragmentablePayloadSizes)
+    {
+        m_rxCount = 0;
+        m_droppedFragments = 0;
+
+        Ptr<ReceiveListErrorModel> errModel = CreateObject<ReceiveListErrorModel>();
+        errModel->SetList({1});
+
+        rxDev->SetAttribute("ReceiveErrorModel", PointerValue(errModel));
+
+        Simulator::Schedule(Seconds(0.0),
+                            &Ipv6RawFragmentationTest::SendPacket,
+                            this,
+                            txSock,
+                            Ipv6Address("2001:db8::1"),
+                            sentPayloadSize);
+        Simulator::Stop(Seconds(1.0));
+        Simulator::Run();
+
+        NS_TEST_EXPECT_MSG_EQ(m_rxCount, 0, "No packet should have been received");
+
+        NS_TEST_EXPECT_MSG_EQ(m_droppedFragments, 1, "Exactly 1 packet should have been dropped.");
+    }
+    Simulator::Destroy();
+}
+
 /**
  * @ingroup internet-test
  *
@@ -322,6 +516,7 @@
         : TestSuite("ipv6-raw", Type::UNIT)
     {
         AddTestCase(new Ipv6RawSocketImplTest, TestCase::Duration::QUICK);
+        AddTestCase(new Ipv6RawFragmentationTest, TestCase::Duration::QUICK);
     }
 };
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/neighbor-cache-test.cc ns-3.46/src/internet/test/neighbor-cache-test.cc
--- ns-3.45/src/internet/test/neighbor-cache-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/neighbor-cache-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -6,6 +6,7 @@
  * Author: Zhiheng Dong <dzh2077@gmail.com>
  */
 
+#include "ns3/arp-cache.h"
 #include "ns3/icmpv4-l4-protocol.h"
 #include "ns3/icmpv6-l4-protocol.h"
 #include "ns3/internet-stack-helper.h"
@@ -15,6 +16,7 @@
 #include "ns3/ipv6-address-helper.h"
 #include "ns3/ipv6-l3-protocol.h"
 #include "ns3/ipv6-routing-helper.h"
+#include "ns3/ndisc-cache.h"
 #include "ns3/neighbor-cache-helper.h"
 #include "ns3/simple-channel.h"
 #include "ns3/simple-net-device-helper.h"
@@ -882,11 +884,42 @@
     std::ostringstream stringStream1v6;
     Ptr<OutputStreamWrapper> ndiscStream = Create<OutputStreamWrapper>(&stringStream1v6);
 
-    // Print cache.
+    // Print cache at time 0.
     Ipv4RoutingHelper::PrintNeighborCacheAllAt(Seconds(0), arpStream);
     Ipv6RoutingHelper::PrintNeighborCacheAllAt(Seconds(0), ndiscStream);
 
+    // Flush cache at time 1 s.
+    Simulator::Schedule(Seconds(1), &ArpCache::Flush, arpCache);
+    Simulator::Schedule(Seconds(1), &NdiscCache::Flush, ndiscCache);
+
+    // Print cache again at time 2 s.
+    std::ostringstream stringStream2v4;
+    Ptr<OutputStreamWrapper> arpStream2 = Create<OutputStreamWrapper>(&stringStream2v4);
+    std::ostringstream stringStream2v6;
+    Ptr<OutputStreamWrapper> ndiscStream2 = Create<OutputStreamWrapper>(&stringStream2v6);
+    Ipv4RoutingHelper::PrintNeighborCacheAllAt(Seconds(2), arpStream2);
+    Ipv6RoutingHelper::PrintNeighborCacheAllAt(Seconds(2), ndiscStream2);
+
+    // Add autogenerated entries at time 3 s again.
+    Simulator::Schedule(Seconds(3), [&neighborCache]() { neighborCache.PopulateNeighborCache(); });
+
+    // Flush cache again at time 4 s.
+    Simulator::Schedule(Seconds(4), &ArpCache::Flush, arpCache);
+    Simulator::Schedule(Seconds(4), &NdiscCache::Flush, ndiscCache);
+
+    // Print cache again at time 5 s.
+    // Check that the autogenerated entries survived the Flush
+    std::ostringstream stringStream5v4;
+    Ptr<OutputStreamWrapper> arpStream5 = Create<OutputStreamWrapper>(&stringStream5v4);
+    std::ostringstream stringStream5v6;
+    Ptr<OutputStreamWrapper> ndiscStream5 = Create<OutputStreamWrapper>(&stringStream5v6);
+    // Limit the printed output to node 0
+    Ipv4RoutingHelper::PrintNeighborCacheAt(Seconds(5), m_nodes.Get(0), arpStream5);
+    Ipv6RoutingHelper::PrintNeighborCacheAt(Seconds(5), m_nodes.Get(0), ndiscStream5);
+
     Simulator::Run();
+
+    // Check the time zero output
     // Check if the STATIC_AUTOGENERATED entries are flushed and the PERMANENT entry is left.
     constexpr auto ArpCache = "ARP Cache of node 0 at time 0\n"
                               "10.1.1.4 dev 0 lladdr 04-06-00:00:00:00:00:01 PERMANENT\n"
@@ -901,6 +934,38 @@
         "NDISC Cache of node 1 at time +0s\n"
         "NDISC Cache of node 2 at time +0s\n";
     NS_TEST_EXPECT_MSG_EQ(stringStream1v6.str(), NdiscCache, "Ndisc cache is incorrect.");
+
+    // Check output after the first flush-- should be empty
+    constexpr auto ArpCache2 = "ARP Cache of node 0 at time 2\n"
+                               "ARP Cache of node 1 at time 2\n"
+                               "ARP Cache of node 2 at time 2\n";
+    NS_TEST_EXPECT_MSG_EQ(stringStream2v4.str(),
+                          ArpCache2,
+                          "Arp cache is incorrect after Flush().");
+    constexpr auto NdiscCache2 = "NDISC Cache of node 0 at time +2s\n"
+                                 "NDISC Cache of node 1 at time +2s\n"
+                                 "NDISC Cache of node 2 at time +2s\n";
+    NS_TEST_EXPECT_MSG_EQ(stringStream2v6.str(),
+                          NdiscCache2,
+                          "Ndisc cache is incorrect after Flush().");
+
+    // Check output after the second flush-- node 0 should still have two
+    // static autogenerated entries for IPv6 and one for IPv4.
+    // This behavior was added in the ns-3.46 release (see issue #851).
+    constexpr auto ArpCache5 =
+        "ARP Cache of node 0 at time 5\n"
+        "10.1.1.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n";
+    constexpr auto NdiscCache5 =
+        "NDISC Cache of node 0 at time +5s\n"
+        "2001::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
+        "fe80::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n";
+    NS_TEST_EXPECT_MSG_EQ(stringStream5v4.str(),
+                          ArpCache5,
+                          "Arp cache is incorrect after second Flush().");
+    NS_TEST_EXPECT_MSG_EQ(stringStream5v6.str(),
+                          NdiscCache5,
+                          "Ndisc cache is incorrect after second Flush().");
+
     Simulator::Destroy();
 }
 
@@ -975,7 +1040,8 @@
     Ipv6RoutingHelper::PrintNeighborCacheAllAt(Seconds(0), ndiscStream);
 
     Simulator::Run();
-    // Check if the STATIC_AUTOGENERATED entries are flushed and the PERMANENT entry is left.
+    // Check if the overlapped scope of PopulateNeighborCache() calls did
+    // not lead to duplicate entries.
     constexpr auto ArpCache =
         "ARP Cache of node 0 at time 0\n"
         "10.1.1.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
@@ -986,7 +1052,8 @@
         "10.1.2.1 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n";
     NS_TEST_EXPECT_MSG_EQ(stringStream1v4.str(), ArpCache, "Arp cache is incorrect.");
 
-    // Check if the STATIC_AUTOGENERATED entries are flushed and the PERMANENT entry is left.
+    // Check if the overlapped scope of PopulateNeighborCache() calls did
+    // not lead to duplicate entries.
     constexpr auto NdiscCache =
         "NDISC Cache of node 0 at time +0s\n"
         "2001::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/tcp-advertised-window-test.cc ns-3.46/src/internet/test/tcp-advertised-window-test.cc
--- ns-3.45/src/internet/test/tcp-advertised-window-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/tcp-advertised-window-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -52,7 +52,7 @@
         : TcpSocketMsgBase(other)
     {
         m_segmentSize = other.m_segmentSize;
-        m_inwalidAwndCb = other.m_inwalidAwndCb;
+        m_invalidAwndCb = other.m_invalidAwndCb;
     }
 
     /**
@@ -78,7 +78,7 @@
 
   private:
     uint16_t OldAdvertisedWindowSize(bool scale = true) const;
-    InvalidAwndCallback m_inwalidAwndCb; //!< Callback
+    InvalidAwndCallback m_invalidAwndCb; //!< Callback
 
     /**
      * @brief Test meta-information: size of the segments that are received.
@@ -93,7 +93,7 @@
 TcpSocketAdvertisedWindowProxy::SetInvalidAwndCb(InvalidAwndCallback cb)
 {
     NS_ASSERT(!cb.IsNull());
-    m_inwalidAwndCb = cb;
+    m_invalidAwndCb = cb;
 }
 
 TypeId
@@ -148,9 +148,9 @@
 
             if (static_cast<uint16_t>(newAwndKnownDifference) != oldAwnd)
             {
-                if (!m_inwalidAwndCb.IsNull())
+                if (!m_invalidAwndCb.IsNull())
                 {
-                    m_inwalidAwndCb(oldAwnd, newAwnd);
+                    m_invalidAwndCb(oldAwnd, newAwnd);
                 }
             }
         }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/tcp-pacing-test.cc ns-3.46/src/internet/test/tcp-pacing-test.cc
--- ns-3.45/src/internet/test/tcp-pacing-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/tcp-pacing-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -242,7 +242,7 @@
 TcpPacingTest::UpdateExpectedInterval()
 {
     double_t factor;
-    Time rtt = 2 * GetPropagationDelay();
+
     if (m_curCwnd < m_ssThresh / 2)
     {
         factor = static_cast<double>(m_pacingSsRatio) / 100;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet/test/tcp-rate-ops-test.cc ns-3.46/src/internet/test/tcp-rate-ops-test.cc
--- ns-3.45/src/internet/test/tcp-rate-ops-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet/test/tcp-rate-ops-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -569,8 +569,7 @@
                             MakeCallback(&TcpRateOps::SkbDelivered, m_rateOps));
     }
     m_expectedAckedSacked = 5 * m_segmentSize;
-    TcpRateOps::TcpRateSample rateSample =
-        m_rateOps->GenerateSample(5 * m_segmentSize, 0, false, priorInFlight, Seconds(0));
+    m_rateOps->GenerateSample(5 * m_segmentSize, 0, false, priorInFlight, Seconds(0));
 }
 
 void
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet-apps/test/dhcp6-test.cc ns-3.46/src/internet-apps/test/dhcp6-test.cc
--- ns-3.45/src/internet-apps/test/dhcp6-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet-apps/test/dhcp6-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -29,8 +29,6 @@
 #include "ns3/ssid.h"
 #include "ns3/test.h"
 #include "ns3/trace-helper.h"
-#include "ns3/wifi-helper.h"
-#include "ns3/yans-wifi-helper.h"
 
 using namespace ns3;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/internet-apps/test/ping-test.cc ns-3.46/src/internet-apps/test/ping-test.cc
--- ns-3.45/src/internet-apps/test/ping-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/internet-apps/test/ping-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -605,7 +605,7 @@
     testcase2v4->SetSimulatorStopTime(Seconds(5));
     testcase2v4->CheckReportTransmitted(1);
     testcase2v4->CheckReportReceived(0);
-    testcase1v4->SetDestinationAddress(Ipv4Address("10.0.0.2"));
+    testcase2v4->SetDestinationAddress(Ipv4Address("10.0.0.2"));
     AddTestCase(testcase2v4, TestCase::Duration::QUICK);
 
     auto testcase2v6 = new PingTestCase(
@@ -697,8 +697,8 @@
     // 5. Test for behavior of pinging an unreachable host when the
     //    network does not send an ICMP unreachable message.
     // Unlimited pings, StopApplication () with no packet in flight
-    // Configuration:  Ping::Count = 0,  Ping start time = 1s
-    //                 Ping stop time = 5.5s.  Ping to unknown destination.
+    // Configuration:  Ping::Count = 5,  Ping start time = 1s
+    //                 Ping stop time = 6.5s.  Ping to unknown destination.
     // Expected behavior:  By default, the timeout value is 1 second.  Ping
     //                     sends first packet at time 1 second, and does not
     //                     receive a response.  At the timeout (simulation time
@@ -900,30 +900,39 @@
     testcase9v6->CheckReportTime(MicroSeconds(3040000));
     AddTestCase(testcase9v6, TestCase::Duration::QUICK);
 
-#ifdef NOTYET
-    //
-    // 10. Test for behavior of pinging on a link that causes IPv4 fragmentation
-    // Configuration:  Ping::Count = 1,  Ping start time = 1s
-    //                 Ping stop time = 2.5s.  Ping to Node 1
-    //                 Ping size set to 2000 bytes.
-    // Expected behavior:  At shortly after time 1 seconds, Ping should
-    //                     successfully exit by recording the successful
-    //                     exchange of one echo request and reply.
-    // How validated:  PingReport trace is checked for number of packets
-    //                 transmitted (5) and  received (0).
-    //                 PingReport time is checked for an explicit time
-    //                 (1.020028s) corresponding to 2000 bytes
-    //                 The packet loss rate should be checked to be 100 percent
-    PingTestCase* testcase10v4 = new PingTestCase("10. Test for IPv4 fragmentation", USEIPV6_FALSE);
+    // 10. Test for behavior of pinging with a big size that causes fragmentation
+    //    Configuration:  Ping::Count = 5,  Ping::Interval = 1s, Ping start
+    //                    time = 1s, Ping stop time = 6.5s,
+    //                    Payload size = 60000B
+    //    Expected behavior:  Pings are sent at times 1, 2, 3, 4, 5 sec.  The
+    //                        number sent equals number received, which equals 5.
+    //    How validated:  PingReport trace is checked for number of packets
+    //                    transmitted and received (5), and number of drops (0).
+    auto testcase10v4 = new PingTestCase("10. 5 pings, heavy payload, no losses, "
+                                         "StopApplication () with no packets in flight IPv4",
+                                         USEIPV6_FALSE);
     testcase10v4->SetStartTime(Seconds(1));
-    testcase10v4->SetStopTime(Seconds(2.5));
-    testcase10v4->SetCount(1);
-    testcase10v4->SetSize(2000);
-    testcase10v4->CheckReportTransmitted(1);
-    testcase10v4->CheckReportReceived(1);
-    testcase10v4->CheckReportTime(MicroSeconds(1020028));
+    testcase10v4->SetStopTime(Seconds(6.5));
+    testcase10v4->SetCount(5);
+    testcase10v4->SetSize(60000);
+    testcase10v4->CheckReportTransmitted(5);
+    testcase10v4->CheckReportReceived(5);
+    testcase10v4->CheckTraceTx(5);
+    testcase10v4->SetDestinationAddress(Ipv4Address("10.0.0.2"));
     AddTestCase(testcase10v4, TestCase::Duration::QUICK);
-#endif
+
+    auto testcase10v6 = new PingTestCase("10. 5 pings, heavy payload,  no losses, "
+                                         "StopApplication () with no packets in flight IPv6",
+                                         USEIPV6_TRUE);
+    testcase10v6->SetStartTime(Seconds(1));
+    testcase10v6->SetStopTime(Seconds(6.5));
+    testcase10v6->SetCount(5);
+    testcase10v6->SetSize(60000);
+    testcase10v6->CheckReportTransmitted(5);
+    testcase10v6->CheckReportReceived(5);
+    testcase10v6->CheckTraceTx(5);
+    testcase10v6->SetDestinationAddress(Ipv6Address("2001:1::200:ff:fe00:2"));
+    AddTestCase(testcase10v6, TestCase::Duration::QUICK);
 }
 
 static PingTestSuite pingTestSuite; //!< Static variable for test initialization
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/802-15-4-ber.eps ns-3.46/src/lr-wpan/doc/802-15-4-ber.eps
--- ns-3.45/src/lr-wpan/doc/802-15-4-ber.eps	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/doc/802-15-4-ber.eps	1969-12-31 16:00:00.000000000 -0800
@@ -1,1030 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0
-%%Title: 802.15.4-ber.eps
-%%Creator: gnuplot 4.4 patchlevel 2
-%%CreationDate: Tue Oct  4 14:51:04 2011
-%%DocumentFonts: (atend)
-%%BoundingBox: 50 50 410 302
-%%EndComments
-%%BeginProlog
-/gnudict 256 dict def
-gnudict begin
-%
-% The following true/false flags may be edited by hand if desired.
-% The unit line width and grayscale image gamma correction may also be changed.
-%
-/Color true def
-/Blacktext false def
-/Solid false def
-/Dashlength 1 def
-/Landscape false def
-/Level1 false def
-/Rounded false def
-/ClipToBoundingBox false def
-/TransparentPatterns false def
-/gnulinewidth 5.000 def
-/userlinewidth gnulinewidth def
-/Gamma 1.0 def
-%
-/vshift -46 def
-/dl1 {
-  10.0 Dashlength mul mul
-  Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if
-} def
-/dl2 {
-  10.0 Dashlength mul mul
-  Rounded { currentlinewidth 0.75 mul add } if
-} def
-/hpt_ 31.5 def
-/vpt_ 31.5 def
-/hpt hpt_ def
-/vpt vpt_ def
-Level1 {} {
-/SDict 10 dict def
-systemdict /pdfmark known not {
-  userdict /pdfmark systemdict /cleartomark get put
-} if
-SDict begin [
-  /Title (802.15.4-ber.eps)
-  /Subject (gnuplot plot)
-  /Creator (gnuplot 4.4 patchlevel 2)
-  /Author (tomh)
-%  /Producer (gnuplot)
-%  /Keywords ()
-  /CreationDate (Tue Oct  4 14:51:04 2011)
-  /DOCINFO pdfmark
-end
-} ifelse
-/doclip {
-  ClipToBoundingBox {
-    newpath 50 50 moveto 410 50 lineto 410 302 lineto 50 302 lineto closepath
-    clip
-  } if
-} def
-%
-% Gnuplot Prolog Version 4.4 (August 2010)
-%
-%/SuppressPDFMark true def
-%
-/M {moveto} bind def
-/L {lineto} bind def
-/R {rmoveto} bind def
-/V {rlineto} bind def
-/N {newpath moveto} bind def
-/Z {closepath} bind def
-/C {setrgbcolor} bind def
-/f {rlineto fill} bind def
-/g {setgray} bind def
-/Gshow {show} def   % May be redefined later in the file to support UTF-8
-/vpt2 vpt 2 mul def
-/hpt2 hpt 2 mul def
-/Lshow {currentpoint stroke M 0 vshift R 
-	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
-/Rshow {currentpoint stroke M dup stringwidth pop neg vshift R
-	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
-/Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R 
-	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
-/UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def
-  /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def
-/DL {Color {setrgbcolor Solid {pop []} if 0 setdash}
- {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def
-/BL {stroke userlinewidth 2 mul setlinewidth
-	Rounded {1 setlinejoin 1 setlinecap} if} def
-/AL {stroke userlinewidth 2 div setlinewidth
-	Rounded {1 setlinejoin 1 setlinecap} if} def
-/UL {dup gnulinewidth mul /userlinewidth exch def
-	dup 1 lt {pop 1} if 10 mul /udl exch def} def
-/PL {stroke userlinewidth setlinewidth
-	Rounded {1 setlinejoin 1 setlinecap} if} def
-3.8 setmiterlimit
-% Default Line colors
-/LCw {1 1 1} def
-/LCb {0 0 0} def
-/LCa {0 0 0} def
-/LC0 {1 0 0} def
-/LC1 {0 1 0} def
-/LC2 {0 0 1} def
-/LC3 {1 0 1} def
-/LC4 {0 1 1} def
-/LC5 {1 1 0} def
-/LC6 {0 0 0} def
-/LC7 {1 0.3 0} def
-/LC8 {0.5 0.5 0.5} def
-% Default Line Types
-/LTw {PL [] 1 setgray} def
-/LTb {BL [] LCb DL} def
-/LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def
-/LT0 {PL [] LC0 DL} def
-/LT1 {PL [4 dl1 2 dl2] LC1 DL} def
-/LT2 {PL [2 dl1 3 dl2] LC2 DL} def
-/LT3 {PL [1 dl1 1.5 dl2] LC3 DL} def
-/LT4 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def
-/LT5 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC5 DL} def
-/LT6 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC6 DL} def
-/LT7 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC7 DL} def
-/LT8 {PL [2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 4 dl2] LC8 DL} def
-/Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def
-/Dia {stroke [] 0 setdash 2 copy vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V closepath stroke
-  Pnt} def
-/Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V
-  currentpoint stroke M
-  hpt neg vpt neg R hpt2 0 V stroke
- } def
-/Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V closepath stroke
-  Pnt} def
-/Crs {stroke [] 0 setdash exch hpt sub exch vpt add M
-  hpt2 vpt2 neg V currentpoint stroke M
-  hpt2 neg 0 R hpt2 vpt2 V stroke} def
-/TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V closepath stroke
-  Pnt} def
-/Star {2 copy Pls Crs} def
-/BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V closepath fill} def
-/TriUF {stroke [] 0 setdash vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V closepath fill} def
-/TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V closepath stroke
-  Pnt} def
-/TriDF {stroke [] 0 setdash vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V closepath fill} def
-/DiaF {stroke [] 0 setdash vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V closepath fill} def
-/Pent {stroke [] 0 setdash 2 copy gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  closepath stroke grestore Pnt} def
-/PentF {stroke [] 0 setdash gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  closepath fill grestore} def
-/Circle {stroke [] 0 setdash 2 copy
-  hpt 0 360 arc stroke Pnt} def
-/CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def
-/C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def
-/C1 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 90 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C2 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 90 180 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C3 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 180 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C4 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 180 270 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C5 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 90 arc
-	2 copy moveto
-	2 copy vpt 180 270 arc closepath fill
-	vpt 0 360 arc} bind def
-/C6 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 90 270 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C7 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 270 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C8 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 270 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C9 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 270 450 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill
-	2 copy moveto
-	2 copy vpt 90 180 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C11 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 180 arc closepath fill
-	2 copy moveto
-	2 copy vpt 270 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C12 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 180 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C13 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 90 arc closepath fill
-	2 copy moveto
-	2 copy vpt 180 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C14 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 90 360 arc closepath fill
-	vpt 0 360 arc} bind def
-/C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
-	neg 0 rlineto closepath} bind def
-/Square {dup Rec} bind def
-/Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def
-/S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def
-/S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def
-/S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
-/S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def
-/S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
-/S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill
-	exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
-/S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def
-/S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill
-	2 copy vpt Square fill Bsquare} bind def
-/S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def
-/S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def
-/S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill
-	Bsquare} bind def
-/S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill
-	Bsquare} bind def
-/S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def
-/S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
-	2 copy vpt Square fill Bsquare} bind def
-/S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
-	2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
-/S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def
-/D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def
-/D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def
-/D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def
-/D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def
-/D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def
-/D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def
-/D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def
-/D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def
-/D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def
-/D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def
-/D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def
-/D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def
-/D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def
-/D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def
-/D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def
-/D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def
-/DiaE {stroke [] 0 setdash vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V closepath stroke} def
-/BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V closepath stroke} def
-/TriUE {stroke [] 0 setdash vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V closepath stroke} def
-/TriDE {stroke [] 0 setdash vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V closepath stroke} def
-/PentE {stroke [] 0 setdash gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  closepath stroke grestore} def
-/CircE {stroke [] 0 setdash 
-  hpt 0 360 arc stroke} def
-/Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def
-/DiaW {stroke [] 0 setdash vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V Opaque stroke} def
-/BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V Opaque stroke} def
-/TriUW {stroke [] 0 setdash vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V Opaque stroke} def
-/TriDW {stroke [] 0 setdash vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V Opaque stroke} def
-/PentW {stroke [] 0 setdash gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  Opaque stroke grestore} def
-/CircW {stroke [] 0 setdash 
-  hpt 0 360 arc Opaque stroke} def
-/BoxFill {gsave Rec 1 setgray fill grestore} def
-/Density {
-  /Fillden exch def
-  currentrgbcolor
-  /ColB exch def /ColG exch def /ColR exch def
-  /ColR ColR Fillden mul Fillden sub 1 add def
-  /ColG ColG Fillden mul Fillden sub 1 add def
-  /ColB ColB Fillden mul Fillden sub 1 add def
-  ColR ColG ColB setrgbcolor} def
-/BoxColFill {gsave Rec PolyFill} def
-/PolyFill {gsave Density fill grestore grestore} def
-/h {rlineto rlineto rlineto gsave closepath fill grestore} bind def
-%
-% PostScript Level 1 Pattern Fill routine for rectangles
-% Usage: x y w h s a XX PatternFill
-%	x,y = lower left corner of box to be filled
-%	w,h = width and height of box
-%	  a = angle in degrees between lines and x-axis
-%	 XX = 0/1 for no/yes cross-hatch
-%
-/PatternFill {gsave /PFa [ 9 2 roll ] def
-  PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate
-  PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec
-  gsave 1 setgray fill grestore clip
-  currentlinewidth 0.5 mul setlinewidth
-  /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def
-  0 0 M PFa 5 get rotate PFs -2 div dup translate
-  0 1 PFs PFa 4 get div 1 add floor cvi
-	{PFa 4 get mul 0 M 0 PFs V} for
-  0 PFa 6 get ne {
-	0 1 PFs PFa 4 get div 1 add floor cvi
-	{PFa 4 get mul 0 2 1 roll M PFs 0 V} for
- } if
-  stroke grestore} def
-%
-/languagelevel where
- {pop languagelevel} {1} ifelse
- 2 lt
-	{/InterpretLevel1 true def}
-	{/InterpretLevel1 Level1 def}
- ifelse
-%
-% PostScript level 2 pattern fill definitions
-%
-/Level2PatternFill {
-/Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8}
-	bind def
-/KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} 
->> matrix makepattern
-/Pat1 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke
-	0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke}
->> matrix makepattern
-/Pat2 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L
-	8 8 L 8 0 L 0 0 L fill}
->> matrix makepattern
-/Pat3 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L
-	0 12 M 12 0 L stroke}
->> matrix makepattern
-/Pat4 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L
-	0 -4 M 12 8 L stroke}
->> matrix makepattern
-/Pat5 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L
-	0 12 M 8 -4 L 4 12 M 10 0 L stroke}
->> matrix makepattern
-/Pat6 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L
-	0 -4 M 8 12 L 4 -4 M 10 8 L stroke}
->> matrix makepattern
-/Pat7 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L
-	12 0 M -4 8 L 12 4 M 0 10 L stroke}
->> matrix makepattern
-/Pat8 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L
-	-4 0 M 12 8 L -4 4 M 8 10 L stroke}
->> matrix makepattern
-/Pat9 exch def
-/Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def
-/Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def
-/Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def
-/Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def
-/Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def
-/Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def
-/Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def
-} def
-%
-%
-%End of PostScript Level 2 code
-%
-/PatternBgnd {
-  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
-} def
-%
-% Substitute for Level 2 pattern fill codes with
-% grayscale if Level 2 support is not selected.
-%
-/Level1PatternFill {
-/Pattern1 {0.250 Density} bind def
-/Pattern2 {0.500 Density} bind def
-/Pattern3 {0.750 Density} bind def
-/Pattern4 {0.125 Density} bind def
-/Pattern5 {0.375 Density} bind def
-/Pattern6 {0.625 Density} bind def
-/Pattern7 {0.875 Density} bind def
-} def
-%
-% Now test for support of Level 2 code
-%
-Level1 {Level1PatternFill} {Level2PatternFill} ifelse
-%
-/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont
-dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall
-currentdict end definefont pop
-/MFshow {
-   { dup 5 get 3 ge
-     { 5 get 3 eq {gsave} {grestore} ifelse }
-     {dup dup 0 get findfont exch 1 get scalefont setfont
-     [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6
-     get exch 4 get {Gshow} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq
-     {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5
-     get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div
-     dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get
-     show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop
-     pop aload pop M} ifelse }ifelse }ifelse }
-     ifelse }
-   forall} def
-/Gswidth {dup type /stringtype eq {stringwidth} {pop (n) stringwidth} ifelse} def
-/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }
- {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont
-     6 get Gswidth pop add} {pop} ifelse} ifelse} forall} def
-/MLshow { currentpoint stroke M
-  0 exch R
-  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
-/MRshow { currentpoint stroke M
-  exch dup MFwidth neg 3 -1 roll R
-  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
-/MCshow { currentpoint stroke M
-  exch dup MFwidth -2 div 3 -1 roll R
-  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
-/XYsave    { [( ) 1 2 true false 3 ()] } bind def
-/XYrestore { [( ) 1 2 true false 4 ()] } bind def
-end
-%%EndProlog
-gnudict begin
-gsave
-doclip
-50 50 translate
-0.050 0.050 scale
-0 setgray
-newpath
-(Times-BoldItalic) findfont 140 scalefont setfont
-1.000 UL
-LTb
-1.000 UL
-LTa
-938 448 M
-6009 0 V
-stroke
-LTb
-938 448 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 448 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-09)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 596 M
-31 0 V
-5978 0 R
--31 0 V
-938 792 M
-31 0 V
-5978 0 R
--31 0 V
-938 892 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 939 M
-6009 0 V
-stroke
-LTb
-938 939 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 939 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-08)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 1087 M
-31 0 V
-5978 0 R
--31 0 V
-938 1283 M
-31 0 V
-5978 0 R
--31 0 V
-938 1383 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 1431 M
-6009 0 V
-stroke
-LTb
-938 1431 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 1431 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-07)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 1579 M
-31 0 V
-5978 0 R
--31 0 V
-938 1774 M
-31 0 V
-5978 0 R
--31 0 V
-938 1875 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 1922 M
-6009 0 V
-stroke
-LTb
-938 1922 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 1922 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-06)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 2070 M
-31 0 V
-5978 0 R
--31 0 V
-938 2266 M
-31 0 V
-5978 0 R
--31 0 V
-938 2366 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 2414 M
-6009 0 V
-stroke
-LTb
-938 2414 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 2414 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-05)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 2562 M
-31 0 V
-5978 0 R
--31 0 V
-938 2757 M
-31 0 V
-5978 0 R
--31 0 V
-938 2858 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 2905 M
-6009 0 V
-stroke
-LTb
-938 2905 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 2905 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.0001)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 3053 M
-31 0 V
-5978 0 R
--31 0 V
-938 3249 M
-31 0 V
-5978 0 R
--31 0 V
-938 3349 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 3397 M
-6009 0 V
-stroke
-LTb
-938 3397 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 3397 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.001)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 3545 M
-31 0 V
-5978 0 R
--31 0 V
-938 3740 M
-31 0 V
-5978 0 R
--31 0 V
-938 3840 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 3888 M
-6009 0 V
-stroke
-LTb
-938 3888 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 3888 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.01)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 4036 M
-31 0 V
-5978 0 R
--31 0 V
-938 4232 M
-31 0 V
-5978 0 R
--31 0 V
-938 4332 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 4380 M
-6009 0 V
-stroke
-LTb
-938 4380 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 4380 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.1)]
-] -46.7 MRshow
-1.000 UL
-LTb
-938 4527 M
-31 0 V
-5978 0 R
--31 0 V
-938 4723 M
-31 0 V
-5978 0 R
--31 0 V
-938 4823 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-LTa
-938 4871 M
-6009 0 V
-stroke
-LTb
-938 4871 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 4871 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1)]
-] -46.7 MRshow
-1.000 UL
-LTb
-1.000 UL
-LTa
-938 448 M
-0 4423 V
-stroke
-LTb
-938 448 M
-0 63 V
-0 4360 R
-0 -63 V
-stroke
-938 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-10)]
-] -46.7 MCshow
-1.000 UL
-LTb
-1.000 UL
-LTa
-2140 448 M
-0 4423 V
-stroke
-LTb
-2140 448 M
-0 63 V
-0 4360 R
-0 -63 V
-stroke
-2140 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-5)]
-] -46.7 MCshow
-1.000 UL
-LTb
-1.000 UL
-LTa
-3342 448 M
-0 4423 V
-stroke
-LTb
-3342 448 M
-0 63 V
-0 4360 R
-0 -63 V
-stroke
-3342 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0)]
-] -46.7 MCshow
-1.000 UL
-LTb
-1.000 UL
-LTa
-4543 448 M
-0 4423 V
-stroke
-LTb
-4543 448 M
-0 63 V
-0 4360 R
-0 -63 V
-stroke
-4543 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 5)]
-] -46.7 MCshow
-1.000 UL
-LTb
-1.000 UL
-LTa
-5745 448 M
-0 4220 V
-0 140 R
-0 63 V
-stroke
-LTb
-5745 448 M
-0 63 V
-0 4360 R
-0 -63 V
-stroke
-5745 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 10)]
-] -46.7 MCshow
-1.000 UL
-LTb
-1.000 UL
-LTa
-6947 448 M
-0 4423 V
-stroke
-LTb
-6947 448 M
-0 63 V
-0 4360 R
-0 -63 V
-stroke
-6947 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 15)]
-] -46.7 MCshow
-1.000 UL
-LTb
-1.000 UL
-LTb
-938 4871 N
-938 448 L
-6009 0 V
-0 4423 V
--6009 0 V
-Z stroke
-LCb setrgbcolor
-112 2659 M
-currentpoint gsave translate -270 rotate 0 0 moveto
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Bit Error Rate \(BER\))]
-] -46.7 MCshow
-grestore
-LTb
-LCb setrgbcolor
-3942 98 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (SNR \(dB\))]
-] -46.7 MCshow
-LTb
-1.000 UP
-1.000 UL
-LTb
-% Begin plot #1
-5.000 UL
-LT0
-LCb setrgbcolor
-6296 4738 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (802.15.4)]
-] -46.7 MRshow
-LT0
-6380 4738 M
-399 0 V
-938 4629 M
-24 -3 V
-24 -2 V
-24 -3 V
-24 -3 V
-24 -3 V
-24 -3 V
-24 -4 V
-24 -3 V
-24 -3 V
-24 -4 V
-24 -3 V
-24 -4 V
-24 -4 V
-25 -4 V
-24 -4 V
-24 -4 V
-24 -5 V
-24 -4 V
-24 -5 V
-24 -5 V
-24 -5 V
-24 -5 V
-24 -5 V
-24 -6 V
-24 -5 V
-24 -6 V
-24 -6 V
-24 -6 V
-24 -6 V
-24 -7 V
-24 -6 V
-24 -7 V
-24 -7 V
-24 -8 V
-24 -7 V
-24 -8 V
-24 -8 V
-24 -8 V
-24 -9 V
-24 -9 V
-24 -9 V
-25 -9 V
-24 -10 V
-24 -9 V
-24 -11 V
-24 -10 V
-24 -11 V
-24 -11 V
-24 -12 V
-24 -11 V
-24 -13 V
-24 -12 V
-24 -13 V
-24 -13 V
-24 -14 V
-24 -14 V
-24 -14 V
-24 -15 V
-24 -16 V
-24 -16 V
-24 -16 V
-24 -17 V
-24 -17 V
-24 -17 V
-24 -19 V
-24 -18 V
-24 -20 V
-24 -20 V
-24 -20 V
-25 -21 V
-24 -22 V
-24 -22 V
-24 -23 V
-24 -23 V
-24 -24 V
-24 -25 V
-24 -26 V
-24 -26 V
-24 -27 V
-24 -28 V
-24 -28 V
-24 -29 V
-24 -30 V
-24 -31 V
-24 -32 V
-24 -32 V
-24 -34 V
-24 -34 V
-24 -35 V
-24 -37 V
-24 -37 V
-24 -38 V
-24 -39 V
-24 -40 V
-24 -42 V
-24 -42 V
-24 -43 V
-25 -45 V
-24 -46 V
-24 -46 V
-24 -49 V
-24 -49 V
-stroke 3390 2910 M
-24 -50 V
-24 -52 V
-24 -53 V
-24 -55 V
-24 -56 V
-24 -57 V
-24 -59 V
-24 -60 V
-24 -61 V
-24 -63 V
-24 -65 V
-24 -66 V
-24 -68 V
-24 -70 V
-24 -71 V
-24 -73 V
-24 -75 V
-24 -76 V
-24 -78 V
-24 -81 V
-24 -82 V
-24 -84 V
-25 -86 V
-24 -88 V
-24 -90 V
-24 -93 V
-24 -94 V
-24 -97 V
-24 -99 V
-24 -101 V
-24 -104 V
-24 -106 V
-11 -49 V
-% End plot #1
-stroke
-1.000 UL
-LTb
-938 4871 N
-938 448 L
-6009 0 V
-0 4423 V
--6009 0 V
-Z stroke
-1.000 UP
-1.000 UL
-LTb
-stroke
-grestore
-end
-showpage
-%%Trailer
-%%DocumentFonts: Times-BoldItalic
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/802-15-4-per-sens.eps ns-3.46/src/lr-wpan/doc/802-15-4-per-sens.eps
--- ns-3.45/src/lr-wpan/doc/802-15-4-per-sens.eps	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/doc/802-15-4-per-sens.eps	1969-12-31 16:00:00.000000000 -0800
@@ -1,2690 +0,0 @@
-%!PS-Adobe-2.0 EPSF-2.0
-%%Title: 802.15.4-per-vs-rxSignal.eps
-%%Creator: gnuplot 5.2 patchlevel 8
-%%CreationDate: Mon Dec 19 13:38:56 2022
-%%DocumentFonts: (atend)
-%%BoundingBox: 50 50 410 302
-%%EndComments
-%%BeginProlog
-/gnudict 256 dict def
-gnudict begin
-%
-% The following true/false flags may be edited by hand if desired.
-% The unit line width and grayscale image gamma correction may also be changed.
-%
-/Color true def
-/Blacktext false def
-/Solid false def
-/Dashlength 1 def
-/Landscape false def
-/Level1 false def
-/Level3 false def
-/Rounded false def
-/ClipToBoundingBox false def
-/SuppressPDFMark false def
-/TransparentPatterns false def
-/gnulinewidth 5.000 def
-/userlinewidth gnulinewidth def
-/Gamma 1.0 def
-/BackgroundColor {-1.000 -1.000 -1.000} def
-%
-/vshift -46 def
-/dl1 {
-  10.0 Dashlength userlinewidth gnulinewidth div mul mul mul
-  Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if
-} def
-/dl2 {
-  10.0 Dashlength userlinewidth gnulinewidth div mul mul mul
-  Rounded { currentlinewidth 0.75 mul add } if
-} def
-/hpt_ 31.5 def
-/vpt_ 31.5 def
-/hpt hpt_ def
-/vpt vpt_ def
-/doclip {
-  ClipToBoundingBox {
-    newpath 50 50 moveto 410 50 lineto 410 302 lineto 50 302 lineto closepath
-    clip
-  } if
-} def
-%
-% Gnuplot Prolog Version 5.2 (Dec 2017)
-%
-%/SuppressPDFMark true def
-%
-/M {moveto} bind def
-/L {lineto} bind def
-/R {rmoveto} bind def
-/V {rlineto} bind def
-/N {newpath moveto} bind def
-/Z {closepath} bind def
-/C {setrgbcolor} bind def
-/f {rlineto fill} bind def
-/g {setgray} bind def
-/Gshow {show} def   % May be redefined later in the file to support UTF-8
-/vpt2 vpt 2 mul def
-/hpt2 hpt 2 mul def
-/Lshow {currentpoint stroke M 0 vshift R 
-	Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def
-/Rshow {currentpoint stroke M dup stringwidth pop neg vshift R
-	Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def
-/Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R 
-	Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def
-/UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def
-  /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def
-/DL {Color {setrgbcolor Solid {pop []} if 0 setdash}
- {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def
-/BL {stroke userlinewidth 2 mul setlinewidth
-	Rounded {1 setlinejoin 1 setlinecap} if} def
-/AL {stroke userlinewidth 2 div setlinewidth
-	Rounded {1 setlinejoin 1 setlinecap} if} def
-/UL {dup gnulinewidth mul /userlinewidth exch def
-	dup 1 lt {pop 1} if 10 mul /udl exch def} def
-/PL {stroke userlinewidth setlinewidth
-	Rounded {1 setlinejoin 1 setlinecap} if} def
-3.8 setmiterlimit
-% Classic Line colors (version 5.0)
-/LCw {1 1 1} def
-/LCb {0 0 0} def
-/LCa {0 0 0} def
-/LC0 {1 0 0} def
-/LC1 {0 1 0} def
-/LC2 {0 0 1} def
-/LC3 {1 0 1} def
-/LC4 {0 1 1} def
-/LC5 {1 1 0} def
-/LC6 {0 0 0} def
-/LC7 {1 0.3 0} def
-/LC8 {0.5 0.5 0.5} def
-% Default dash patterns (version 5.0)
-/LTB {BL [] LCb DL} def
-/LTw {PL [] 1 setgray} def
-/LTb {PL [] LCb DL} def
-/LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def
-/LT0 {PL [] LC0 DL} def
-/LT1 {PL [2 dl1 3 dl2] LC1 DL} def
-/LT2 {PL [1 dl1 1.5 dl2] LC2 DL} def
-/LT3 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC3 DL} def
-/LT4 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def
-/LT5 {PL [4 dl1 2 dl2] LC5 DL} def
-/LT6 {PL [1.5 dl1 1.5 dl2 1.5 dl1 1.5 dl2 1.5 dl1 6 dl2] LC6 DL} def
-/LT7 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC7 DL} def
-/LT8 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC8 DL} def
-/SL {[] 0 setdash} def
-/Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def
-/Dia {stroke [] 0 setdash 2 copy vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V closepath stroke
-  Pnt} def
-/Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V
-  currentpoint stroke M
-  hpt neg vpt neg R hpt2 0 V stroke
- } def
-/Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V closepath stroke
-  Pnt} def
-/Crs {stroke [] 0 setdash exch hpt sub exch vpt add M
-  hpt2 vpt2 neg V currentpoint stroke M
-  hpt2 neg 0 R hpt2 vpt2 V stroke} def
-/TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V closepath stroke
-  Pnt} def
-/Star {2 copy Pls Crs} def
-/BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V closepath fill} def
-/TriUF {stroke [] 0 setdash vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V closepath fill} def
-/TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V closepath stroke
-  Pnt} def
-/TriDF {stroke [] 0 setdash vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V closepath fill} def
-/DiaF {stroke [] 0 setdash vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V closepath fill} def
-/Pent {stroke [] 0 setdash 2 copy gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  closepath stroke grestore Pnt} def
-/PentF {stroke [] 0 setdash gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  closepath fill grestore} def
-/Circle {stroke [] 0 setdash 2 copy
-  hpt 0 360 arc stroke Pnt} def
-/CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def
-/C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def
-/C1 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 90 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C2 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 90 180 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C3 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 180 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C4 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 180 270 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C5 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 90 arc
-	2 copy moveto
-	2 copy vpt 180 270 arc closepath fill
-	vpt 0 360 arc} bind def
-/C6 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 90 270 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C7 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 270 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C8 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 270 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C9 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 270 450 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill
-	2 copy moveto
-	2 copy vpt 90 180 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C11 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 180 arc closepath fill
-	2 copy moveto
-	2 copy vpt 270 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C12 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 180 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C13 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 0 90 arc closepath fill
-	2 copy moveto
-	2 copy vpt 180 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/C14 {BL [] 0 setdash 2 copy moveto
-	2 copy vpt 90 360 arc closepath fill
-	vpt 0 360 arc} bind def
-/C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill
-	vpt 0 360 arc closepath} bind def
-/Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
-	neg 0 rlineto closepath} bind def
-/Square {dup Rec} bind def
-/Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def
-/S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def
-/S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def
-/S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
-/S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def
-/S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
-/S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill
-	exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
-/S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def
-/S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill
-	2 copy vpt Square fill Bsquare} bind def
-/S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def
-/S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def
-/S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill
-	Bsquare} bind def
-/S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill
-	Bsquare} bind def
-/S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def
-/S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
-	2 copy vpt Square fill Bsquare} bind def
-/S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
-	2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
-/S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def
-/D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def
-/D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def
-/D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def
-/D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def
-/D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def
-/D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def
-/D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def
-/D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def
-/D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def
-/D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def
-/D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def
-/D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def
-/D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def
-/D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def
-/D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def
-/D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def
-/DiaE {stroke [] 0 setdash vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V closepath stroke} def
-/BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V closepath stroke} def
-/TriUE {stroke [] 0 setdash vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V closepath stroke} def
-/TriDE {stroke [] 0 setdash vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V closepath stroke} def
-/PentE {stroke [] 0 setdash gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  closepath stroke grestore} def
-/CircE {stroke [] 0 setdash 
-  hpt 0 360 arc stroke} def
-/Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def
-/DiaW {stroke [] 0 setdash vpt add M
-  hpt neg vpt neg V hpt vpt neg V
-  hpt vpt V hpt neg vpt V Opaque stroke} def
-/BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M
-  0 vpt2 neg V hpt2 0 V 0 vpt2 V
-  hpt2 neg 0 V Opaque stroke} def
-/TriUW {stroke [] 0 setdash vpt 1.12 mul add M
-  hpt neg vpt -1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt 1.62 mul V Opaque stroke} def
-/TriDW {stroke [] 0 setdash vpt 1.12 mul sub M
-  hpt neg vpt 1.62 mul V
-  hpt 2 mul 0 V
-  hpt neg vpt -1.62 mul V Opaque stroke} def
-/PentW {stroke [] 0 setdash gsave
-  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
-  Opaque stroke grestore} def
-/CircW {stroke [] 0 setdash 
-  hpt 0 360 arc Opaque stroke} def
-/BoxFill {gsave Rec 1 setgray fill grestore} def
-/Density {
-  /Fillden exch def
-  currentrgbcolor
-  /ColB exch def /ColG exch def /ColR exch def
-  /ColR ColR Fillden mul Fillden sub 1 add def
-  /ColG ColG Fillden mul Fillden sub 1 add def
-  /ColB ColB Fillden mul Fillden sub 1 add def
-  ColR ColG ColB setrgbcolor} def
-/BoxColFill {gsave Rec PolyFill} def
-/PolyFill {gsave Density fill grestore grestore} def
-/h {rlineto rlineto rlineto closepath gsave fill grestore stroke} bind def
-%
-% PostScript Level 1 Pattern Fill routine for rectangles
-% Usage: x y w h s a XX PatternFill
-%	x,y = lower left corner of box to be filled
-%	w,h = width and height of box
-%	  a = angle in degrees between lines and x-axis
-%	 XX = 0/1 for no/yes cross-hatch
-%
-/PatternFill {gsave /PFa [ 9 2 roll ] def
-  PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate
-  PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec
-  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
-  clip
-  currentlinewidth 0.5 mul setlinewidth
-  /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def
-  0 0 M PFa 5 get rotate PFs -2 div dup translate
-  0 1 PFs PFa 4 get div 1 add floor cvi
-	{PFa 4 get mul 0 M 0 PFs V} for
-  0 PFa 6 get ne {
-	0 1 PFs PFa 4 get div 1 add floor cvi
-	{PFa 4 get mul 0 2 1 roll M PFs 0 V} for
- } if
-  stroke grestore} def
-%
-/languagelevel where
- {pop languagelevel} {1} ifelse
-dup 2 lt
-	{/InterpretLevel1 true def
-	 /InterpretLevel3 false def}
-	{/InterpretLevel1 Level1 def
-	 2 gt
-	    {/InterpretLevel3 Level3 def}
-	    {/InterpretLevel3 false def}
-	 ifelse }
- ifelse
-%
-% PostScript level 2 pattern fill definitions
-%
-/Level2PatternFill {
-/Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8}
-	bind def
-/KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} 
->> matrix makepattern
-/Pat1 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke
-	0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke}
->> matrix makepattern
-/Pat2 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L
-	8 8 L 8 0 L 0 0 L fill}
->> matrix makepattern
-/Pat3 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L
-	0 12 M 12 0 L stroke}
->> matrix makepattern
-/Pat4 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L
-	0 -4 M 12 8 L stroke}
->> matrix makepattern
-/Pat5 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L
-	0 12 M 8 -4 L 4 12 M 10 0 L stroke}
->> matrix makepattern
-/Pat6 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L
-	0 -4 M 8 12 L 4 -4 M 10 8 L stroke}
->> matrix makepattern
-/Pat7 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L
-	12 0 M -4 8 L 12 4 M 0 10 L stroke}
->> matrix makepattern
-/Pat8 exch def
-<< Tile8x8
- /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L
-	-4 0 M 12 8 L -4 4 M 8 10 L stroke}
->> matrix makepattern
-/Pat9 exch def
-/Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def
-/Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def
-/Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def
-/Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def
-/Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def
-/Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def
-/Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def
-} def
-%
-%
-%End of PostScript Level 2 code
-%
-/PatternBgnd {
-  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
-} def
-%
-% Substitute for Level 2 pattern fill codes with
-% grayscale if Level 2 support is not selected.
-%
-/Level1PatternFill {
-/Pattern1 {0.250 Density} bind def
-/Pattern2 {0.500 Density} bind def
-/Pattern3 {0.750 Density} bind def
-/Pattern4 {0.125 Density} bind def
-/Pattern5 {0.375 Density} bind def
-/Pattern6 {0.625 Density} bind def
-/Pattern7 {0.875 Density} bind def
-} def
-%
-% Now test for support of Level 2 code
-%
-Level1 {Level1PatternFill} {Level2PatternFill} ifelse
-%
-/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont
-dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall
-currentdict end definefont pop
-%
-/Metrics {ExtendTextBox Gswidth} def
-/Lwidth {currentpoint stroke M 0 vshift R Metrics} def
-/Rwidth {currentpoint stroke M dup stringwidth pop neg vshift R Metrics} def
-/Cwidth {currentpoint stroke M dup stringwidth pop -2 div vshift R Metrics} def
-/GLwidth {currentpoint stroke M 0 vshift R {ExtendTextBox} forall} def
-/GRwidth {currentpoint stroke M dup Gwidth vshift R {ExtendTextBox} forall} def
-/GCwidth {currentpoint stroke M dup Gwidth 2 div vshift R {ExtendTextBox} forall} def
-/GLwidth2 {0 Gwidth AddGlyphWidth} def
-/GRwidth2 {Gwidth -1 mul 0 AddGlyphWidth} def
-/GCwidth2 {Gwidth 2 div dup -1 mul AddGlyphWidth} def
-/AddGlyphWidth { dup TBx2 gt {userdict /TBx2 3 -1 roll put} {pop} ifelse
-                 dup TBx1 lt {userdict /TBx1 3 -1 roll put} {pop} ifelse } def
-/MFshow {
-   { dup 5 get 3 ge
-     { 5 get 3 eq {gsave} {grestore} ifelse }
-     {dup dup 0 get findfont exch 1 get scalefont setfont
-     [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6
-     get exch 4 get {textshow} {Metrics pop 0 R} ifelse }if dup 5 get 0 eq
-     {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5
-     get 1 eq {dup 2 get exch dup 3 get exch 6 get Gswidth pop -2 div
-     dup 0 R} {dup 6 get Gswidth pop -2 div 0 R 6 get
-     textshow 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop
-     pop aload pop M} ifelse }ifelse }ifelse }
-     ifelse }
-   forall} def
-/Gswidth {dup type /stringtype eq {stringwidth} {pop (n) stringwidth} ifelse} def
-/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }
- {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont
-     6 get Gswidth pop add} {pop} ifelse} ifelse} forall} def
-/MLshow { currentpoint stroke M
-  0 exch R
-  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
-/MRshow { currentpoint stroke M
-  exch dup MFwidth neg 3 -1 roll R
-  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
-/MCshow { currentpoint stroke M
-  exch dup MFwidth -2 div 3 -1 roll R
-  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
-/XYsave    { [( ) 1 2 true false 3 ()] } bind def
-/XYrestore { [( ) 1 2 true false 4 ()] } bind def
-Level1 SuppressPDFMark or 
-{} {
-/SDict 10 dict def
-systemdict /pdfmark known not {
-  userdict /pdfmark systemdict /cleartomark get put
-} if
-SDict begin [
-  /Title (802.15.4-per-vs-rxSignal.eps)
-  /Subject (gnuplot plot)
-  /Creator (gnuplot 5.2 patchlevel 8)
-%  /Producer (gnuplot)
-%  /Keywords ()
-  /CreationDate (Mon Dec 19 13:38:56 2022)
-  /DOCINFO pdfmark
-end
-} ifelse
-%
-% Support for boxed text - Ethan A Merritt Sep 2016
-%
-/InitTextBox { userdict /TBy2 3 -1 roll put userdict /TBx2 3 -1 roll put
-           userdict /TBy1 3 -1 roll put userdict /TBx1 3 -1 roll put
-	   /Boxing true def } def
-/ExtendTextBox { dup type /stringtype eq
-    { Boxing { gsave dup false charpath pathbbox
-      dup TBy2 gt {userdict /TBy2 3 -1 roll put} {pop} ifelse
-      dup TBx2 gt {userdict /TBx2 3 -1 roll put} {pop} ifelse
-      dup TBy1 lt {userdict /TBy1 3 -1 roll put} {pop} ifelse
-      dup TBx1 lt {userdict /TBx1 3 -1 roll put} {pop} ifelse
-      grestore } if }
-    {} ifelse} def
-/PopTextBox { newpath TBx1 TBxmargin sub TBy1 TBymargin sub M
-               TBx1 TBxmargin sub TBy2 TBymargin add L
-	       TBx2 TBxmargin add TBy2 TBymargin add L
-	       TBx2 TBxmargin add TBy1 TBymargin sub L closepath } def
-/DrawTextBox { PopTextBox stroke /Boxing false def} def
-/FillTextBox { gsave PopTextBox fill grestore /Boxing false def} def
-0 0 0 0 InitTextBox
-/TBxmargin 20 def
-/TBymargin 20 def
-/Boxing false def
-/textshow { ExtendTextBox Gshow } def
-%
-end
-%%EndProlog
-%%Page: 1 1
-gnudict begin
-gsave
-doclip
-50 50 translate
-0.050 0.050 scale
-0 setgray
-newpath
-(Times-BoldItalic) findfont 140 scalefont setfont
-BackgroundColor 0 lt 3 1 roll 0 lt exch 0 lt or or not {BackgroundColor C 1.000 0 0 7200.00 5040.00 BoxColFill} if
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-938 448 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 448 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 448 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
-[(Times-BoldItalic) 112.0 70.0 true true 0 (-12)]
-] -60.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-/vshift -46 def
-1.000 UL
-LTb
-LCb setrgbcolor
-938 768 M
-31 0 V
-5978 0 R
--31 0 V
-938 851 M
-31 0 V
-5978 0 R
--31 0 V
-938 902 M
-31 0 V
-5978 0 R
--31 0 V
-938 938 M
-31 0 V
-5978 0 R
--31 0 V
-938 966 M
-31 0 V
-5978 0 R
--31 0 V
-938 989 M
-31 0 V
-5978 0 R
--31 0 V
-938 1009 M
-31 0 V
-5978 0 R
--31 0 V
-938 1026 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 1041 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 1041 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 1041 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
-[(Times-BoldItalic) 112.0 70.0 true true 0 (-10)]
-] -60.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-938 1360 M
-31 0 V
-5978 0 R
--31 0 V
-938 1444 M
-31 0 V
-5978 0 R
--31 0 V
-938 1494 M
-31 0 V
-5978 0 R
--31 0 V
-938 1530 M
-31 0 V
-5978 0 R
--31 0 V
-938 1558 M
-31 0 V
-5978 0 R
--31 0 V
-938 1581 M
-31 0 V
-5978 0 R
--31 0 V
-938 1601 M
-31 0 V
-5978 0 R
--31 0 V
-938 1618 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 1633 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 1633 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 1633 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
-[(Times-BoldItalic) 112.0 70.0 true true 0 (-8)]
-] -60.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-938 1953 M
-31 0 V
-5978 0 R
--31 0 V
-938 2036 M
-31 0 V
-5978 0 R
--31 0 V
-938 2087 M
-31 0 V
-5978 0 R
--31 0 V
-938 2123 M
-31 0 V
-5978 0 R
--31 0 V
-938 2151 M
-31 0 V
-5978 0 R
--31 0 V
-938 2174 M
-31 0 V
-5978 0 R
--31 0 V
-938 2194 M
-31 0 V
-5978 0 R
--31 0 V
-938 2211 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 2226 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 2226 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 2226 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
-[(Times-BoldItalic) 112.0 70.0 true true 0 (-6)]
-] -60.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-938 2545 M
-31 0 V
-5978 0 R
--31 0 V
-938 2629 M
-31 0 V
-5978 0 R
--31 0 V
-938 2679 M
-31 0 V
-5978 0 R
--31 0 V
-938 2715 M
-31 0 V
-5978 0 R
--31 0 V
-938 2743 M
-31 0 V
-5978 0 R
--31 0 V
-938 2766 M
-31 0 V
-5978 0 R
--31 0 V
-938 2786 M
-31 0 V
-5978 0 R
--31 0 V
-938 2803 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 2818 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 2818 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 2818 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.0001)]
-] -46.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-938 3138 M
-31 0 V
-5978 0 R
--31 0 V
-938 3221 M
-31 0 V
-5978 0 R
--31 0 V
-938 3272 M
-31 0 V
-5978 0 R
--31 0 V
-938 3308 M
-31 0 V
-5978 0 R
--31 0 V
-938 3336 M
-31 0 V
-5978 0 R
--31 0 V
-938 3359 M
-31 0 V
-5978 0 R
--31 0 V
-938 3379 M
-31 0 V
-5978 0 R
--31 0 V
-938 3396 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 3411 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 3411 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 3411 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.01)]
-] -46.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-938 3730 M
-31 0 V
-5978 0 R
--31 0 V
-938 3814 M
-31 0 V
-5978 0 R
--31 0 V
-938 3864 M
-31 0 V
-5978 0 R
--31 0 V
-938 3900 M
-31 0 V
-5978 0 R
--31 0 V
-938 3928 M
-31 0 V
-5978 0 R
--31 0 V
-938 3952 M
-31 0 V
-5978 0 R
--31 0 V
-938 3971 M
-31 0 V
-5978 0 R
--31 0 V
-938 3988 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 4003 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 4003 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 4003 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1)]
-] -46.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-938 4323 M
-31 0 V
-5978 0 R
--31 0 V
-938 4406 M
-31 0 V
-5978 0 R
--31 0 V
-938 4457 M
-31 0 V
-5978 0 R
--31 0 V
-938 4493 M
-31 0 V
-5978 0 R
--31 0 V
-938 4521 M
-31 0 V
-5978 0 R
--31 0 V
-938 4544 M
-31 0 V
-5978 0 R
--31 0 V
-938 4564 M
-31 0 V
-5978 0 R
--31 0 V
-938 4581 M
-31 0 V
-5978 0 R
--31 0 V
-stroke
-0.500 UL
-LTa
-LCa setrgbcolor
-938 4596 M
-6009 0 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 4596 M
-63 0 V
-5946 0 R
--63 0 V
-stroke
-854 4596 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 100)]
-] -46.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-938 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-938 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-938 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-110)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-1367 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-1367 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-1367 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-108)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-1796 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-1796 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-1796 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-106)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-2226 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-2226 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-2226 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-104)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-2655 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-2655 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-2655 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-102)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-3084 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-3084 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-3084 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-100)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-3513 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-3513 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-3513 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-98)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-3943 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-3943 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-3943 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-96)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-4372 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-4372 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-4372 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-94)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-4801 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-4801 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-4801 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-92)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-5230 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-5230 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-5230 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-90)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-5659 448 M
-0 3828 V
-0 280 R
-0 63 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-5659 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-5659 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-88)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-6089 448 M
-0 3828 V
-0 280 R
-0 63 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-6089 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-6089 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-86)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-6518 448 M
-0 3828 V
-0 280 R
-0 63 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-6518 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-6518 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-84)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-0.500 UL
-LTa
-LCa setrgbcolor
-6947 448 M
-0 4171 V
-stroke
-1.000 UL
-LTb
-LCb setrgbcolor
-6947 448 M
-0 63 V
-0 4108 R
-0 -63 V
-stroke
-6947 308 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-82)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-1.000 UL
-LTb
-LCb setrgbcolor
-1.000 UL
-LTB
-LCb setrgbcolor
-938 4619 N
-938 448 L
-6009 0 V
-0 4171 V
--6009 0 V
-Z stroke
-1.000 UP
-1.000 UL
-LTb
-LCb setrgbcolor
-LCb setrgbcolor
-133 2533 M
-currentpoint gsave translate -270 rotate 0 0 moveto
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Packet Error Rate \(%\))]
-] -46.7 MCshow
-grestore
-/Times-BoldItalic findfont 140 scalefont setfont
-LTb
-LCb setrgbcolor
-3942 98 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Rx signal \(dBm\))]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-LTb
-LCb setrgbcolor
-3942 4829 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Pkt Payload \(MSDU\) size = 7 bytes | Tx power = 0 dBm | Rx Sensitivity \(Theo\) = -106.58 dBm)]
-] -46.7 MCshow
-/Times-BoldItalic findfont 140 scalefont setfont
-LTb
-% Begin plot #1
-5.000 UL
-LTb
-LC0 setrgbcolor
-LCb setrgbcolor
-6296 4486 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Experimental)]
-] -46.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-5.000 UL
-LTb
-LC0 setrgbcolor
-6380 4486 M
-399 0 V
-938 4591 M
-2 -2 V
-2 1 V
-2 -1 V
-3 1 V
-2 -1 V
-2 -1 V
-2 0 V
-2 1 V
-2 1 V
-2 -2 V
-3 1 V
-2 1 V
-2 -2 V
-2 0 V
-2 -1 V
-2 -1 V
-2 0 V
-3 -1 V
-2 1 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-3 -1 V
-2 0 V
-2 2 V
-2 -1 V
-2 -1 V
-2 0 V
-2 0 V
-3 -1 V
-2 1 V
-2 -2 V
-2 1 V
-2 -1 V
-2 0 V
-2 0 V
-3 1 V
-2 -2 V
-2 -2 V
-2 3 V
-2 -1 V
-2 -1 V
-2 -4 V
-3 1 V
-2 3 V
-2 -4 V
-2 1 V
-2 -3 V
-2 3 V
-2 -2 V
-3 -1 V
-2 2 V
-2 0 V
-2 -3 V
-2 -1 V
-2 0 V
-2 -1 V
-3 0 V
-2 -2 V
-2 0 V
-2 -1 V
-2 -1 V
-2 3 V
-2 -7 V
-3 2 V
-2 2 V
-2 -1 V
-2 -1 V
-2 -2 V
-2 3 V
-3 -3 V
-2 1 V
-2 1 V
-2 -6 V
-2 0 V
-2 -2 V
-2 -3 V
-3 2 V
-2 0 V
-2 2 V
-2 -2 V
-2 -2 V
-2 0 V
-2 -3 V
-3 -2 V
-2 -1 V
-2 1 V
-2 2 V
-2 -2 V
-2 -2 V
-2 0 V
-3 -3 V
-2 3 V
-2 -9 V
-2 6 V
-2 -1 V
-2 -6 V
-2 8 V
-3 0 V
-2 -10 V
-2 5 V
-2 -4 V
-2 -4 V
-2 4 V
-2 -5 V
-3 10 V
-2 -10 V
-2 -5 V
-2 2 V
-2 2 V
-2 -8 V
-3 6 V
-2 -2 V
-2 -3 V
-2 3 V
-2 -7 V
-2 2 V
-2 0 V
-3 1 V
-2 -6 V
-2 -1 V
-2 1 V
-2 -4 V
-2 3 V
-2 -3 V
-3 -6 V
-2 6 V
-2 -12 V
-2 4 V
-2 -4 V
-2 -2 V
-2 6 V
-3 -5 V
-2 -1 V
-2 2 V
-2 -1 V
-2 -2 V
-2 -5 V
-2 2 V
-3 -4 V
-2 -4 V
-2 -7 V
-2 7 V
-2 1 V
-2 -1 V
-2 -6 V
-3 -5 V
-2 -5 V
-2 7 V
-2 -9 V
-2 2 V
-2 -8 V
-2 9 V
-3 4 V
-2 -15 V
-2 8 V
-2 0 V
-2 -1 V
-2 -7 V
-3 3 V
-2 2 V
-2 -10 V
-2 1 V
-2 2 V
-2 -5 V
-2 -3 V
-3 -1 V
-2 0 V
-2 -2 V
-2 -1 V
-2 0 V
-2 4 V
-2 -6 V
-3 -14 V
-2 15 V
-2 -10 V
-2 -28 V
-2 22 V
-2 0 V
-2 -11 V
-3 8 V
-2 -9 V
-2 -4 V
-2 8 V
-2 6 V
-2 -7 V
-2 -6 V
-3 -9 V
-2 21 V
-2 -22 V
-2 -14 V
-2 22 V
-2 -11 V
-2 0 V
-3 3 V
-2 -8 V
-2 -5 V
-2 7 V
-2 -14 V
-2 3 V
-3 -11 V
-2 8 V
-2 12 V
-2 -21 V
-2 -10 V
-2 14 V
-2 0 V
-3 -8 V
-2 6 V
-2 -7 V
-2 -5 V
-2 9 V
-2 -10 V
-2 -18 V
-3 3 V
-2 -5 V
-2 7 V
-2 8 V
-2 9 V
-2 -15 V
-2 -13 V
-3 3 V
-2 9 V
-2 -17 V
-2 -5 V
-2 9 V
-2 0 V
-2 4 V
-3 -5 V
-2 3 V
-2 -10 V
-2 -24 V
-2 19 V
-2 -9 V
-2 -19 V
-3 17 V
-2 -5 V
-2 -8 V
-2 13 V
-2 -28 V
-2 -2 V
-2 -1 V
-3 12 V
-2 -26 V
-2 15 V
-2 9 V
-stroke 1468 4293 M
-2 0 V
-2 2 V
-3 -9 V
-2 -15 V
-2 10 V
-2 3 V
-2 -36 V
-2 18 V
-2 6 V
-3 -5 V
-2 -3 V
-2 -24 V
-2 32 V
-2 -32 V
-2 6 V
-2 7 V
-3 -28 V
-2 13 V
-2 -18 V
-2 22 V
-2 6 V
-2 -12 V
-2 6 V
-3 10 V
-2 -25 V
-2 -17 V
-2 -2 V
-2 -11 V
-2 28 V
-2 -7 V
-3 20 V
-2 -13 V
-2 -37 V
-2 6 V
-2 11 V
-2 -37 V
-2 42 V
-3 -19 V
-2 17 V
-2 -33 V
-2 19 V
-2 -37 V
-2 14 V
-3 28 V
-2 -31 V
-2 -15 V
-2 4 V
-2 42 V
-2 -39 V
-2 21 V
-3 -28 V
-2 7 V
-2 15 V
-2 -39 V
-2 58 V
-2 -96 V
-2 70 V
-3 -42 V
-2 -28 V
-2 80 V
-2 -47 V
-2 -27 V
-2 -12 V
-2 18 V
-3 -73 V
-2 99 V
-2 4 V
-2 -36 V
-2 53 V
-2 -71 V
-2 -7 V
-3 0 V
-2 -8 V
-2 33 V
-2 6 V
-2 0 V
-2 -46 V
-2 0 V
-3 22 V
-2 -7 V
-2 13 V
-2 -13 V
-2 7 V
-2 -22 V
-2 -18 V
-3 64 V
-2 -95 V
-2 40 V
-2 -81 V
-2 105 V
-2 -53 V
-3 -23 V
-2 43 V
-2 -31 V
-2 -26 V
-2 -15 V
-2 81 V
-2 -9 V
-3 -72 V
-2 63 V
-2 -22 V
-2 11 V
-2 45 V
-2 -68 V
-2 -29 V
-3 0 V
-2 29 V
-2 -29 V
-2 41 V
-2 -26 V
-2 0 V
-2 -75 V
-3 23 V
-2 89 V
-2 -89 V
-2 -89 V
-2 109 V
-2 -43 V
-2 0 V
-3 -29 V
-2 89 V
-4 -89 R
-2 72 V
-2 -109 V
-2 126 V
-3 0 V
-2 -126 V
-2 -141 V
-2 250 V
-2 -109 V
-2 89 V
-3 -230 V
-2 89 V
-2 0 V
-2 89 V
-2 0 V
-2 52 V
-2 -141 V
-3 52 V
-2 -52 V
-2 0 V
-2 89 V
-2 0 V
-2 0 V
-2 -178 V
-3 141 V
-2 -52 V
-2 0 V
-2 52 V
-2 -141 V
-2 89 V
-2 -89 V
-3 89 V
-2 89 V
-2 -89 V
-2 0 V
-4 52 R
-2 37 V
-5 -89 R
-2 -89 V
-2 89 V
-2 0 V
-2 0 V
-2 -89 V
-3 89 V
-2 -89 V
-2 0 V
-2 141 V
-2 -141 V
-2 89 V
-2 -89 V
-5 89 R
-2 52 V
-2 -52 V
-2 -89 V
-2 141 V
-3 -141 V
-4 0 R
-2 141 V
-4 -52 R
-11 0 R
-6 0 R
-3 -89 V
-2 89 V
-2 -89 V
-2 0 V
-2 0 V
-2 0 V
-2 0 V
-3 89 V
-4 -89 R
-4 0 R
-4 0 R
-11 0 R
-30 0 R
-2 89 V
-5 -89 R
-81 0 R
-5 0 R
-4 0 R
-21 0 R
-65 0 R
-% End plot #1
-% Begin plot #2
-stroke
-3.000 UL
-LTb
-LC1 setrgbcolor
-LCb setrgbcolor
-6296 4346 M
-[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Theoretical)]
-] -46.7 MRshow
-/Times-BoldItalic findfont 140 scalefont setfont
-3.000 UL
-LTb
-LC1 setrgbcolor
-6380 4346 M
-399 0 V
-938 4586 M
-2 0 V
-2 0 V
-2 0 V
-3 -1 V
-2 0 V
-2 0 V
-2 0 V
-2 -1 V
-2 0 V
-2 0 V
-3 -1 V
-2 0 V
-2 0 V
-2 -1 V
-2 0 V
-2 0 V
-2 -1 V
-3 0 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-2 0 V
-3 0 V
-2 -1 V
-2 0 V
-2 -1 V
-2 0 V
-2 0 V
-2 -1 V
-3 0 V
-2 -1 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-2 0 V
-3 -1 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-3 -1 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-2 0 V
-2 -1 V
-3 -1 V
-2 0 V
-2 -1 V
-2 -1 V
-2 0 V
-2 -1 V
-2 -1 V
-3 0 V
-2 -1 V
-2 -1 V
-2 0 V
-2 -1 V
-2 -1 V
-2 -1 V
-3 0 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 0 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 0 V
-2 -1 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 0 V
-2 -1 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -1 V
-3 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -1 V
-2 -1 V
-2 -1 V
-3 -2 V
-2 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -1 V
-2 -2 V
-3 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-3 -1 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -1 V
-3 -2 V
-2 -1 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-3 -1 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -1 V
-3 -2 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -1 V
-2 -2 V
-3 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-3 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -1 V
-2 -2 V
-3 -2 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-3 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-3 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -1 V
-2 -2 V
-2 -2 V
-3 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-3 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -3 V
-3 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-3 -2 V
-2 -3 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-3 -3 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -2 V
-2 -3 V
-2 -2 V
-3 -2 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -2 V
-2 -3 V
-2 -2 V
-3 -2 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -2 V
-2 -3 V
-2 -2 V
-3 -3 V
-2 -2 V
-2 -2 V
-2 -3 V
-stroke 1468 4265 M
-2 -2 V
-2 -2 V
-3 -3 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-3 -2 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-3 -3 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-3 -2 V
-2 -3 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -2 V
-2 -3 V
-3 -3 V
-2 -2 V
-2 -3 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -3 V
-3 -2 V
-2 -3 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -3 V
-3 -3 V
-2 -2 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -2 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -3 V
-2 -2 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -4 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-3 -4 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -4 V
-2 -3 V
-3 -3 V
-2 -3 V
-2 -4 V
-2 -3 V
-2 -3 V
-2 -3 V
-2 -4 V
-3 -3 V
-2 -3 V
-2 -4 V
-2 -3 V
-2 -3 V
-2 -4 V
-2 -3 V
-3 -3 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -3 V
-2 -3 V
-2 -4 V
-3 -3 V
-2 -4 V
-2 -3 V
-2 -3 V
-2 -4 V
-2 -3 V
-3 -4 V
-2 -3 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -3 V
-2 -4 V
-3 -3 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -4 V
-2 -3 V
-2 -4 V
-3 -3 V
-2 -4 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -3 V
-2 -4 V
-3 -4 V
-2 -3 V
-2 -4 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -3 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -3 V
-2 -4 V
-3 -4 V
-2 -4 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -4 V
-2 -3 V
-2 -4 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-3 -4 V
-2 -5 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -4 V
-2 -5 V
-3 -4 V
-2 -4 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -4 V
-3 -5 V
-2 -4 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -4 V
-2 -5 V
-3 -4 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -5 V
-3 -4 V
-2 -5 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -5 V
-2 -4 V
-3 -5 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -5 V
-2 -4 V
-2 -5 V
-stroke 2002 3410 M
-3 -5 V
-2 -4 V
-2 -5 V
-2 -5 V
-2 -4 V
-2 -5 V
-2 -5 V
-3 -4 V
-2 -5 V
-2 -5 V
-2 -4 V
-2 -5 V
-2 -5 V
-2 -5 V
-3 -4 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -4 V
-3 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-3 -4 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-3 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-3 -6 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-3 -5 V
-2 -6 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -5 V
-2 -6 V
-3 -5 V
-2 -5 V
-2 -5 V
-2 -6 V
-2 -5 V
-2 -5 V
-3 -6 V
-2 -5 V
-2 -5 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -5 V
-3 -5 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -5 V
-3 -6 V
-2 -5 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -5 V
-2 -6 V
-3 -5 V
-2 -6 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -6 V
-2 -5 V
-3 -6 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -5 V
-3 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -5 V
-2 -6 V
-2 -6 V
-3 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-3 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-3 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-3 -6 V
-2 -7 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -7 V
-3 -6 V
-2 -6 V
-2 -7 V
-2 -6 V
-2 -6 V
-2 -6 V
-2 -7 V
-3 -6 V
-2 -7 V
-2 -6 V
-2 -6 V
-2 -7 V
-2 -6 V
-2 -7 V
-3 -6 V
-2 -7 V
-2 -6 V
-2 -7 V
-2 -6 V
-2 -7 V
-3 -6 V
-2 -7 V
-2 -6 V
-2 -7 V
-2 -7 V
-2 -6 V
-2 -7 V
-3 -6 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -6 V
-2 -7 V
-2 -7 V
-3 -7 V
-2 -6 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -6 V
-3 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-3 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-3 -7 V
-2 -7 V
-2 -8 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -7 V
-3 -8 V
-2 -7 V
-2 -7 V
-2 -7 V
-2 -8 V
-2 -7 V
-3 -7 V
-2 -8 V
-2 -7 V
-2 -7 V
-2 -8 V
-2 -7 V
-2 -8 V
-3 -7 V
-2 -7 V
-2 -8 V
-2 -7 V
-2 -8 V
-2 -7 V
-2 -8 V
-3 -8 V
-2 -7 V
-2 -8 V
-2 -7 V
-2 -8 V
-2 -8 V
-2 -7 V
-3 -8 V
-2 -8 V
-2 -7 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -7 V
-3 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-3 -7 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-3 -8 V
-2 -9 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-2 -8 V
-3 -8 V
-2 -9 V
-2 -8 V
-stroke 2537 1853 M
-2 -8 V
-2 -8 V
-2 -9 V
-2 -8 V
-3 -8 V
-2 -8 V
-2 -9 V
-2 -8 V
-2 -9 V
-2 -8 V
-2 -8 V
-3 -9 V
-2 -8 V
-2 -9 V
-2 -8 V
-2 -9 V
-2 -8 V
-2 -9 V
-3 -9 V
-2 -8 V
-2 -9 V
-2 -8 V
-2 -9 V
-2 -9 V
-2 -8 V
-3 -9 V
-2 -9 V
-2 -9 V
-2 -9 V
-2 -8 V
-2 -9 V
-2 -9 V
-3 -9 V
-2 -9 V
-2 -9 V
-2 -9 V
-2 -9 V
-2 -9 V
-3 -8 V
-2 -9 V
-2 -10 V
-2 -9 V
-2 -9 V
-2 -9 V
-2 -9 V
-3 -9 V
-2 -9 V
-2 -9 V
-2 -10 V
-2 -9 V
-2 -9 V
-2 -9 V
-3 -10 V
-2 -9 V
-2 -9 V
-2 -10 V
-2 -9 V
-2 -9 V
-2 -10 V
-3 -9 V
-2 -10 V
-2 -9 V
-2 -10 V
-2 -9 V
-2 -10 V
-2 -9 V
-3 -10 V
-2 -10 V
-2 -9 V
-2 -10 V
-2 -9 V
-2 -10 V
-2 -10 V
-3 -10 V
-2 -9 V
-2 -10 V
-2 -10 V
-2 -10 V
-2 -10 V
-3 -10 V
-2 -9 V
-2 -10 V
-2 -10 V
-2 -11 V
-2 -9 V
-2 -11 V
-3 -9 V
-2 -10 V
-2 -11 V
-2 -10 V
-2 -10 V
-2 -11 V
-2 -9 V
-3 -10 V
-2 -11 V
-2 -11 V
-2 -8 V
-2 -9 V
-2 -15 V
-2 -11 V
-3 -5 V
-2 -13 V
-2 -13 V
-2 -8 V
-2 -7 V
-2 -18 V
-2 -9 V
-3 -10 V
-2 -12 V
-2 -12 V
-2 0 V
-2 -13 V
-2 -16 V
-2 -17 V
-3 0 V
-2 -20 V
-2 0 V
-2 -23 V
-2 0 V
-2 0 V
-2 -29 V
-3 0 V
-2 0 V
-2 -37 V
-2 0 V
-2 0 V
-2 -52 V
-3 0 V
-2 0 V
-2 0 V
-2 0 V
-2 0 V
-2 -89 V
-2 0 V
-3 0 V
-2 0 V
-2 0 V
-2 0 V
-2 0 V
-2 0 V
-2 0 V
-3 0 V
-2 0 V
-2 0 V
-2 0 V
-% End plot #2
-stroke
-2.000 UL
-LTb
-LCb setrgbcolor
-1.000 UL
-LTB
-LCb setrgbcolor
-938 4619 N
-938 448 L
-6009 0 V
-0 4171 V
--6009 0 V
-Z stroke
-1.000 UP
-1.000 UL
-[] 0 setdash
-0.00 0.50 1.00 C
-938 4003 M
-6009 0 V
-stroke
-LTb
-LCb setrgbcolor
-stroke
-grestore
-end
-showpage
-%%Trailer
-%%DocumentFonts: Times-BoldItalic
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/802-15-4-psr-distance.eps ns-3.46/src/lr-wpan/doc/802-15-4-psr-distance.eps
--- ns-3.45/src/lr-wpan/doc/802-15-4-psr-distance.eps	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/doc/802-15-4-psr-distance.eps	1969-12-31 16:00:00.000000000 -0800
@@ -1,590 +0,0 @@
-%!PS-Adobe-3.0 EPSF-3.0
-%%Creator: cairo 1.16.0 (https://cairographics.org)
-%%CreationDate: Tue Feb  7 16:42:56 2023
-%%Pages: 1
-%%DocumentData: Clean7Bit
-%%LanguageLevel: 2
-%%BoundingBox: 4 1 354 245
-%%EndComments
-%%BeginProlog
-50 dict begin
-/q { gsave } bind def
-/Q { grestore } bind def
-/cm { 6 array astore concat } bind def
-/w { setlinewidth } bind def
-/J { setlinecap } bind def
-/j { setlinejoin } bind def
-/M { setmiterlimit } bind def
-/d { setdash } bind def
-/m { moveto } bind def
-/l { lineto } bind def
-/c { curveto } bind def
-/h { closepath } bind def
-/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
-      0 exch rlineto 0 rlineto closepath } bind def
-/S { stroke } bind def
-/f { fill } bind def
-/f* { eofill } bind def
-/n { newpath } bind def
-/W { clip } bind def
-/W* { eoclip } bind def
-/BT { } bind def
-/ET { } bind def
-/BDC { mark 3 1 roll /BDC pdfmark } bind def
-/EMC { mark /EMC pdfmark } bind def
-/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
-/Tj { show currentpoint cairo_store_point } bind def
-/TJ {
-  {
-    dup
-    type /stringtype eq
-    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
-  } forall
-  currentpoint cairo_store_point
-} bind def
-/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
-    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
-/Tf { pop /cairo_font exch def /cairo_font_matrix where
-      { pop cairo_selectfont } if } bind def
-/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
-      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
-      /cairo_font where { pop cairo_selectfont } if } bind def
-/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
-      cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
-/g { setgray } bind def
-/rg { setrgbcolor } bind def
-/d1 { setcachedevice } bind def
-/cairo_data_source {
-  CairoDataIndex CairoData length lt
-    { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def }
-    { () } ifelse
-} def
-/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def
-/cairo_image { image cairo_flush_ascii85_file } def
-/cairo_imagemask { imagemask cairo_flush_ascii85_file } def
-%%EndProlog
-%%BeginSetup
-%%BeginResource: font f-0-0
-%!FontType1-1.1 f-0-0 1.0
-11 dict begin
-/FontName /f-0-0 def
-/PaintType 0 def
-/FontType 1 def
-/FontMatrix [0.001 0 0 0.001 0 0] readonly def
-/FontBBox {-120 -205 917 699                                 } readonly def
-/Encoding 256 array
-0 1 255 {1 index exch /.notdef put} for
-dup 32 /space put
-dup 40 /parenleft put
-dup 41 /parenright put
-dup 45 /hyphen put
-dup 46 /period put
-dup 48 /zero put
-dup 49 /one put
-dup 50 /two put
-dup 52 /four put
-dup 53 /five put
-dup 54 /six put
-dup 55 /seven put
-dup 56 /eight put
-dup 57 /nine put
-dup 59 /semicolon put
-dup 61 /equal put
-dup 66 /B put
-dup 68 /D put
-dup 77 /M put
-dup 80 /P put
-dup 82 /R put
-dup 83 /S put
-dup 85 /U put
-dup 97 /a put
-dup 98 /b put
-dup 99 /c put
-dup 100 /d put
-dup 101 /e put
-dup 104 /h put
-dup 105 /i put
-dup 107 /k put
-dup 108 /l put
-dup 109 /m put
-dup 110 /n put
-dup 111 /o put
-dup 112 /p put
-dup 114 /r put
-dup 115 /s put
-dup 116 /t put
-dup 117 /u put
-dup 119 /w put
-dup 120 /x put
-dup 121 /y put
-dup 122 /z put
-readonly def
-currentdict end
-currentfile eexec
-f983ef0097ece636fb4a96c74d26ab84185f6dfa4a16a7a1c27bbe3f1156aea698df336d20b467
-b10e7f33846656653c5ac6962759d3056cbdb3190bac614b984bf5a132dc418192443014ba63de
-800d392b6fea026574bb2535fd7bb5338f35bf15a88ea328fdaa49670c7852e3d060f3c5d6b07f
-2ef6d0f22646c5d18e19a2ae3ee120390f6dd96f76dcf1e127de5e9299077a00c17c0d71e36e5b
-9d5ec58fceda57739a6a4214d4b79d6c48d2784b60c320323c7acddddf34db833cac0cf109f799
-69d114a330d372e5c978a66acc84e3fe5557f6240856a013ffaa0199444e5c5036f775eba4a5c5
-8cde66cf604b9aca2178431127b8a1ff7ed633a65c04600af5f573483112251ca91d1147e394b8
-770feb7fd46a77e2961ec91bb9263dc0e43eb9a3b990c9761127f2236d69136be42a8ece293f20
-5e8c6985d36b970354af6976b59de1a9aee59b1b7c4d57d3e7115622fce48a99cd7903af13d778
-b61bdf26278782d0626afcd805edf6882452f3ba0b8a06550e5e742680a1db9e9c38aff42a0b05
-0a9f5f0b9355ad3cd836918714c3f69d1b8ce860e052d6ee0bf9c73c967566711ee88068b4f1e1
-8e9f1de06e22b50a1802b961bf321e086c078478c600fa019a221bda4d0691a1bb176b02a3095e
-c2a8437df5f02ae027612189ff9fa60c7236e5bf6cafe3cf2387597370a08fa1249ace038b4c9a
-ecc6e711908d08521015920bfc534c4cf64bf8005abe859dc2969a27784051abe57be19aba6937
-c8d9cd449d007816c1381fc06b1f9d0f750dc5eda5f766e4245b5797d2d8e322f2a38ed3880ae7
-13f2edc17311c12c168e50150fe0e343da65e3f2bd139450022b55e23392a2de02f289617dd4cd
-f3c47d52ea553d5a2feaf00f8aa0c17f95745f872dce13d2e1a26248be73aef3e76cf72414b24a
-a796fcf2778035fbd97ad4fc2b916c3a324e4d36cee9fcb580e5d1d9073ae58a01be98418b9425
-0619218c1fcba7037a689ec83fc42d6dea7d609e3cc45d07e289084a878c33a77c492427e6408f
-895707f95831bf9c8b230d9aa553f2e62ed301bf822df01c64e122b25bb3e929552940d69d9bea
-0db22cc1f90a5cf9eb63dd3fd52f41d5c1c8a9ac478b48459e5882b062bc78675aa1e2d6e70326
-69af62ed53d03ed4c7e7b4c3d5c63878fc98a0f891b0b3f4112f9203b201b4df315d423d009273
-6dd784bf0eebd9bc9407c803adaa20de750884ade854491b14660b23ce1830344c320cb26e2bd2
-41b916c30c94de287fd3b8ab8116011e8c5e43c528d22dbc4f1bf6400e422b7f0e02eb53adf5a0
-8f5a1d4fb192188430efa7dd558329569b4cdf8f07ca29b0f906bdb164ecd6762e55c4113af599
-e4b4abcdd41d05de6bd6add6fb8f684b0d9583a56602d13c5b64e2e837ec5c238704efe8039f95
-b5edc8221765f744db766f5224c324cab2ecc72cb20b58b5f19426e5d29f3a5b429cee7b45a71d
-781ea61d2ce93533201e8706f71d3a9c29b4b2db6398a8a9ecbcf3588ca6da6fca2a72fbe479ad
-0af932e399f3932445b10b4740fb1d437ccabc5b42701242666828fdc8b131c8ea8eca9e0b822c
-7f88e9fc49256dc6f6e52fc0a00c38428324478492d15b18959fb09cf28004562bf53b6eca151a
-7994261c2c3e6fb99fa87fe90500277c32f4d902dc6405f5cf752555994d05bd98c9902a518cc6
-1b3ac3ffd041ed82d8279a2a1c3c5729aa6dfd811b08ac5715c20fb012eb3ddb611d5aa0386a5d
-cd8d878e1b90baa9073032eb31ed3f35385621284e8fd6d31b0bdd56f214c324928eb57bbe7b4d
-24cd67ee34b6a22c77a6d80ff843102c723511c3c261dec9462b6a191384d99d52545a9bbae451
-89c114aacd395f5d2ed9b9c2b5eab9f109c36c915f36678ee984a1b8a65b38ed6d48ef11648b9a
-4e21d51bae9df39b17e0cc40a0cd3c453f85bcadcef2210d39d1b3259c3cd7bce8f8da5cc94cdd
-32201bc55a2f74431d84f5573b59e6e1ac3d7b3b80725961993759f63077b206d987d8f61ab3b2
-1173653792b1e586728bbfbbd5687d6acac39c5c984ccf92242196b4ab5d5408b6949f35803fc5
-f4840b0b561802400007802c4467b55610152573415ba53f207b104de7d912c5bf47751d85385d
-f45b5728f0c7222dd4800d300e92a631f5523738c581300c61c41099563b1cc5d5d75fdfa6a249
-6e883227020870adfff63688a6d6e32d649e3e802919138035d53be2663efcbafa6f3f01c12dd5
-e73272506a4e1e0a0ba4ee185c8f2631f1c47991bcd441a3fb971a920a995d56e51abb9273c056
-ab190ba8b3eab9924dcf25e9eaf74fd2a2adeb0fe586522738c94df776270068587b9e2951285d
-f961df30828870115939160f7baca86e9b7eeee4778159d4b82acb2b4934970ca8af657637ce28
-1fc7195fff0c26a35b5763d1c84b75f45df695b55f565e83e72dca59c528fc9c2f9fb8bb1d3836
-0b3f87cbcd36f96e6680960b5f78d1660180ea3ba73c0df17e9d1b3c4939c8dd8eb4a95277934c
-a417af85e4f3ceee61bd0d6a18687471d8dec2cfb65d8a1ee30adcd50f6354045e61aa3f1d35d1
-a5f39c1228be448f4e15fee8a8309d3144e8e494b5483680599ce430e1e7b219b8e156f6dd0049
-e34e53d0463376b77b365bebaf08f9c1514f7b66520544953582916823f17d70ba3646a8d420e0
-07cca059a45276212c40599e79d8cd2b1768f964d3a364e65baafd767f43b2ab562de3050724c3
-0e8e11fd2f429ff7590b97f861f1ee9d19a3cfa66a8c755960b45cb8dfaffd80e3426e5c57e65c
-f5ea49f3504806bc96527c9b20987e99de44c09e93de6c7dab1bd4a2ba5476fc3209c1b421dfdb
-a91a8568087d8f7b706b522af6f181829a9ae7266789ff18cbbeaedaaef7f7df4c4ae7873dac2e
-0f8b1d43cebb6087bc2398837c6b8e6b2aec3e55c66cf3db3293fc371e7d93b32853fed1723b5e
-ca9932759d854db4dd5069aaa31f51a515bb9ae6342a583080ddfd2173a7b0e9143fca950495d3
-a90a7ec9bbbfaa2ba03661b05c8e85b6f3edfd82444b1d335b21d502b430f1dbfa2fd93e0f4b3b
-dc096f564e3d4ab470152b785dd2c05a9d69973665c5b67fc0d81151141a5eb78880086ad276b4
-ef039c78a77ed5e80044d87a0767a416d5f4739a1735917d99c5b207f9c94fa903d7063c3ff62d
-c2a2079ed2707d88a77c5c5009dab9d223e0efb33bdc736af0f85564ef88d1853f13343fdeb271
-fce4d42038c0e0fe544309f063b6f1f3dc9018a0e2893da5f1fb30cf003fb23deb46d13e7b51fb
-ab4610af7efb3827e5f0a27ed173c385e7a4f03b167971b69d6e57059e5380d6b521090540c8fd
-706dc8ddfd3397a05db5d030b5cae26330de17394c40234329bec6cba36f5ee51ac0cef01d5c9a
-186d73e1242855e94eda47507a65de5c8a568ac2ea69c0446ff2faa0615532eae5ef142fe8ce7a
-c08c058d68db0bf5a1ea72a74c763f76d475ca73eec18bb3de194e564628f7986dabf118d08b49
-08a26376d508991051ade1dbb85c7188a1c5140b9b874a56d8aa08ea8243404a5c626ad5d989b0
-0df27dd5fde4d705a87b97f0cf165a4903c32b40d7db2cc9ea2a709992a1804f621468f1f1f25a
-7301cc4d96574ef8b4fe7113397b378d0650bafec63eca65cda58a490bcc6a7840141503652dd0
-69e3860d1254aa78438f6d06e702040289f25d6c333df3e938dad48118b155d4a0bd893be04744
-bc41a02adda4f451785b5f29651a70b520add99694fe534e985df16edbcabfb29fc9f80570c599
-6bc0311534500bcd860f5e5dd8c3a5595fd0c16c0b4a71e6b19d8c65ec009d85728416e98865b6
-f732c97849a322d5d15933023627c4c3b493cd25fe787bd8a602c185c58ffed03d9b64b84f68b3
-7c041eec4d32420af95c174da76b1822d66d98873d7050d124387f9454d11b6b43f978a7dc5893
-341815d40bf7489a4443acf4e6249d8ed0ac31b2fb85d9a06a9061c180106238213253423d3e16
-e62c1c035ffa6be588b5e105ccbde9537ddb9e86eb9eee887e01ca91420e20dae0b338c928423d
-5dcd021828050e57213768c79faa75ba1958d7b43eea506e5fc0683955d0d93903e6510af75c47
-97d05c1c001252743623028d78a293054bed8847112656cf36567ba99eaff4a09d2e12a7664645
-38884477d00ebdaf62fc1f110a2b59efd877c9e570c127cd89801d5d2eab8de294085771fa38b6
-1584efb3877e4edb76957de903b0bc880a703adf57b73628cf6481491360bf081f999a347a3b8c
-ed28d04a74857774ac390d7b18d0719cd4b7c14a9fea42e80026d96486b29266ad8a2a31557023
-a581a882c8f8b294bd02bcca17e0cc3b47bee6d9f378323de02482101664a0189c7b69dd1bd91d
-36d45e95050ba0a29225a9ea038f03c6635840d3c794fbf42c4e2d61d8c25c152d3ebbd52dc5c5
-8e2d8b6f36136dcfa92b409c80ce96398f9292e48894a435494d72e399b82f87fc6e2a1025371a
-f68aa5572d8eb827b649e37e6b108c8643bccd73c90aa42bef97e51ca27ff45051056b679a459e
-c938e3ad5494ef9389a4213589d526bd5cdbe0795bf78b83097b893dfa661faec6214ff7c15896
-98485ab72a3a314546fd4440dca92cc0c126aed9bc5851aca6ac87b8948cc54023da7d1ebddb67
-021b357ecad8b8f54aa91b8ffb3ecfe8addce021a7c8454186b56c1c27e720bac49021546acd47
-6a8ad779af8973e641a47f5c79a86e61a6174aa7b529dbc8c9c1042270c20aff1608ec8fcd53fc
-bbabcc21985096706d9d313adbf1adf29926fd1dde0d5c688e4b1d7d0d6802824c6c7b7fd0ea98
-d1d06622520286704add2b5f2370aaeb0533694f9883478a75344fdd3505c7b6c4ad5a37abe943
-0ae1c3d2550309668dac31d748eb4e956c8894a18d11f387d16934356ec7379494d77d0393b94d
-5245f1f71d77de7b4d89f5529f6b5b9bd2744df09173be9a5e4c573c4ef5a1096ee82a2a53e883
-04f379afc6868b0eefd62a5cb2d1d21aba066937639b9fe5b10208da697f40a39e6ee11d621502
-366c546aac60fc79c6d05cea9d9e8d8ffa67ff442e75f4f28ac62a2660346e329b56fac248f3a4
-7665157eeba01b807b65c7bc9eba5d059faf5987212330ac3f7a04278de1cfc8e01ebe136443df
-edc5df38f539f573bed294de93639ffb430dd3f982f4ba760784841dc87ce0df076c1760609276
-b67f976e226e56fd9a24f5bc442a7a9cc3872f16a3a4647bdef24151c51ea7c2554be9841f5243
-99a21a28d33dd7cb294976da44ee73e52744c8bfac0581982d7ef27be12cba1d89078051ae1c5b
-5f2ab4752035faa6bc6de10370a935d9110f47400e08f3235bbeb4ca7cffbb7dac1e6e22ee5a58
-c7b33e7acf65586470c087594454484186d92f60d3603af307e5169b10e812e344a98555d6bcd9
-b6befeefbf526274a0f8fab7eedf23f1c5523323b2c0f0e4a9141bfdd3772d02deedd69b3937bf
-8533a6f205702e6a703446a4c13828f115bd547e59971e050d6b55c176c8e32d3f09338ee665b4
-a2f6f8692e1613f8168f3dff482fc3462aca3227a0f464aa065a8b97409aecd9b2b86831f190cd
-d988af54d7e2e6ce2600d74b78473ac42534cb1a4712afae659ecbf12cb11a958609e5a5701cff
-32acaae52f3423032687119953a0fb7b4c412086e460224d7451ec10effbb707fef8de4e43d9c3
-b0c2519b1df462943db7b4d1e5cc638021e6a3c1a1a72f3a28cb372b1f639dc74270734f43ba20
-2a5bcc805421f806e068ba068bdb0ea2b3f481a5dc6d99707caef1dff7ea9359da1b8b82cfd9b7
-b3a382a2d9eb740c9fed9948bbec3878eaa4ee5f6bbc39af5e39db0af35359e8ad124646b3e786
-737e06d8d7044d2ef7dbf7fbfd6e7a19d9b236ae7262aafa4c026bdf999aca8ca153e306fafde0
-5d8ae9d74f13913aed7c6dc3386f348b84e5442cc9fb6049eec5706a79398802772c40b383657b
-bd5c4b445777e0236710339fa7c57068737504b28d36ee8115d704b5efdd0062f9007f176c85d1
-3a35a6807d4a4cab3d2a57fa2aa7b4f83f44d734cbcc59ef84e42d8e62df197853570308bff37d
-f02a7730b82559893bdad5620bd6252f7d6e7a7877968c5736b1d328a2e6e2ddac3f75914ebba7
-6ed377bdeea8a4dcfce30c81859bc0f192593683311995037b169ee87fb0a2ea898679ee597106
-3e38185ff9a53be81919b04760a07ca721589b67975e893e12f61e5637c15afddfa1bb5c8a94bd
-1610e97903f46d34830f3dcd6bc8b925812af6cd30c1889c4429d67ccae457844775e1f4638326
-f4b4dbd66575fc71b986017406ecc04e89ea26f3a1b457af7aa5c2391899a51f53620549dd9aa5
-5af140070bcc439d4ec60a749cbd2339cd2405c5223a5e9a517f62e2b50cb00c514e79614e7f9b
-40c6af1f1a842080c15022b49dd86872db7841166b777df67caf278d22a829f269047b3fe1143c
-c16f137cb6edf3d9dbb8574e5411a8e69c1fce97fafafe3bce921d280cad1c0d2c3fd3cfd39c2c
-66f92c5ba458c5bc2baca4d9c4e67d9838827a0b3bb33d1e0bfd981a8b88fb8fa542e4d07956e5
-5c773b2bcd1fa5f6d0b84bc9f35436cf21004e59c7c4ded8aa8f61fc31b61e9e5cfed76043f697
-90069da95284172fd4a769f3ac5ead35882eca37bccba6cfe3fd00a1a5320c1e583cea4d338069
-168b633c2bb960add60699076f9553d65ec1cfcbe15f4696e470bba0d2d20b810bbb94de0e066a
-53cedc32f5a667d044df997a23d38ab60630bf1ecb4a63ae6e85ddbe826f6c208e8fa013536d67
-7a57a10237989400d0fb5c5680f40fe842a6d7827eb6dfbefb66d2ffec4a21f3184d9a7b8892dc
-f1842e755bfe07c3415d50b31650cb2fe423024399e3f1d48e833c6bd1a5882b3d897a48476774
-7447a56fd2f9f785928dc623b45e04c0534414e458c8084db9c0fb7b869303f03a7db0d24e106f
-c4569f9ad4f42ef096c1e73197358bc5b79a0140eec788fd815a595d138623d724e9f46bd75c74
-0c66781572cdd5d8c4b61a71c1de857c6f7e52a0a65413cb461dcfdaec8a7f6d5a527b5da11fbb
-f0779c15a11f3f2f81f38a02238917e270ff6bb47a21b36a20348a34108f5471f5eca0d2f684f0
-18ad7ac5f52b67d145963537534e3d5d487b65d38ce310cd1f5464b8d39b904e396b343097761d
-12ee73ff8fad544bb8ae894a77a71cbb6e0bc0262360f5f2eacdb52640f3fc5071e71ded3eb0f7
-3150a3afaac2882a0f4a78eb4de7ac732b7c201afcf70a1ff3e49bb4a7e786e1c48860023768ad
-8c40390bdba129bc40a3accc154a3a55a32b16e8dec5ba2f7a51f3c22821f00e913614955c3c74
-165f4b84d6e1f43137ed572e4a387bc7dafdcf0c015fc2b7ebaf1cc69c191bae34f569f29d93ec
-df6d8ce8647b68f96ac1444530b4abd76ace164eee01f6cb07c1457761846cfceb3c7ed3e8dce5
-b173f356312ed03851a1941dad7ce47f352efd3ebdc8b1a10984fc39408fc765d3ea63e5eee4ac
-c48969e9d770d53ae1f2afb7a7690063466ef9dfdee47448671dccff63d5139be1b3cf1c33537d
-5f191a73d3a8a4956a7b8c84828fc1445ff041a84474eaf7b45bf67dc9e621b44119005512e9d8
-0a89fb10ca9227cce67c6cbfc6f45bde1433a9e389888003a31591f77f7b65727bdefb150a2298
-66eba692c0a080dc7a926cb27caf77fa352404ece37bc5f69b88a8878f735c0066554b294ac76c
-e90583a5f0dbbb0c33fd9f52b75ffa450d7aa2e3cd0f7c01874c927eb0d818f4fabddb6c50df24
-855bf3f9984a0ef65a93e2e3d782794f2ed0262ac86a8ab343fdeda76c787cb5e68dff2b3e6cda
-3ab1f8b646fe1c9b63176ce5d9721d9e217883a5809f44377c2f61291eb3a8b8d5e4f406343451
-da9c11ca53ef9eb934f8b1a44f1bb8cd202cb1742d8213735777fdbacf7f0933a0b0bc8fd13084
-db3410a6736c1acdf9682cd633bfa27714697c08b2b3ae0812bd96b2b14c7d0df99e26dc08598f
-70d24ee32b43619119bbecb71a1738e95103d9ff1513216077a2cc1c786660f544c31155eca5ff
-20deb39075b09e281a06df04dea50179e88a2bb1b98d05560b1f1bbf6df981594b47a9035b554d
-c79b44e9cd91381d2ed71c6bb7eadc4422ee3c27ab678a22a785786904b1bca4919b40cc05ab1c
-c2faa2f1f2c1da946484660942f5288e5bdb044790c15edc3c979beab118101083e94631b8b9a2
-ed92c51c056294b7863e76d01cabe5bec973ba40ee485d88196c908d032051bb55144de8966328
-66de750fb8dc983487507a7b5ec1babf6cf080c6c0dd002b6e305cfdd97c426725fd648ad995e7
-4bd8d67e4e03d68fc7c789d243a25cff3f52c7bf4ee758bcb62d1c951102c0a81eebb224fceea6
-522ae93dc8c9af630a13e2382f24bea74c6279859901aca5e1479dd17ca58e635e5768203b7314
-f7f92e74bde2a7baf3b8acea39f800ebca4b2b2a40fe5cb0a671f836607e86c42d06e51ccba1e2
-4e14918d443bd792e836edae89639f36825e698eec03b7f649858a10886a900c371c890564d199
-1a8dc48644381aced59f4e8c8fc388da4911a9d25bde9e47566e54216044a7b08d1cefe9861e6f
-651357f25b526e9b54ae62c904094616a2285491292de7fb4f95235a3902170601c15d52b9bc85
-c153bb27d4ab8cd01c80863c6f34b784dc5f28f196c822a0ae59551b92148b7ee92a428a1ac9ed
-fb51cab977ae915e0c1c80033f22da741fce179cc91b5ebb7a3dd3bf579d7ced93f14f23e09a44
-954ad9d4cd2fca916a9e444f1ebee056779087ee33dc155a16484e938d38d09a97d551f1e12c62
-c1f90ac16a297e5f73add55f9606180d34e8e37b28006da4dcfb0e842647a46f6c44df4ef27d96
-aa8b26441324a228ca896ce8a5cf37b93a6b50f95776835fa5c041069c9d8e9a9edfe302aebb01
-97756c6fd3d6d3c2d6dae32c8a1148dbde0953a20d4d75489cac0447c3100bd2d15beee4043861
-c077c7b6ff2742daf44c2562a03d85a3d91d7deddce813f8cbdff39127c94d500900a31f68bee4
-903187e2defe546dd1d7a4106049c7a902b3abeaae9297d50eecfe2df733004ed34cfb26d7e93d
-99dff2bf37759d9f75a8b0ba0b85df6fe2e208d1947f5dd2c3c44bfa0348b3484eb3f29c053a1e
-9aba025c012e85b2b1c153e67ac2dbfe7d5c0d384edf06bb9063b5541956df3990517c7ab6eaaa
-18d771fac8f1ec9f99c6c3a34a422255498d6254c1601ef1fed76719306b6cc3debf99445c53cc
-c189d3b4ce6a3b036c58414e6be5df2602a6f7b6df3dc95cbec600c62972f6be5d48ebc2104043
-b7d7659cfa004c9647f0c1d7429281cec88a51161779c2f9f872aa9a12163acf2f276e3355c102
-ca4d472167913e2ed8b8d442ac2981d730bee5afcb4f9f06871d24f79f433dea17a6d827b21c7a
-f81b5d1d58d74cec4e6903c9a5f22ec3280000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000000000000000000
-cleartomark
-%%EndResource
-%%EndSetup
-%%Page: 1 1
-%%BeginPageSetup
-%%PageBoundingBox: 4 1 354 245
-%%EndPageSetup
-q 4 1 350 244 rectclip
-1 0 0 -1 0 252 cm q
-0 g
-0.25 w
-0 J
-0 j
-[] 0.0 d
-3.8 M q 1 0 0 -1 0 0 cm
-34.301 -229.602 m 37.449 -229.602 l 347.352 -229.602 m 344.199 -229.602
- l S Q
-BT
-7 0 0 -7 26.599999 231.935201 Tm
-/f-0-0 1 Tf
-(0)Tj
-ET
-q 1 0 0 -1 0 0 cm
-34.301 -187.898 m 37.449 -187.898 l 347.352 -187.898 m 344.199 -187.898
- l S Q
-BT
-7 0 0 -7 21.349999 190.235202 Tm
-/f-0-0 1 Tf
-(0.2)Tj
-ET
-q 1 0 0 -1 0 0 cm
-34.301 -146.199 m 37.449 -146.199 l 347.352 -146.199 m 344.199 -146.199
- l S Q
-BT
-7 0 0 -7 21.349999 148.535003 Tm
-/f-0-0 1 Tf
-(0.4)Tj
-ET
-q 1 0 0 -1 0 0 cm
-34.301 -104.449 m 37.449 -104.449 l 347.352 -104.449 m 344.199 -104.449
- l S Q
-BT
-7 0 0 -7 21.349999 106.785004 Tm
-/f-0-0 1 Tf
-(0.6)Tj
-ET
-q 1 0 0 -1 0 0 cm
-34.301 -62.75 m 37.449 -62.75 l 347.352 -62.75 m 344.199 -62.75 l S Q
-BT
-7 0 0 -7 21.349999 65.085005 Tm
-/f-0-0 1 Tf
-(0.8)Tj
-ET
-q 1 0 0 -1 0 0 cm
-34.301 -21.051 m 37.449 -21.051 l 347.352 -21.051 m 344.199 -21.051 l S Q
-BT
-7 0 0 -7 26.599999 23.385006 Tm
-/f-0-0 1 Tf
-(1)Tj
-ET
-q 1 0 0 -1 0 0 cm
-34.301 -229.602 m 34.301 -226.449 l 34.301 -21.051 m 34.301 -24.199 l S Q
-BT
-7 0 0 -7 33.424999 238.9352 Tm
-/f-0-0 1 Tf
-(0)Tj
-ET
-q 1 0 0 -1 0 0 cm
-65.602 -229.602 m 65.602 -226.449 l 65.602 -21.051 m 65.602 -24.199 l S Q
-BT
-7 0 0 -7 62.974998 238.9352 Tm
-/f-0-0 1 Tf
-(20)Tj
-ET
-q 1 0 0 -1 0 0 cm
-96.898 -229.602 m 96.898 -226.449 l 96.898 -21.051 m 96.898 -24.199 l S Q
-BT
-7 0 0 -7 94.274998 238.9352 Tm
-/f-0-0 1 Tf
-(40)Tj
-ET
-q 1 0 0 -1 0 0 cm
-128.199 -229.602 m 128.199 -226.449 l 128.199 -21.051 m 128.199 -24.199
- l S Q
-BT
-7 0 0 -7 125.574997 238.9352 Tm
-/f-0-0 1 Tf
-(60)Tj
-ET
-q 1 0 0 -1 0 0 cm
-159.5 -229.602 m 159.5 -226.449 l 159.5 -21.051 m 159.5 -24.199 l S Q
-BT
-7 0 0 -7 156.874996 238.9352 Tm
-/f-0-0 1 Tf
-(80)Tj
-ET
-q 1 0 0 -1 0 0 cm
-190.852 -229.602 m 190.852 -226.449 l 190.852 -21.051 m 190.852 -24.199
- l S Q
-BT
-7 0 0 -7 186.474995 238.9352 Tm
-/f-0-0 1 Tf
-(100)Tj
-ET
-q 1 0 0 -1 0 0 cm
-222.148 -229.602 m 222.148 -226.449 l 222.148 -21.051 m 222.148 -24.199
- l S Q
-BT
-7 0 0 -7 217.774995 238.9352 Tm
-/f-0-0 1 Tf
-(120)Tj
-ET
-q 1 0 0 -1 0 0 cm
-253.449 -229.602 m 253.449 -226.449 l 253.449 -21.051 m 253.449 -24.199
- l S Q
-BT
-7 0 0 -7 249.074994 238.9352 Tm
-/f-0-0 1 Tf
-(140)Tj
-ET
-q 1 0 0 -1 0 0 cm
-284.75 -229.602 m 284.75 -226.449 l 284.75 -21.051 m 284.75 -24.199 l S Q
-BT
-7 0 0 -7 280.374993 238.9352 Tm
-/f-0-0 1 Tf
-(160)Tj
-ET
-q 1 0 0 -1 0 0 cm
-316.051 -229.602 m 316.051 -226.449 l 316.051 -21.051 m 316.051 -24.199
- l S Q
-BT
-7 0 0 -7 311.674992 238.9352 Tm
-/f-0-0 1 Tf
-(180)Tj
-ET
-q 1 0 0 -1 0 0 cm
-347.352 -229.602 m 347.352 -226.449 l 347.352 -21.051 m 347.352 -24.199
- l S Q
-BT
-7 0 0 -7 342.974991 238.9352 Tm
-/f-0-0 1 Tf
-(200)Tj
-ET
-0.5 w
-q 1 0 0 -1 0 0 cm
-34.301 -21.051 313.051 -208.551 re S Q
-BT
-0 -7 -7 0 8.98516 164.330902 Tm
-/f-0-0 1 Tf
-(Packet Success Rate \(PSR\))Tj
-7 0 0 -7 173.010996 249.43516 Tm
-(distance \(m\))Tj
-18.922714 31.342856 Td
-(-85)Tj
-ET
-0.580392 0 0.831373 rg
-0.75 w
-q 1 0 0 -1 0 0 cm
-319 -27.699 m 338.949 -27.699 l 35.852 -21.051 m 60.898 -21.051 l 62.449
- -21.449 l 64.051 -21.449 l 65.602 -23.75 l 67.148 -36.699 l 68.75 -55.449
- l 70.301 -110.102 l 71.852 -156.199 l 73.449 -206.051 l 75 -224.602 l 76.551
- -229.398 l 78.148 -229.602 l 345.801 -229.602 l S Q
-0 g
-BT
-7 0 0 -7 305.468992 37.035005 Tm
-/f-0-0 1 Tf
-(-90)Tj
-ET
-0 0.619608 0.45098 rg
-q 1 0 0 -1 0 0 cm
-319 -34.699 m 338.949 -34.699 l 35.852 -21.051 m 76.551 -21.051 l 78.148
- -22.699 l 79.699 -23.551 l 81.25 -32.5 l 82.801 -39.801 l 84.398 -62.949
- l 85.949 -95.699 l 87.5 -134.5 l 89.102 -176.398 l 90.648 -204.551 l 92.199
- -220 l 93.801 -227.5 l 95.352 -229.398 l 96.898 -229.199 l 98.5 -229.602
- l 345.801 -229.602 l S Q
-0 g
-BT
-7 0 0 -7 305.468992 44.035005 Tm
-/f-0-0 1 Tf
-(-95)Tj
-ET
-0.341176 0.709804 0.909804 rg
-q 1 0 0 -1 0 0 cm
-319 -41.699 m 338.949 -41.699 l 35.852 -21.051 m 93.801 -21.051 l 95.352
- -21.449 l 96.898 -21.25 l 98.5 -22.102 l 100.051 -24.199 l 101.602 -27.699
- l 103.148 -34.602 l 104.75 -38.352 l 106.301 -53.148 l 107.852 -71.301 
-l 109.449 -94.25 l 111 -124.5 l 112.551 -149.5 l 114.148 -173.301 l 115.699
- -200.199 l 117.25 -210.199 l 118.801 -221.699 l 120.398 -224.801 l 121.949
- -228.949 l 123.5 -228.352 l 125.102 -229.602 l 345.801 -229.602 l S Q
-0 g
-BT
-7 0 0 -7 301.968992 51.035005 Tm
-/f-0-0 1 Tf
-(-100)Tj
-ET
-0.901961 0.619608 0 rg
-q 1 0 0 -1 0 0 cm
-319 -48.699 m 338.949 -48.699 l 35.852 -21.051 m 118.801 -21.051 l 120.398
- -21.25 l 121.949 -21.449 l 123.5 -21.25 l 125.102 -21.449 l 126.648 -22.699
- l 128.199 -22.301 l 129.801 -24.199 l 131.352 -25.449 l 132.898 -30 l 134.5
- -29.801 l 136.051 -35.648 l 137.602 -44.602 l 139.148 -55.648 l 140.75 
--62.949 l 142.301 -80.301 l 143.852 -94.648 l 145.449 -119.5 l 147 -133.051
- l 148.551 -151.801 l 150.148 -168.301 l 151.699 -189.148 l 153.25 -197.25
- l 154.801 -206.25 l 156.398 -215.398 l 157.949 -223.352 l 159.5 -222.699
- l 161.102 -226.449 l 162.648 -229.199 l 164.199 -229.602 l 165.801 -229.602
- l 167.352 -229.398 l 168.898 -229.602 l 345.801 -229.602 l S Q
-0 g
-BT
-7 0 0 -7 301.968992 58.035005 Tm
-/f-0-0 1 Tf
-(-105)Tj
-ET
-0.941176 0.890196 0.258824 rg
-q 1 0 0 -1 0 0 cm
-319 -55.699 m 338.949 -55.699 l 35.852 -21.051 m 157.949 -21.051 l 159.5
- -21.25 l 161.102 -21.051 l 164.199 -21.051 l 165.801 -21.25 l 167.352 -22.102
- l 168.898 -21.25 l 170.5 -22.102 l 172.051 -23.551 l 173.602 -22.949 l 
-175.148 -25.199 l 176.75 -25.199 l 178.301 -27.5 l 179.852 -29.398 l 181.449
- -34.602 l 183 -39.602 l 184.551 -40.449 l 186.148 -43.551 l 187.699 -54.648
- l 189.25 -59.852 l 190.852 -74.449 l 192.398 -80.051 l 193.949 -89.25 l
- 195.5 -95.898 l 197.102 -119.5 l 198.648 -132.398 l 200.199 -142.648 l 
-201.801 -155.75 l 203.352 -161.398 l 204.898 -174.75 l 206.5 -192.5 l 208.051
- -199.551 l 209.602 -206.051 l 211.148 -215.398 l 212.75 -216.648 l 214.301
- -221.25 l 215.852 -223.551 l 217.449 -224.398 l 219 -227.301 l 220.551 
--227.949 l 222.148 -227.301 l 223.699 -228.949 l 225.25 -228.75 l 226.852
- -229.398 l 228.398 -229.398 l 229.949 -229.602 l 345.801 -229.602 l S Q
-0 g
-BT
-7 0 0 -7 293.218993 65.035005 Tm
-/f-0-0 1 Tf
-(-106.58)Tj
-ET
-0 0.45098 0.698039 rg
-q 1 0 0 -1 0 0 cm
-319 -62.699 m 338.949 -62.699 l 35.852 -21.051 m 170.5 -21.051 l 172.051
- -21.25 l 173.602 -21.051 l 178.301 -21.051 l 179.852 -21.449 l 181.449 
--21.25 l 183 -21.25 l 184.551 -21.051 l 186.148 -22.102 l 187.699 -21.898
- l 189.25 -23.551 l 190.852 -24.801 l 192.398 -24.602 l 193.949 -25 l 195.5
- -27.301 l 197.102 -29.602 l 198.648 -31.25 l 200.199 -32.75 l 201.801 -37.551
- l 203.352 -38.801 l 204.898 -46.301 l 206.5 -48.801 l 208.051 -60.648 l
- 209.602 -65.449 l 211.148 -66.5 l 212.75 -86.352 l 214.301 -92.148 l 215.852
- -101.949 l 217.449 -117.801 l 219 -123.25 l 220.551 -133.898 l 222.148 
--147.648 l 223.699 -164.551 l 225.25 -167.25 l 226.852 -180.602 l 228.398
- -184.949 l 229.949 -193.75 l 231.5 -200.199 l 233.102 -210.852 l 234.648
- -213.949 l 236.199 -217.102 l 237.801 -220.199 l 239.352 -224.398 l 240.898
- -225.449 l 242.5 -226.051 l 244.051 -228.148 l 245.602 -228.75 l 247.148
- -229.199 l 248.75 -229.398 l 250.301 -228.949 l 251.852 -229.602 l 345.801
- -229.602 l S Q
-0 g
-BT
-7 0 0 -7 301.968992 72.035004 Tm
-/f-0-0 1 Tf
-(-110)Tj
-ET
-0.901961 0.121569 0.0588235 rg
-q 1 0 0 -1 0 0 cm
-319 -69.699 m 338.949 -69.699 l 35.852 -21.051 m 220.551 -21.051 l 222.148
- -21.25 l 225.25 -21.25 l 226.852 -21.449 l 228.398 -21.449 l 229.949 -21.898
- l 231.5 -22.102 l 233.102 -22.699 l 234.648 -21.898 l 236.199 -22.5 l 237.801
- -22.949 l 239.352 -23.75 l 240.898 -26.051 l 242.5 -25.648 l 244.051 -27.5
- l 245.602 -28.75 l 247.148 -29.801 l 248.75 -35 l 250.301 -35.648 l 251.852
- -36.898 l 253.449 -38.352 l 255 -44 l 256.551 -47.551 l 258.148 -54 l 259.699
- -58.602 l 261.25 -68.602 l 262.852 -65.25 l 264.398 -79.648 l 265.949 -85.051
- l 267.5 -89.648 l 269.102 -94.648 l 270.648 -108.449 l 272.199 -111.551
- l 273.801 -124.051 l 275.352 -135.148 l 276.898 -140.352 l 278.5 -152.25
- l 280.051 -155.551 l 281.602 -167.648 l 283.148 -174.352 l 284.75 -182.25
- l 286.301 -188.949 l 287.852 -195.398 l 289.449 -200.602 l 291 -203.949
- l 292.551 -211.852 l 294.148 -212.898 l 295.699 -215.852 l 297.25 -219.602
- l 298.852 -220 l 300.398 -222.102 l 301.949 -225.199 l 303.5 -227.102 l
- 305.102 -228.148 l 306.648 -227.301 l 308.199 -228.148 l 309.801 -227.949
- l 311.352 -228.949 l 312.898 -229.602 l 314.5 -229.602 l 316.051 -229.199
- l 317.602 -229.398 l 319.199 -229.602 l 320.75 -229.398 l 322.301 -229.602
- l 345.801 -229.602 l S Q
-0 g
-0.5 w
-q 1 0 0 -1 0 0 cm
-34.301 -21.051 313.051 -208.551 re S Q
-BT
-7 0 0 -7 99.558998 12.885006 Tm
-/f-0-0 1 Tf
-(Packet \(MSDU\) size = 7 bytes; tx power = 0 dBm; channel = 11)Tj
-ET
-Q Q
-showpage
-%%Trailer
-end
-%%EOF
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/figures/802-15-4-ber.eps ns-3.46/src/lr-wpan/doc/figures/802-15-4-ber.eps
--- ns-3.45/src/lr-wpan/doc/figures/802-15-4-ber.eps	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/lr-wpan/doc/figures/802-15-4-ber.eps	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,1030 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: 802.15.4-ber.eps
+%%Creator: gnuplot 4.4 patchlevel 2
+%%CreationDate: Tue Oct  4 14:51:04 2011
+%%DocumentFonts: (atend)
+%%BoundingBox: 50 50 410 302
+%%EndComments
+%%BeginProlog
+/gnudict 256 dict def
+gnudict begin
+%
+% The following true/false flags may be edited by hand if desired.
+% The unit line width and grayscale image gamma correction may also be changed.
+%
+/Color true def
+/Blacktext false def
+/Solid false def
+/Dashlength 1 def
+/Landscape false def
+/Level1 false def
+/Rounded false def
+/ClipToBoundingBox false def
+/TransparentPatterns false def
+/gnulinewidth 5.000 def
+/userlinewidth gnulinewidth def
+/Gamma 1.0 def
+%
+/vshift -46 def
+/dl1 {
+  10.0 Dashlength mul mul
+  Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if
+} def
+/dl2 {
+  10.0 Dashlength mul mul
+  Rounded { currentlinewidth 0.75 mul add } if
+} def
+/hpt_ 31.5 def
+/vpt_ 31.5 def
+/hpt hpt_ def
+/vpt vpt_ def
+Level1 {} {
+/SDict 10 dict def
+systemdict /pdfmark known not {
+  userdict /pdfmark systemdict /cleartomark get put
+} if
+SDict begin [
+  /Title (802.15.4-ber.eps)
+  /Subject (gnuplot plot)
+  /Creator (gnuplot 4.4 patchlevel 2)
+  /Author (tomh)
+%  /Producer (gnuplot)
+%  /Keywords ()
+  /CreationDate (Tue Oct  4 14:51:04 2011)
+  /DOCINFO pdfmark
+end
+} ifelse
+/doclip {
+  ClipToBoundingBox {
+    newpath 50 50 moveto 410 50 lineto 410 302 lineto 50 302 lineto closepath
+    clip
+  } if
+} def
+%
+% Gnuplot Prolog Version 4.4 (August 2010)
+%
+%/SuppressPDFMark true def
+%
+/M {moveto} bind def
+/L {lineto} bind def
+/R {rmoveto} bind def
+/V {rlineto} bind def
+/N {newpath moveto} bind def
+/Z {closepath} bind def
+/C {setrgbcolor} bind def
+/f {rlineto fill} bind def
+/g {setgray} bind def
+/Gshow {show} def   % May be redefined later in the file to support UTF-8
+/vpt2 vpt 2 mul def
+/hpt2 hpt 2 mul def
+/Lshow {currentpoint stroke M 0 vshift R 
+	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
+/Rshow {currentpoint stroke M dup stringwidth pop neg vshift R
+	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
+/Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R 
+	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
+/UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def
+  /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def
+/DL {Color {setrgbcolor Solid {pop []} if 0 setdash}
+ {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def
+/BL {stroke userlinewidth 2 mul setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+/AL {stroke userlinewidth 2 div setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+/UL {dup gnulinewidth mul /userlinewidth exch def
+	dup 1 lt {pop 1} if 10 mul /udl exch def} def
+/PL {stroke userlinewidth setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+3.8 setmiterlimit
+% Default Line colors
+/LCw {1 1 1} def
+/LCb {0 0 0} def
+/LCa {0 0 0} def
+/LC0 {1 0 0} def
+/LC1 {0 1 0} def
+/LC2 {0 0 1} def
+/LC3 {1 0 1} def
+/LC4 {0 1 1} def
+/LC5 {1 1 0} def
+/LC6 {0 0 0} def
+/LC7 {1 0.3 0} def
+/LC8 {0.5 0.5 0.5} def
+% Default Line Types
+/LTw {PL [] 1 setgray} def
+/LTb {BL [] LCb DL} def
+/LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def
+/LT0 {PL [] LC0 DL} def
+/LT1 {PL [4 dl1 2 dl2] LC1 DL} def
+/LT2 {PL [2 dl1 3 dl2] LC2 DL} def
+/LT3 {PL [1 dl1 1.5 dl2] LC3 DL} def
+/LT4 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def
+/LT5 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC5 DL} def
+/LT6 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC6 DL} def
+/LT7 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC7 DL} def
+/LT8 {PL [2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 4 dl2] LC8 DL} def
+/Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def
+/Dia {stroke [] 0 setdash 2 copy vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke
+  Pnt} def
+/Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V
+  currentpoint stroke M
+  hpt neg vpt neg R hpt2 0 V stroke
+ } def
+/Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke
+  Pnt} def
+/Crs {stroke [] 0 setdash exch hpt sub exch vpt add M
+  hpt2 vpt2 neg V currentpoint stroke M
+  hpt2 neg 0 R hpt2 vpt2 V stroke} def
+/TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke
+  Pnt} def
+/Star {2 copy Pls Crs} def
+/BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath fill} def
+/TriUF {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath fill} def
+/TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke
+  Pnt} def
+/TriDF {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath fill} def
+/DiaF {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath fill} def
+/Pent {stroke [] 0 setdash 2 copy gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore Pnt} def
+/PentF {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath fill grestore} def
+/Circle {stroke [] 0 setdash 2 copy
+  hpt 0 360 arc stroke Pnt} def
+/CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def
+/C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def
+/C1 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C2 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C3 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C4 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 180 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C5 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc
+	2 copy moveto
+	2 copy vpt 180 270 arc closepath fill
+	vpt 0 360 arc} bind def
+/C6 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C7 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C8 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 270 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C9 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 270 450 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill
+	2 copy moveto
+	2 copy vpt 90 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C11 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 180 arc closepath fill
+	2 copy moveto
+	2 copy vpt 270 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C12 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 180 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C13 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc closepath fill
+	2 copy moveto
+	2 copy vpt 180 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C14 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 360 arc closepath fill
+	vpt 0 360 arc} bind def
+/C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
+	neg 0 rlineto closepath} bind def
+/Square {dup Rec} bind def
+/Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def
+/S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def
+/S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def
+/S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
+/S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def
+/S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
+/S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill
+	exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
+/S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def
+/S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill
+	2 copy vpt Square fill Bsquare} bind def
+/S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def
+/S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def
+/S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill
+	Bsquare} bind def
+/S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill
+	Bsquare} bind def
+/S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def
+/S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+	2 copy vpt Square fill Bsquare} bind def
+/S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+	2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
+/S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def
+/D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def
+/D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def
+/D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def
+/D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def
+/D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def
+/D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def
+/D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def
+/D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def
+/D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def
+/D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def
+/D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def
+/D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def
+/D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def
+/D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def
+/D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def
+/D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def
+/DiaE {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke} def
+/BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke} def
+/TriUE {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke} def
+/TriDE {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke} def
+/PentE {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore} def
+/CircE {stroke [] 0 setdash 
+  hpt 0 360 arc stroke} def
+/Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def
+/DiaW {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V Opaque stroke} def
+/BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V Opaque stroke} def
+/TriUW {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V Opaque stroke} def
+/TriDW {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V Opaque stroke} def
+/PentW {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  Opaque stroke grestore} def
+/CircW {stroke [] 0 setdash 
+  hpt 0 360 arc Opaque stroke} def
+/BoxFill {gsave Rec 1 setgray fill grestore} def
+/Density {
+  /Fillden exch def
+  currentrgbcolor
+  /ColB exch def /ColG exch def /ColR exch def
+  /ColR ColR Fillden mul Fillden sub 1 add def
+  /ColG ColG Fillden mul Fillden sub 1 add def
+  /ColB ColB Fillden mul Fillden sub 1 add def
+  ColR ColG ColB setrgbcolor} def
+/BoxColFill {gsave Rec PolyFill} def
+/PolyFill {gsave Density fill grestore grestore} def
+/h {rlineto rlineto rlineto gsave closepath fill grestore} bind def
+%
+% PostScript Level 1 Pattern Fill routine for rectangles
+% Usage: x y w h s a XX PatternFill
+%	x,y = lower left corner of box to be filled
+%	w,h = width and height of box
+%	  a = angle in degrees between lines and x-axis
+%	 XX = 0/1 for no/yes cross-hatch
+%
+/PatternFill {gsave /PFa [ 9 2 roll ] def
+  PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate
+  PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec
+  gsave 1 setgray fill grestore clip
+  currentlinewidth 0.5 mul setlinewidth
+  /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def
+  0 0 M PFa 5 get rotate PFs -2 div dup translate
+  0 1 PFs PFa 4 get div 1 add floor cvi
+	{PFa 4 get mul 0 M 0 PFs V} for
+  0 PFa 6 get ne {
+	0 1 PFs PFa 4 get div 1 add floor cvi
+	{PFa 4 get mul 0 2 1 roll M PFs 0 V} for
+ } if
+  stroke grestore} def
+%
+/languagelevel where
+ {pop languagelevel} {1} ifelse
+ 2 lt
+	{/InterpretLevel1 true def}
+	{/InterpretLevel1 Level1 def}
+ ifelse
+%
+% PostScript level 2 pattern fill definitions
+%
+/Level2PatternFill {
+/Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8}
+	bind def
+/KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} 
+>> matrix makepattern
+/Pat1 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke
+	0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke}
+>> matrix makepattern
+/Pat2 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L
+	8 8 L 8 0 L 0 0 L fill}
+>> matrix makepattern
+/Pat3 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L
+	0 12 M 12 0 L stroke}
+>> matrix makepattern
+/Pat4 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L
+	0 -4 M 12 8 L stroke}
+>> matrix makepattern
+/Pat5 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L
+	0 12 M 8 -4 L 4 12 M 10 0 L stroke}
+>> matrix makepattern
+/Pat6 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L
+	0 -4 M 8 12 L 4 -4 M 10 8 L stroke}
+>> matrix makepattern
+/Pat7 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L
+	12 0 M -4 8 L 12 4 M 0 10 L stroke}
+>> matrix makepattern
+/Pat8 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L
+	-4 0 M 12 8 L -4 4 M 8 10 L stroke}
+>> matrix makepattern
+/Pat9 exch def
+/Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def
+/Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def
+/Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def
+/Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def
+/Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def
+/Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def
+/Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def
+} def
+%
+%
+%End of PostScript Level 2 code
+%
+/PatternBgnd {
+  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
+} def
+%
+% Substitute for Level 2 pattern fill codes with
+% grayscale if Level 2 support is not selected.
+%
+/Level1PatternFill {
+/Pattern1 {0.250 Density} bind def
+/Pattern2 {0.500 Density} bind def
+/Pattern3 {0.750 Density} bind def
+/Pattern4 {0.125 Density} bind def
+/Pattern5 {0.375 Density} bind def
+/Pattern6 {0.625 Density} bind def
+/Pattern7 {0.875 Density} bind def
+} def
+%
+% Now test for support of Level 2 code
+%
+Level1 {Level1PatternFill} {Level2PatternFill} ifelse
+%
+/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont
+dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall
+currentdict end definefont pop
+/MFshow {
+   { dup 5 get 3 ge
+     { 5 get 3 eq {gsave} {grestore} ifelse }
+     {dup dup 0 get findfont exch 1 get scalefont setfont
+     [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6
+     get exch 4 get {Gshow} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq
+     {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5
+     get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div
+     dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get
+     show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop
+     pop aload pop M} ifelse }ifelse }ifelse }
+     ifelse }
+   forall} def
+/Gswidth {dup type /stringtype eq {stringwidth} {pop (n) stringwidth} ifelse} def
+/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }
+ {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont
+     6 get Gswidth pop add} {pop} ifelse} ifelse} forall} def
+/MLshow { currentpoint stroke M
+  0 exch R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/MRshow { currentpoint stroke M
+  exch dup MFwidth neg 3 -1 roll R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/MCshow { currentpoint stroke M
+  exch dup MFwidth -2 div 3 -1 roll R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/XYsave    { [( ) 1 2 true false 3 ()] } bind def
+/XYrestore { [( ) 1 2 true false 4 ()] } bind def
+end
+%%EndProlog
+gnudict begin
+gsave
+doclip
+50 50 translate
+0.050 0.050 scale
+0 setgray
+newpath
+(Times-BoldItalic) findfont 140 scalefont setfont
+1.000 UL
+LTb
+1.000 UL
+LTa
+938 448 M
+6009 0 V
+stroke
+LTb
+938 448 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 448 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-09)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 596 M
+31 0 V
+5978 0 R
+-31 0 V
+938 792 M
+31 0 V
+5978 0 R
+-31 0 V
+938 892 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 939 M
+6009 0 V
+stroke
+LTb
+938 939 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 939 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-08)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 1087 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1283 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1383 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 1431 M
+6009 0 V
+stroke
+LTb
+938 1431 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 1431 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-07)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 1579 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1774 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1875 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 1922 M
+6009 0 V
+stroke
+LTb
+938 1922 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 1922 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-06)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 2070 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2266 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2366 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 2414 M
+6009 0 V
+stroke
+LTb
+938 2414 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 2414 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1e-05)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 2562 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2757 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2858 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 2905 M
+6009 0 V
+stroke
+LTb
+938 2905 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 2905 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.0001)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 3053 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3249 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3349 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 3397 M
+6009 0 V
+stroke
+LTb
+938 3397 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 3397 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.001)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 3545 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3740 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3840 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 3888 M
+6009 0 V
+stroke
+LTb
+938 3888 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 3888 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.01)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 4036 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4232 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4332 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 4380 M
+6009 0 V
+stroke
+LTb
+938 4380 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 4380 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.1)]
+] -46.7 MRshow
+1.000 UL
+LTb
+938 4527 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4723 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4823 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+LTa
+938 4871 M
+6009 0 V
+stroke
+LTb
+938 4871 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 4871 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1)]
+] -46.7 MRshow
+1.000 UL
+LTb
+1.000 UL
+LTa
+938 448 M
+0 4423 V
+stroke
+LTb
+938 448 M
+0 63 V
+0 4360 R
+0 -63 V
+stroke
+938 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-10)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTa
+2140 448 M
+0 4423 V
+stroke
+LTb
+2140 448 M
+0 63 V
+0 4360 R
+0 -63 V
+stroke
+2140 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-5)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTa
+3342 448 M
+0 4423 V
+stroke
+LTb
+3342 448 M
+0 63 V
+0 4360 R
+0 -63 V
+stroke
+3342 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTa
+4543 448 M
+0 4423 V
+stroke
+LTb
+4543 448 M
+0 63 V
+0 4360 R
+0 -63 V
+stroke
+4543 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 5)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTa
+5745 448 M
+0 4220 V
+0 140 R
+0 63 V
+stroke
+LTb
+5745 448 M
+0 63 V
+0 4360 R
+0 -63 V
+stroke
+5745 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 10)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTa
+6947 448 M
+0 4423 V
+stroke
+LTb
+6947 448 M
+0 63 V
+0 4360 R
+0 -63 V
+stroke
+6947 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 15)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTb
+938 4871 N
+938 448 L
+6009 0 V
+0 4423 V
+-6009 0 V
+Z stroke
+LCb setrgbcolor
+112 2659 M
+currentpoint gsave translate -270 rotate 0 0 moveto
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Bit Error Rate \(BER\))]
+] -46.7 MCshow
+grestore
+LTb
+LCb setrgbcolor
+3942 98 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (SNR \(dB\))]
+] -46.7 MCshow
+LTb
+1.000 UP
+1.000 UL
+LTb
+% Begin plot #1
+5.000 UL
+LT0
+LCb setrgbcolor
+6296 4738 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (802.15.4)]
+] -46.7 MRshow
+LT0
+6380 4738 M
+399 0 V
+938 4629 M
+24 -3 V
+24 -2 V
+24 -3 V
+24 -3 V
+24 -3 V
+24 -3 V
+24 -4 V
+24 -3 V
+24 -3 V
+24 -4 V
+24 -3 V
+24 -4 V
+24 -4 V
+25 -4 V
+24 -4 V
+24 -4 V
+24 -5 V
+24 -4 V
+24 -5 V
+24 -5 V
+24 -5 V
+24 -5 V
+24 -5 V
+24 -6 V
+24 -5 V
+24 -6 V
+24 -6 V
+24 -6 V
+24 -6 V
+24 -7 V
+24 -6 V
+24 -7 V
+24 -7 V
+24 -8 V
+24 -7 V
+24 -8 V
+24 -8 V
+24 -8 V
+24 -9 V
+24 -9 V
+24 -9 V
+25 -9 V
+24 -10 V
+24 -9 V
+24 -11 V
+24 -10 V
+24 -11 V
+24 -11 V
+24 -12 V
+24 -11 V
+24 -13 V
+24 -12 V
+24 -13 V
+24 -13 V
+24 -14 V
+24 -14 V
+24 -14 V
+24 -15 V
+24 -16 V
+24 -16 V
+24 -16 V
+24 -17 V
+24 -17 V
+24 -17 V
+24 -19 V
+24 -18 V
+24 -20 V
+24 -20 V
+24 -20 V
+25 -21 V
+24 -22 V
+24 -22 V
+24 -23 V
+24 -23 V
+24 -24 V
+24 -25 V
+24 -26 V
+24 -26 V
+24 -27 V
+24 -28 V
+24 -28 V
+24 -29 V
+24 -30 V
+24 -31 V
+24 -32 V
+24 -32 V
+24 -34 V
+24 -34 V
+24 -35 V
+24 -37 V
+24 -37 V
+24 -38 V
+24 -39 V
+24 -40 V
+24 -42 V
+24 -42 V
+24 -43 V
+25 -45 V
+24 -46 V
+24 -46 V
+24 -49 V
+24 -49 V
+stroke 3390 2910 M
+24 -50 V
+24 -52 V
+24 -53 V
+24 -55 V
+24 -56 V
+24 -57 V
+24 -59 V
+24 -60 V
+24 -61 V
+24 -63 V
+24 -65 V
+24 -66 V
+24 -68 V
+24 -70 V
+24 -71 V
+24 -73 V
+24 -75 V
+24 -76 V
+24 -78 V
+24 -81 V
+24 -82 V
+24 -84 V
+25 -86 V
+24 -88 V
+24 -90 V
+24 -93 V
+24 -94 V
+24 -97 V
+24 -99 V
+24 -101 V
+24 -104 V
+24 -106 V
+11 -49 V
+% End plot #1
+stroke
+1.000 UL
+LTb
+938 4871 N
+938 448 L
+6009 0 V
+0 4423 V
+-6009 0 V
+Z stroke
+1.000 UP
+1.000 UL
+LTb
+stroke
+grestore
+end
+showpage
+%%Trailer
+%%DocumentFonts: Times-BoldItalic
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/figures/802-15-4-per-sens.eps ns-3.46/src/lr-wpan/doc/figures/802-15-4-per-sens.eps
--- ns-3.45/src/lr-wpan/doc/figures/802-15-4-per-sens.eps	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/lr-wpan/doc/figures/802-15-4-per-sens.eps	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,2690 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: 802.15.4-per-vs-rxSignal.eps
+%%Creator: gnuplot 5.2 patchlevel 8
+%%CreationDate: Mon Dec 19 13:38:56 2022
+%%DocumentFonts: (atend)
+%%BoundingBox: 50 50 410 302
+%%EndComments
+%%BeginProlog
+/gnudict 256 dict def
+gnudict begin
+%
+% The following true/false flags may be edited by hand if desired.
+% The unit line width and grayscale image gamma correction may also be changed.
+%
+/Color true def
+/Blacktext false def
+/Solid false def
+/Dashlength 1 def
+/Landscape false def
+/Level1 false def
+/Level3 false def
+/Rounded false def
+/ClipToBoundingBox false def
+/SuppressPDFMark false def
+/TransparentPatterns false def
+/gnulinewidth 5.000 def
+/userlinewidth gnulinewidth def
+/Gamma 1.0 def
+/BackgroundColor {-1.000 -1.000 -1.000} def
+%
+/vshift -46 def
+/dl1 {
+  10.0 Dashlength userlinewidth gnulinewidth div mul mul mul
+  Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if
+} def
+/dl2 {
+  10.0 Dashlength userlinewidth gnulinewidth div mul mul mul
+  Rounded { currentlinewidth 0.75 mul add } if
+} def
+/hpt_ 31.5 def
+/vpt_ 31.5 def
+/hpt hpt_ def
+/vpt vpt_ def
+/doclip {
+  ClipToBoundingBox {
+    newpath 50 50 moveto 410 50 lineto 410 302 lineto 50 302 lineto closepath
+    clip
+  } if
+} def
+%
+% Gnuplot Prolog Version 5.2 (Dec 2017)
+%
+%/SuppressPDFMark true def
+%
+/M {moveto} bind def
+/L {lineto} bind def
+/R {rmoveto} bind def
+/V {rlineto} bind def
+/N {newpath moveto} bind def
+/Z {closepath} bind def
+/C {setrgbcolor} bind def
+/f {rlineto fill} bind def
+/g {setgray} bind def
+/Gshow {show} def   % May be redefined later in the file to support UTF-8
+/vpt2 vpt 2 mul def
+/hpt2 hpt 2 mul def
+/Lshow {currentpoint stroke M 0 vshift R 
+	Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def
+/Rshow {currentpoint stroke M dup stringwidth pop neg vshift R
+	Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def
+/Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R 
+	Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def
+/UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def
+  /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def
+/DL {Color {setrgbcolor Solid {pop []} if 0 setdash}
+ {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def
+/BL {stroke userlinewidth 2 mul setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+/AL {stroke userlinewidth 2 div setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+/UL {dup gnulinewidth mul /userlinewidth exch def
+	dup 1 lt {pop 1} if 10 mul /udl exch def} def
+/PL {stroke userlinewidth setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+3.8 setmiterlimit
+% Classic Line colors (version 5.0)
+/LCw {1 1 1} def
+/LCb {0 0 0} def
+/LCa {0 0 0} def
+/LC0 {1 0 0} def
+/LC1 {0 1 0} def
+/LC2 {0 0 1} def
+/LC3 {1 0 1} def
+/LC4 {0 1 1} def
+/LC5 {1 1 0} def
+/LC6 {0 0 0} def
+/LC7 {1 0.3 0} def
+/LC8 {0.5 0.5 0.5} def
+% Default dash patterns (version 5.0)
+/LTB {BL [] LCb DL} def
+/LTw {PL [] 1 setgray} def
+/LTb {PL [] LCb DL} def
+/LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def
+/LT0 {PL [] LC0 DL} def
+/LT1 {PL [2 dl1 3 dl2] LC1 DL} def
+/LT2 {PL [1 dl1 1.5 dl2] LC2 DL} def
+/LT3 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC3 DL} def
+/LT4 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def
+/LT5 {PL [4 dl1 2 dl2] LC5 DL} def
+/LT6 {PL [1.5 dl1 1.5 dl2 1.5 dl1 1.5 dl2 1.5 dl1 6 dl2] LC6 DL} def
+/LT7 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC7 DL} def
+/LT8 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC8 DL} def
+/SL {[] 0 setdash} def
+/Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def
+/Dia {stroke [] 0 setdash 2 copy vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke
+  Pnt} def
+/Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V
+  currentpoint stroke M
+  hpt neg vpt neg R hpt2 0 V stroke
+ } def
+/Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke
+  Pnt} def
+/Crs {stroke [] 0 setdash exch hpt sub exch vpt add M
+  hpt2 vpt2 neg V currentpoint stroke M
+  hpt2 neg 0 R hpt2 vpt2 V stroke} def
+/TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke
+  Pnt} def
+/Star {2 copy Pls Crs} def
+/BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath fill} def
+/TriUF {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath fill} def
+/TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke
+  Pnt} def
+/TriDF {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath fill} def
+/DiaF {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath fill} def
+/Pent {stroke [] 0 setdash 2 copy gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore Pnt} def
+/PentF {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath fill grestore} def
+/Circle {stroke [] 0 setdash 2 copy
+  hpt 0 360 arc stroke Pnt} def
+/CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def
+/C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def
+/C1 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C2 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C3 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C4 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 180 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C5 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc
+	2 copy moveto
+	2 copy vpt 180 270 arc closepath fill
+	vpt 0 360 arc} bind def
+/C6 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C7 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C8 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 270 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C9 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 270 450 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill
+	2 copy moveto
+	2 copy vpt 90 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C11 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 180 arc closepath fill
+	2 copy moveto
+	2 copy vpt 270 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C12 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 180 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C13 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc closepath fill
+	2 copy moveto
+	2 copy vpt 180 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C14 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 360 arc closepath fill
+	vpt 0 360 arc} bind def
+/C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
+	neg 0 rlineto closepath} bind def
+/Square {dup Rec} bind def
+/Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def
+/S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def
+/S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def
+/S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
+/S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def
+/S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
+/S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill
+	exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
+/S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def
+/S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill
+	2 copy vpt Square fill Bsquare} bind def
+/S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def
+/S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def
+/S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill
+	Bsquare} bind def
+/S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill
+	Bsquare} bind def
+/S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def
+/S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+	2 copy vpt Square fill Bsquare} bind def
+/S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+	2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
+/S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def
+/D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def
+/D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def
+/D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def
+/D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def
+/D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def
+/D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def
+/D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def
+/D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def
+/D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def
+/D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def
+/D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def
+/D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def
+/D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def
+/D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def
+/D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def
+/D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def
+/DiaE {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke} def
+/BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke} def
+/TriUE {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke} def
+/TriDE {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke} def
+/PentE {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore} def
+/CircE {stroke [] 0 setdash 
+  hpt 0 360 arc stroke} def
+/Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def
+/DiaW {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V Opaque stroke} def
+/BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V Opaque stroke} def
+/TriUW {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V Opaque stroke} def
+/TriDW {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V Opaque stroke} def
+/PentW {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  Opaque stroke grestore} def
+/CircW {stroke [] 0 setdash 
+  hpt 0 360 arc Opaque stroke} def
+/BoxFill {gsave Rec 1 setgray fill grestore} def
+/Density {
+  /Fillden exch def
+  currentrgbcolor
+  /ColB exch def /ColG exch def /ColR exch def
+  /ColR ColR Fillden mul Fillden sub 1 add def
+  /ColG ColG Fillden mul Fillden sub 1 add def
+  /ColB ColB Fillden mul Fillden sub 1 add def
+  ColR ColG ColB setrgbcolor} def
+/BoxColFill {gsave Rec PolyFill} def
+/PolyFill {gsave Density fill grestore grestore} def
+/h {rlineto rlineto rlineto closepath gsave fill grestore stroke} bind def
+%
+% PostScript Level 1 Pattern Fill routine for rectangles
+% Usage: x y w h s a XX PatternFill
+%	x,y = lower left corner of box to be filled
+%	w,h = width and height of box
+%	  a = angle in degrees between lines and x-axis
+%	 XX = 0/1 for no/yes cross-hatch
+%
+/PatternFill {gsave /PFa [ 9 2 roll ] def
+  PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate
+  PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec
+  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
+  clip
+  currentlinewidth 0.5 mul setlinewidth
+  /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def
+  0 0 M PFa 5 get rotate PFs -2 div dup translate
+  0 1 PFs PFa 4 get div 1 add floor cvi
+	{PFa 4 get mul 0 M 0 PFs V} for
+  0 PFa 6 get ne {
+	0 1 PFs PFa 4 get div 1 add floor cvi
+	{PFa 4 get mul 0 2 1 roll M PFs 0 V} for
+ } if
+  stroke grestore} def
+%
+/languagelevel where
+ {pop languagelevel} {1} ifelse
+dup 2 lt
+	{/InterpretLevel1 true def
+	 /InterpretLevel3 false def}
+	{/InterpretLevel1 Level1 def
+	 2 gt
+	    {/InterpretLevel3 Level3 def}
+	    {/InterpretLevel3 false def}
+	 ifelse }
+ ifelse
+%
+% PostScript level 2 pattern fill definitions
+%
+/Level2PatternFill {
+/Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8}
+	bind def
+/KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} 
+>> matrix makepattern
+/Pat1 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke
+	0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke}
+>> matrix makepattern
+/Pat2 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L
+	8 8 L 8 0 L 0 0 L fill}
+>> matrix makepattern
+/Pat3 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L
+	0 12 M 12 0 L stroke}
+>> matrix makepattern
+/Pat4 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L
+	0 -4 M 12 8 L stroke}
+>> matrix makepattern
+/Pat5 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L
+	0 12 M 8 -4 L 4 12 M 10 0 L stroke}
+>> matrix makepattern
+/Pat6 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L
+	0 -4 M 8 12 L 4 -4 M 10 8 L stroke}
+>> matrix makepattern
+/Pat7 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L
+	12 0 M -4 8 L 12 4 M 0 10 L stroke}
+>> matrix makepattern
+/Pat8 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L
+	-4 0 M 12 8 L -4 4 M 8 10 L stroke}
+>> matrix makepattern
+/Pat9 exch def
+/Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def
+/Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def
+/Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def
+/Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def
+/Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def
+/Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def
+/Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def
+} def
+%
+%
+%End of PostScript Level 2 code
+%
+/PatternBgnd {
+  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
+} def
+%
+% Substitute for Level 2 pattern fill codes with
+% grayscale if Level 2 support is not selected.
+%
+/Level1PatternFill {
+/Pattern1 {0.250 Density} bind def
+/Pattern2 {0.500 Density} bind def
+/Pattern3 {0.750 Density} bind def
+/Pattern4 {0.125 Density} bind def
+/Pattern5 {0.375 Density} bind def
+/Pattern6 {0.625 Density} bind def
+/Pattern7 {0.875 Density} bind def
+} def
+%
+% Now test for support of Level 2 code
+%
+Level1 {Level1PatternFill} {Level2PatternFill} ifelse
+%
+/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont
+dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall
+currentdict end definefont pop
+%
+/Metrics {ExtendTextBox Gswidth} def
+/Lwidth {currentpoint stroke M 0 vshift R Metrics} def
+/Rwidth {currentpoint stroke M dup stringwidth pop neg vshift R Metrics} def
+/Cwidth {currentpoint stroke M dup stringwidth pop -2 div vshift R Metrics} def
+/GLwidth {currentpoint stroke M 0 vshift R {ExtendTextBox} forall} def
+/GRwidth {currentpoint stroke M dup Gwidth vshift R {ExtendTextBox} forall} def
+/GCwidth {currentpoint stroke M dup Gwidth 2 div vshift R {ExtendTextBox} forall} def
+/GLwidth2 {0 Gwidth AddGlyphWidth} def
+/GRwidth2 {Gwidth -1 mul 0 AddGlyphWidth} def
+/GCwidth2 {Gwidth 2 div dup -1 mul AddGlyphWidth} def
+/AddGlyphWidth { dup TBx2 gt {userdict /TBx2 3 -1 roll put} {pop} ifelse
+                 dup TBx1 lt {userdict /TBx1 3 -1 roll put} {pop} ifelse } def
+/MFshow {
+   { dup 5 get 3 ge
+     { 5 get 3 eq {gsave} {grestore} ifelse }
+     {dup dup 0 get findfont exch 1 get scalefont setfont
+     [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6
+     get exch 4 get {textshow} {Metrics pop 0 R} ifelse }if dup 5 get 0 eq
+     {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5
+     get 1 eq {dup 2 get exch dup 3 get exch 6 get Gswidth pop -2 div
+     dup 0 R} {dup 6 get Gswidth pop -2 div 0 R 6 get
+     textshow 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop
+     pop aload pop M} ifelse }ifelse }ifelse }
+     ifelse }
+   forall} def
+/Gswidth {dup type /stringtype eq {stringwidth} {pop (n) stringwidth} ifelse} def
+/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }
+ {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont
+     6 get Gswidth pop add} {pop} ifelse} ifelse} forall} def
+/MLshow { currentpoint stroke M
+  0 exch R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/MRshow { currentpoint stroke M
+  exch dup MFwidth neg 3 -1 roll R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/MCshow { currentpoint stroke M
+  exch dup MFwidth -2 div 3 -1 roll R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/XYsave    { [( ) 1 2 true false 3 ()] } bind def
+/XYrestore { [( ) 1 2 true false 4 ()] } bind def
+Level1 SuppressPDFMark or 
+{} {
+/SDict 10 dict def
+systemdict /pdfmark known not {
+  userdict /pdfmark systemdict /cleartomark get put
+} if
+SDict begin [
+  /Title (802.15.4-per-vs-rxSignal.eps)
+  /Subject (gnuplot plot)
+  /Creator (gnuplot 5.2 patchlevel 8)
+%  /Producer (gnuplot)
+%  /Keywords ()
+  /CreationDate (Mon Dec 19 13:38:56 2022)
+  /DOCINFO pdfmark
+end
+} ifelse
+%
+% Support for boxed text - Ethan A Merritt Sep 2016
+%
+/InitTextBox { userdict /TBy2 3 -1 roll put userdict /TBx2 3 -1 roll put
+           userdict /TBy1 3 -1 roll put userdict /TBx1 3 -1 roll put
+	   /Boxing true def } def
+/ExtendTextBox { dup type /stringtype eq
+    { Boxing { gsave dup false charpath pathbbox
+      dup TBy2 gt {userdict /TBy2 3 -1 roll put} {pop} ifelse
+      dup TBx2 gt {userdict /TBx2 3 -1 roll put} {pop} ifelse
+      dup TBy1 lt {userdict /TBy1 3 -1 roll put} {pop} ifelse
+      dup TBx1 lt {userdict /TBx1 3 -1 roll put} {pop} ifelse
+      grestore } if }
+    {} ifelse} def
+/PopTextBox { newpath TBx1 TBxmargin sub TBy1 TBymargin sub M
+               TBx1 TBxmargin sub TBy2 TBymargin add L
+	       TBx2 TBxmargin add TBy2 TBymargin add L
+	       TBx2 TBxmargin add TBy1 TBymargin sub L closepath } def
+/DrawTextBox { PopTextBox stroke /Boxing false def} def
+/FillTextBox { gsave PopTextBox fill grestore /Boxing false def} def
+0 0 0 0 InitTextBox
+/TBxmargin 20 def
+/TBymargin 20 def
+/Boxing false def
+/textshow { ExtendTextBox Gshow } def
+%
+end
+%%EndProlog
+%%Page: 1 1
+gnudict begin
+gsave
+doclip
+50 50 translate
+0.050 0.050 scale
+0 setgray
+newpath
+(Times-BoldItalic) findfont 140 scalefont setfont
+BackgroundColor 0 lt 3 1 roll 0 lt exch 0 lt or or not {BackgroundColor C 1.000 0 0 7200.00 5040.00 BoxColFill} if
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+938 448 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 448 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 448 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
+[(Times-BoldItalic) 112.0 70.0 true true 0 (-12)]
+] -60.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+/vshift -46 def
+1.000 UL
+LTb
+LCb setrgbcolor
+938 768 M
+31 0 V
+5978 0 R
+-31 0 V
+938 851 M
+31 0 V
+5978 0 R
+-31 0 V
+938 902 M
+31 0 V
+5978 0 R
+-31 0 V
+938 938 M
+31 0 V
+5978 0 R
+-31 0 V
+938 966 M
+31 0 V
+5978 0 R
+-31 0 V
+938 989 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1009 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1026 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 1041 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 1041 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 1041 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
+[(Times-BoldItalic) 112.0 70.0 true true 0 (-10)]
+] -60.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+938 1360 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1444 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1494 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1530 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1558 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1581 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1601 M
+31 0 V
+5978 0 R
+-31 0 V
+938 1618 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 1633 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 1633 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 1633 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
+[(Times-BoldItalic) 112.0 70.0 true true 0 (-8)]
+] -60.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+938 1953 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2036 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2087 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2123 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2151 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2174 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2194 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2211 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 2226 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 2226 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 2226 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1x10)]
+[(Times-BoldItalic) 112.0 70.0 true true 0 (-6)]
+] -60.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+938 2545 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2629 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2679 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2715 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2743 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2766 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2786 M
+31 0 V
+5978 0 R
+-31 0 V
+938 2803 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 2818 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 2818 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 2818 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.0001)]
+] -46.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+938 3138 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3221 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3272 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3308 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3336 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3359 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3379 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3396 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 3411 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 3411 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 3411 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 0.01)]
+] -46.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+938 3730 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3814 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3864 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3900 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3928 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3952 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3971 M
+31 0 V
+5978 0 R
+-31 0 V
+938 3988 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 4003 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 4003 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 4003 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 1)]
+] -46.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+938 4323 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4406 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4457 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4493 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4521 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4544 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4564 M
+31 0 V
+5978 0 R
+-31 0 V
+938 4581 M
+31 0 V
+5978 0 R
+-31 0 V
+stroke
+0.500 UL
+LTa
+LCa setrgbcolor
+938 4596 M
+6009 0 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 4596 M
+63 0 V
+5946 0 R
+-63 0 V
+stroke
+854 4596 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 ( 100)]
+] -46.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+938 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+938 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+938 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-110)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+1367 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+1367 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+1367 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-108)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+1796 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+1796 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+1796 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-106)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+2226 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+2226 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+2226 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-104)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+2655 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+2655 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+2655 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-102)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+3084 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+3084 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+3084 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-100)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+3513 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+3513 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+3513 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-98)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+3943 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+3943 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+3943 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-96)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+4372 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+4372 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+4372 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-94)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+4801 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+4801 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+4801 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-92)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+5230 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+5230 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+5230 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-90)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+5659 448 M
+0 3828 V
+0 280 R
+0 63 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+5659 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+5659 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-88)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+6089 448 M
+0 3828 V
+0 280 R
+0 63 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+6089 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+6089 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-86)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+6518 448 M
+0 3828 V
+0 280 R
+0 63 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+6518 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+6518 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-84)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+0.500 UL
+LTa
+LCa setrgbcolor
+6947 448 M
+0 4171 V
+stroke
+1.000 UL
+LTb
+LCb setrgbcolor
+6947 448 M
+0 63 V
+0 4108 R
+0 -63 V
+stroke
+6947 308 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (-82)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+1.000 UL
+LTb
+LCb setrgbcolor
+1.000 UL
+LTB
+LCb setrgbcolor
+938 4619 N
+938 448 L
+6009 0 V
+0 4171 V
+-6009 0 V
+Z stroke
+1.000 UP
+1.000 UL
+LTb
+LCb setrgbcolor
+LCb setrgbcolor
+133 2533 M
+currentpoint gsave translate -270 rotate 0 0 moveto
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Packet Error Rate \(%\))]
+] -46.7 MCshow
+grestore
+/Times-BoldItalic findfont 140 scalefont setfont
+LTb
+LCb setrgbcolor
+3942 98 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Rx signal \(dBm\))]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+LTb
+LCb setrgbcolor
+3942 4829 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Pkt Payload \(MSDU\) size = 7 bytes | Tx power = 0 dBm | Rx Sensitivity \(Theo\) = -106.58 dBm)]
+] -46.7 MCshow
+/Times-BoldItalic findfont 140 scalefont setfont
+LTb
+% Begin plot #1
+5.000 UL
+LTb
+LC0 setrgbcolor
+LCb setrgbcolor
+6296 4486 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Experimental)]
+] -46.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+5.000 UL
+LTb
+LC0 setrgbcolor
+6380 4486 M
+399 0 V
+938 4591 M
+2 -2 V
+2 1 V
+2 -1 V
+3 1 V
+2 -1 V
+2 -1 V
+2 0 V
+2 1 V
+2 1 V
+2 -2 V
+3 1 V
+2 1 V
+2 -2 V
+2 0 V
+2 -1 V
+2 -1 V
+2 0 V
+3 -1 V
+2 1 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+3 -1 V
+2 0 V
+2 2 V
+2 -1 V
+2 -1 V
+2 0 V
+2 0 V
+3 -1 V
+2 1 V
+2 -2 V
+2 1 V
+2 -1 V
+2 0 V
+2 0 V
+3 1 V
+2 -2 V
+2 -2 V
+2 3 V
+2 -1 V
+2 -1 V
+2 -4 V
+3 1 V
+2 3 V
+2 -4 V
+2 1 V
+2 -3 V
+2 3 V
+2 -2 V
+3 -1 V
+2 2 V
+2 0 V
+2 -3 V
+2 -1 V
+2 0 V
+2 -1 V
+3 0 V
+2 -2 V
+2 0 V
+2 -1 V
+2 -1 V
+2 3 V
+2 -7 V
+3 2 V
+2 2 V
+2 -1 V
+2 -1 V
+2 -2 V
+2 3 V
+3 -3 V
+2 1 V
+2 1 V
+2 -6 V
+2 0 V
+2 -2 V
+2 -3 V
+3 2 V
+2 0 V
+2 2 V
+2 -2 V
+2 -2 V
+2 0 V
+2 -3 V
+3 -2 V
+2 -1 V
+2 1 V
+2 2 V
+2 -2 V
+2 -2 V
+2 0 V
+3 -3 V
+2 3 V
+2 -9 V
+2 6 V
+2 -1 V
+2 -6 V
+2 8 V
+3 0 V
+2 -10 V
+2 5 V
+2 -4 V
+2 -4 V
+2 4 V
+2 -5 V
+3 10 V
+2 -10 V
+2 -5 V
+2 2 V
+2 2 V
+2 -8 V
+3 6 V
+2 -2 V
+2 -3 V
+2 3 V
+2 -7 V
+2 2 V
+2 0 V
+3 1 V
+2 -6 V
+2 -1 V
+2 1 V
+2 -4 V
+2 3 V
+2 -3 V
+3 -6 V
+2 6 V
+2 -12 V
+2 4 V
+2 -4 V
+2 -2 V
+2 6 V
+3 -5 V
+2 -1 V
+2 2 V
+2 -1 V
+2 -2 V
+2 -5 V
+2 2 V
+3 -4 V
+2 -4 V
+2 -7 V
+2 7 V
+2 1 V
+2 -1 V
+2 -6 V
+3 -5 V
+2 -5 V
+2 7 V
+2 -9 V
+2 2 V
+2 -8 V
+2 9 V
+3 4 V
+2 -15 V
+2 8 V
+2 0 V
+2 -1 V
+2 -7 V
+3 3 V
+2 2 V
+2 -10 V
+2 1 V
+2 2 V
+2 -5 V
+2 -3 V
+3 -1 V
+2 0 V
+2 -2 V
+2 -1 V
+2 0 V
+2 4 V
+2 -6 V
+3 -14 V
+2 15 V
+2 -10 V
+2 -28 V
+2 22 V
+2 0 V
+2 -11 V
+3 8 V
+2 -9 V
+2 -4 V
+2 8 V
+2 6 V
+2 -7 V
+2 -6 V
+3 -9 V
+2 21 V
+2 -22 V
+2 -14 V
+2 22 V
+2 -11 V
+2 0 V
+3 3 V
+2 -8 V
+2 -5 V
+2 7 V
+2 -14 V
+2 3 V
+3 -11 V
+2 8 V
+2 12 V
+2 -21 V
+2 -10 V
+2 14 V
+2 0 V
+3 -8 V
+2 6 V
+2 -7 V
+2 -5 V
+2 9 V
+2 -10 V
+2 -18 V
+3 3 V
+2 -5 V
+2 7 V
+2 8 V
+2 9 V
+2 -15 V
+2 -13 V
+3 3 V
+2 9 V
+2 -17 V
+2 -5 V
+2 9 V
+2 0 V
+2 4 V
+3 -5 V
+2 3 V
+2 -10 V
+2 -24 V
+2 19 V
+2 -9 V
+2 -19 V
+3 17 V
+2 -5 V
+2 -8 V
+2 13 V
+2 -28 V
+2 -2 V
+2 -1 V
+3 12 V
+2 -26 V
+2 15 V
+2 9 V
+stroke 1468 4293 M
+2 0 V
+2 2 V
+3 -9 V
+2 -15 V
+2 10 V
+2 3 V
+2 -36 V
+2 18 V
+2 6 V
+3 -5 V
+2 -3 V
+2 -24 V
+2 32 V
+2 -32 V
+2 6 V
+2 7 V
+3 -28 V
+2 13 V
+2 -18 V
+2 22 V
+2 6 V
+2 -12 V
+2 6 V
+3 10 V
+2 -25 V
+2 -17 V
+2 -2 V
+2 -11 V
+2 28 V
+2 -7 V
+3 20 V
+2 -13 V
+2 -37 V
+2 6 V
+2 11 V
+2 -37 V
+2 42 V
+3 -19 V
+2 17 V
+2 -33 V
+2 19 V
+2 -37 V
+2 14 V
+3 28 V
+2 -31 V
+2 -15 V
+2 4 V
+2 42 V
+2 -39 V
+2 21 V
+3 -28 V
+2 7 V
+2 15 V
+2 -39 V
+2 58 V
+2 -96 V
+2 70 V
+3 -42 V
+2 -28 V
+2 80 V
+2 -47 V
+2 -27 V
+2 -12 V
+2 18 V
+3 -73 V
+2 99 V
+2 4 V
+2 -36 V
+2 53 V
+2 -71 V
+2 -7 V
+3 0 V
+2 -8 V
+2 33 V
+2 6 V
+2 0 V
+2 -46 V
+2 0 V
+3 22 V
+2 -7 V
+2 13 V
+2 -13 V
+2 7 V
+2 -22 V
+2 -18 V
+3 64 V
+2 -95 V
+2 40 V
+2 -81 V
+2 105 V
+2 -53 V
+3 -23 V
+2 43 V
+2 -31 V
+2 -26 V
+2 -15 V
+2 81 V
+2 -9 V
+3 -72 V
+2 63 V
+2 -22 V
+2 11 V
+2 45 V
+2 -68 V
+2 -29 V
+3 0 V
+2 29 V
+2 -29 V
+2 41 V
+2 -26 V
+2 0 V
+2 -75 V
+3 23 V
+2 89 V
+2 -89 V
+2 -89 V
+2 109 V
+2 -43 V
+2 0 V
+3 -29 V
+2 89 V
+4 -89 R
+2 72 V
+2 -109 V
+2 126 V
+3 0 V
+2 -126 V
+2 -141 V
+2 250 V
+2 -109 V
+2 89 V
+3 -230 V
+2 89 V
+2 0 V
+2 89 V
+2 0 V
+2 52 V
+2 -141 V
+3 52 V
+2 -52 V
+2 0 V
+2 89 V
+2 0 V
+2 0 V
+2 -178 V
+3 141 V
+2 -52 V
+2 0 V
+2 52 V
+2 -141 V
+2 89 V
+2 -89 V
+3 89 V
+2 89 V
+2 -89 V
+2 0 V
+4 52 R
+2 37 V
+5 -89 R
+2 -89 V
+2 89 V
+2 0 V
+2 0 V
+2 -89 V
+3 89 V
+2 -89 V
+2 0 V
+2 141 V
+2 -141 V
+2 89 V
+2 -89 V
+5 89 R
+2 52 V
+2 -52 V
+2 -89 V
+2 141 V
+3 -141 V
+4 0 R
+2 141 V
+4 -52 R
+11 0 R
+6 0 R
+3 -89 V
+2 89 V
+2 -89 V
+2 0 V
+2 0 V
+2 0 V
+2 0 V
+3 89 V
+4 -89 R
+4 0 R
+4 0 R
+11 0 R
+30 0 R
+2 89 V
+5 -89 R
+81 0 R
+5 0 R
+4 0 R
+21 0 R
+65 0 R
+% End plot #1
+% Begin plot #2
+stroke
+3.000 UL
+LTb
+LC1 setrgbcolor
+LCb setrgbcolor
+6296 4346 M
+[ [(Times-BoldItalic) 140.0 0.0 true true 0 (Theoretical)]
+] -46.7 MRshow
+/Times-BoldItalic findfont 140 scalefont setfont
+3.000 UL
+LTb
+LC1 setrgbcolor
+6380 4346 M
+399 0 V
+938 4586 M
+2 0 V
+2 0 V
+2 0 V
+3 -1 V
+2 0 V
+2 0 V
+2 0 V
+2 -1 V
+2 0 V
+2 0 V
+3 -1 V
+2 0 V
+2 0 V
+2 -1 V
+2 0 V
+2 0 V
+2 -1 V
+3 0 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+2 0 V
+3 0 V
+2 -1 V
+2 0 V
+2 -1 V
+2 0 V
+2 0 V
+2 -1 V
+3 0 V
+2 -1 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+2 0 V
+3 -1 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+3 -1 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+2 0 V
+2 -1 V
+3 -1 V
+2 0 V
+2 -1 V
+2 -1 V
+2 0 V
+2 -1 V
+2 -1 V
+3 0 V
+2 -1 V
+2 -1 V
+2 0 V
+2 -1 V
+2 -1 V
+2 -1 V
+3 0 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 0 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 0 V
+2 -1 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 0 V
+2 -1 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -1 V
+3 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -1 V
+2 -1 V
+2 -1 V
+3 -2 V
+2 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -1 V
+2 -2 V
+3 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+3 -1 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -1 V
+3 -2 V
+2 -1 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+3 -1 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -1 V
+3 -2 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -1 V
+2 -2 V
+3 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+3 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -1 V
+2 -2 V
+3 -2 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+3 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+3 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -1 V
+2 -2 V
+2 -2 V
+3 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+3 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -3 V
+3 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+3 -2 V
+2 -3 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+3 -3 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -2 V
+2 -3 V
+2 -2 V
+3 -2 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -2 V
+2 -3 V
+2 -2 V
+3 -2 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -2 V
+2 -3 V
+2 -2 V
+3 -3 V
+2 -2 V
+2 -2 V
+2 -3 V
+stroke 1468 4265 M
+2 -2 V
+2 -2 V
+3 -3 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+3 -2 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+3 -3 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+3 -2 V
+2 -3 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -2 V
+2 -3 V
+3 -3 V
+2 -2 V
+2 -3 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -3 V
+3 -2 V
+2 -3 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -3 V
+3 -3 V
+2 -2 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -2 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -3 V
+2 -2 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -4 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+3 -4 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -4 V
+2 -3 V
+3 -3 V
+2 -3 V
+2 -4 V
+2 -3 V
+2 -3 V
+2 -3 V
+2 -4 V
+3 -3 V
+2 -3 V
+2 -4 V
+2 -3 V
+2 -3 V
+2 -4 V
+2 -3 V
+3 -3 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -3 V
+2 -3 V
+2 -4 V
+3 -3 V
+2 -4 V
+2 -3 V
+2 -3 V
+2 -4 V
+2 -3 V
+3 -4 V
+2 -3 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -3 V
+2 -4 V
+3 -3 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -4 V
+2 -3 V
+2 -4 V
+3 -3 V
+2 -4 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -3 V
+2 -4 V
+3 -4 V
+2 -3 V
+2 -4 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -3 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -3 V
+2 -4 V
+3 -4 V
+2 -4 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -4 V
+2 -3 V
+2 -4 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+3 -4 V
+2 -5 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -4 V
+2 -5 V
+3 -4 V
+2 -4 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -4 V
+3 -5 V
+2 -4 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -4 V
+2 -5 V
+3 -4 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -5 V
+3 -4 V
+2 -5 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -5 V
+2 -4 V
+3 -5 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -5 V
+2 -4 V
+2 -5 V
+stroke 2002 3410 M
+3 -5 V
+2 -4 V
+2 -5 V
+2 -5 V
+2 -4 V
+2 -5 V
+2 -5 V
+3 -4 V
+2 -5 V
+2 -5 V
+2 -4 V
+2 -5 V
+2 -5 V
+2 -5 V
+3 -4 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -4 V
+3 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+3 -4 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+3 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+3 -6 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+3 -5 V
+2 -6 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -5 V
+2 -6 V
+3 -5 V
+2 -5 V
+2 -5 V
+2 -6 V
+2 -5 V
+2 -5 V
+3 -6 V
+2 -5 V
+2 -5 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -5 V
+3 -5 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -5 V
+3 -6 V
+2 -5 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -5 V
+2 -6 V
+3 -5 V
+2 -6 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -6 V
+2 -5 V
+3 -6 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -5 V
+3 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -5 V
+2 -6 V
+2 -6 V
+3 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+3 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+3 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+3 -6 V
+2 -7 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -7 V
+3 -6 V
+2 -6 V
+2 -7 V
+2 -6 V
+2 -6 V
+2 -6 V
+2 -7 V
+3 -6 V
+2 -7 V
+2 -6 V
+2 -6 V
+2 -7 V
+2 -6 V
+2 -7 V
+3 -6 V
+2 -7 V
+2 -6 V
+2 -7 V
+2 -6 V
+2 -7 V
+3 -6 V
+2 -7 V
+2 -6 V
+2 -7 V
+2 -7 V
+2 -6 V
+2 -7 V
+3 -6 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -6 V
+2 -7 V
+2 -7 V
+3 -7 V
+2 -6 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -6 V
+3 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+3 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+3 -7 V
+2 -7 V
+2 -8 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -7 V
+3 -8 V
+2 -7 V
+2 -7 V
+2 -7 V
+2 -8 V
+2 -7 V
+3 -7 V
+2 -8 V
+2 -7 V
+2 -7 V
+2 -8 V
+2 -7 V
+2 -8 V
+3 -7 V
+2 -7 V
+2 -8 V
+2 -7 V
+2 -8 V
+2 -7 V
+2 -8 V
+3 -8 V
+2 -7 V
+2 -8 V
+2 -7 V
+2 -8 V
+2 -8 V
+2 -7 V
+3 -8 V
+2 -8 V
+2 -7 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -7 V
+3 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+3 -7 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+3 -8 V
+2 -9 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+2 -8 V
+3 -8 V
+2 -9 V
+2 -8 V
+stroke 2537 1853 M
+2 -8 V
+2 -8 V
+2 -9 V
+2 -8 V
+3 -8 V
+2 -8 V
+2 -9 V
+2 -8 V
+2 -9 V
+2 -8 V
+2 -8 V
+3 -9 V
+2 -8 V
+2 -9 V
+2 -8 V
+2 -9 V
+2 -8 V
+2 -9 V
+3 -9 V
+2 -8 V
+2 -9 V
+2 -8 V
+2 -9 V
+2 -9 V
+2 -8 V
+3 -9 V
+2 -9 V
+2 -9 V
+2 -9 V
+2 -8 V
+2 -9 V
+2 -9 V
+3 -9 V
+2 -9 V
+2 -9 V
+2 -9 V
+2 -9 V
+2 -9 V
+3 -8 V
+2 -9 V
+2 -10 V
+2 -9 V
+2 -9 V
+2 -9 V
+2 -9 V
+3 -9 V
+2 -9 V
+2 -9 V
+2 -10 V
+2 -9 V
+2 -9 V
+2 -9 V
+3 -10 V
+2 -9 V
+2 -9 V
+2 -10 V
+2 -9 V
+2 -9 V
+2 -10 V
+3 -9 V
+2 -10 V
+2 -9 V
+2 -10 V
+2 -9 V
+2 -10 V
+2 -9 V
+3 -10 V
+2 -10 V
+2 -9 V
+2 -10 V
+2 -9 V
+2 -10 V
+2 -10 V
+3 -10 V
+2 -9 V
+2 -10 V
+2 -10 V
+2 -10 V
+2 -10 V
+3 -10 V
+2 -9 V
+2 -10 V
+2 -10 V
+2 -11 V
+2 -9 V
+2 -11 V
+3 -9 V
+2 -10 V
+2 -11 V
+2 -10 V
+2 -10 V
+2 -11 V
+2 -9 V
+3 -10 V
+2 -11 V
+2 -11 V
+2 -8 V
+2 -9 V
+2 -15 V
+2 -11 V
+3 -5 V
+2 -13 V
+2 -13 V
+2 -8 V
+2 -7 V
+2 -18 V
+2 -9 V
+3 -10 V
+2 -12 V
+2 -12 V
+2 0 V
+2 -13 V
+2 -16 V
+2 -17 V
+3 0 V
+2 -20 V
+2 0 V
+2 -23 V
+2 0 V
+2 0 V
+2 -29 V
+3 0 V
+2 0 V
+2 -37 V
+2 0 V
+2 0 V
+2 -52 V
+3 0 V
+2 0 V
+2 0 V
+2 0 V
+2 0 V
+2 -89 V
+2 0 V
+3 0 V
+2 0 V
+2 0 V
+2 0 V
+2 0 V
+2 0 V
+2 0 V
+3 0 V
+2 0 V
+2 0 V
+2 0 V
+% End plot #2
+stroke
+2.000 UL
+LTb
+LCb setrgbcolor
+1.000 UL
+LTB
+LCb setrgbcolor
+938 4619 N
+938 448 L
+6009 0 V
+0 4171 V
+-6009 0 V
+Z stroke
+1.000 UP
+1.000 UL
+[] 0 setdash
+0.00 0.50 1.00 C
+938 4003 M
+6009 0 V
+stroke
+LTb
+LCb setrgbcolor
+stroke
+grestore
+end
+showpage
+%%Trailer
+%%DocumentFonts: Times-BoldItalic
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/figures/802-15-4-psr-distance.eps ns-3.46/src/lr-wpan/doc/figures/802-15-4-psr-distance.eps
--- ns-3.45/src/lr-wpan/doc/figures/802-15-4-psr-distance.eps	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/lr-wpan/doc/figures/802-15-4-psr-distance.eps	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,590 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: cairo 1.16.0 (https://cairographics.org)
+%%CreationDate: Tue Feb  7 16:42:56 2023
+%%Pages: 1
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%BoundingBox: 4 1 354 245
+%%EndComments
+%%BeginProlog
+50 dict begin
+/q { gsave } bind def
+/Q { grestore } bind def
+/cm { 6 array astore concat } bind def
+/w { setlinewidth } bind def
+/J { setlinecap } bind def
+/j { setlinejoin } bind def
+/M { setmiterlimit } bind def
+/d { setdash } bind def
+/m { moveto } bind def
+/l { lineto } bind def
+/c { curveto } bind def
+/h { closepath } bind def
+/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
+      0 exch rlineto 0 rlineto closepath } bind def
+/S { stroke } bind def
+/f { fill } bind def
+/f* { eofill } bind def
+/n { newpath } bind def
+/W { clip } bind def
+/W* { eoclip } bind def
+/BT { } bind def
+/ET { } bind def
+/BDC { mark 3 1 roll /BDC pdfmark } bind def
+/EMC { mark /EMC pdfmark } bind def
+/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
+/Tj { show currentpoint cairo_store_point } bind def
+/TJ {
+  {
+    dup
+    type /stringtype eq
+    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
+  } forall
+  currentpoint cairo_store_point
+} bind def
+/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
+    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
+/Tf { pop /cairo_font exch def /cairo_font_matrix where
+      { pop cairo_selectfont } if } bind def
+/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
+      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
+      /cairo_font where { pop cairo_selectfont } if } bind def
+/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
+      cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
+/g { setgray } bind def
+/rg { setrgbcolor } bind def
+/d1 { setcachedevice } bind def
+/cairo_data_source {
+  CairoDataIndex CairoData length lt
+    { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def }
+    { () } ifelse
+} def
+/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def
+/cairo_image { image cairo_flush_ascii85_file } def
+/cairo_imagemask { imagemask cairo_flush_ascii85_file } def
+%%EndProlog
+%%BeginSetup
+%%BeginResource: font f-0-0
+%!FontType1-1.1 f-0-0 1.0
+11 dict begin
+/FontName /f-0-0 def
+/PaintType 0 def
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0] readonly def
+/FontBBox {-120 -205 917 699                                 } readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 32 /space put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 45 /hyphen put
+dup 46 /period put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 59 /semicolon put
+dup 61 /equal put
+dup 66 /B put
+dup 68 /D put
+dup 77 /M put
+dup 80 /P put
+dup 82 /R put
+dup 83 /S put
+dup 85 /U put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 104 /h put
+dup 105 /i put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+readonly def
+currentdict end
+currentfile eexec
+f983ef0097ece636fb4a96c74d26ab84185f6dfa4a16a7a1c27bbe3f1156aea698df336d20b467
+b10e7f33846656653c5ac6962759d3056cbdb3190bac614b984bf5a132dc418192443014ba63de
+800d392b6fea026574bb2535fd7bb5338f35bf15a88ea328fdaa49670c7852e3d060f3c5d6b07f
+2ef6d0f22646c5d18e19a2ae3ee120390f6dd96f76dcf1e127de5e9299077a00c17c0d71e36e5b
+9d5ec58fceda57739a6a4214d4b79d6c48d2784b60c320323c7acddddf34db833cac0cf109f799
+69d114a330d372e5c978a66acc84e3fe5557f6240856a013ffaa0199444e5c5036f775eba4a5c5
+8cde66cf604b9aca2178431127b8a1ff7ed633a65c04600af5f573483112251ca91d1147e394b8
+770feb7fd46a77e2961ec91bb9263dc0e43eb9a3b990c9761127f2236d69136be42a8ece293f20
+5e8c6985d36b970354af6976b59de1a9aee59b1b7c4d57d3e7115622fce48a99cd7903af13d778
+b61bdf26278782d0626afcd805edf6882452f3ba0b8a06550e5e742680a1db9e9c38aff42a0b05
+0a9f5f0b9355ad3cd836918714c3f69d1b8ce860e052d6ee0bf9c73c967566711ee88068b4f1e1
+8e9f1de06e22b50a1802b961bf321e086c078478c600fa019a221bda4d0691a1bb176b02a3095e
+c2a8437df5f02ae027612189ff9fa60c7236e5bf6cafe3cf2387597370a08fa1249ace038b4c9a
+ecc6e711908d08521015920bfc534c4cf64bf8005abe859dc2969a27784051abe57be19aba6937
+c8d9cd449d007816c1381fc06b1f9d0f750dc5eda5f766e4245b5797d2d8e322f2a38ed3880ae7
+13f2edc17311c12c168e50150fe0e343da65e3f2bd139450022b55e23392a2de02f289617dd4cd
+f3c47d52ea553d5a2feaf00f8aa0c17f95745f872dce13d2e1a26248be73aef3e76cf72414b24a
+a796fcf2778035fbd97ad4fc2b916c3a324e4d36cee9fcb580e5d1d9073ae58a01be98418b9425
+0619218c1fcba7037a689ec83fc42d6dea7d609e3cc45d07e289084a878c33a77c492427e6408f
+895707f95831bf9c8b230d9aa553f2e62ed301bf822df01c64e122b25bb3e929552940d69d9bea
+0db22cc1f90a5cf9eb63dd3fd52f41d5c1c8a9ac478b48459e5882b062bc78675aa1e2d6e70326
+69af62ed53d03ed4c7e7b4c3d5c63878fc98a0f891b0b3f4112f9203b201b4df315d423d009273
+6dd784bf0eebd9bc9407c803adaa20de750884ade854491b14660b23ce1830344c320cb26e2bd2
+41b916c30c94de287fd3b8ab8116011e8c5e43c528d22dbc4f1bf6400e422b7f0e02eb53adf5a0
+8f5a1d4fb192188430efa7dd558329569b4cdf8f07ca29b0f906bdb164ecd6762e55c4113af599
+e4b4abcdd41d05de6bd6add6fb8f684b0d9583a56602d13c5b64e2e837ec5c238704efe8039f95
+b5edc8221765f744db766f5224c324cab2ecc72cb20b58b5f19426e5d29f3a5b429cee7b45a71d
+781ea61d2ce93533201e8706f71d3a9c29b4b2db6398a8a9ecbcf3588ca6da6fca2a72fbe479ad
+0af932e399f3932445b10b4740fb1d437ccabc5b42701242666828fdc8b131c8ea8eca9e0b822c
+7f88e9fc49256dc6f6e52fc0a00c38428324478492d15b18959fb09cf28004562bf53b6eca151a
+7994261c2c3e6fb99fa87fe90500277c32f4d902dc6405f5cf752555994d05bd98c9902a518cc6
+1b3ac3ffd041ed82d8279a2a1c3c5729aa6dfd811b08ac5715c20fb012eb3ddb611d5aa0386a5d
+cd8d878e1b90baa9073032eb31ed3f35385621284e8fd6d31b0bdd56f214c324928eb57bbe7b4d
+24cd67ee34b6a22c77a6d80ff843102c723511c3c261dec9462b6a191384d99d52545a9bbae451
+89c114aacd395f5d2ed9b9c2b5eab9f109c36c915f36678ee984a1b8a65b38ed6d48ef11648b9a
+4e21d51bae9df39b17e0cc40a0cd3c453f85bcadcef2210d39d1b3259c3cd7bce8f8da5cc94cdd
+32201bc55a2f74431d84f5573b59e6e1ac3d7b3b80725961993759f63077b206d987d8f61ab3b2
+1173653792b1e586728bbfbbd5687d6acac39c5c984ccf92242196b4ab5d5408b6949f35803fc5
+f4840b0b561802400007802c4467b55610152573415ba53f207b104de7d912c5bf47751d85385d
+f45b5728f0c7222dd4800d300e92a631f5523738c581300c61c41099563b1cc5d5d75fdfa6a249
+6e883227020870adfff63688a6d6e32d649e3e802919138035d53be2663efcbafa6f3f01c12dd5
+e73272506a4e1e0a0ba4ee185c8f2631f1c47991bcd441a3fb971a920a995d56e51abb9273c056
+ab190ba8b3eab9924dcf25e9eaf74fd2a2adeb0fe586522738c94df776270068587b9e2951285d
+f961df30828870115939160f7baca86e9b7eeee4778159d4b82acb2b4934970ca8af657637ce28
+1fc7195fff0c26a35b5763d1c84b75f45df695b55f565e83e72dca59c528fc9c2f9fb8bb1d3836
+0b3f87cbcd36f96e6680960b5f78d1660180ea3ba73c0df17e9d1b3c4939c8dd8eb4a95277934c
+a417af85e4f3ceee61bd0d6a18687471d8dec2cfb65d8a1ee30adcd50f6354045e61aa3f1d35d1
+a5f39c1228be448f4e15fee8a8309d3144e8e494b5483680599ce430e1e7b219b8e156f6dd0049
+e34e53d0463376b77b365bebaf08f9c1514f7b66520544953582916823f17d70ba3646a8d420e0
+07cca059a45276212c40599e79d8cd2b1768f964d3a364e65baafd767f43b2ab562de3050724c3
+0e8e11fd2f429ff7590b97f861f1ee9d19a3cfa66a8c755960b45cb8dfaffd80e3426e5c57e65c
+f5ea49f3504806bc96527c9b20987e99de44c09e93de6c7dab1bd4a2ba5476fc3209c1b421dfdb
+a91a8568087d8f7b706b522af6f181829a9ae7266789ff18cbbeaedaaef7f7df4c4ae7873dac2e
+0f8b1d43cebb6087bc2398837c6b8e6b2aec3e55c66cf3db3293fc371e7d93b32853fed1723b5e
+ca9932759d854db4dd5069aaa31f51a515bb9ae6342a583080ddfd2173a7b0e9143fca950495d3
+a90a7ec9bbbfaa2ba03661b05c8e85b6f3edfd82444b1d335b21d502b430f1dbfa2fd93e0f4b3b
+dc096f564e3d4ab470152b785dd2c05a9d69973665c5b67fc0d81151141a5eb78880086ad276b4
+ef039c78a77ed5e80044d87a0767a416d5f4739a1735917d99c5b207f9c94fa903d7063c3ff62d
+c2a2079ed2707d88a77c5c5009dab9d223e0efb33bdc736af0f85564ef88d1853f13343fdeb271
+fce4d42038c0e0fe544309f063b6f1f3dc9018a0e2893da5f1fb30cf003fb23deb46d13e7b51fb
+ab4610af7efb3827e5f0a27ed173c385e7a4f03b167971b69d6e57059e5380d6b521090540c8fd
+706dc8ddfd3397a05db5d030b5cae26330de17394c40234329bec6cba36f5ee51ac0cef01d5c9a
+186d73e1242855e94eda47507a65de5c8a568ac2ea69c0446ff2faa0615532eae5ef142fe8ce7a
+c08c058d68db0bf5a1ea72a74c763f76d475ca73eec18bb3de194e564628f7986dabf118d08b49
+08a26376d508991051ade1dbb85c7188a1c5140b9b874a56d8aa08ea8243404a5c626ad5d989b0
+0df27dd5fde4d705a87b97f0cf165a4903c32b40d7db2cc9ea2a709992a1804f621468f1f1f25a
+7301cc4d96574ef8b4fe7113397b378d0650bafec63eca65cda58a490bcc6a7840141503652dd0
+69e3860d1254aa78438f6d06e702040289f25d6c333df3e938dad48118b155d4a0bd893be04744
+bc41a02adda4f451785b5f29651a70b520add99694fe534e985df16edbcabfb29fc9f80570c599
+6bc0311534500bcd860f5e5dd8c3a5595fd0c16c0b4a71e6b19d8c65ec009d85728416e98865b6
+f732c97849a322d5d15933023627c4c3b493cd25fe787bd8a602c185c58ffed03d9b64b84f68b3
+7c041eec4d32420af95c174da76b1822d66d98873d7050d124387f9454d11b6b43f978a7dc5893
+341815d40bf7489a4443acf4e6249d8ed0ac31b2fb85d9a06a9061c180106238213253423d3e16
+e62c1c035ffa6be588b5e105ccbde9537ddb9e86eb9eee887e01ca91420e20dae0b338c928423d
+5dcd021828050e57213768c79faa75ba1958d7b43eea506e5fc0683955d0d93903e6510af75c47
+97d05c1c001252743623028d78a293054bed8847112656cf36567ba99eaff4a09d2e12a7664645
+38884477d00ebdaf62fc1f110a2b59efd877c9e570c127cd89801d5d2eab8de294085771fa38b6
+1584efb3877e4edb76957de903b0bc880a703adf57b73628cf6481491360bf081f999a347a3b8c
+ed28d04a74857774ac390d7b18d0719cd4b7c14a9fea42e80026d96486b29266ad8a2a31557023
+a581a882c8f8b294bd02bcca17e0cc3b47bee6d9f378323de02482101664a0189c7b69dd1bd91d
+36d45e95050ba0a29225a9ea038f03c6635840d3c794fbf42c4e2d61d8c25c152d3ebbd52dc5c5
+8e2d8b6f36136dcfa92b409c80ce96398f9292e48894a435494d72e399b82f87fc6e2a1025371a
+f68aa5572d8eb827b649e37e6b108c8643bccd73c90aa42bef97e51ca27ff45051056b679a459e
+c938e3ad5494ef9389a4213589d526bd5cdbe0795bf78b83097b893dfa661faec6214ff7c15896
+98485ab72a3a314546fd4440dca92cc0c126aed9bc5851aca6ac87b8948cc54023da7d1ebddb67
+021b357ecad8b8f54aa91b8ffb3ecfe8addce021a7c8454186b56c1c27e720bac49021546acd47
+6a8ad779af8973e641a47f5c79a86e61a6174aa7b529dbc8c9c1042270c20aff1608ec8fcd53fc
+bbabcc21985096706d9d313adbf1adf29926fd1dde0d5c688e4b1d7d0d6802824c6c7b7fd0ea98
+d1d06622520286704add2b5f2370aaeb0533694f9883478a75344fdd3505c7b6c4ad5a37abe943
+0ae1c3d2550309668dac31d748eb4e956c8894a18d11f387d16934356ec7379494d77d0393b94d
+5245f1f71d77de7b4d89f5529f6b5b9bd2744df09173be9a5e4c573c4ef5a1096ee82a2a53e883
+04f379afc6868b0eefd62a5cb2d1d21aba066937639b9fe5b10208da697f40a39e6ee11d621502
+366c546aac60fc79c6d05cea9d9e8d8ffa67ff442e75f4f28ac62a2660346e329b56fac248f3a4
+7665157eeba01b807b65c7bc9eba5d059faf5987212330ac3f7a04278de1cfc8e01ebe136443df
+edc5df38f539f573bed294de93639ffb430dd3f982f4ba760784841dc87ce0df076c1760609276
+b67f976e226e56fd9a24f5bc442a7a9cc3872f16a3a4647bdef24151c51ea7c2554be9841f5243
+99a21a28d33dd7cb294976da44ee73e52744c8bfac0581982d7ef27be12cba1d89078051ae1c5b
+5f2ab4752035faa6bc6de10370a935d9110f47400e08f3235bbeb4ca7cffbb7dac1e6e22ee5a58
+c7b33e7acf65586470c087594454484186d92f60d3603af307e5169b10e812e344a98555d6bcd9
+b6befeefbf526274a0f8fab7eedf23f1c5523323b2c0f0e4a9141bfdd3772d02deedd69b3937bf
+8533a6f205702e6a703446a4c13828f115bd547e59971e050d6b55c176c8e32d3f09338ee665b4
+a2f6f8692e1613f8168f3dff482fc3462aca3227a0f464aa065a8b97409aecd9b2b86831f190cd
+d988af54d7e2e6ce2600d74b78473ac42534cb1a4712afae659ecbf12cb11a958609e5a5701cff
+32acaae52f3423032687119953a0fb7b4c412086e460224d7451ec10effbb707fef8de4e43d9c3
+b0c2519b1df462943db7b4d1e5cc638021e6a3c1a1a72f3a28cb372b1f639dc74270734f43ba20
+2a5bcc805421f806e068ba068bdb0ea2b3f481a5dc6d99707caef1dff7ea9359da1b8b82cfd9b7
+b3a382a2d9eb740c9fed9948bbec3878eaa4ee5f6bbc39af5e39db0af35359e8ad124646b3e786
+737e06d8d7044d2ef7dbf7fbfd6e7a19d9b236ae7262aafa4c026bdf999aca8ca153e306fafde0
+5d8ae9d74f13913aed7c6dc3386f348b84e5442cc9fb6049eec5706a79398802772c40b383657b
+bd5c4b445777e0236710339fa7c57068737504b28d36ee8115d704b5efdd0062f9007f176c85d1
+3a35a6807d4a4cab3d2a57fa2aa7b4f83f44d734cbcc59ef84e42d8e62df197853570308bff37d
+f02a7730b82559893bdad5620bd6252f7d6e7a7877968c5736b1d328a2e6e2ddac3f75914ebba7
+6ed377bdeea8a4dcfce30c81859bc0f192593683311995037b169ee87fb0a2ea898679ee597106
+3e38185ff9a53be81919b04760a07ca721589b67975e893e12f61e5637c15afddfa1bb5c8a94bd
+1610e97903f46d34830f3dcd6bc8b925812af6cd30c1889c4429d67ccae457844775e1f4638326
+f4b4dbd66575fc71b986017406ecc04e89ea26f3a1b457af7aa5c2391899a51f53620549dd9aa5
+5af140070bcc439d4ec60a749cbd2339cd2405c5223a5e9a517f62e2b50cb00c514e79614e7f9b
+40c6af1f1a842080c15022b49dd86872db7841166b777df67caf278d22a829f269047b3fe1143c
+c16f137cb6edf3d9dbb8574e5411a8e69c1fce97fafafe3bce921d280cad1c0d2c3fd3cfd39c2c
+66f92c5ba458c5bc2baca4d9c4e67d9838827a0b3bb33d1e0bfd981a8b88fb8fa542e4d07956e5
+5c773b2bcd1fa5f6d0b84bc9f35436cf21004e59c7c4ded8aa8f61fc31b61e9e5cfed76043f697
+90069da95284172fd4a769f3ac5ead35882eca37bccba6cfe3fd00a1a5320c1e583cea4d338069
+168b633c2bb960add60699076f9553d65ec1cfcbe15f4696e470bba0d2d20b810bbb94de0e066a
+53cedc32f5a667d044df997a23d38ab60630bf1ecb4a63ae6e85ddbe826f6c208e8fa013536d67
+7a57a10237989400d0fb5c5680f40fe842a6d7827eb6dfbefb66d2ffec4a21f3184d9a7b8892dc
+f1842e755bfe07c3415d50b31650cb2fe423024399e3f1d48e833c6bd1a5882b3d897a48476774
+7447a56fd2f9f785928dc623b45e04c0534414e458c8084db9c0fb7b869303f03a7db0d24e106f
+c4569f9ad4f42ef096c1e73197358bc5b79a0140eec788fd815a595d138623d724e9f46bd75c74
+0c66781572cdd5d8c4b61a71c1de857c6f7e52a0a65413cb461dcfdaec8a7f6d5a527b5da11fbb
+f0779c15a11f3f2f81f38a02238917e270ff6bb47a21b36a20348a34108f5471f5eca0d2f684f0
+18ad7ac5f52b67d145963537534e3d5d487b65d38ce310cd1f5464b8d39b904e396b343097761d
+12ee73ff8fad544bb8ae894a77a71cbb6e0bc0262360f5f2eacdb52640f3fc5071e71ded3eb0f7
+3150a3afaac2882a0f4a78eb4de7ac732b7c201afcf70a1ff3e49bb4a7e786e1c48860023768ad
+8c40390bdba129bc40a3accc154a3a55a32b16e8dec5ba2f7a51f3c22821f00e913614955c3c74
+165f4b84d6e1f43137ed572e4a387bc7dafdcf0c015fc2b7ebaf1cc69c191bae34f569f29d93ec
+df6d8ce8647b68f96ac1444530b4abd76ace164eee01f6cb07c1457761846cfceb3c7ed3e8dce5
+b173f356312ed03851a1941dad7ce47f352efd3ebdc8b1a10984fc39408fc765d3ea63e5eee4ac
+c48969e9d770d53ae1f2afb7a7690063466ef9dfdee47448671dccff63d5139be1b3cf1c33537d
+5f191a73d3a8a4956a7b8c84828fc1445ff041a84474eaf7b45bf67dc9e621b44119005512e9d8
+0a89fb10ca9227cce67c6cbfc6f45bde1433a9e389888003a31591f77f7b65727bdefb150a2298
+66eba692c0a080dc7a926cb27caf77fa352404ece37bc5f69b88a8878f735c0066554b294ac76c
+e90583a5f0dbbb0c33fd9f52b75ffa450d7aa2e3cd0f7c01874c927eb0d818f4fabddb6c50df24
+855bf3f9984a0ef65a93e2e3d782794f2ed0262ac86a8ab343fdeda76c787cb5e68dff2b3e6cda
+3ab1f8b646fe1c9b63176ce5d9721d9e217883a5809f44377c2f61291eb3a8b8d5e4f406343451
+da9c11ca53ef9eb934f8b1a44f1bb8cd202cb1742d8213735777fdbacf7f0933a0b0bc8fd13084
+db3410a6736c1acdf9682cd633bfa27714697c08b2b3ae0812bd96b2b14c7d0df99e26dc08598f
+70d24ee32b43619119bbecb71a1738e95103d9ff1513216077a2cc1c786660f544c31155eca5ff
+20deb39075b09e281a06df04dea50179e88a2bb1b98d05560b1f1bbf6df981594b47a9035b554d
+c79b44e9cd91381d2ed71c6bb7eadc4422ee3c27ab678a22a785786904b1bca4919b40cc05ab1c
+c2faa2f1f2c1da946484660942f5288e5bdb044790c15edc3c979beab118101083e94631b8b9a2
+ed92c51c056294b7863e76d01cabe5bec973ba40ee485d88196c908d032051bb55144de8966328
+66de750fb8dc983487507a7b5ec1babf6cf080c6c0dd002b6e305cfdd97c426725fd648ad995e7
+4bd8d67e4e03d68fc7c789d243a25cff3f52c7bf4ee758bcb62d1c951102c0a81eebb224fceea6
+522ae93dc8c9af630a13e2382f24bea74c6279859901aca5e1479dd17ca58e635e5768203b7314
+f7f92e74bde2a7baf3b8acea39f800ebca4b2b2a40fe5cb0a671f836607e86c42d06e51ccba1e2
+4e14918d443bd792e836edae89639f36825e698eec03b7f649858a10886a900c371c890564d199
+1a8dc48644381aced59f4e8c8fc388da4911a9d25bde9e47566e54216044a7b08d1cefe9861e6f
+651357f25b526e9b54ae62c904094616a2285491292de7fb4f95235a3902170601c15d52b9bc85
+c153bb27d4ab8cd01c80863c6f34b784dc5f28f196c822a0ae59551b92148b7ee92a428a1ac9ed
+fb51cab977ae915e0c1c80033f22da741fce179cc91b5ebb7a3dd3bf579d7ced93f14f23e09a44
+954ad9d4cd2fca916a9e444f1ebee056779087ee33dc155a16484e938d38d09a97d551f1e12c62
+c1f90ac16a297e5f73add55f9606180d34e8e37b28006da4dcfb0e842647a46f6c44df4ef27d96
+aa8b26441324a228ca896ce8a5cf37b93a6b50f95776835fa5c041069c9d8e9a9edfe302aebb01
+97756c6fd3d6d3c2d6dae32c8a1148dbde0953a20d4d75489cac0447c3100bd2d15beee4043861
+c077c7b6ff2742daf44c2562a03d85a3d91d7deddce813f8cbdff39127c94d500900a31f68bee4
+903187e2defe546dd1d7a4106049c7a902b3abeaae9297d50eecfe2df733004ed34cfb26d7e93d
+99dff2bf37759d9f75a8b0ba0b85df6fe2e208d1947f5dd2c3c44bfa0348b3484eb3f29c053a1e
+9aba025c012e85b2b1c153e67ac2dbfe7d5c0d384edf06bb9063b5541956df3990517c7ab6eaaa
+18d771fac8f1ec9f99c6c3a34a422255498d6254c1601ef1fed76719306b6cc3debf99445c53cc
+c189d3b4ce6a3b036c58414e6be5df2602a6f7b6df3dc95cbec600c62972f6be5d48ebc2104043
+b7d7659cfa004c9647f0c1d7429281cec88a51161779c2f9f872aa9a12163acf2f276e3355c102
+ca4d472167913e2ed8b8d442ac2981d730bee5afcb4f9f06871d24f79f433dea17a6d827b21c7a
+f81b5d1d58d74cec4e6903c9a5f22ec3280000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+%%EndResource
+%%EndSetup
+%%Page: 1 1
+%%BeginPageSetup
+%%PageBoundingBox: 4 1 354 245
+%%EndPageSetup
+q 4 1 350 244 rectclip
+1 0 0 -1 0 252 cm q
+0 g
+0.25 w
+0 J
+0 j
+[] 0.0 d
+3.8 M q 1 0 0 -1 0 0 cm
+34.301 -229.602 m 37.449 -229.602 l 347.352 -229.602 m 344.199 -229.602
+ l S Q
+BT
+7 0 0 -7 26.599999 231.935201 Tm
+/f-0-0 1 Tf
+(0)Tj
+ET
+q 1 0 0 -1 0 0 cm
+34.301 -187.898 m 37.449 -187.898 l 347.352 -187.898 m 344.199 -187.898
+ l S Q
+BT
+7 0 0 -7 21.349999 190.235202 Tm
+/f-0-0 1 Tf
+(0.2)Tj
+ET
+q 1 0 0 -1 0 0 cm
+34.301 -146.199 m 37.449 -146.199 l 347.352 -146.199 m 344.199 -146.199
+ l S Q
+BT
+7 0 0 -7 21.349999 148.535003 Tm
+/f-0-0 1 Tf
+(0.4)Tj
+ET
+q 1 0 0 -1 0 0 cm
+34.301 -104.449 m 37.449 -104.449 l 347.352 -104.449 m 344.199 -104.449
+ l S Q
+BT
+7 0 0 -7 21.349999 106.785004 Tm
+/f-0-0 1 Tf
+(0.6)Tj
+ET
+q 1 0 0 -1 0 0 cm
+34.301 -62.75 m 37.449 -62.75 l 347.352 -62.75 m 344.199 -62.75 l S Q
+BT
+7 0 0 -7 21.349999 65.085005 Tm
+/f-0-0 1 Tf
+(0.8)Tj
+ET
+q 1 0 0 -1 0 0 cm
+34.301 -21.051 m 37.449 -21.051 l 347.352 -21.051 m 344.199 -21.051 l S Q
+BT
+7 0 0 -7 26.599999 23.385006 Tm
+/f-0-0 1 Tf
+(1)Tj
+ET
+q 1 0 0 -1 0 0 cm
+34.301 -229.602 m 34.301 -226.449 l 34.301 -21.051 m 34.301 -24.199 l S Q
+BT
+7 0 0 -7 33.424999 238.9352 Tm
+/f-0-0 1 Tf
+(0)Tj
+ET
+q 1 0 0 -1 0 0 cm
+65.602 -229.602 m 65.602 -226.449 l 65.602 -21.051 m 65.602 -24.199 l S Q
+BT
+7 0 0 -7 62.974998 238.9352 Tm
+/f-0-0 1 Tf
+(20)Tj
+ET
+q 1 0 0 -1 0 0 cm
+96.898 -229.602 m 96.898 -226.449 l 96.898 -21.051 m 96.898 -24.199 l S Q
+BT
+7 0 0 -7 94.274998 238.9352 Tm
+/f-0-0 1 Tf
+(40)Tj
+ET
+q 1 0 0 -1 0 0 cm
+128.199 -229.602 m 128.199 -226.449 l 128.199 -21.051 m 128.199 -24.199
+ l S Q
+BT
+7 0 0 -7 125.574997 238.9352 Tm
+/f-0-0 1 Tf
+(60)Tj
+ET
+q 1 0 0 -1 0 0 cm
+159.5 -229.602 m 159.5 -226.449 l 159.5 -21.051 m 159.5 -24.199 l S Q
+BT
+7 0 0 -7 156.874996 238.9352 Tm
+/f-0-0 1 Tf
+(80)Tj
+ET
+q 1 0 0 -1 0 0 cm
+190.852 -229.602 m 190.852 -226.449 l 190.852 -21.051 m 190.852 -24.199
+ l S Q
+BT
+7 0 0 -7 186.474995 238.9352 Tm
+/f-0-0 1 Tf
+(100)Tj
+ET
+q 1 0 0 -1 0 0 cm
+222.148 -229.602 m 222.148 -226.449 l 222.148 -21.051 m 222.148 -24.199
+ l S Q
+BT
+7 0 0 -7 217.774995 238.9352 Tm
+/f-0-0 1 Tf
+(120)Tj
+ET
+q 1 0 0 -1 0 0 cm
+253.449 -229.602 m 253.449 -226.449 l 253.449 -21.051 m 253.449 -24.199
+ l S Q
+BT
+7 0 0 -7 249.074994 238.9352 Tm
+/f-0-0 1 Tf
+(140)Tj
+ET
+q 1 0 0 -1 0 0 cm
+284.75 -229.602 m 284.75 -226.449 l 284.75 -21.051 m 284.75 -24.199 l S Q
+BT
+7 0 0 -7 280.374993 238.9352 Tm
+/f-0-0 1 Tf
+(160)Tj
+ET
+q 1 0 0 -1 0 0 cm
+316.051 -229.602 m 316.051 -226.449 l 316.051 -21.051 m 316.051 -24.199
+ l S Q
+BT
+7 0 0 -7 311.674992 238.9352 Tm
+/f-0-0 1 Tf
+(180)Tj
+ET
+q 1 0 0 -1 0 0 cm
+347.352 -229.602 m 347.352 -226.449 l 347.352 -21.051 m 347.352 -24.199
+ l S Q
+BT
+7 0 0 -7 342.974991 238.9352 Tm
+/f-0-0 1 Tf
+(200)Tj
+ET
+0.5 w
+q 1 0 0 -1 0 0 cm
+34.301 -21.051 313.051 -208.551 re S Q
+BT
+0 -7 -7 0 8.98516 164.330902 Tm
+/f-0-0 1 Tf
+(Packet Success Rate \(PSR\))Tj
+7 0 0 -7 173.010996 249.43516 Tm
+(distance \(m\))Tj
+18.922714 31.342856 Td
+(-85)Tj
+ET
+0.580392 0 0.831373 rg
+0.75 w
+q 1 0 0 -1 0 0 cm
+319 -27.699 m 338.949 -27.699 l 35.852 -21.051 m 60.898 -21.051 l 62.449
+ -21.449 l 64.051 -21.449 l 65.602 -23.75 l 67.148 -36.699 l 68.75 -55.449
+ l 70.301 -110.102 l 71.852 -156.199 l 73.449 -206.051 l 75 -224.602 l 76.551
+ -229.398 l 78.148 -229.602 l 345.801 -229.602 l S Q
+0 g
+BT
+7 0 0 -7 305.468992 37.035005 Tm
+/f-0-0 1 Tf
+(-90)Tj
+ET
+0 0.619608 0.45098 rg
+q 1 0 0 -1 0 0 cm
+319 -34.699 m 338.949 -34.699 l 35.852 -21.051 m 76.551 -21.051 l 78.148
+ -22.699 l 79.699 -23.551 l 81.25 -32.5 l 82.801 -39.801 l 84.398 -62.949
+ l 85.949 -95.699 l 87.5 -134.5 l 89.102 -176.398 l 90.648 -204.551 l 92.199
+ -220 l 93.801 -227.5 l 95.352 -229.398 l 96.898 -229.199 l 98.5 -229.602
+ l 345.801 -229.602 l S Q
+0 g
+BT
+7 0 0 -7 305.468992 44.035005 Tm
+/f-0-0 1 Tf
+(-95)Tj
+ET
+0.341176 0.709804 0.909804 rg
+q 1 0 0 -1 0 0 cm
+319 -41.699 m 338.949 -41.699 l 35.852 -21.051 m 93.801 -21.051 l 95.352
+ -21.449 l 96.898 -21.25 l 98.5 -22.102 l 100.051 -24.199 l 101.602 -27.699
+ l 103.148 -34.602 l 104.75 -38.352 l 106.301 -53.148 l 107.852 -71.301 
+l 109.449 -94.25 l 111 -124.5 l 112.551 -149.5 l 114.148 -173.301 l 115.699
+ -200.199 l 117.25 -210.199 l 118.801 -221.699 l 120.398 -224.801 l 121.949
+ -228.949 l 123.5 -228.352 l 125.102 -229.602 l 345.801 -229.602 l S Q
+0 g
+BT
+7 0 0 -7 301.968992 51.035005 Tm
+/f-0-0 1 Tf
+(-100)Tj
+ET
+0.901961 0.619608 0 rg
+q 1 0 0 -1 0 0 cm
+319 -48.699 m 338.949 -48.699 l 35.852 -21.051 m 118.801 -21.051 l 120.398
+ -21.25 l 121.949 -21.449 l 123.5 -21.25 l 125.102 -21.449 l 126.648 -22.699
+ l 128.199 -22.301 l 129.801 -24.199 l 131.352 -25.449 l 132.898 -30 l 134.5
+ -29.801 l 136.051 -35.648 l 137.602 -44.602 l 139.148 -55.648 l 140.75 
+-62.949 l 142.301 -80.301 l 143.852 -94.648 l 145.449 -119.5 l 147 -133.051
+ l 148.551 -151.801 l 150.148 -168.301 l 151.699 -189.148 l 153.25 -197.25
+ l 154.801 -206.25 l 156.398 -215.398 l 157.949 -223.352 l 159.5 -222.699
+ l 161.102 -226.449 l 162.648 -229.199 l 164.199 -229.602 l 165.801 -229.602
+ l 167.352 -229.398 l 168.898 -229.602 l 345.801 -229.602 l S Q
+0 g
+BT
+7 0 0 -7 301.968992 58.035005 Tm
+/f-0-0 1 Tf
+(-105)Tj
+ET
+0.941176 0.890196 0.258824 rg
+q 1 0 0 -1 0 0 cm
+319 -55.699 m 338.949 -55.699 l 35.852 -21.051 m 157.949 -21.051 l 159.5
+ -21.25 l 161.102 -21.051 l 164.199 -21.051 l 165.801 -21.25 l 167.352 -22.102
+ l 168.898 -21.25 l 170.5 -22.102 l 172.051 -23.551 l 173.602 -22.949 l 
+175.148 -25.199 l 176.75 -25.199 l 178.301 -27.5 l 179.852 -29.398 l 181.449
+ -34.602 l 183 -39.602 l 184.551 -40.449 l 186.148 -43.551 l 187.699 -54.648
+ l 189.25 -59.852 l 190.852 -74.449 l 192.398 -80.051 l 193.949 -89.25 l
+ 195.5 -95.898 l 197.102 -119.5 l 198.648 -132.398 l 200.199 -142.648 l 
+201.801 -155.75 l 203.352 -161.398 l 204.898 -174.75 l 206.5 -192.5 l 208.051
+ -199.551 l 209.602 -206.051 l 211.148 -215.398 l 212.75 -216.648 l 214.301
+ -221.25 l 215.852 -223.551 l 217.449 -224.398 l 219 -227.301 l 220.551 
+-227.949 l 222.148 -227.301 l 223.699 -228.949 l 225.25 -228.75 l 226.852
+ -229.398 l 228.398 -229.398 l 229.949 -229.602 l 345.801 -229.602 l S Q
+0 g
+BT
+7 0 0 -7 293.218993 65.035005 Tm
+/f-0-0 1 Tf
+(-106.58)Tj
+ET
+0 0.45098 0.698039 rg
+q 1 0 0 -1 0 0 cm
+319 -62.699 m 338.949 -62.699 l 35.852 -21.051 m 170.5 -21.051 l 172.051
+ -21.25 l 173.602 -21.051 l 178.301 -21.051 l 179.852 -21.449 l 181.449 
+-21.25 l 183 -21.25 l 184.551 -21.051 l 186.148 -22.102 l 187.699 -21.898
+ l 189.25 -23.551 l 190.852 -24.801 l 192.398 -24.602 l 193.949 -25 l 195.5
+ -27.301 l 197.102 -29.602 l 198.648 -31.25 l 200.199 -32.75 l 201.801 -37.551
+ l 203.352 -38.801 l 204.898 -46.301 l 206.5 -48.801 l 208.051 -60.648 l
+ 209.602 -65.449 l 211.148 -66.5 l 212.75 -86.352 l 214.301 -92.148 l 215.852
+ -101.949 l 217.449 -117.801 l 219 -123.25 l 220.551 -133.898 l 222.148 
+-147.648 l 223.699 -164.551 l 225.25 -167.25 l 226.852 -180.602 l 228.398
+ -184.949 l 229.949 -193.75 l 231.5 -200.199 l 233.102 -210.852 l 234.648
+ -213.949 l 236.199 -217.102 l 237.801 -220.199 l 239.352 -224.398 l 240.898
+ -225.449 l 242.5 -226.051 l 244.051 -228.148 l 245.602 -228.75 l 247.148
+ -229.199 l 248.75 -229.398 l 250.301 -228.949 l 251.852 -229.602 l 345.801
+ -229.602 l S Q
+0 g
+BT
+7 0 0 -7 301.968992 72.035004 Tm
+/f-0-0 1 Tf
+(-110)Tj
+ET
+0.901961 0.121569 0.0588235 rg
+q 1 0 0 -1 0 0 cm
+319 -69.699 m 338.949 -69.699 l 35.852 -21.051 m 220.551 -21.051 l 222.148
+ -21.25 l 225.25 -21.25 l 226.852 -21.449 l 228.398 -21.449 l 229.949 -21.898
+ l 231.5 -22.102 l 233.102 -22.699 l 234.648 -21.898 l 236.199 -22.5 l 237.801
+ -22.949 l 239.352 -23.75 l 240.898 -26.051 l 242.5 -25.648 l 244.051 -27.5
+ l 245.602 -28.75 l 247.148 -29.801 l 248.75 -35 l 250.301 -35.648 l 251.852
+ -36.898 l 253.449 -38.352 l 255 -44 l 256.551 -47.551 l 258.148 -54 l 259.699
+ -58.602 l 261.25 -68.602 l 262.852 -65.25 l 264.398 -79.648 l 265.949 -85.051
+ l 267.5 -89.648 l 269.102 -94.648 l 270.648 -108.449 l 272.199 -111.551
+ l 273.801 -124.051 l 275.352 -135.148 l 276.898 -140.352 l 278.5 -152.25
+ l 280.051 -155.551 l 281.602 -167.648 l 283.148 -174.352 l 284.75 -182.25
+ l 286.301 -188.949 l 287.852 -195.398 l 289.449 -200.602 l 291 -203.949
+ l 292.551 -211.852 l 294.148 -212.898 l 295.699 -215.852 l 297.25 -219.602
+ l 298.852 -220 l 300.398 -222.102 l 301.949 -225.199 l 303.5 -227.102 l
+ 305.102 -228.148 l 306.648 -227.301 l 308.199 -228.148 l 309.801 -227.949
+ l 311.352 -228.949 l 312.898 -229.602 l 314.5 -229.602 l 316.051 -229.199
+ l 317.602 -229.398 l 319.199 -229.602 l 320.75 -229.398 l 322.301 -229.602
+ l 345.801 -229.602 l S Q
+0 g
+0.5 w
+q 1 0 0 -1 0 0 cm
+34.301 -21.051 313.051 -208.551 re S Q
+BT
+7 0 0 -7 99.558998 12.885006 Tm
+/f-0-0 1 Tf
+(Packet \(MSDU\) size = 7 bytes; tx power = 0 dBm; channel = 11)Tj
+ET
+Q Q
+showpage
+%%Trailer
+end
+%%EOF
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/doc/lr-wpan.rst ns-3.46/src/lr-wpan/doc/lr-wpan.rst
--- ns-3.45/src/lr-wpan/doc/lr-wpan.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/doc/lr-wpan.rst	2025-10-01 18:46:32.000000000 -0700
@@ -1,10 +1,10 @@
-.. include:: replace.txt
-.. highlight:: cpp
-.. highlight:: bash
 
 IEEE 802.15.4: Low-Rate Wireless Personal Area Network (LR-WPAN)
 ================================================================
 
+.. include:: replace.txt
+.. highlight:: cpp
+
 This chapter describes the implementation of |ns3| models for the
 low-rate, wireless personal area network (LR-WPAN) as specified by
 IEEE standard 802.15.4 (2003,2006,2011). The current emphasis is on direct transmissions running on both,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/model/lr-wpan-mac.cc ns-3.46/src/lr-wpan/model/lr-wpan-mac.cc
--- ns-3.45/src/lr-wpan/model/lr-wpan-mac.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/model/lr-wpan-mac.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,7 +15,6 @@
 
 #include "lr-wpan-constants.h"
 #include "lr-wpan-csmaca.h"
-#include "lr-wpan-mac-header.h"
 #include "lr-wpan-mac-pl-headers.h"
 #include "lr-wpan-mac-trailer.h"
 
@@ -1030,6 +1029,55 @@
 }
 
 void
+LrWpanMac::ReceiveInPromiscuousMode(uint8_t lqi,
+                                    const LrWpanMacHeader& receivedMacHdr,
+                                    Ptr<Packet> p)
+{
+    NS_LOG_FUNCTION(this);
+
+    NS_LOG_DEBUG("promiscuous mode, forwarding up");
+
+    // TODO: Fix here, this should trigger different Indication Callbacks
+    // depending the type of frame received (data,command, beacon)
+    if (!m_mcpsDataIndicationCallback.IsNull())
+    {
+        McpsDataIndicationParams params;
+        params.m_dsn = receivedMacHdr.GetSeqNum();
+        params.m_mpduLinkQuality = lqi;
+        params.m_srcPanId = receivedMacHdr.GetSrcPanId();
+        params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
+
+        switch (params.m_srcAddrMode)
+        {
+        case SHORT_ADDR:
+            params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
+            break;
+        case EXT_ADDR:
+            params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
+            break;
+        default:
+            break;
+        }
+
+        params.m_dstPanId = receivedMacHdr.GetDstPanId();
+        params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
+
+        switch (params.m_dstAddrMode)
+        {
+        case SHORT_ADDR:
+            params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
+            break;
+        case EXT_ADDR:
+            params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
+            break;
+        default:
+            break;
+        }
+        m_mcpsDataIndicationCallback(params, p);
+    }
+}
+
+void
 LrWpanMac::SendOneBeacon()
 {
     NS_LOG_FUNCTION(this);
@@ -1754,7 +1802,7 @@
 }
 
 void
-LrWpanMac::ReceiveBeacon(uint8_t lqi, Ptr<Packet> p)
+LrWpanMac::ReceiveBeacon(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p)
 {
     NS_LOG_FUNCTION(this << lqi << p);
     // The received beacon size in symbols
@@ -1771,13 +1819,7 @@
     NS_LOG_DEBUG("Beacon Received; forwarding up (m_macBeaconRxTime: "
                  << m_macBeaconRxTime.As(Time::S) << ")");
 
-    // Strip the MAC header, the trailer and the Beacon Payload
-    LrWpanMacTrailer receivedMacTrailer;
-    p->RemoveTrailer(receivedMacTrailer);
-
-    LrWpanMacHeader receivedMacHdr;
-    p->RemoveHeader(receivedMacHdr);
-
+    // Strip the Beacon Payload
     BeaconPayloadHeader receivedMacPayload;
     p->RemoveHeader(receivedMacPayload);
 
@@ -1958,6 +2000,310 @@
 }
 
 void
+LrWpanMac::ReceiveCommand(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p)
+{
+    NS_LOG_FUNCTION(this << lqi << p);
+
+    auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
+
+    CommandPayloadHeader receivedMacPayload;
+    p->RemoveHeader(receivedMacPayload);
+
+    switch (receivedMacPayload.GetCommandFrameType())
+    {
+    case CommandPayloadHeader::BEACON_REQ:
+        if (m_csmaCa->IsUnSlottedCsmaCa() && m_coor)
+        {
+            // Jitter = Between 0 and 2 aUnitBackoffPeriods
+            // (0, 320us or 640us in 2.4Ghz O-QPSK)
+            // While this jitter is not described by the standard,
+            // it reduces the probability of collisions in beacons
+            // transmitted as a result of a beacon request
+            Time jitter =
+                Seconds(static_cast<double>(m_uniformVar->GetInteger(0, 3) * aUnitBackoffPeriod) /
+                        symbolRate);
+
+            Simulator::Schedule((jitter), &LrWpanMac::SendOneBeacon, this);
+        }
+        else
+        {
+            NS_LOG_DEBUG("Beacon Request command received in beacon mode: Ignore");
+        }
+        break;
+    case CommandPayloadHeader::ORPHAN_NOTIF:
+        if (m_coor)
+        {
+            if (!m_mlmeOrphanIndicationCallback.IsNull())
+            {
+                MlmeOrphanIndicationParams orphanParams;
+                orphanParams.m_orphanAddr = receivedMacHdr.GetExtSrcAddr();
+                m_mlmeOrphanIndicationCallback(orphanParams);
+            }
+        }
+        break;
+    case CommandPayloadHeader::COOR_REALIGN:
+        if (m_scanOrphanEvent.IsPending())
+        {
+            // Coordinator located, no need to keep scanning other channels
+            m_scanOrphanEvent.Cancel();
+
+            m_macPanIdScan = 0;
+            m_pendPrimitive = MLME_NONE;
+            m_channelScanIndex = 0;
+
+            // Update the device information with the received information
+            // from the Coordinator Realigment command.
+            m_macPanId = receivedMacPayload.GetPanId();
+            m_shortAddress = receivedMacPayload.GetShortAddr();
+            m_macCoordExtendedAddress = receivedMacHdr.GetExtSrcAddr();
+            m_macCoordShortAddress = receivedMacPayload.GetCoordShortAddr();
+
+            if (!m_mlmeScanConfirmCallback.IsNull())
+            {
+                MlmeScanConfirmParams confirmParams;
+                confirmParams.m_scanType = m_scanParams.m_scanType;
+                confirmParams.m_chPage = m_scanParams.m_chPage;
+                confirmParams.m_status = MacStatus::SUCCESS;
+                m_mlmeScanConfirmCallback(confirmParams);
+            }
+            m_scanParams = {};
+        }
+        // TODO: handle Coordinator realignment when not
+        //       used during an orphan scan.
+        break;
+    default:
+        break;
+    }
+}
+
+void
+LrWpanMac::ReceiveData(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p)
+{
+    NS_LOG_FUNCTION(this << lqi << p);
+
+    NS_LOG_DEBUG("Data Packet is for me; forwarding up");
+
+    if (!m_mcpsDataIndicationCallback.IsNull())
+    {
+        McpsDataIndicationParams params;
+        params.m_dsn = receivedMacHdr.GetSeqNum();
+        params.m_mpduLinkQuality = lqi;
+        params.m_srcPanId = receivedMacHdr.GetSrcPanId();
+        params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
+
+        switch (params.m_srcAddrMode)
+        {
+        case SHORT_ADDR:
+            params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
+            break;
+        case EXT_ADDR:
+            params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
+            break;
+        default:
+            break;
+        }
+
+        params.m_dstPanId = receivedMacHdr.GetDstPanId();
+        params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
+
+        switch (params.m_dstAddrMode)
+        {
+        case SHORT_ADDR:
+            params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
+            break;
+        case EXT_ADDR:
+            params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
+            break;
+        default:
+            break;
+        }
+
+        m_mcpsDataIndicationCallback(params, p);
+    }
+}
+
+void
+LrWpanMac::ReceiveAcknowledgment(const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p)
+{
+    NS_LOG_FUNCTION(this << p);
+
+    // Make a copy of the original transmitted packet that required ACK and
+    // extract its MAC header.
+    Ptr<Packet> txPkt = m_txPkt->Copy();
+    LrWpanMacHeader txMacHdr;
+    txPkt->RemoveHeader(txMacHdr);
+
+    // If it is an ACK with an unexpected sequence number, mark the current
+    // transmission as failed and start a retransmit. (cf 7.5.6.4.3)
+    if (receivedMacHdr.GetSeqNum() != txMacHdr.GetSeqNum())
+    {
+        m_ackWaitTimeout.Cancel();
+        if (!PrepareRetransmission())
+        {
+            m_setMacState.Cancel();
+            m_setMacState = Simulator::ScheduleNow(&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
+        }
+        else
+        {
+            m_setMacState.Cancel();
+            m_setMacState = Simulator::ScheduleNow(&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
+        }
+
+        return;
+    }
+
+    // If it is an ACK with the expected sequence number, finish the transmission
+    m_ackWaitTimeout.Cancel();
+    m_macTxOkTrace(m_txPkt);
+
+    // TODO: check  if the IFS is the correct size after ACK.
+    double symbolRate = m_phy->GetDataOrSymbolRate(false);
+    Time ifsWaitTime = Seconds((double)GetIfsSize() / symbolRate);
+
+    if (txMacHdr.IsCommand())
+    {
+        // We received an ACK to a command, we need to take actions depending on the
+        // transmitted command.
+
+        // Extract the command payload of the originally transmitted packet to know
+        // what command we transmitted.
+        CommandPayloadHeader txCmdPayload;
+        txPkt->RemoveHeader(txCmdPayload);
+
+        switch (txCmdPayload.GetCommandFrameType())
+        {
+        case CommandPayloadHeader::ASSOCIATION_REQ: {
+            Time waitTime = Seconds(static_cast<double>(m_macResponseWaitTime) / symbolRate);
+            if (!m_beaconTrackingOn)
+            {
+                m_respWaitTimeout =
+                    Simulator::Schedule(waitTime, &LrWpanMac::SendDataRequestCommand, this);
+            }
+            else
+            {
+                // TODO: The data must be extracted by the coordinator within
+                // macResponseWaitTime on timeout, MLME-ASSOCIATE.confirm is set
+                // with status NO_DATA, and this should trigger the cancellation
+                // of the beacon tracking (MLME-SYNC.request  trackBeacon
+                // =FALSE)
+            }
+            break;
+        }
+
+        case CommandPayloadHeader::ASSOCIATION_RESP: {
+            // MLME-comm-status.Indication generated as a result of an
+            // association response command, therefore src and dst address use
+            // extended mode (see 5.3.2.1)
+            if (!m_mlmeCommStatusIndicationCallback.IsNull())
+            {
+                MlmeCommStatusIndicationParams commStatusParams;
+                commStatusParams.m_panId = m_macPanId;
+                commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
+                commStatusParams.m_srcExtAddr = txMacHdr.GetExtSrcAddr();
+                commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
+                commStatusParams.m_dstExtAddr = txMacHdr.GetExtDstAddr();
+                commStatusParams.m_status = MacStatus::SUCCESS;
+                m_mlmeCommStatusIndicationCallback(commStatusParams);
+            }
+            // Remove element from Pending Transaction List
+            RemovePendTxQElement(m_txPkt->Copy());
+            break;
+        }
+
+        case CommandPayloadHeader::DATA_REQ: {
+            if (!m_ignoreDataCmdAck)
+            {
+                // Schedule an event in case the Association Response Command
+                // never reached this device during an association process.
+                Time waitTime = Seconds(static_cast<double>(m_assocRespCmdWaitTime) / symbolRate);
+                m_assocResCmdWaitTimeout =
+                    Simulator::Schedule(waitTime, &LrWpanMac::LostAssocRespCommand, this);
+            }
+
+            if (!m_mlmePollConfirmCallback.IsNull())
+            {
+                MlmePollConfirmParams pollConfirmParams;
+                pollConfirmParams.m_status = MacStatus::SUCCESS;
+                m_mlmePollConfirmCallback(pollConfirmParams);
+            }
+            break;
+        }
+
+        case CommandPayloadHeader::COOR_REALIGN: {
+            // ACK of coordinator realigment commands is not specified in the
+            // standard, in here, we assume they are required as in other
+            // commands.
+            if (!m_mlmeCommStatusIndicationCallback.IsNull())
+            {
+                MlmeCommStatusIndicationParams commStatusParams;
+                commStatusParams.m_panId = m_macPanId;
+                commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
+                commStatusParams.m_srcExtAddr = txMacHdr.GetExtSrcAddr();
+                commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
+                commStatusParams.m_dstExtAddr = txMacHdr.GetExtDstAddr();
+                commStatusParams.m_status = MacStatus::SUCCESS;
+                m_mlmeCommStatusIndicationCallback(commStatusParams);
+            }
+            break;
+        }
+
+        default: {
+            // TODO: add response to other request commands (e.g. Orphan)
+            break;
+        }
+        }
+    }
+    else
+    {
+        // Receive ACK to data packet
+        if (!m_mcpsDataConfirmCallback.IsNull())
+        {
+            Ptr<TxQueueElement> txQElement = m_txQueue.front();
+            McpsDataConfirmParams confirmParams;
+            confirmParams.m_msduHandle = txQElement->txQMsduHandle;
+            confirmParams.m_status = MacStatus::SUCCESS;
+            m_mcpsDataConfirmCallback(confirmParams);
+        }
+    }
+
+    // Ack was successfully received, wait for the Interframe Space (IFS) and
+    // then proceed
+    RemoveFirstTxQElement();
+    m_setMacState.Cancel();
+    m_setMacState = Simulator::ScheduleNow(&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
+    m_ifsEvent = Simulator::Schedule(ifsWaitTime, &LrWpanMac::IfsWaitTimeout, this, ifsWaitTime);
+}
+
+void
+LrWpanMac::PrintReceivedPacket(const LrWpanMacHeader& receivedMacHdr)
+{
+    if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
+        receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
+    {
+        NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetShortSrcAddr() << "] to ["
+                                     << receivedMacHdr.GetShortDstAddr() << "]");
+    }
+    else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
+             receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
+    {
+        NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetExtSrcAddr() << "] to ["
+                                     << receivedMacHdr.GetExtDstAddr() << "]");
+    }
+    else if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
+             receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
+    {
+        NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetShortSrcAddr() << "] to ["
+                                     << receivedMacHdr.GetExtDstAddr() << "]");
+    }
+    else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
+             receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
+    {
+        NS_LOG_DEBUG("Packet from [" << receivedMacHdr.GetExtSrcAddr() << "] to ["
+                                     << receivedMacHdr.GetShortDstAddr() << "]");
+    }
+}
+
+void
 LrWpanMac::CheckQueue()
 {
     NS_LOG_FUNCTION(this);
@@ -2051,575 +2397,260 @@
     NS_ASSERT(m_macState == MAC_IDLE || m_macState == MAC_ACK_PENDING || m_macState == MAC_CSMA);
     NS_LOG_FUNCTION(this << psduLength << p << (uint16_t)lqi);
 
-    bool acceptFrame;
-
-    // from sec 7.5.6.2 Reception and rejection, Std802.15.4-2006
-    // level 1 filtering, test FCS field and reject if frame fails
-    // level 2 filtering if promiscuous mode pass frame to higher layer otherwise perform level 3
-    // filtering level 3 filtering accept frame if Frame type and version is not reserved, and if
-    // there is a dstPanId then dstPanId=m_macPanId or broadcastPanId, and if there is a
-    // shortDstAddr then shortDstAddr =shortMacAddr or broadcastAddr, and if beacon frame then
-    // srcPanId = m_macPanId if only srcAddr field in Data or Command frame,accept frame if
-    // srcPanId=m_macPanId
+    Ptr<Packet> originalPkt = p->Copy();
 
-    Ptr<Packet> originalPkt = p->Copy();                           // because we will strip headers
-    auto symbolRate = (uint64_t)m_phy->GetDataOrSymbolRate(false); // symbols per second
-    m_promiscSnifferTrace(originalPkt);
-
-    m_macPromiscRxTrace(originalPkt);
-    // XXX no rejection tracing (to macRxDropTrace) being performed below
+    // If active, pass the complete packet to the traces
+    if (!m_promiscSnifferTrace.IsEmpty())
+    {
+        m_promiscSnifferTrace(p->Copy());
+    }
+    else if (!m_macPromiscRxTrace.IsEmpty())
+    {
+        m_macPromiscRxTrace(p->Copy());
+    }
 
+    // Extract the MAC trailer
     LrWpanMacTrailer receivedMacTrailer;
     p->RemoveTrailer(receivedMacTrailer);
+
+    // Extract the MAC Header from the packet
+    LrWpanMacHeader receivedMacHdr;
+    p->RemoveHeader(receivedMacHdr);
+
     if (Node::ChecksumEnabled())
     {
         receivedMacTrailer.EnableFcs(true);
     }
 
-    // level 1 filtering
+    // From section 7.5.6.2 Reception and rejection, IEEE 802.15.4-2006
+    // - Level 1 filtering: Test FCS field and reject if frame fails.
+    // - Level 2 filtering: If promiscuous mode pass frame to higher layer
+    //   otherwise perform Level 3 filtering.
+    // - Level 3 filtering: Accept frame if Frame type and version is not reserved, and if
+    //   there is a dstPanId then dstPanId=m_macPanId or broadcastPanId, and if there is a
+    //   shortDstAddr then shortDstAddr=shortMacAddr or broadcastAddr, and if beacon frame then
+    //   srcPanId = m_macPanId if only srcAddr field in Data or Command frame,accept frame if
+    //   srcPanId=m_macPanId.
+
+    // Level 1 filtering
     if (!receivedMacTrailer.CheckFcs(p))
     {
         m_macRxDropTrace(originalPkt);
+        return;
     }
-    else
+
+    // Level 2 filtering
+    if (m_macPromiscuousMode)
     {
-        LrWpanMacHeader receivedMacHdr;
-        p->RemoveHeader(receivedMacHdr);
+        PrintReceivedPacket(receivedMacHdr);
+        ReceiveInPromiscuousMode(lqi, receivedMacHdr, p);
+        return;
+    }
 
-        McpsDataIndicationParams params;
-        params.m_dsn = receivedMacHdr.GetSeqNum();
-        params.m_mpduLinkQuality = lqi;
-        params.m_srcPanId = receivedMacHdr.GetSrcPanId();
-        params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode();
-        switch (params.m_srcAddrMode)
-        {
-        case SHORT_ADDR:
-            params.m_srcAddr = receivedMacHdr.GetShortSrcAddr();
-            break;
-        case EXT_ADDR:
-            params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr();
-            break;
-        default:
-            break;
-        }
-        params.m_dstPanId = receivedMacHdr.GetDstPanId();
-        params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode();
-        switch (params.m_dstAddrMode)
+    // Level 3 frame filtering
+    bool acceptFrame;
+    acceptFrame = (receivedMacHdr.GetType() != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
+
+    if (acceptFrame)
+    {
+        acceptFrame = (receivedMacHdr.GetFrameVer() <= 1);
+    }
+
+    if (acceptFrame && (receivedMacHdr.GetDstAddrMode() > 1))
+    {
+        // Accept frame if one of the following is true:
+
+        // 1) Have the same macPanId
+        // 2) Is Message to all PANs
+        // 3) Is a beacon or command frame and the macPanId is not present (bootstrap)
+        acceptFrame = ((receivedMacHdr.GetDstPanId() == m_macPanId ||
+                        receivedMacHdr.GetDstPanId() == 0xffff) ||
+                       (m_macPanId == 0xffff && receivedMacHdr.IsBeacon())) ||
+                      (m_macPanId == 0xffff && receivedMacHdr.IsCommand());
+    }
+
+    if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR))
+    {
+        if (receivedMacHdr.GetShortDstAddr() == m_shortAddress)
         {
-        case SHORT_ADDR:
-            params.m_dstAddr = receivedMacHdr.GetShortDstAddr();
-            break;
-        case EXT_ADDR:
-            params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr();
-            break;
-        default:
-            break;
+            // unicast, for me
+            acceptFrame = true;
         }
-
-        if (m_macPromiscuousMode)
+        else if (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
+                 receivedMacHdr.GetShortDstAddr().IsMulticast())
         {
-            // level 2 filtering
-            if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
-                receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
-            {
-                NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstAddr
-                                             << "]");
-            }
-            else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
-                     receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
-            {
-                NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to ["
-                                             << params.m_dstExtAddr << "]");
-            }
-            else if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
-                     receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
-            {
-                NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstExtAddr
-                                             << "]");
-            }
-            else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
-                     receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
-            {
-                NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to [" << params.m_dstAddr
-                                             << "]");
-            }
-
-            // TODO: Fix here, this should trigger different Indication Callbacks
-            // depending the type of frame received (data,command, beacon)
-            if (!m_mcpsDataIndicationCallback.IsNull())
-            {
-                NS_LOG_DEBUG("promiscuous mode, forwarding up");
-                m_mcpsDataIndicationCallback(params, p);
-            }
-            else
-            {
-                NS_LOG_ERROR(this << " Data Indication Callback not initialized");
-            }
+            // Broadcast or multicast.
+            // Discard broadcast/multicast with the ACK bit set.
+            acceptFrame = !receivedMacHdr.IsAckReq();
         }
         else
         {
-            // level 3 frame filtering
-            acceptFrame = (receivedMacHdr.GetType() != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
+            acceptFrame = false;
+        }
+    }
 
-            if (acceptFrame)
-            {
-                acceptFrame = (receivedMacHdr.GetFrameVer() <= 1);
-            }
+    if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == EXT_ADDR))
+    {
+        acceptFrame = (receivedMacHdr.GetExtDstAddr() == m_macExtendedAddress);
+    }
 
-            if (acceptFrame && (receivedMacHdr.GetDstAddrMode() > 1))
-            {
-                // Accept frame if one of the following is true:
+    if (acceptFrame && m_scanEvent.IsPending())
+    {
+        if (!receivedMacHdr.IsBeacon())
+        {
+            acceptFrame = false;
+        }
+    }
+    else if (acceptFrame && m_scanOrphanEvent.IsPending())
+    {
+        if (!receivedMacHdr.IsCommand())
+        {
+            acceptFrame = false;
+        }
+    }
+    else if (m_scanEnergyEvent.IsPending())
+    {
+        // Reject any frames if energy scan is running
+        acceptFrame = false;
+    }
 
-                // 1) Have the same macPanId
-                // 2) Is Message to all PANs
-                // 3) Is a beacon or command frame and the macPanId is not present (bootstrap)
-                acceptFrame = ((receivedMacHdr.GetDstPanId() == m_macPanId ||
-                                receivedMacHdr.GetDstPanId() == 0xffff) ||
-                               (m_macPanId == 0xffff && receivedMacHdr.IsBeacon())) ||
-                              (m_macPanId == 0xffff && receivedMacHdr.IsCommand());
-            }
+    // Check device is panCoor with association permit when receiving Association Request
+    // Commands.
+    if (acceptFrame && (receivedMacHdr.IsCommand() && receivedMacHdr.IsAckReq()))
+    {
+        CommandPayloadHeader receivedMacPayload;
+        p->PeekHeader(receivedMacPayload);
 
-            if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == SHORT_ADDR))
-            {
-                if (receivedMacHdr.GetShortDstAddr() == m_shortAddress)
-                {
-                    // unicast, for me
-                    acceptFrame = true;
-                }
-                else if (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
-                         receivedMacHdr.GetShortDstAddr().IsMulticast())
-                {
-                    // Broadcast or multicast.
-                    // Discard broadcast/multicast with the ACK bit set.
-                    acceptFrame = !receivedMacHdr.IsAckReq();
-                }
-                else
-                {
-                    acceptFrame = false;
-                }
-            }
+        if (receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::ASSOCIATION_REQ &&
+            !(m_macAssociationPermit && m_coor))
+        {
+            acceptFrame = false;
+        }
 
-            if (acceptFrame && (receivedMacHdr.GetDstAddrMode() == EXT_ADDR))
-            {
-                acceptFrame = (receivedMacHdr.GetExtDstAddr() == m_macExtendedAddress);
-            }
+        // Although ACKs do not use CSMA to to be transmitted, we need to make sure
+        // that the transmitted ACK will not collide with the transmission of a beacon
+        // when beacon-enabled mode is running in the coordinator.
+        if (acceptFrame && (m_csmaCa->IsSlottedCsmaCa() && m_capEvent.IsPending()))
+        {
+            Time timeLeftInCap = Simulator::GetDelayLeft(m_capEvent);
+            uint64_t ackSymbols = lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
+                                  ceil(6 * m_phy->GetPhySymbolsPerOctet());
+            auto symbolRate = m_phy->GetDataOrSymbolRate(false); // symbols per second
+            Time ackTime = Seconds((double)ackSymbols / symbolRate);
 
-            if (acceptFrame && m_scanEvent.IsPending())
-            {
-                if (!receivedMacHdr.IsBeacon())
-                {
-                    acceptFrame = false;
-                }
-            }
-            else if (acceptFrame && m_scanOrphanEvent.IsPending())
-            {
-                if (!receivedMacHdr.IsCommand())
-                {
-                    acceptFrame = false;
-                }
-            }
-            else if (m_scanEnergyEvent.IsPending())
+            if (ackTime >= timeLeftInCap)
             {
-                // Reject any frames if energy scan is running
+                NS_LOG_DEBUG("Command frame received but not enough time to transmit ACK "
+                             "before the end of CAP ");
                 acceptFrame = false;
             }
+        }
+    }
 
-            // Check device is panCoor with association permit when receiving Association Request
-            // Commands.
-            // TODO:: Simple coordinators should also be able to receive it (currently only Pan
-            // Coordinators are checked)
-            if (acceptFrame && (receivedMacHdr.IsCommand() && receivedMacHdr.IsAckReq()))
-            {
-                CommandPayloadHeader receivedMacPayload;
-                p->PeekHeader(receivedMacPayload);
-
-                if (receivedMacPayload.GetCommandFrameType() ==
-                        CommandPayloadHeader::ASSOCIATION_REQ &&
-                    !(m_macAssociationPermit && m_coor))
-                {
-                    acceptFrame = false;
-                }
-
-                // Although ACKs do not use CSMA to to be transmitted, we need to make sure
-                // that the transmitted ACK will not collide with the transmission of a beacon
-                // when beacon-enabled mode is running in the coordinator.
-                if (acceptFrame && (m_csmaCa->IsSlottedCsmaCa() && m_capEvent.IsPending()))
-                {
-                    Time timeLeftInCap = Simulator::GetDelayLeft(m_capEvent);
-                    uint64_t ackSymbols = lrwpan::aTurnaroundTime + m_phy->GetPhySHRDuration() +
-                                          ceil(6 * m_phy->GetPhySymbolsPerOctet());
-                    Time ackTime = Seconds((double)ackSymbols / symbolRate);
-
-                    if (ackTime >= timeLeftInCap)
-                    {
-                        NS_LOG_DEBUG("Command frame received but not enough time to transmit ACK "
-                                     "before the end of CAP ");
-                        acceptFrame = false;
-                    }
-                }
-            }
+    if (!acceptFrame)
+    {
+        m_macRxDropTrace(originalPkt);
+        return;
+    }
 
-            if (acceptFrame)
+    m_macRxTrace(originalPkt);
+    // \todo: What should we do if we receive a frame while waiting for an ACK?
+    //        Especially if this frame has the ACK request bit set, should we reply with
+    //        an ACK, possibly missing the pending ACK?
+
+    // If the received frame is a frame with the ACK request bit set, we immediately
+    // send back an ACK. If we are currently waiting for a pending ACK, we assume the
+    // ACK was lost and trigger a retransmission after sending the ACK.
+    if ((receivedMacHdr.IsData() || receivedMacHdr.IsCommand()) && receivedMacHdr.IsAckReq() &&
+        !(receivedMacHdr.GetDstAddrMode() == SHORT_ADDR &&
+          (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
+           receivedMacHdr.GetShortDstAddr().IsMulticast())))
+    {
+        // If this is a data or mac command frame, which is not a broadcast or
+        // multicast, with ack req set, generate and send an ack frame. If there is a
+        // CSMA medium access in progress we cancel the medium access for sending the
+        // ACK frame. A new transmission attempt will be started after the ACK was send.
+        if (m_macState == MAC_ACK_PENDING)
+        {
+            m_ackWaitTimeout.Cancel();
+            PrepareRetransmission();
+        }
+        else if (m_macState == MAC_CSMA)
+        {
+            // \todo: If we receive a packet while doing CSMA/CA, should  we drop the
+            // packet because of channel busy,
+            //        or should we restart CSMA/CA for the packet after sending the ACK?
+            // Currently we simply restart CSMA/CA after sending the ACK.
+            NS_LOG_DEBUG("Received a packet with ACK required while in CSMA. Cancel "
+                         "current CSMA-CA");
+            m_csmaCa->Cancel();
+        }
+        // Cancel any pending MAC state change, ACKs have higher priority.
+        m_setMacState.Cancel();
+        ChangeMacState(MAC_IDLE);
+
+        // save received packet and LQI to process the appropriate indication/response
+        // after sending ACK (PD-DATA.confirm)
+        m_rxPkt = originalPkt;
+        m_lastRxFrameLqi = lqi;
+
+        // LOG Commands with ACK required.
+        CommandPayloadHeader receivedMacPayload;
+        p->PeekHeader(receivedMacPayload);
+        switch (receivedMacPayload.GetCommandFrameType())
+        {
+        case CommandPayloadHeader::DATA_REQ:
+            NS_LOG_DEBUG("Data Request Command Received; processing ACK");
+            break;
+        case CommandPayloadHeader::ASSOCIATION_REQ:
+            NS_LOG_DEBUG("Association Request Command Received; processing ACK");
+            break;
+        case CommandPayloadHeader::ASSOCIATION_RESP: {
+            if (m_assocResCmdWaitTimeout.IsPending())
             {
-                m_macRxTrace(originalPkt);
-                // \todo: What should we do if we receive a frame while waiting for an ACK?
-                //        Especially if this frame has the ACK request bit set, should we reply with
-                //        an ACK, possibly missing the pending ACK?
-
-                // If the received frame is a frame with the ACK request bit set, we immediately
-                // send back an ACK. If we are currently waiting for a pending ACK, we assume the
-                // ACK was lost and trigger a retransmission after sending the ACK.
-                if ((receivedMacHdr.IsData() || receivedMacHdr.IsCommand()) &&
-                    receivedMacHdr.IsAckReq() &&
-                    !(receivedMacHdr.GetDstAddrMode() == SHORT_ADDR &&
-                      (receivedMacHdr.GetShortDstAddr().IsBroadcast() ||
-                       receivedMacHdr.GetShortDstAddr().IsMulticast())))
-                {
-                    // If this is a data or mac command frame, which is not a broadcast or
-                    // multicast, with ack req set, generate and send an ack frame. If there is a
-                    // CSMA medium access in progress we cancel the medium access for sending the
-                    // ACK frame. A new transmission attempt will be started after the ACK was send.
-                    if (m_macState == MAC_ACK_PENDING)
-                    {
-                        m_ackWaitTimeout.Cancel();
-                        PrepareRetransmission();
-                    }
-                    else if (m_macState == MAC_CSMA)
-                    {
-                        // \todo: If we receive a packet while doing CSMA/CA, should  we drop the
-                        // packet because of channel busy,
-                        //        or should we restart CSMA/CA for the packet after sending the ACK?
-                        // Currently we simply restart CSMA/CA after sending the ACK.
-                        NS_LOG_DEBUG("Received a packet with ACK required while in CSMA. Cancel "
-                                     "current CSMA-CA");
-                        m_csmaCa->Cancel();
-                    }
-                    // Cancel any pending MAC state change, ACKs have higher priority.
-                    m_setMacState.Cancel();
-                    ChangeMacState(MAC_IDLE);
-
-                    // save received packet and LQI to process the appropriate indication/response
-                    // after sending ACK (PD-DATA.confirm)
-                    m_rxPkt = originalPkt->Copy();
-                    m_lastRxFrameLqi = lqi;
-
-                    // LOG Commands with ACK required.
-                    CommandPayloadHeader receivedMacPayload;
-                    p->PeekHeader(receivedMacPayload);
-                    switch (receivedMacPayload.GetCommandFrameType())
-                    {
-                    case CommandPayloadHeader::DATA_REQ:
-                        NS_LOG_DEBUG("Data Request Command Received; processing ACK");
-                        break;
-                    case CommandPayloadHeader::ASSOCIATION_REQ:
-                        NS_LOG_DEBUG("Association Request Command Received; processing ACK");
-                        break;
-                    case CommandPayloadHeader::ASSOCIATION_RESP: {
-                        if (m_assocResCmdWaitTimeout.IsPending())
-                        {
-                            m_assocResCmdWaitTimeout
-                                .Cancel(); // cancel event to a lost assoc resp cmd.
-                            NS_LOG_DEBUG("Association Response Command Received; processing ACK");
-                        }
-                        else
-                        {
-                            // Association response command was received before (or never received)
-                            // a Data request command ACK. This is an extreme case and it is
-                            // essentially caused by saturation in the network.
-                            // We turn a flag ON to not react once
-                            // we finally receive the Data request command ACK. This behavior is not
-                            // standard, but necessary to address this flaw in design of the
-                            // original association process.
-                            m_ignoreDataCmdAck = true;
-                            NS_LOG_DEBUG("Assoc. Resp Cmd received before Data Req. Cmd. in "
-                                         "Association request");
-                        }
-                        break;
-                    }
-                    default:
-                        break;
-                    }
-
-                    m_setMacState = Simulator::ScheduleNow(&LrWpanMac::SendAck,
-                                                           this,
-                                                           receivedMacHdr.GetSeqNum());
-                }
-
-                if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
-                    receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
-                {
-                    NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to [" << params.m_dstAddr
-                                                 << "]");
-                }
-                else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
-                         receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
-                {
-                    NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to ["
-                                                 << params.m_dstExtAddr << "]");
-                }
-                else if (receivedMacHdr.GetSrcAddrMode() == SHORT_ADDR &&
-                         receivedMacHdr.GetDstAddrMode() == EXT_ADDR)
-                {
-                    NS_LOG_DEBUG("Packet from [" << params.m_srcAddr << "] to ["
-                                                 << params.m_dstExtAddr << "]");
-                }
-                else if (receivedMacHdr.GetSrcAddrMode() == EXT_ADDR &&
-                         receivedMacHdr.GetDstAddrMode() == SHORT_ADDR)
-                {
-                    NS_LOG_DEBUG("Packet from [" << params.m_srcExtAddr << "] to ["
-                                                 << params.m_dstAddr << "]");
-                }
-
-                if (receivedMacHdr.IsBeacon())
-                {
-                    ReceiveBeacon(lqi, originalPkt);
-                }
-                else if (receivedMacHdr.IsCommand())
-                {
-                    // Handle the reception of frame commands that do not require ACK
-                    // (i.e. Beacon Request, Orphan notification, Coordinator Realigment)
-                    CommandPayloadHeader receivedMacPayload;
-                    p->PeekHeader(receivedMacPayload);
-
-                    switch (receivedMacPayload.GetCommandFrameType())
-                    {
-                    case CommandPayloadHeader::BEACON_REQ:
-                        if (m_csmaCa->IsUnSlottedCsmaCa() && m_coor)
-                        {
-                            // Jitter = Between 0 and 2 aUnitBackoffPeriods
-                            // (0, 320us or 640us in 2.4Ghz O-QPSK)
-                            // While this jitter is not described by the standard,
-                            // it reduces the probability of collisions in beacons
-                            // transmitted as a result of a beacon request
-                            Time jitter =
-                                Seconds(static_cast<double>(m_uniformVar->GetInteger(0, 3) *
-                                                            aUnitBackoffPeriod) /
-                                        symbolRate);
-
-                            Simulator::Schedule((jitter), &LrWpanMac::SendOneBeacon, this);
-                        }
-                        else
-                        {
-                            m_macRxDropTrace(originalPkt);
-                        }
-                        break;
-                    case CommandPayloadHeader::ORPHAN_NOTIF:
-                        if (!m_mlmeOrphanIndicationCallback.IsNull())
-                        {
-                            if (m_coor)
-                            {
-                                MlmeOrphanIndicationParams orphanParams;
-                                orphanParams.m_orphanAddr = receivedMacHdr.GetExtSrcAddr();
-                                m_mlmeOrphanIndicationCallback(orphanParams);
-                            }
-                        }
-                        break;
-                    case CommandPayloadHeader::COOR_REALIGN:
-                        if (m_scanOrphanEvent.IsPending())
-                        {
-                            // Coordinator located, no need to keep scanning other channels
-                            m_scanOrphanEvent.Cancel();
-
-                            m_macPanIdScan = 0;
-                            m_pendPrimitive = MLME_NONE;
-                            m_channelScanIndex = 0;
-
-                            // Update the device information with the received information
-                            // from the Coordinator Realigment command.
-                            m_macPanId = receivedMacPayload.GetPanId();
-                            m_shortAddress = receivedMacPayload.GetShortAddr();
-                            m_macCoordExtendedAddress = receivedMacHdr.GetExtSrcAddr();
-                            m_macCoordShortAddress = receivedMacPayload.GetCoordShortAddr();
-
-                            if (!m_mlmeScanConfirmCallback.IsNull())
-                            {
-                                MlmeScanConfirmParams confirmParams;
-                                confirmParams.m_scanType = m_scanParams.m_scanType;
-                                confirmParams.m_chPage = m_scanParams.m_chPage;
-                                confirmParams.m_status = MacStatus::SUCCESS;
-                                m_mlmeScanConfirmCallback(confirmParams);
-                            }
-                            m_scanParams = {};
-                        }
-                        // TODO: handle Coordinator realignment when not
-                        //       used during an orphan scan.
-                        break;
-                    default:
-                        m_macRxDropTrace(originalPkt);
-                        break;
-                    }
-                }
-                else if (receivedMacHdr.IsData() && !m_mcpsDataIndicationCallback.IsNull())
-                {
-                    // If it is a data frame, push it up the stack.
-                    NS_LOG_DEBUG("Data Packet is for me; forwarding up");
-                    m_mcpsDataIndicationCallback(params, p);
-                }
-                else if (receivedMacHdr.IsAcknowledgment() && m_txPkt &&
-                         m_macState == MAC_ACK_PENDING)
-                {
-                    LrWpanMacHeader peekedMacHdr;
-                    m_txPkt->PeekHeader(peekedMacHdr);
-                    // If it is an ACK with the expected sequence number, finish the transmission
-                    if (receivedMacHdr.GetSeqNum() == peekedMacHdr.GetSeqNum())
-                    {
-                        m_ackWaitTimeout.Cancel();
-                        m_macTxOkTrace(m_txPkt);
-
-                        // TODO: check  if the IFS is the correct size after ACK.
-                        Time ifsWaitTime = Seconds((double)GetIfsSize() / symbolRate);
-
-                        // We received an ACK to a command
-                        if (peekedMacHdr.IsCommand())
-                        {
-                            // check the original sent command frame which belongs to this received
-                            // ACK
-                            Ptr<Packet> pkt = m_txPkt->Copy();
-                            LrWpanMacHeader macHdr;
-                            CommandPayloadHeader cmdPayload;
-                            pkt->RemoveHeader(macHdr);
-                            pkt->RemoveHeader(cmdPayload);
-
-                            switch (cmdPayload.GetCommandFrameType())
-                            {
-                            case CommandPayloadHeader::ASSOCIATION_REQ: {
-                                double symbolRate = m_phy->GetDataOrSymbolRate(false);
-                                Time waitTime = Seconds(static_cast<double>(m_macResponseWaitTime) /
-                                                        symbolRate);
-                                if (!m_beaconTrackingOn)
-                                {
-                                    m_respWaitTimeout =
-                                        Simulator::Schedule(waitTime,
-                                                            &LrWpanMac::SendDataRequestCommand,
-                                                            this);
-                                }
-                                else
-                                {
-                                    // TODO: The data must be extracted by the coordinator within
-                                    // macResponseWaitTime on timeout, MLME-ASSOCIATE.confirm is set
-                                    // with status NO_DATA, and this should trigger the cancellation
-                                    // of the beacon tracking (MLME-SYNC.request  trackBeacon
-                                    // =FALSE)
-                                }
-                                break;
-                            }
-
-                            case CommandPayloadHeader::ASSOCIATION_RESP: {
-                                // MLME-comm-status.Indication generated as a result of an
-                                // association response command, therefore src and dst address use
-                                // extended mode (see 5.3.2.1)
-                                if (!m_mlmeCommStatusIndicationCallback.IsNull())
-                                {
-                                    MlmeCommStatusIndicationParams commStatusParams;
-                                    commStatusParams.m_panId = m_macPanId;
-                                    commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
-                                    commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
-                                    commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
-                                    commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
-                                    commStatusParams.m_status = MacStatus::SUCCESS;
-                                    m_mlmeCommStatusIndicationCallback(commStatusParams);
-                                }
-                                // Remove element from Pending Transaction List
-                                RemovePendTxQElement(m_txPkt->Copy());
-                                break;
-                            }
-
-                            case CommandPayloadHeader::DATA_REQ: {
-                                if (!m_ignoreDataCmdAck)
-                                {
-                                    // Schedule an event in case the Association Response Command
-                                    // never reached this device during an association process.
-                                    double symbolRate = m_phy->GetDataOrSymbolRate(false);
-                                    Time waitTime = Seconds(
-                                        static_cast<double>(m_assocRespCmdWaitTime) / symbolRate);
-                                    m_assocResCmdWaitTimeout =
-                                        Simulator::Schedule(waitTime,
-                                                            &LrWpanMac::LostAssocRespCommand,
-                                                            this);
-                                }
-
-                                if (!m_mlmePollConfirmCallback.IsNull())
-                                {
-                                    MlmePollConfirmParams pollConfirmParams;
-                                    pollConfirmParams.m_status = MacStatus::SUCCESS;
-                                    m_mlmePollConfirmCallback(pollConfirmParams);
-                                }
-                                break;
-                            }
-
-                            case CommandPayloadHeader::COOR_REALIGN: {
-                                // ACK of coordinator realigment commands is not specified in the
-                                // standard, in here, we assume they are required as in other
-                                // commands.
-                                if (!m_mlmeCommStatusIndicationCallback.IsNull())
-                                {
-                                    MlmeCommStatusIndicationParams commStatusParams;
-                                    commStatusParams.m_panId = m_macPanId;
-                                    commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
-                                    commStatusParams.m_srcExtAddr = macHdr.GetExtSrcAddr();
-                                    commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
-                                    commStatusParams.m_dstExtAddr = macHdr.GetExtDstAddr();
-                                    commStatusParams.m_status = MacStatus::SUCCESS;
-                                    m_mlmeCommStatusIndicationCallback(commStatusParams);
-                                }
-                            }
-
-                            default: {
-                                // TODO: add response to other request commands (e.g. Orphan)
-                                break;
-                            }
-                            }
-                        }
-                        else
-                        {
-                            if (!m_mcpsDataConfirmCallback.IsNull())
-                            {
-                                Ptr<TxQueueElement> txQElement = m_txQueue.front();
-                                McpsDataConfirmParams confirmParams;
-                                confirmParams.m_msduHandle = txQElement->txQMsduHandle;
-                                confirmParams.m_status = MacStatus::SUCCESS;
-                                m_mcpsDataConfirmCallback(confirmParams);
-                            }
-                        }
-
-                        // Ack was successfully received, wait for the Interframe Space (IFS) and
-                        // then proceed
-                        RemoveFirstTxQElement();
-                        m_setMacState.Cancel();
-                        m_setMacState =
-                            Simulator::ScheduleNow(&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
-                        m_ifsEvent = Simulator::Schedule(ifsWaitTime,
-                                                         &LrWpanMac::IfsWaitTimeout,
-                                                         this,
-                                                         ifsWaitTime);
-                    }
-                    else
-                    {
-                        // If it is an ACK with an unexpected sequence number, mark the current
-                        // transmission as failed and start a retransmit. (cf 7.5.6.4.3)
-                        m_ackWaitTimeout.Cancel();
-                        if (!PrepareRetransmission())
-                        {
-                            m_setMacState.Cancel();
-                            m_setMacState = Simulator::ScheduleNow(&LrWpanMac::SetLrWpanMacState,
-                                                                   this,
-                                                                   MAC_IDLE);
-                        }
-                        else
-                        {
-                            m_setMacState.Cancel();
-                            m_setMacState = Simulator::ScheduleNow(&LrWpanMac::SetLrWpanMacState,
-                                                                   this,
-                                                                   MAC_CSMA);
-                        }
-                    }
-                }
+                m_assocResCmdWaitTimeout.Cancel(); // cancel event to a lost assoc resp cmd.
+                NS_LOG_DEBUG("Association Response Command Received; processing ACK");
             }
             else
             {
-                m_macRxDropTrace(originalPkt);
+                // Association response command was received before (or never received)
+                // a Data request command ACK. This is an extreme case and it is
+                // essentially caused by saturation in the network.
+                // We turn a flag ON to not react once
+                // we finally receive the Data request command ACK. This behavior is not
+                // standard, but necessary to address this flaw in design of the
+                // original association process.
+                m_ignoreDataCmdAck = true;
+                NS_LOG_DEBUG("Assoc. Resp Cmd received before Data Req. Cmd. in "
+                             "Association request");
             }
+            break;
+        }
+        default:
+            break;
         }
+
+        m_setMacState =
+            Simulator::ScheduleNow(&LrWpanMac::SendAck, this, receivedMacHdr.GetSeqNum());
+    }
+
+    PrintReceivedPacket(receivedMacHdr);
+
+    if (receivedMacHdr.IsBeacon())
+    {
+        ReceiveBeacon(lqi, receivedMacHdr, p);
+    }
+    else if (receivedMacHdr.IsCommand())
+    {
+        ReceiveCommand(lqi, receivedMacHdr, p);
+    }
+    else if (receivedMacHdr.IsData())
+    {
+        ReceiveData(lqi, receivedMacHdr, p);
+    }
+    else if (receivedMacHdr.IsAcknowledgment() && m_txPkt && m_macState == MAC_ACK_PENDING)
+    {
+        ReceiveAcknowledgment(receivedMacHdr, p);
     }
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/model/lr-wpan-mac.h ns-3.46/src/lr-wpan/model/lr-wpan-mac.h
--- ns-3.45/src/lr-wpan/model/lr-wpan-mac.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/model/lr-wpan-mac.h	2025-10-01 18:46:32.000000000 -0700
@@ -16,6 +16,7 @@
 
 #include "lr-wpan-fields.h"
 #include "lr-wpan-mac-base.h"
+#include "lr-wpan-mac-header.h"
 #include "lr-wpan-phy.h"
 
 #include "ns3/event-id.h"
@@ -759,6 +760,17 @@
     };
 
     /**
+     * Process a frame when promiscuous mode is active.
+     *
+     * @param lqi The LQI value of the received packet
+     * @param receivedMacHdr The reference to the received MAC header
+     * @param p The packet containing the MAC payload
+     */
+    void ReceiveInPromiscuousMode(uint8_t lqi,
+                                  const LrWpanMacHeader& receivedMacHdr,
+                                  Ptr<Packet> p);
+
+    /**
      * Called to send a single beacon frame.
      */
     void SendOneBeacon();
@@ -858,10 +870,45 @@
     /**
      * Used to process the reception of a beacon packet.
      *
-     * @param lqi The value of the link quality indicator (LQI) of the received packet
-     * @param p The packet containing the MAC header and the beacon payload information
+     * @param lqi The value of the link quality indicator (LQI) of the received packet.
+     * @param receivedMacHdr The reference to the received MAC header.
+     * @param p The packet containing the beacon payload information.
+     */
+    void ReceiveBeacon(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p);
+
+    /**
+     * Used to process the reception of a command packet.
+     *
+     * @param lqi The value of the link quality indicator (LQI) of the received packet.
+     * @param receivedMacHdr The reference to the received MAC header.
+     * @param p The packet containing the command payload information.
+     */
+    void ReceiveCommand(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p);
+
+    /**
+     * Used to process the reception of data.
+     *
+     * @param lqi The value of the link quality indicator (LQI) of the received packet.
+     * @param receivedMacHdr The reference to the received MAC header.
+     * @param p The packet containing the data payload.
+     */
+    void ReceiveData(uint8_t lqi, const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p);
+
+    /**
+     * Used to process an acknowledgment packet.
+     *
+     * @param receivedMacHdr The reference to the received MAC header.
+     * @param p The packet containing the MAC header and the data payload.
+     */
+    void ReceiveAcknowledgment(const LrWpanMacHeader& receivedMacHdr, Ptr<Packet> p);
+
+    /**
+     * Display the MAC header contents of a successfully received packet when
+     * logs are active.
+     *
+     * @param receivedMacHdr The reference of the received MAC header
      */
-    void ReceiveBeacon(uint8_t lqi, Ptr<Packet> p);
+    void PrintReceivedPacket(const LrWpanMacHeader& receivedMacHdr);
 
     /**
      * Send an acknowledgment packet for the given sequence number.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lr-wpan/test/lr-wpan-ack-test.cc ns-3.46/src/lr-wpan/test/lr-wpan-ack-test.cc
--- ns-3.45/src/lr-wpan/test/lr-wpan-ack-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lr-wpan/test/lr-wpan-ack-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -158,6 +158,8 @@
 void
 LrWpanAckTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     // Test setup:
     // Two nodes well in communication range.
     // Node 1 sends a request packet to node 2 with ACK request bit set. Node 2
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/CMakeLists.txt ns-3.46/src/lte/CMakeLists.txt
--- ns-3.45/src/lte/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -2,19 +2,25 @@
 set(emu_headers)
 set(emu_features)
 set(emu_libraries)
-if(${ENABLE_EMU})
-  set(emu_sources
-      helper/emu-epc-helper.cc
-  )
-  set(emu_headers
-      helper/emu-epc-helper.h
-  )
-  set(emu_features
-      EmuFdNetDevice
-  )
-  set(emu_libraries
-      ${libfd-net-device}
+if(DEFINED
+   ENABLE_EMUNETDEV
+)
+  if(${ENABLE_EMU}
+     AND ${ENABLE_EMUNETDEV}
   )
+    set(emu_sources
+        helper/emu-epc-helper.cc
+    )
+    set(emu_headers
+        helper/emu-epc-helper.h
+    )
+    set(emu_features
+        EmuFdNetDevice
+    )
+    set(emu_libraries
+        ${libfd-net-device}
+    )
+  endif()
 endif()
 
 set(source_files
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/doc/Makefile ns-3.46/src/lte/doc/Makefile
--- ns-3.45/src/lte/doc/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/doc/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,9 +1,6 @@
-EPSTOPDF = epstopdf
-DIA = dia
-SEQDIAG = seqdiag
-DOT = dot
-CONVERT = convert -density 250
+include $(CURDIR)/../../../doc/sphinx/defines.mk
 
+SEQDIAG = seqdiag
 
 SOURCE = source
 FIGURES = $(SOURCE)/figures
@@ -221,16 +218,7 @@
 	$(EPSTOPDF) $< -o=$@
 	if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
 
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/doc/source/lte-design.rst ns-3.46/src/lte/doc/source/lte-design.rst
--- ns-3.45/src/lte/doc/source/lte-design.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/doc/source/lte-design.rst	2025-10-01 18:46:32.000000000 -0700
@@ -2269,7 +2269,7 @@
 :ref:`sec-control-channels-phy-error-model`). Once, the UE is unable to decode
 20 consecutive frames, i.e., the Qout evaluation period (200ms) is reached, an
 out-of-sync indication is sent to the UE RRC layer (see ``LteUeRrc::DoNotifyOutOfSync``).
-Else, the counter for the unsuccessfuly decoded frames is reset to zero. At the
+Else, the counter for the unsuccessfully decoded frames is reset to zero. At the
 LteUeRrc, when the number of consecutive out-of-sync indications matches with the
 value of N310 parameter, the T310 timer is started and LteUePhy is notified to start
 measuring for in-sync indications (see ``LteUePhy::DoStartInSyncDetection``). We note
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/examples/CMakeLists.txt ns-3.46/src/lte/examples/CMakeLists.txt
--- ns-3.45/src/lte/examples/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/examples/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -36,13 +36,19 @@
   )
 endforeach()
 
-if(${ENABLE_EMU})
-  build_lib_example(
-    NAME lena-simple-epc-emu
-    SOURCE_FILES lena-simple-epc-emu.cc
-    LIBRARIES_TO_LINK
-      ${liblte}
-      ${libfd-net-device}
-      ${libconfig-store}
+if(DEFINED
+   ENABLE_EMUNETDEV
+)
+  if(${ENABLE_EMU}
+     AND ${ENABLE_EMUNETDEV}
   )
+    build_lib_example(
+      NAME lena-simple-epc-emu
+      SOURCE_FILES lena-simple-epc-emu.cc
+      LIBRARIES_TO_LINK
+        ${liblte}
+        ${libfd-net-device}
+        ${libconfig-store}
+    )
+  endif()
 endif()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/examples/lena-dual-stripe.cc ns-3.46/src/lte/examples/lena-dual-stripe.cc
--- ns-3.45/src/lte/examples/lena-dual-stripe.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/examples/lena-dual-stripe.cc	2025-10-01 18:46:32.000000000 -0700
@@ -26,6 +26,10 @@
 // 3GPP R4-092042, Section 4.2.1 Dual Stripe Model
 // note that the term "apartments" used in that document matches with
 // the term "room" used in the BuildingsMobilityModel
+//
+// A user can pass the command-line --ns3::LteHexGridEnbTopologyHelper::EnableWraparound=1
+// to setup and use the hexagonal wraparound model, which causes all cells to receive
+// similar interference, rather than central cells receiving a lot more than edge cells.
 
 using namespace ns3;
 
@@ -272,7 +276,7 @@
 /// How many macro sites there are
 static ns3::GlobalValue g_nMacroEnbSites("nMacroEnbSites",
                                          "How many macro sites there are",
-                                         ns3::UintegerValue(3),
+                                         ns3::UintegerValue(7),
                                          ns3::MakeUintegerChecker<uint32_t>());
 
 /// (minimum) number of sites along the X-axis of the hex grid
@@ -638,7 +642,12 @@
     lteHelper->SetEnbDeviceAttribute("UlBandwidth", UintegerValue(macroEnbBandwidth));
     NetDeviceContainer macroEnbDevs =
         lteHexGridEnbTopologyHelper->SetPositionAndInstallEnbDevice(macroEnbs);
-
+    Ptr<WraparoundModel> wraparoundModel = lteHexGridEnbTopologyHelper->GetWraparoundModel();
+    if (wraparoundModel)
+    {
+        lteHelper->GetDownlinkSpectrumChannel()->UnidirectionalAggregateObject(wraparoundModel);
+        lteHelper->GetUplinkSpectrumChannel()->UnidirectionalAggregateObject(wraparoundModel);
+    }
     if (epc)
     {
         // this enables handover for macro eNBs
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/examples/lena-rem-sector-antenna.cc ns-3.46/src/lte/examples/lena-rem-sector-antenna.cc
--- ns-3.45/src/lte/examples/lena-rem-sector-antenna.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/examples/lena-rem-sector-antenna.cc	2025-10-01 18:46:32.000000000 -0700
@@ -70,7 +70,7 @@
     std::vector<Vector> enbPosition;
     Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
     Ptr<Building> building;
-    building = Create<Building>();
+    building = CreateObject<Building>();
     building->SetBoundaries(
         Box(0.0, nRooms * roomLength, 0.0, nRooms * roomLength, 0.0, roomHeight));
     building->SetBuildingType(Building::Residential);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/emu-epc-helper.cc ns-3.46/src/lte/helper/emu-epc-helper.cc
--- ns-3.45/src/lte/helper/emu-epc-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/emu-epc-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -31,8 +31,14 @@
     : NoBackhaulEpcHelper()
 {
     NS_LOG_FUNCTION(this);
-    // To access the attribute value within the constructor
-    ObjectBase::ConstructSelf(AttributeConstructionList());
+}
+
+void
+EmuEpcHelper::NotifyConstructionCompleted()
+{
+    NoBackhaulEpcHelper::NotifyConstructionCompleted();
+
+    NS_LOG_FUNCTION(this);
 
     // Create EmuFdNetDevice for SGW
     EmuFdNetDeviceHelper emu;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/emu-epc-helper.h ns-3.46/src/lte/helper/emu-epc-helper.h
--- ns-3.45/src/lte/helper/emu-epc-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/emu-epc-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -55,6 +55,9 @@
                 std::vector<uint16_t> cellIds) override;
     void AddX2Interface(Ptr<Node> enbNode1, Ptr<Node> enbNode2) override;
 
+  protected:
+    void NotifyConstructionCompleted() override;
+
   private:
     /**
      * helper to assign addresses to S1-U NetDevices
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/lte-hex-grid-enb-topology-helper.cc ns-3.46/src/lte/helper/lte-hex-grid-enb-topology-helper.cc
--- ns-3.45/src/lte/helper/lte-hex-grid-enb-topology-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/lte-hex-grid-enb-topology-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -12,6 +12,7 @@
 
 #include "ns3/abort.h"
 #include "ns3/double.h"
+#include "ns3/hexagonal-wraparound-model.h"
 #include "ns3/log.h"
 #include "ns3/pointer.h"
 
@@ -72,7 +73,12 @@
                 "The number of sites in even rows (odd rows will have one additional site).",
                 UintegerValue(1),
                 MakeUintegerAccessor(&LteHexGridEnbTopologyHelper::m_gridWidth),
-                MakeUintegerChecker<uint32_t>());
+                MakeUintegerChecker<uint32_t>())
+            .AddAttribute("EnableWraparound",
+                          "Enable hexagonal wraparound model.",
+                          BooleanValue(false),
+                          MakeBooleanAccessor(&LteHexGridEnbTopologyHelper::m_installWraparound),
+                          MakeBooleanChecker());
     return tid;
 }
 
@@ -95,6 +101,13 @@
 {
     NS_LOG_FUNCTION(this);
     NetDeviceContainer enbDevs;
+    Ptr<HexagonalWraparoundModel> wraparoundModel;
+    if (m_installWraparound)
+    {
+        wraparoundModel = CreateObject<HexagonalWraparoundModel>();
+        wraparoundModel->SetSiteDistance(m_d);
+        wraparoundModel->SetNumSites(c.GetN() / 3);
+    }
     const double xydfactor = std::sqrt(0.75);
     double yd = xydfactor * m_d;
     for (uint32_t n = 0; n < c.GetN(); ++n)
@@ -155,8 +168,22 @@
         mm->SetPosition(Vector(x, y, m_siteHeight));
         m_lteHelper->SetEnbAntennaModelAttribute("Orientation", DoubleValue(antennaOrientation));
         enbDevs.Add(m_lteHelper->InstallEnbDevice(node));
+        if (m_installWraparound && (n % 3 == 0))
+        {
+            wraparoundModel->AddSitePosition(mm->GetPosition());
+        }
+    }
+    if (m_installWraparound)
+    {
+        m_wraparoundModel = wraparoundModel;
     }
     return enbDevs;
 }
 
+Ptr<WraparoundModel>
+LteHexGridEnbTopologyHelper::GetWraparoundModel() const
+{
+    return m_wraparoundModel;
+}
+
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/lte-hex-grid-enb-topology-helper.h ns-3.46/src/lte/helper/lte-hex-grid-enb-topology-helper.h
--- ns-3.45/src/lte/helper/lte-hex-grid-enb-topology-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/lte-hex-grid-enb-topology-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -11,6 +11,8 @@
 
 #include "lte-helper.h"
 
+#include "ns3/wraparound-model.h"
+
 namespace ns3
 {
 
@@ -59,6 +61,13 @@
      */
     NetDeviceContainer SetPositionAndInstallEnbDevice(NodeContainer c);
 
+    /**
+     * @brief Get the configured wraparound model.
+     * If wraparound is not enabled, a null pointer is returned instead.
+     * @return a pointer to the wraparound model
+     */
+    Ptr<WraparoundModel> GetWraparoundModel() const;
+
   private:
     /**
      * Pointer to LteHelper object
@@ -96,6 +105,16 @@
      * The height [m] of each site
      */
     uint32_t m_siteHeight;
+
+    /**
+     * Boolean flag indicating whether to install or not wraparound model
+     */
+    bool m_installWraparound;
+
+    /**
+     * Wraparound model pointer
+     */
+    Ptr<WraparoundModel> m_wraparoundModel;
 };
 
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/no-backhaul-epc-helper.cc ns-3.46/src/lte/helper/no-backhaul-epc-helper.cc
--- ns-3.45/src/lte/helper/no-backhaul-epc-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/no-backhaul-epc-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -45,8 +45,12 @@
       m_s5LinkMtu(3000)
 {
     NS_LOG_FUNCTION(this);
-    // To access the attribute value within the constructor
-    ObjectBase::ConstructSelf(AttributeConstructionList());
+}
+
+void
+NoBackhaulEpcHelper::NotifyConstructionCompleted()
+{
+    EpcHelper::NotifyConstructionCompleted();
 
     int retval;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/no-backhaul-epc-helper.h ns-3.46/src/lte/helper/no-backhaul-epc-helper.h
--- ns-3.45/src/lte/helper/no-backhaul-epc-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/no-backhaul-epc-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -76,6 +76,8 @@
     int64_t AssignStreams(int64_t stream) override;
 
   protected:
+    void NotifyConstructionCompleted() override;
+
     /**
      * @brief DoAddX2Interface: Call AddX2Interface on top of the Enb device pointers
      *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/point-to-point-epc-helper.cc ns-3.46/src/lte/helper/point-to-point-epc-helper.cc
--- ns-3.45/src/lte/helper/point-to-point-epc-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/point-to-point-epc-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -28,8 +28,14 @@
     : NoBackhaulEpcHelper()
 {
     NS_LOG_FUNCTION(this);
-    // To access the attribute value within the constructor
-    ObjectBase::ConstructSelf(AttributeConstructionList());
+}
+
+void
+PointToPointEpcHelper::NotifyConstructionCompleted()
+{
+    NoBackhaulEpcHelper::NotifyConstructionCompleted();
+
+    NS_LOG_FUNCTION(this);
 
     // since we use point-to-point links for the backhaul links,
     // we use a /30 subnet which can hold exactly two addresses
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/helper/point-to-point-epc-helper.h ns-3.46/src/lte/helper/point-to-point-epc-helper.h
--- ns-3.45/src/lte/helper/point-to-point-epc-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/helper/point-to-point-epc-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -51,6 +51,9 @@
                 Ptr<NetDevice> lteEnbNetDevice,
                 std::vector<uint16_t> cellIds) override;
 
+  protected:
+    void NotifyConstructionCompleted() override;
+
   private:
     /**
      * S1-U interfaces
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/a2-a4-rsrq-handover-algorithm.cc ns-3.46/src/lte/model/a2-a4-rsrq-handover-algorithm.cc
--- ns-3.45/src/lte/model/a2-a4-rsrq-handover-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/a2-a4-rsrq-handover-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -253,4 +253,4 @@
     }
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/a2-a4-rsrq-handover-algorithm.h ns-3.46/src/lte/model/a2-a4-rsrq-handover-algorithm.h
--- ns-3.45/src/lte/model/a2-a4-rsrq-handover-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/a2-a4-rsrq-handover-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -178,6 +178,6 @@
     LteHandoverManagementSapProvider* m_handoverManagementSapProvider;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* A2_A4_RSRQ_HANDOVER_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/a3-rsrp-handover-algorithm.cc ns-3.46/src/lte/model/a3-rsrp-handover-algorithm.cc
--- ns-3.45/src/lte/model/a3-rsrp-handover-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/a3-rsrp-handover-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -172,4 +172,4 @@
     return true;
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/a3-rsrp-handover-algorithm.h ns-3.46/src/lte/model/a3-rsrp-handover-algorithm.h
--- ns-3.45/src/lte/model/a3-rsrp-handover-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/a3-rsrp-handover-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -110,6 +110,6 @@
     LteHandoverManagementSapProvider* m_handoverManagementSapProvider;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* A3_RSRP_HANDOVER_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/ff-mac-csched-sap.h ns-3.46/src/lte/model/ff-mac-csched-sap.h
--- ns-3.45/src/lte/model/ff-mac-csched-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/ff-mac-csched-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -500,6 +500,6 @@
     m_scheduler->DoCschedUeReleaseReq(params);
 }
 
-} // end namespace ns3
+} // namespace ns3
 
 #endif /* FF_MAC_CSCHED_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-anr.cc ns-3.46/src/lte/model/lte-anr.cc
--- ns-3.45/src/lte/model/lte-anr.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-anr.cc	2025-10-01 18:46:32.000000000 -0700
@@ -233,4 +233,4 @@
     return &(it->second);
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-anr.h ns-3.46/src/lte/model/lte-anr.h
--- ns-3.45/src/lte/model/lte-anr.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-anr.h	2025-10-01 18:46:32.000000000 -0700
@@ -223,6 +223,6 @@
     uint16_t m_servingCellId;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_ANR_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-anr-sap.cc ns-3.46/src/lte/model/lte-anr-sap.cc
--- ns-3.45/src/lte/model/lte-anr-sap.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-anr-sap.cc	2025-10-01 18:46:32.000000000 -0700
@@ -20,4 +20,4 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-anr-sap.h ns-3.46/src/lte/model/lte-anr-sap.h
--- ns-3.45/src/lte/model/lte-anr-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-anr-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -216,6 +216,6 @@
     return m_owner->DoAddUeMeasReportConfigForAnr(reportConfig);
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_ANR_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ccm-mac-sap.cc ns-3.46/src/lte/model/lte-ccm-mac-sap.cc
--- ns-3.45/src/lte/model/lte-ccm-mac-sap.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ccm-mac-sap.cc	2025-10-01 18:46:32.000000000 -0700
@@ -20,4 +20,4 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ccm-mac-sap.h ns-3.46/src/lte/model/lte-ccm-mac-sap.h
--- ns-3.45/src/lte/model/lte-ccm-mac-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ccm-mac-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -204,6 +204,6 @@
     m_owner->DoNotifyHarqDeliveryFailure();
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_CCM_MAC_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ccm-rrc-sap.cc ns-3.46/src/lte/model/lte-ccm-rrc-sap.cc
--- ns-3.45/src/lte/model/lte-ccm-rrc-sap.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ccm-rrc-sap.cc	2025-10-01 18:46:32.000000000 -0700
@@ -20,4 +20,4 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ccm-rrc-sap.h ns-3.46/src/lte/model/lte-ccm-rrc-sap.h
--- ns-3.45/src/lte/model/lte-ccm-rrc-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ccm-rrc-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -384,6 +384,6 @@
     return m_owner->DoSetNumberOfComponentCarriers(noOfComponentCarriers);
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_CCM_RRC_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-enb-component-carrier-manager.cc ns-3.46/src/lte/model/lte-enb-component-carrier-manager.cc
--- ns-3.45/src/lte/model/lte-enb-component-carrier-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-enb-component-carrier-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -121,4 +121,4 @@
     m_ccmRrcSapUser->SetNumberOfComponentCarriers(noOfComponentCarriers);
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-enb-component-carrier-manager.h ns-3.46/src/lte/model/lte-enb-component-carrier-manager.h
--- ns-3.45/src/lte/model/lte-enb-component-carrier-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-enb-component-carrier-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -212,6 +212,6 @@
                              //!< calls from the eNodeB RRC instance.
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_ENB_COMPONENT_CARRIER_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-enb-mac.h ns-3.46/src/lte/model/lte-enb-mac.h
--- ns-3.45/src/lte/model/lte-enb-mac.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-enb-mac.h	2025-10-01 18:46:32.000000000 -0700
@@ -454,6 +454,6 @@
     uint8_t m_componentCarrierId;
 };
 
-} // end namespace ns3
+} // namespace ns3
 
 #endif /* LTE_ENB_MAC_ENTITY_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-enb-rrc.cc ns-3.46/src/lte/model/lte-enb-rrc.cc
--- ns-3.45/src/lte/model/lte-enb-rrc.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-enb-rrc.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1217,9 +1217,6 @@
     // This case is added to NS-3 in order to handle bearer de-activation scenario for CONNECTED
     // state UE
     case CONNECTED_NORMALLY:
-        NS_LOG_INFO("ignoring RecvRrcConnectionReconfigurationCompleted in state " << m_state);
-        break;
-
     case HANDOVER_LEAVING:
         NS_LOG_INFO("ignoring RecvRrcConnectionReconfigurationCompleted in state " << m_state);
         break;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-algorithm.cc ns-3.46/src/lte/model/lte-ffr-algorithm.cc
--- ns-3.45/src/lte/model/lte-ffr-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -167,4 +167,4 @@
     SetUlBandwidth(ulBandwidth);
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-algorithm.h ns-3.46/src/lte/model/lte-ffr-algorithm.h
--- ns-3.45/src/lte/model/lte-ffr-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -245,6 +245,6 @@
     bool m_needReconfiguration; /**< If true FR algorithm will be reconfigured*/
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-distributed-algorithm.cc ns-3.46/src/lte/model/lte-ffr-distributed-algorithm.cc
--- ns-3.45/src/lte/model/lte-ffr-distributed-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-distributed-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -703,4 +703,4 @@
     }
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-distributed-algorithm.h ns-3.46/src/lte/model/lte-ffr-distributed-algorithm.h
--- ns-3.45/src/lte/model/lte-ffr-distributed-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-distributed-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -180,6 +180,6 @@
     std::map<uint16_t, std::vector<bool>> m_rntp; ///< RNTP
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FR_DISTRIBUTED_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-enhanced-algorithm.cc ns-3.46/src/lte/model/lte-ffr-enhanced-algorithm.cc
--- ns-3.45/src/lte/model/lte-ffr-enhanced-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-enhanced-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -927,4 +927,4 @@
     NS_LOG_WARN("Method should not be called, because it is empty");
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-enhanced-algorithm.h ns-3.46/src/lte/model/lte-ffr-enhanced-algorithm.h
--- ns-3.45/src/lte/model/lte-ffr-enhanced-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-enhanced-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -183,6 +183,6 @@
     uint8_t m_measId;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_ENHANCED_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-rrc-sap.h ns-3.46/src/lte/model/lte-ffr-rrc-sap.h
--- ns-3.45/src/lte/model/lte-ffr-rrc-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-rrc-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -247,6 +247,6 @@
     m_owner->DoSendLoadInformation(params);
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_RRC_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-sap.h ns-3.46/src/lte/model/lte-ffr-sap.h
--- ns-3.45/src/lte/model/lte-ffr-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -270,6 +270,6 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-soft-algorithm.cc ns-3.46/src/lte/model/lte-ffr-soft-algorithm.cc
--- ns-3.45/src/lte/model/lte-ffr-soft-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-soft-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -704,4 +704,4 @@
     NS_LOG_WARN("Method should not be called, because it is empty");
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ffr-soft-algorithm.h ns-3.46/src/lte/model/lte-ffr-soft-algorithm.h
--- ns-3.45/src/lte/model/lte-ffr-soft-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ffr-soft-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -153,6 +153,6 @@
     uint8_t m_measId;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_SOFT_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-hard-algorithm.cc ns-3.46/src/lte/model/lte-fr-hard-algorithm.cc
--- ns-3.45/src/lte/model/lte-fr-hard-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-hard-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -380,4 +380,4 @@
     NS_LOG_WARN("Method should not be called, because it is empty");
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-hard-algorithm.h ns-3.46/src/lte/model/lte-fr-hard-algorithm.h
--- ns-3.45/src/lte/model/lte-fr-hard-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-hard-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -115,6 +115,6 @@
     std::vector<bool> m_ulRbgMap; ///< UL RBG Map
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FR_HARD_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-no-op-algorithm.cc ns-3.46/src/lte/model/lte-fr-no-op-algorithm.cc
--- ns-3.45/src/lte/model/lte-fr-no-op-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-no-op-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -176,4 +176,4 @@
     NS_LOG_WARN("Method should not be called, because it is empty");
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-no-op-algorithm.h ns-3.46/src/lte/model/lte-fr-no-op-algorithm.h
--- ns-3.45/src/lte/model/lte-fr-no-op-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-no-op-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -89,6 +89,6 @@
     LteFfrRrcSapProvider* m_ffrRrcSapProvider; ///< FFR RRC SAP provider
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_NO_OP_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-soft-algorithm.cc ns-3.46/src/lte/model/lte-fr-soft-algorithm.cc
--- ns-3.45/src/lte/model/lte-fr-soft-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-soft-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -566,4 +566,4 @@
     NS_LOG_WARN("Method should not be called, because it is empty");
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-soft-algorithm.h ns-3.46/src/lte/model/lte-fr-soft-algorithm.h
--- ns-3.45/src/lte/model/lte-fr-soft-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-soft-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -144,6 +144,6 @@
     uint8_t m_measId;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FR_SOFT_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-strict-algorithm.cc ns-3.46/src/lte/model/lte-fr-strict-algorithm.cc
--- ns-3.45/src/lte/model/lte-fr-strict-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-strict-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -578,4 +578,4 @@
     NS_LOG_WARN("Method should not be called, since it is empty");
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-fr-strict-algorithm.h ns-3.46/src/lte/model/lte-fr-strict-algorithm.h
--- ns-3.45/src/lte/model/lte-fr-strict-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-fr-strict-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -144,6 +144,6 @@
     uint8_t m_measId;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FR_STRICT_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-handover-algorithm.cc ns-3.46/src/lte/model/lte-handover-algorithm.cc
--- ns-3.45/src/lte/model/lte-handover-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-handover-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -38,4 +38,4 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-handover-algorithm.h ns-3.46/src/lte/model/lte-handover-algorithm.h
--- ns-3.45/src/lte/model/lte-handover-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-handover-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -93,6 +93,6 @@
     virtual void DoReportUeMeas(uint16_t rnti, LteRrcSap::MeasResults measResults) = 0;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_HANDOVER_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-handover-management-sap.cc ns-3.46/src/lte/model/lte-handover-management-sap.cc
--- ns-3.45/src/lte/model/lte-handover-management-sap.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-handover-management-sap.cc	2025-10-01 18:46:32.000000000 -0700
@@ -20,4 +20,4 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-handover-management-sap.h ns-3.46/src/lte/model/lte-handover-management-sap.h
--- ns-3.45/src/lte/model/lte-handover-management-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-handover-management-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -184,6 +184,6 @@
     return m_owner->DoTriggerHandover(rnti, targetCellId);
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_HANDOVER_MANAGEMENT_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-mi-error-model.cc ns-3.46/src/lte/model/lte-mi-error-model.cc
--- ns-3.45/src/lte/model/lte-mi-error-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-mi-error-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -23,9 +23,9 @@
 #include "ns3/pointer.h"
 
 #include <cmath>
+#include <cstdint>
+#include <cstdlib>
 #include <list>
-#include <stdint.h>
-#include <stdlib.h>
 #include <vector>
 
 namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ue-ccm-rrc-sap.cc ns-3.46/src/lte/model/lte-ue-ccm-rrc-sap.cc
--- ns-3.45/src/lte/model/lte-ue-ccm-rrc-sap.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ue-ccm-rrc-sap.cc	2025-10-01 18:46:32.000000000 -0700
@@ -20,4 +20,4 @@
 {
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ue-ccm-rrc-sap.h ns-3.46/src/lte/model/lte-ue-ccm-rrc-sap.h
--- ns-3.45/src/lte/model/lte-ue-ccm-rrc-sap.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ue-ccm-rrc-sap.h	2025-10-01 18:46:32.000000000 -0700
@@ -235,6 +235,6 @@
     m_owner->DoSetNumberOfComponentCarriers(noOfComponentCarriers);
 }
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_UE_CCM_RRC_SAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ue-component-carrier-manager.cc ns-3.46/src/lte/model/lte-ue-component-carrier-manager.cc
--- ns-3.45/src/lte/model/lte-ue-component-carrier-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ue-component-carrier-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -96,4 +96,4 @@
     m_ccmRrcSapUser->SetNumberOfComponentCarriers(noOfComponentCarriers);
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ue-component-carrier-manager.h ns-3.46/src/lte/model/lte-ue-component-carrier-manager.h
--- ns-3.45/src/lte/model/lte-ue-component-carrier-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ue-component-carrier-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -97,6 +97,6 @@
                               //!< flows of this UE.
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_UE_COMPONENT_CARRIER_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ue-rrc.cc ns-3.46/src/lte/model/lte-ue-rrc.cc
--- ns-3.45/src/lte/model/lte-ue-rrc.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ue-rrc.cc	2025-10-01 18:46:32.000000000 -0700
@@ -32,6 +32,22 @@
 
 namespace ns3
 {
+/**
+ * @brief Artificial delay of UE measurements procedure.
+ *
+ * i.e. the period between the time layer-1-filtered measurements from PHY
+ * layer is received and the earliest time the actual measurement report
+ * submission to the serving cell is invoked.
+ *
+ * This delay exists because of racing condition between several UE measurements
+ * functions which happen to be scheduled at the same time. The delay ensures
+ * that:
+ *  - measurements (e.g., layer-3 filtering) are always performed before
+ *    reporting, thus the latter always use the latest measured RSRP and RSRQ;
+ *    and
+ *  - time-to-trigger check is always performed before the reporting, so there
+ *    would still be chance for it to cancel the reporting if necessary.
+ */
 const Time UE_MEASUREMENT_REPORT_DELAY = MicroSeconds(1);
 
 NS_LOG_COMPONENT_DEFINE("LteUeRrc");
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/lte-ue-rrc.h ns-3.46/src/lte/model/lte-ue-rrc.h
--- ns-3.45/src/lte/model/lte-ue-rrc.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/lte-ue-rrc.h	2025-10-01 18:46:32.000000000 -0700
@@ -34,25 +34,6 @@
 
 namespace ns3
 {
-
-/**
- * @brief Artificial delay of UE measurements procedure.
- *
- * i.e. the period between the time layer-1-filtered measurements from PHY
- * layer is received and the earliest time the actual measurement report
- * submission to the serving cell is invoked.
- *
- * This delay exists because of racing condition between several UE measurements
- * functions which happen to be scheduled at the same time. The delay ensures
- * that:
- *  - measurements (e.g., layer-3 filtering) are always performed before
- *    reporting, thus the latter always use the latest measured RSRP and RSRQ;
- *    and
- *  - time-to-trigger check is always performed before the reporting, so there
- *    would still be chance for it to cancel the reporting if necessary.
- */
-LTE_EXPORT extern const Time UE_MEASUREMENT_REPORT_DELAY;
-
 class LteRlc;
 class LteMacSapProvider;
 class LteUeCmacSapUser;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/no-op-component-carrier-manager.cc ns-3.46/src/lte/model/no-op-component-carrier-manager.cc
--- ns-3.45/src/lte/model/no-op-component-carrier-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/no-op-component-carrier-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -478,4 +478,4 @@
     }
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/no-op-component-carrier-manager.h ns-3.46/src/lte/model/no-op-component-carrier-manager.h
--- ns-3.45/src/lte/model/no-op-component-carrier-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/no-op-component-carrier-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -180,6 +180,6 @@
     // end of class RrComponentCarrierManager
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* NO_OP_COMPONENT_CARRIER_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/no-op-handover-algorithm.cc ns-3.46/src/lte/model/no-op-handover-algorithm.cc
--- ns-3.45/src/lte/model/no-op-handover-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/no-op-handover-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -75,4 +75,4 @@
     NS_LOG_FUNCTION(this << rnti << (uint16_t)measResults.measId);
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/no-op-handover-algorithm.h ns-3.46/src/lte/model/no-op-handover-algorithm.h
--- ns-3.45/src/lte/model/no-op-handover-algorithm.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/no-op-handover-algorithm.h	2025-10-01 18:46:32.000000000 -0700
@@ -62,6 +62,6 @@
     LteHandoverManagementSapProvider* m_handoverManagementSapProvider;
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* NO_OP_HANDOVER_ALGORITHM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/simple-ue-component-carrier-manager.cc ns-3.46/src/lte/model/simple-ue-component-carrier-manager.cc
--- ns-3.45/src/lte/model/simple-ue-component-carrier-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/simple-ue-component-carrier-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -368,4 +368,4 @@
     return m_ccmMacSapUser;
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/model/simple-ue-component-carrier-manager.h ns-3.46/src/lte/model/simple-ue-component-carrier-manager.h
--- ns-3.45/src/lte/model/simple-ue-component-carrier-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/model/simple-ue-component-carrier-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -130,6 +130,6 @@
     LteMacSapProvider* m_ccmMacSapProvider; //!< Receive API calls from the UE RLC instance
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* SIMPLE_UE_COMPONENT_CARRIER_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-ffr-simple.cc ns-3.46/src/lte/test/lte-ffr-simple.cc
--- ns-3.45/src/lte/test/lte-ffr-simple.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-ffr-simple.cc	2025-10-01 18:46:32.000000000 -0700
@@ -306,4 +306,4 @@
     NS_LOG_FUNCTION(this);
 }
 
-} // end of namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-ffr-simple.h ns-3.46/src/lte/test/lte-ffr-simple.h
--- ns-3.45/src/lte/test/lte-ffr-simple.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-ffr-simple.h	2025-10-01 18:46:32.000000000 -0700
@@ -147,6 +147,6 @@
     bool m_accumulatedMode; ///< whether to use the TPC accumulated mode
 };
 
-} // end of namespace ns3
+} // namespace ns3
 
 #endif /* LTE_FFR_SIMPLE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-simple-spectrum-phy.cc ns-3.46/src/lte/test/lte-simple-spectrum-phy.cc
--- ns-3.45/src/lte/test/lte-simple-spectrum-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-simple-spectrum-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -114,7 +114,6 @@
 
     NS_LOG_FUNCTION(this << spectrumRxParams);
     Ptr<const SpectrumValue> rxPsd = spectrumRxParams->psd;
-    Time duration = spectrumRxParams->duration;
 
     // the device might start RX only if the signal is of a type
     // understood by this device - in this case, an LTE signal.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-carrier-aggregation.cc ns-3.46/src/lte/test/lte-test-carrier-aggregation.cc
--- ns-3.45/src/lte/test/lte-test-carrier-aggregation.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-carrier-aggregation.cc	2025-10-01 18:46:32.000000000 -0700
@@ -361,6 +361,7 @@
 {
     NS_LOG_FUNCTION(this << m_nUser << m_dist << m_dlBandwidth << m_ulBandwidth
                          << m_numberOfComponentCarriers);
+    SetDataDir(NS_TEST_SOURCEDIR);
 
     Config::SetDefault("ns3::LteEnbNetDevice::DlEarfcn", UintegerValue(100));
     Config::SetDefault("ns3::LteEnbNetDevice::UlEarfcn", UintegerValue(100 + 18000));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-cqa-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-cqa-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-cqa-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-cqa-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -292,6 +292,7 @@
 LenaCqaFfMacSchedulerTestCase1::DoRun()
 {
     NS_LOG_FUNCTION(this << GetName());
+    SetDataDir(NS_TEST_SOURCEDIR);
 
     if (!m_errorModelEnabled)
     {
@@ -561,6 +562,8 @@
 void
 LenaCqaFfMacSchedulerTestCase2::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-deactivate-bearer.cc ns-3.46/src/lte/test/lte-test-deactivate-bearer.cc
--- ns-3.45/src/lte/test/lte-test-deactivate-bearer.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-deactivate-bearer.cc	2025-10-01 18:46:32.000000000 -0700
@@ -129,6 +129,7 @@
 void
 LenaDeactivateBearerTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     uint32_t originalSeed = RngSeedManager::GetSeed();
     uint32_t originalRun = RngSeedManager::GetRun();
     RngSeedManager::SetSeed(1);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-deactivate-bearer.h ns-3.46/src/lte/test/lte-test-deactivate-bearer.h
--- ns-3.45/src/lte/test/lte-test-deactivate-bearer.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-deactivate-bearer.h	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 #ifndef LENA_TEST_DEACTIVATE_BEARER_H
 #define LENA_TEST_DEACTIVATE_BEARER_H
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-fdbet-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -221,6 +221,7 @@
 void
 LenaFdBetFfMacSchedulerTestCase1::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
@@ -403,6 +404,7 @@
 LenaFdBetFfMacSchedulerTestCase2::DoRun()
 {
     NS_LOG_FUNCTION(this);
+    SetDataDir(NS_TEST_SOURCEDIR);
 
     if (!m_errorModelEnabled)
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-fdmt-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -198,7 +198,7 @@
 LenaFdMtFfMacSchedulerTestCase::DoRun()
 {
     NS_LOG_FUNCTION(this << m_nUser << m_dist);
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-fdtbfq-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-fdtbfq-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-fdtbfq-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-fdtbfq-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -293,7 +293,7 @@
 LenaFdTbfqFfMacSchedulerTestCase1::DoRun()
 {
     NS_LOG_FUNCTION(this << GetName());
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
@@ -568,6 +568,8 @@
 void
 LenaFdTbfqFfMacSchedulerTestCase2::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-harq.cc ns-3.46/src/lte/test/lte-test-harq.cc
--- ns-3.45/src/lte/test/lte-test-harq.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-harq.cc	2025-10-01 18:46:32.000000000 -0700
@@ -96,6 +96,7 @@
 void
 LenaHarqTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     Config::SetDefault("ns3::LteAmc::Ber", DoubleValue(m_amcBer));
     Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
     Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-link-adaptation.cc ns-3.46/src/lte/test/lte-test-link-adaptation.cc
--- ns-3.45/src/lte/test/lte-test-link-adaptation.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-link-adaptation.cc	2025-10-01 18:46:32.000000000 -0700
@@ -127,6 +127,7 @@
 void
 LteLinkAdaptationTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     Config::Reset();
     Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
     Config::SetDefault("ns3::LteAmc::Ber", DoubleValue(0.00005));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-mimo.cc ns-3.46/src/lte/test/lte-test-mimo.cc
--- ns-3.45/src/lte/test/lte-test-mimo.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-mimo.cc	2025-10-01 18:46:32.000000000 -0700
@@ -113,6 +113,7 @@
 LenaMimoTestCase::DoRun()
 {
     NS_LOG_FUNCTION(this << GetName());
+    SetDataDir(NS_TEST_SOURCEDIR);
     Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
     Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
     Config::SetDefault("ns3::LteHelper::UseIdealRrc", BooleanValue(m_useIdealRrc));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-pathloss-model.cc ns-3.46/src/lte/test/lte-test-pathloss-model.cc
--- ns-3.45/src/lte/test/lte-test-pathloss-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-pathloss-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -159,6 +159,7 @@
 void
 LtePathlossModelSystemTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     Config::SetDefault("ns3::MacStatsCalculator::DlOutputFilename",
                        StringValue(CreateTempDirFilename("DlMacStats.txt")));
     Config::SetDefault("ns3::MacStatsCalculator::UlOutputFilename",
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-pf-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-pf-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-pf-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-pf-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -239,7 +239,7 @@
 LenaPfFfMacSchedulerTestCase1::DoRun()
 {
     NS_LOG_FUNCTION(this << m_nUser << m_dist);
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
@@ -418,6 +418,8 @@
 LenaPfFfMacSchedulerTestCase2::DoRun()
 {
     NS_LOG_FUNCTION(this);
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-phy-error-model.cc ns-3.46/src/lte/test/lte-test-phy-error-model.cc
--- ns-3.45/src/lte/test/lte-test-phy-error-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-phy-error-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -148,6 +148,7 @@
 void
 LenaDataPhyErrorModelTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     double ber = 0.03;
     Config::SetDefault("ns3::LteAmc::Ber", DoubleValue(ber));
     Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
@@ -309,6 +310,8 @@
 void
 LenaDlCtrlPhyErrorModelTestCase::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     double ber = 0.03;
     Config::SetDefault("ns3::LteAmc::Ber", DoubleValue(ber));
     Config::SetDefault("ns3::LteAmc::AmcModel", EnumValue(LteAmc::PiroEW2010));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-pss-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-pss-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-pss-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-pss-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -290,7 +290,7 @@
 LenaPssFfMacSchedulerTestCase1::DoRun()
 {
     NS_LOG_FUNCTION(this << GetName());
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
@@ -563,6 +563,8 @@
 void
 LenaPssFfMacSchedulerTestCase2::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-radio-link-failure.cc ns-3.46/src/lte/test/lte-test-radio-link-failure.cc
--- ns-3.45/src/lte/test/lte-test-radio-link-failure.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-radio-link-failure.cc	2025-10-01 18:46:32.000000000 -0700
@@ -167,6 +167,7 @@
     // LogComponentEnable ("LteUeRrc", logLevel);
     // LogComponentEnable ("LteEnbRrc", logLevel);
     // LogComponentEnable ("LteRadioLinkFailureTest", logLevel);
+    SetDataDir(NS_TEST_SOURCEDIR);
 
     Config::SetDefault("ns3::MacStatsCalculator::DlOutputFilename",
                        StringValue(CreateTempDirFilename("DlMacStats.txt")));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-rr-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-rr-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -201,6 +201,7 @@
 LenaRrFfMacSchedulerTestCase::DoRun()
 {
     NS_LOG_FUNCTION(this << m_nUser << m_dist);
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-tdbet-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -221,6 +221,7 @@
 void
 LenaTdBetFfMacSchedulerTestCase1::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
@@ -408,6 +409,7 @@
 LenaTdBetFfMacSchedulerTestCase2::DoRun()
 {
     NS_LOG_FUNCTION(this);
+    SetDataDir(NS_TEST_SOURCEDIR);
 
     if (!m_errorModelEnabled)
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-tdmt-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -197,7 +197,7 @@
 LenaTdMtFfMacSchedulerTestCase::DoRun()
 {
     NS_LOG_FUNCTION(this << m_nUser << m_dist);
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-tdtbfq-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-tdtbfq-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-tdtbfq-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-tdtbfq-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -293,7 +293,7 @@
 LenaTdTbfqFfMacSchedulerTestCase1::DoRun()
 {
     NS_LOG_FUNCTION(this << GetName());
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
@@ -567,6 +567,8 @@
 void
 LenaTdTbfqFfMacSchedulerTestCase2::DoRun()
 {
+    SetDataDir(NS_TEST_SOURCEDIR);
+
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-tta-ff-mac-scheduler.cc ns-3.46/src/lte/test/lte-test-tta-ff-mac-scheduler.cc
--- ns-3.45/src/lte/test/lte-test-tta-ff-mac-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-tta-ff-mac-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -197,7 +197,7 @@
 LenaTtaFfMacSchedulerTestCase::DoRun()
 {
     NS_LOG_FUNCTION(this << m_nUser << m_dist);
-
+    SetDataDir(NS_TEST_SOURCEDIR);
     if (!m_errorModelEnabled)
     {
         Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/lte-test-ue-measurements.cc ns-3.46/src/lte/test/lte-test-ue-measurements.cc
--- ns-3.45/src/lte/test/lte-test-ue-measurements.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/lte-test-ue-measurements.cc	2025-10-01 18:46:32.000000000 -0700
@@ -42,6 +42,8 @@
 
 NS_LOG_COMPONENT_DEFINE("LteUeMeasurementsTest");
 
+const Time UE_MEASUREMENT_REPORT_DELAY = MicroSeconds(1);
+
 // ===== LTE-UE-MEASUREMENTS TEST SUITE ==================================== //
 
 void
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/lte/test/test-lte-epc-e2e-data.cc ns-3.46/src/lte/test/test-lte-epc-e2e-data.cc
--- ns-3.45/src/lte/test/test-lte-epc-e2e-data.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/lte/test/test-lte-epc-e2e-data.cc	2025-10-01 18:46:32.000000000 -0700
@@ -116,6 +116,7 @@
 LteEpcE2eDataTestCase::DoRun()
 {
     NS_LOG_FUNCTION(this << GetName());
+    SetDataDir(NS_TEST_SOURCEDIR);
     Config::Reset();
     Config::SetDefault("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue(false));
     Config::SetDefault("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue(false));
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mesh/doc/Makefile ns-3.46/src/mesh/doc/Makefile
--- ns-3.45/src/mesh/doc/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mesh/doc/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,8 +1,4 @@
-EPSTOPDF = epstopdf
-DIA = dia
-DOT = dot
-CONVERT = convert -density 250
-
+include $(CURDIR)/../../../doc/sphinx/defines.mk
 
 SOURCE = source
 FIGURES = $(SOURCE)/figures
@@ -39,16 +35,7 @@
 	$(EPSTOPDF) $< -o=$@
 	if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
 
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mesh/model/dot11s/hwmp-protocol.cc ns-3.46/src/mesh/model/dot11s/hwmp-protocol.cc
--- ns-3.45/src/mesh/model/dot11s/hwmp-protocol.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mesh/model/dot11s/hwmp-protocol.cc	2025-10-01 18:46:32.000000000 -0700
@@ -181,6 +181,8 @@
     if (m_isRoot)
     {
         Time randomStart = Seconds(m_coefficient->GetValue());
+        NS_LOG_INFO("Root is starting proactive PREQ timer to expire at "
+                    << randomStart.As(Time::S));
         m_proactivePreqTimer =
             Simulator::Schedule(randomStart, &HwmpProtocol::SendProactivePreq, this);
     }
@@ -412,7 +414,7 @@
 {
     NS_LOG_FUNCTION(this << from << interface << fromMp << metric);
     preq.IncrementMetric(metric);
-    // acceptance cretirea:
+    // acceptance criteria:
     auto i = m_hwmpSeqnoMetricDatabase.find(preq.GetOriginatorAddress());
     bool freshInfo(true);
     if (i != m_hwmpSeqnoMetricDatabase.end())
@@ -598,7 +600,7 @@
 {
     NS_LOG_FUNCTION(this << from << interface << fromMp << metric);
     prep.IncrementMetric(metric);
-    // acceptance cretirea:
+    // acceptance criteria:
     auto i = m_hwmpSeqnoMetricDatabase.find(prep.GetOriginatorAddress());
     bool freshInfo(true);
     uint32_t sequence = prep.GetDestinationSeqNumber();
@@ -705,7 +707,7 @@
                           Mac48Address fromMp)
 {
     NS_LOG_FUNCTION(this << from << interface << fromMp);
-    // Acceptance cretirea:
+    // Acceptance criteria:
     NS_LOG_DEBUG("I am " << GetAddress() << ", received PERR from " << from);
     std::vector<FailedDestination> retval;
     HwmpRtable::LookupResult result;
@@ -735,6 +737,8 @@
                        uint32_t lifetime,
                        uint32_t interface)
 {
+    NS_LOG_FUNCTION(this << src << dst << retransmitter << initMetric << originatorDsn
+                         << destinationSN << lifetime << interface);
     IePrep prep;
     prep.SetHopcount(0);
     prep.SetTtl(m_maxTtl);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mesh/model/dot11s/hwmp-rtable.cc ns-3.46/src/mesh/model/dot11s/hwmp-rtable.cc
--- ns-3.45/src/mesh/model/dot11s/hwmp-rtable.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mesh/model/dot11s/hwmp-rtable.cc	2025-10-01 18:46:32.000000000 -0700
@@ -59,19 +59,12 @@
 {
     NS_LOG_FUNCTION(this << destination << retransmitter << interface << metric
                          << lifetime.GetSeconds() << seqnum);
-    auto i = m_routes.find(destination);
-    if (i == m_routes.end())
-    {
-        ReactiveRoute newroute;
-        m_routes[destination] = newroute;
-    }
-    i = m_routes.find(destination);
-    NS_ASSERT(i != m_routes.end());
-    i->second.retransmitter = retransmitter;
-    i->second.interface = interface;
-    i->second.metric = metric;
-    i->second.whenExpire = Simulator::Now() + lifetime;
-    i->second.seqnum = seqnum;
+    auto& route = m_routes[destination]; // find existing record or create new
+    route.retransmitter = retransmitter;
+    route.interface = interface;
+    route.metric = metric;
+    route.whenExpire = Simulator::Now() + lifetime;
+    route.seqnum = seqnum;
 }
 
 void
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mesh/model/mesh-wifi-interface-mac.cc ns-3.46/src/mesh/model/mesh-wifi-interface-mac.cc
--- ns-3.45/src/mesh/model/mesh-wifi-interface-mac.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mesh/model/mesh-wifi-interface-mac.cc	2025-10-01 18:46:32.000000000 -0700
@@ -189,7 +189,7 @@
      * Now we use dirty channel switch -- just change frequency
      */
     GetWifiPhy()->SetOperatingChannel(
-        WifiPhy::ChannelTuple{new_id, 0, GetWifiPhy()->GetPhyBand(), 0});
+        WifiPhy::ChannelTuple{static_cast<uint8_t>(new_id), 0, GetWifiPhy()->GetPhyBand(), 0});
     // Don't know NAV on new channel
     GetLink(SINGLE_LINK_OP_ID).channelAccessManager->NotifyNavResetNow(Seconds(0));
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mesh/test/dot11s/hwmp-proactive-regression.cc ns-3.46/src/mesh/test/dot11s/hwmp-proactive-regression.cc
--- ns-3.45/src/mesh/test/dot11s/hwmp-proactive-regression.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mesh/test/dot11s/hwmp-proactive-regression.cc	2025-10-01 18:46:32.000000000 -0700
@@ -13,6 +13,7 @@
 #include "ns3/internet-stack-helper.h"
 #include "ns3/ipv4-address-helper.h"
 #include "ns3/ipv4-interface-container.h"
+#include "ns3/log.h"
 #include "ns3/mesh-helper.h"
 #include "ns3/mobility-helper.h"
 #include "ns3/mobility-model.h"
@@ -28,6 +29,8 @@
 
 using namespace ns3;
 
+NS_LOG_COMPONENT_DEFINE("HwmpProactiveRegression");
+
 /// Unique PCAP file name prefix
 const char* const PREFIX = "hwmp-proactive-regression-test";
 
@@ -167,6 +170,7 @@
     {
         socket->Send(Create<Packet>(100));
         m_sentPktsCounter++;
+        NS_LOG_INFO("Send packet; total sent = " << m_sentPktsCounter);
         Simulator::ScheduleWithContext(socket->GetNode()->GetId(),
                                        Seconds(0.5),
                                        &HwmpProactiveRegressionTest::SendData,
@@ -182,6 +186,8 @@
     Address from;
     while ((packet = socket->RecvFrom(from)))
     {
+        NS_LOG_INFO("Receive packet from " << InetSocketAddress::ConvertFrom(from).GetIpv4()
+                                           << "; return to sender");
         packet->RemoveAllPacketTags();
         packet->RemoveAllByteTags();
 
@@ -196,5 +202,6 @@
     Address from;
     while ((packet = socket->RecvFrom(from)))
     {
+        NS_LOG_INFO("Receive packet from " << InetSocketAddress::ConvertFrom(from).GetIpv4());
     }
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/CMakeLists.txt ns-3.46/src/mobility/CMakeLists.txt
--- ns-3.45/src/mobility/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -57,4 +57,5 @@
     test/rectangle-closest-border-test.cc
     test/steady-state-random-waypoint-mobility-model-test.cc
     test/waypoint-mobility-model-test.cc
+  GENERATE_EXPORT_HEADER
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/constant-acceleration-mobility-model.h ns-3.46/src/mobility/model/constant-acceleration-mobility-model.h
--- ns-3.45/src/mobility/model/constant-acceleration-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/constant-acceleration-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -33,6 +33,13 @@
      */
     ConstantAccelerationMobilityModel();
     ~ConstantAccelerationMobilityModel() override;
+
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<ConstantAccelerationMobilityModel>(*this);
+    }
+
     /**
      * Set the model's velocity and acceleration
      * @param velocity the velocity (m/s)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/constant-position-mobility-model.h ns-3.46/src/mobility/model/constant-position-mobility-model.h
--- ns-3.45/src/mobility/model/constant-position-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/constant-position-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -33,6 +33,12 @@
     ConstantPositionMobilityModel();
     ~ConstantPositionMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<ConstantPositionMobilityModel>(*this);
+    }
+
   private:
     Vector DoGetPosition() const override;
     void DoSetPosition(const Vector& position) override;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/constant-velocity-mobility-model.h ns-3.46/src/mobility/model/constant-velocity-mobility-model.h
--- ns-3.45/src/mobility/model/constant-velocity-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/constant-velocity-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -39,6 +39,12 @@
     ConstantVelocityMobilityModel();
     ~ConstantVelocityMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<ConstantVelocityMobilityModel>(*this);
+    }
+
     /**
      * @param speed the new speed to set.
      *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/gauss-markov-mobility-model.h ns-3.46/src/mobility/model/gauss-markov-mobility-model.h
--- ns-3.45/src/mobility/model/gauss-markov-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/gauss-markov-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -78,6 +78,12 @@
     GaussMarkovMobilityModel();
     ~GaussMarkovMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<GaussMarkovMobilityModel>(*this);
+    }
+
   private:
     /**
      * Initialize the model and calculate new velocity, direction, and pitch
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/geocentric-constant-position-mobility-model.cc ns-3.46/src/mobility/model/geocentric-constant-position-mobility-model.cc
--- ns-3.45/src/mobility/model/geocentric-constant-position-mobility-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/geocentric-constant-position-mobility-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -9,7 +9,7 @@
 
 #include "ns3/angles.h"
 
-#include <math.h>
+#include <cmath>
 
 /**
  *  @file
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/geocentric-constant-position-mobility-model.h ns-3.46/src/mobility/model/geocentric-constant-position-mobility-model.h
--- ns-3.45/src/mobility/model/geocentric-constant-position-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/geocentric-constant-position-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -37,6 +37,12 @@
     GeocentricConstantPositionMobilityModel() = default;
     ~GeocentricConstantPositionMobilityModel() override = default;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<GeocentricConstantPositionMobilityModel>(*this);
+    }
+
     /**
      * @brief Computes elevation angle between a ground terminal and a HAPS/Satellite.
      * After calculating the plane perpendicular to a cartesian position vector,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/hierarchical-mobility-model.h ns-3.46/src/mobility/model/hierarchical-mobility-model.h
--- ns-3.45/src/mobility/model/hierarchical-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/hierarchical-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -54,6 +54,12 @@
 
     HierarchicalMobilityModel();
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<HierarchicalMobilityModel>(*this);
+    }
+
     /**
      * @return the child mobility model.
      *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/mobility-model.h ns-3.46/src/mobility/model/mobility-model.h
--- ns-3.45/src/mobility/model/mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -8,6 +8,7 @@
 #ifndef MOBILITY_MODEL_H
 #define MOBILITY_MODEL_H
 
+#include "ns3/mobility-export.h"
 #include "ns3/object.h"
 #include "ns3/traced-callback.h"
 #include "ns3/vector.h"
@@ -25,7 +26,7 @@
  *
  * This is a base class for all specific mobility models.
  */
-class MobilityModel : public Object
+class MOBILITY_EXPORT MobilityModel : public Object
 {
   public:
     /**
@@ -37,6 +38,15 @@
     ~MobilityModel() override = 0;
 
     /**
+     * Copy function allows one to copy the underlying MobilityModel
+     * from a MobilityModel pointer, by calling each children Copy implementation.
+     * This is primarily used by wraparound models for the spectrum channel.
+     *
+     * @return a copy of the current mobility model
+     */
+    virtual Ptr<MobilityModel> Copy() const = 0;
+
+    /**
      * @return the current position
      */
     Vector GetPosition() const;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/random-direction-2d-mobility-model.h ns-3.46/src/mobility/model/random-direction-2d-mobility-model.h
--- ns-3.45/src/mobility/model/random-direction-2d-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/random-direction-2d-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -42,6 +42,12 @@
     RandomDirection2dMobilityModel();
     ~RandomDirection2dMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<RandomDirection2dMobilityModel>(*this);
+    }
+
   private:
     /**
      * Set a new direction and speed
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/random-walk-2d-mobility-model.h ns-3.46/src/mobility/model/random-walk-2d-mobility-model.h
--- ns-3.45/src/mobility/model/random-walk-2d-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/random-walk-2d-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -48,6 +48,12 @@
 
     ~RandomWalk2dMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<RandomWalk2dMobilityModel>(*this);
+    }
+
     /** An enum representing the different working modes of this module. */
     enum Mode
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/random-waypoint-mobility-model.h ns-3.46/src/mobility/model/random-waypoint-mobility-model.h
--- ns-3.45/src/mobility/model/random-waypoint-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/random-waypoint-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -50,6 +50,12 @@
 
     ~RandomWaypointMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<RandomWaypointMobilityModel>(*this);
+    }
+
   protected:
     void DoInitialize() override;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/steady-state-random-waypoint-mobility-model.h ns-3.46/src/mobility/model/steady-state-random-waypoint-mobility-model.h
--- ns-3.45/src/mobility/model/steady-state-random-waypoint-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/steady-state-random-waypoint-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -53,6 +53,12 @@
     SteadyStateRandomWaypointMobilityModel();
     ~SteadyStateRandomWaypointMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<SteadyStateRandomWaypointMobilityModel>(*this);
+    }
+
   protected:
     void DoInitialize() override;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mobility/model/waypoint-mobility-model.h ns-3.46/src/mobility/model/waypoint-mobility-model.h
--- ns-3.45/src/mobility/model/waypoint-mobility-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mobility/model/waypoint-mobility-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -89,6 +89,12 @@
     WaypointMobilityModel();
     ~WaypointMobilityModel() override;
 
+    // Inherited from MobilityModel
+    Ptr<MobilityModel> Copy() const override
+    {
+        return CreateObject<WaypointMobilityModel>(*this);
+    }
+
     /**
      * @param waypoint waypoint to append to the object path.
      *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/mpi/model/remote-channel-bundle-manager.cc ns-3.46/src/mpi/model/remote-channel-bundle-manager.cc
--- ns-3.45/src/mpi/model/remote-channel-bundle-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/mpi/model/remote-channel-bundle-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -48,7 +48,7 @@
     NS_ASSERT(!g_initialized);
     NS_ASSERT(g_remoteChannelBundles.find(systemId) == g_remoteChannelBundles.end());
 
-    Ptr<RemoteChannelBundle> remoteChannelBundle = Create<RemoteChannelBundle>(systemId);
+    auto remoteChannelBundle = CreateObject<RemoteChannelBundle>(systemId);
 
     g_remoteChannelBundles[systemId] = remoteChannelBundle;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/netanim/CMakeLists.txt ns-3.46/src/netanim/CMakeLists.txt
--- ns-3.45/src/netanim/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/netanim/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -3,7 +3,6 @@
   SOURCE_FILES model/animation-interface.cc
   HEADER_FILES model/animation-interface.h
   LIBRARIES_TO_LINK
-    ${libwimax}
     ${libwifi}
     ${liblte}
     ${libuan}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/netanim/doc/animation.rst ns-3.46/src/netanim/doc/animation.rst
--- ns-3.45/src/netanim/doc/animation.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/netanim/doc/animation.rst	2025-10-01 18:46:32.000000000 -0700
@@ -87,7 +87,7 @@
 ================
 Prerequisites
 ~~~~~~~~~~~~~
-Qt5 (5.4 and over) is required to build NetAnim. The ns-3 Installation Guide
+Qt5 (5.4 and over) and CMake are required to build NetAnim. The ns-3 Installation Guide
 lists some packages to install for some
 `Linux <https://www.nsnam.org/docs/installation/html/linux.html#optional>`_ systems,
 for `macOS <https://www.nsnam.org/docs/installation/html/macos.html#optional>`, and
@@ -102,28 +102,22 @@
 
 .. sourcecode:: bash
 
-  $ cd netanim
-  $ make clean
-  $ qmake NetAnim.pro
-  $ make
-
-
-Note: qmake could be "qmake-qt5" in some systems
-
-This should create an executable named "NetAnim" in the same directory:
-
-.. sourcecode:: bash
-
-  $ ls -l NetAnim
- -rwxr-xr-x 1 john john 390395 2012-05-22 08:32 NetAnim
+   $ git clone https://gitlab.com/nsnam/netanim.git
+   $ cd netanim
+   $ mkdir build && cd build
+   $ cmake .. && cmake --build .
+
+This should create an executable named "netanim" in the `build/bin` directory.
+If you prefer, you can move or copy this binary to another directory on
+your file system.
 
 Usage
 =====
 Using NetAnim is a two-step process
 
-Step 1:Generate the animation XML trace file during simulation using "ns3::AnimationInterface" in the |ns3| code base.
+Step 1: Generate the animation XML trace file during simulation using "ns3::AnimationInterface" in the |ns3| code base.
 
-Step 2:Load the XML trace file generated in Step 1 with the offline Qt-based animator named NetAnim.
+Step 2: Load the XML trace file generated in Step 1 with NetAnim.
 
 Step 1: Generate XML animation trace file
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -203,7 +197,6 @@
 With the above statement, AnimationInterface records the meta-data of each packet in the xml trace file. Metadata can be used by NetAnim to provide better statistics and filter, along with providing some brief information about the packet such as TCP sequence number or source & destination IP address during packet animation.
 
 CAUTION: Enabling this feature will result in larger XML trace files.
-Please do NOT enable this feature when using Wimax links.
 
 ::
 
@@ -231,7 +224,7 @@
 Step 2: Loading the XML in NetAnim
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-1. Assuming NetAnim was built, use the command "./NetAnim" to launch NetAnim. Please review the section "Building NetAnim" if NetAnim is not available.
+1. Assuming NetAnim was built, use the command "./netanim" to launch NetAnim. Please review the section "Building NetAnim" if NetAnim is not available.
 2. When NetAnim is opened, click on the File open button at the top-left corner, select the XML file generated during Step 1.
 3. Hit the green play button to begin animation.
 
@@ -240,6 +233,8 @@
 
 Wiki
 ====
-For detailed instructions on installing "NetAnim", F.A.Qs and loading the XML trace file
+For more documentation on "NetAnim", F.A.Qs and loading the XML trace file
 (mentioned earlier) using NetAnim please refer:
 http://www.nsnam.org/wiki/NetAnim
+
+Please note that the wiki may refer to stale installation instructions.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/netanim/model/animation-interface.cc ns-3.46/src/netanim/model/animation-interface.cc
--- ns-3.45/src/netanim/model/animation-interface.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/netanim/model/animation-interface.cc	2025-10-01 18:46:32.000000000 -0700
@@ -22,7 +22,6 @@
 
 // ns3 includes
 #ifdef __WIN32__
-#include "ns3/bs-net-device.h"
 #include "ns3/csma-net-device.h"
 #endif
 #include "animation-interface.h"
@@ -49,7 +48,6 @@
 #include "ns3/wifi-mac.h"
 #include "ns3/wifi-net-device.h"
 #include "ns3/wifi-psdu.h"
-#include "ns3/wimax-mac-header.h"
 
 namespace ns3
 {
@@ -95,11 +93,10 @@
      * The .dll.a/.lib however, only gets linked if we instantiate at
      * least one symbol exported by the .dll.
      *
-     * To ensure TypeIds from the Csma, Uan, Wifi and Wimax
+     * To ensure TypeIds from the Csma, Uan, and Wifi
      * modules are registered during runtime, we need to instantiate
      * at least one symbol exported by each of these module libraries.
      */
-    static BaseStationNetDevice b;
     static CsmaNetDevice c;
     static WifiNetDevice w;
     static UanNetDevice u;
@@ -477,7 +474,6 @@
     if (!Simulator::IsFinished())
     {
         PurgePendingPackets(AnimationInterface::WIFI);
-        PurgePendingPackets(AnimationInterface::WIMAX);
         PurgePendingPackets(AnimationInterface::LTE);
         PurgePendingPackets(AnimationInterface::CSMA);
         PurgePendingPackets(AnimationInterface::LRWPAN);
@@ -1069,20 +1065,6 @@
 }
 
 void
-AnimationInterface::WimaxTxTrace(std::string context, Ptr<const Packet> p, const Mac48Address& m)
-{
-    NS_LOG_FUNCTION(this);
-    return GenericWirelessTxTrace(context, p, AnimationInterface::WIMAX);
-}
-
-void
-AnimationInterface::WimaxRxTrace(std::string context, Ptr<const Packet> p, const Mac48Address& m)
-{
-    NS_LOG_FUNCTION(this);
-    return GenericWirelessRxTrace(context, p, AnimationInterface::WIMAX);
-}
-
-void
 AnimationInterface::LteTxTrace(std::string context, Ptr<const Packet> p, const Mac48Address& m)
 {
     NS_LOG_FUNCTION(this);
@@ -1346,10 +1328,6 @@
         pendingPackets = &m_pendingCsmaPackets;
         break;
     }
-    case AnimationInterface::WIMAX: {
-        pendingPackets = &m_pendingWimaxPackets;
-        break;
-    }
     case AnimationInterface::LTE: {
         pendingPackets = &m_pendingLtePackets;
         break;
@@ -1380,10 +1358,6 @@
         result = "CSMA";
         break;
     }
-    case AnimationInterface::WIMAX: {
-        result = "WIMAX";
-        break;
-    }
     case AnimationInterface::LTE: {
         result = "LTE";
         break;
@@ -1614,10 +1588,6 @@
     Config::ConnectWithoutContextFailSafe(
         "/NodeList/*/$ns3::MobilityModel/CourseChange",
         MakeCallback(&AnimationInterface::MobilityCourseChangeTrace, this));
-    Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Tx",
-                            MakeCallback(&AnimationInterface::WimaxTxTrace, this));
-    Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Rx",
-                            MakeCallback(&AnimationInterface::WimaxRxTrace, this));
     Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::LteNetDevice/Tx",
                             MakeCallback(&AnimationInterface::LteTxTrace, this));
     Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::LteNetDevice/Rx",
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/netanim/model/animation-interface.h ns-3.46/src/netanim/model/animation-interface.h
--- ns-3.45/src/netanim/model/animation-interface.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/netanim/model/animation-interface.h	2025-10-01 18:46:32.000000000 -0700
@@ -531,7 +531,6 @@
         UAN,
         LTE,
         WIFI,
-        WIMAX,
         CSMA,
         LRWPAN
     };
@@ -652,7 +651,6 @@
     uint32_t m_wifiPhyRxDropCounterId; ///< wifi Phy receive drop counter ID
 
     AnimUidPacketInfoMap m_pendingWifiPackets;   ///< pending wifi packets
-    AnimUidPacketInfoMap m_pendingWimaxPackets;  ///< pending wimax packets
     AnimUidPacketInfoMap m_pendingLrWpanPackets; ///< pending LR-WPAN packets
     AnimUidPacketInfoMap m_pendingLtePackets;    ///< pending LTE packets
     AnimUidPacketInfoMap m_pendingCsmaPackets;   ///< pending CSMA packets
@@ -1079,20 +1077,6 @@
      */
     void LrWpanPhyRxBeginTrace(std::string context, Ptr<const Packet> p);
     /**
-     * WIMax transmit trace function
-     * @param context the context
-     * @param p the packet
-     * @param m the MAC address
-     */
-    void WimaxTxTrace(std::string context, Ptr<const Packet> p, const Mac48Address& m);
-    /**
-     * WIMax receive trace function
-     * @param context the context
-     * @param p the packet
-     * @param m the MAC address
-     */
-    void WimaxRxTrace(std::string context, Ptr<const Packet> p, const Mac48Address& m);
-    /**
      * CSMA Phy transmit begin trace function
      * @param context the context
      * @param p the packet
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/netanim/_required_netanim_version.py ns-3.46/src/netanim/_required_netanim_version.py
--- ns-3.45/src/netanim/_required_netanim_version.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/netanim/_required_netanim_version.py	1969-12-31 16:00:00.000000000 -0800
@@ -1,9 +0,0 @@
-# Store version information for required netanim version, used by
-# ns-3-allinone/download.py.
-# If specifying a released netanim version, specify the required netanim
-# version as, e.g. 'netanim-3.108'
-# If specifying a commit on the development tree, specify it like this based
-# on 'git describe --tags' command.  Example, if the latest release was 3.108,
-# and 'git describe --tags' reports "netanim-3.108-6-g8e7c0a9", then write the
-# version string below as 'netanim-3.108.post6+ng8e7c0a9'
-__required_netanim_version__ = "netanim-3.109"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/CMakeLists.txt ns-3.46/src/network/CMakeLists.txt
--- ns-3.45/src/network/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -101,7 +101,6 @@
     model/tag-buffer.h
     model/tag.h
     model/trailer.h
-    test/header-serialization-test.h
     utils/address-utils.h
     utils/bit-deserializer.h
     utils/bit-serializer.h
@@ -115,6 +114,7 @@
     utils/ethernet-trailer.h
     utils/flow-id-tag.h
     utils/generic-phy.h
+    utils/header-serialization-test.h
     utils/inet-socket-address.h
     utils/inet6-socket-address.h
     utils/ipv4-address.h
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/helper/trace-helper.cc ns-3.46/src/network/helper/trace-helper.cc
--- ns-3.45/src/network/helper/trace-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/helper/trace-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,8 +15,8 @@
 #include "ns3/pcap-file-wrapper.h"
 #include "ns3/ptr.h"
 
+#include <cstdint>
 #include <fstream>
-#include <stdint.h>
 #include <string>
 
 namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/model/packet-metadata.cc ns-3.46/src/network/model/packet-metadata.cc
--- ns-3.45/src/network/model/packet-metadata.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/model/packet-metadata.cc	2025-10-01 18:46:32.000000000 -0700
@@ -108,7 +108,6 @@
 bool
 PacketMetadata::IsSharedPointerOk(uint16_t pointer) const
 {
-    NS_LOG_FUNCTION(this << pointer);
     bool ok = pointer == 0xffff || pointer <= m_data->m_size;
     return ok;
 }
@@ -116,7 +115,6 @@
 bool
 PacketMetadata::IsPointerOk(uint16_t pointer) const
 {
-    NS_LOG_FUNCTION(this << pointer);
     bool ok = pointer == 0xffff || pointer <= m_used;
     return ok;
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/model/packet-tag-list.h ns-3.46/src/network/model/packet-tag-list.h
--- ns-3.45/src/network/model/packet-tag-list.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/model/packet-tag-list.h	2025-10-01 18:46:32.000000000 -0700
@@ -69,18 +69,18 @@
  * @enddot
  *
  *   - Tags are stored in serialized form in a tree of TagData
- *     structures. (<tt>T1-T7</tt> in the diagram)
+ *     structures. (``T1-T7`` in the diagram)
  *
  *   - Each TagData points (\c next pointers in the diagram)
  *     toward the root of the tree, which is a null pointer.
  *
  *   - \c count is the number of incoming pointers to this
  *     TagData.  Branch points, where branches merge or join, have
- *     <tt>count \> 1</tt> (\c T3, \c T5); successive links along
- *     a branch have <tt>count = 1</tt> (\c T1, \c T2, \c T4, \c T6, \c T7).
+ *     ``count \> 1`` (\c T3, \c T5); successive links along
+ *     a branch have ``count = 1`` (\c T1, \c T2, \c T4, \c T6, \c T7).
  *
  *   - Each PacketTagList points to a specific TagData,
- *     which is the most recent Tag added to the packet. (<tt>T5-T7</tt>)
+ *     which is the most recent Tag added to the packet. (``T5-T7``)
  *
  *   - Conceptually, therefore, each Packet has a PacketTagList which
  *     points to a singly-linked list of TagData.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/model/socket.h ns-3.46/src/network/model/socket.h
--- ns-3.45/src/network/model/socket.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/model/socket.h	2025-10-01 18:46:32.000000000 -0700
@@ -169,7 +169,7 @@
      *        completed. The callback is passed  back a pointer to
      *        the same socket object.
      * @param connectionFailed this callback is invoked when the
-     *        connection request initiated by the user is unsuccessfuly
+     *        connection request initiated by the user is unsuccessfully
      *        completed. The callback is passed back a pointer to the
      *        same socket object.
      */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/test/header-serialization-test.h ns-3.46/src/network/test/header-serialization-test.h
--- ns-3.45/src/network/test/header-serialization-test.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/test/header-serialization-test.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Davide Magrin <magrin.davide@gmail.com>
- *          Stefano Avallone <stavallo@unina.it>
- */
-
-#ifndef NS3_TEST_HDR_SERIALIZE_H
-#define NS3_TEST_HDR_SERIALIZE_H
-
-#include "ns3/buffer.h"
-#include "ns3/test.h"
-
-namespace ns3
-{
-
-/**
- * Subclass of TestCase class adding the ability to test the serialization and
- * deserialization of a Header object.
- */
-class HeaderSerializationTestCase : public TestCase
-{
-  protected:
-    /**
-     * @brief Constructor.
-     *
-     * @param [in] name The name of the new TestCase created
-     */
-    HeaderSerializationTestCase(std::string name)
-        : TestCase(name)
-    {
-    }
-
-  public:
-    /**
-     * Serialize the given header in a buffer, then create a new header by
-     * deserializing from the buffer and serialize the new header into a new buffer.
-     * Verify that the two buffers have the same size and the same content.
-     *
-     * @tparam T \deduced Type of the given header
-     * @tparam Args \deduced Type of arguments to pass to the constructor of the header
-     * @param [in] hdr the header to test
-     * @param [in] args the arguments to construct the new header
-     */
-    template <typename T, typename... Args>
-    void TestHeaderSerialization(const T& hdr, Args&&... args);
-};
-
-} // namespace ns3
-
-/***************************************************************
- *  Implementation of the templates declared above.
- ***************************************************************/
-
-namespace ns3
-{
-
-template <typename T, typename... Args>
-void
-HeaderSerializationTestCase::TestHeaderSerialization(const T& hdr, Args&&... args)
-{
-    Buffer buffer;
-    buffer.AddAtStart(hdr.GetSerializedSize());
-    hdr.Serialize(buffer.Begin());
-
-    T otherHdr(std::forward<Args>(args)...);
-    otherHdr.Deserialize(buffer.Begin());
-    Buffer otherBuffer;
-    otherBuffer.AddAtStart(otherHdr.GetSerializedSize());
-    otherHdr.Serialize(otherBuffer.Begin());
-
-    NS_TEST_ASSERT_MSG_EQ(buffer.GetSize(), otherBuffer.GetSize(), "Size of buffers differs");
-
-    Buffer::Iterator bufferIterator = buffer.Begin();
-    Buffer::Iterator otherBufferIterator = otherBuffer.Begin();
-    for (uint32_t j = 0; j < buffer.GetSize(); j++)
-    {
-        uint8_t bufferVal = bufferIterator.ReadU8();
-        uint8_t otherBufferVal = otherBufferIterator.ReadU8();
-        NS_TEST_EXPECT_MSG_EQ(+bufferVal,
-                              +otherBufferVal,
-                              "Serialization -> Deserialization -> Serialization "
-                                  << "is different than Serialization at byte " << j);
-    }
-}
-
-} // namespace ns3
-
-#endif /* NS3_TEST_HDR_SERIALIZE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/crc32.cc ns-3.46/src/network/utils/crc32.cc
--- ns-3.45/src/network/utils/crc32.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/crc32.cc	2025-10-01 18:46:32.000000000 -0700
@@ -13,7 +13,7 @@
  * COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
  * code or tables extracted from it, as desired without restriction.
  */
-#include <stdint.h>
+#include <cstdint>
 
 namespace ns3
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/header-serialization-test.h ns-3.46/src/network/utils/header-serialization-test.h
--- ns-3.45/src/network/utils/header-serialization-test.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/network/utils/header-serialization-test.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors: Davide Magrin <magrin.davide@gmail.com>
+ *          Stefano Avallone <stavallo@unina.it>
+ */
+
+#ifndef NS3_TEST_HDR_SERIALIZE_H
+#define NS3_TEST_HDR_SERIALIZE_H
+
+#include "ns3/buffer.h"
+#include "ns3/test.h"
+
+/**
+ * @file
+ * @ingroup network
+ * Contains the implementation of the HeaderSerializationTestCase base class.
+ * It is used to generate tests that verify whether a header, when encoded,
+ * then decoded, then re-encoded, matches the original encoded header byte-for-byte.
+ */
+
+namespace ns3
+{
+
+/**
+ * Subclass of TestCase class adding the ability to test the serialization and
+ * deserialization of a Header object.
+ */
+class HeaderSerializationTestCase : public TestCase
+{
+  protected:
+    /**
+     * @brief Constructor.
+     *
+     * @param [in] name The name of the new TestCase created
+     */
+    HeaderSerializationTestCase(std::string name)
+        : TestCase(name)
+    {
+    }
+
+  public:
+    /**
+     * Serialize the given header in a buffer, then create a new header by
+     * deserializing from the buffer and serialize the new header into a new buffer.
+     * Verify that the two buffers have the same size and the same content.
+     *
+     * @tparam T \deduced Type of the given header
+     * @tparam Args \deduced Type of arguments to pass to the constructor of the header
+     * @param [in] hdr the header to test
+     * @param [in] args the arguments to construct the new header
+     */
+    template <typename T, typename... Args>
+    void TestHeaderSerialization(const T& hdr, Args&&... args);
+};
+
+} // namespace ns3
+
+/***************************************************************
+ *  Implementation of the templates declared above.
+ ***************************************************************/
+
+namespace ns3
+{
+
+template <typename T, typename... Args>
+void
+HeaderSerializationTestCase::TestHeaderSerialization(const T& hdr, Args&&... args)
+{
+    Buffer buffer;
+    buffer.AddAtStart(hdr.GetSerializedSize());
+    hdr.Serialize(buffer.Begin());
+
+    T otherHdr(std::forward<Args>(args)...);
+    otherHdr.Deserialize(buffer.Begin());
+    Buffer otherBuffer;
+    otherBuffer.AddAtStart(otherHdr.GetSerializedSize());
+    otherHdr.Serialize(otherBuffer.Begin());
+
+    NS_TEST_ASSERT_MSG_EQ(buffer.GetSize(), otherBuffer.GetSize(), "Size of buffers differs");
+
+    Buffer::Iterator bufferIterator = buffer.Begin();
+    Buffer::Iterator otherBufferIterator = otherBuffer.Begin();
+    for (uint32_t j = 0; j < buffer.GetSize(); j++)
+    {
+        uint8_t bufferVal = bufferIterator.ReadU8();
+        uint8_t otherBufferVal = otherBufferIterator.ReadU8();
+        NS_TEST_EXPECT_MSG_EQ(+bufferVal,
+                              +otherBufferVal,
+                              "Serialization -> Deserialization -> Serialization "
+                                  << "is different than Serialization at byte " << j);
+    }
+}
+
+} // namespace ns3
+
+#endif /* NS3_TEST_HDR_SERIALIZE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/inet6-socket-address.cc ns-3.46/src/network/utils/inet6-socket-address.cc
--- ns-3.45/src/network/utils/inet6-socket-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/inet6-socket-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -86,7 +86,8 @@
     return addr.CheckCompatible(GetType(), 18); /* 16 (address) + 2  (port) */
 }
 
-Inet6SocketAddress::operator Address() const
+Inet6SocketAddress::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/inet-socket-address.cc ns-3.46/src/network/utils/inet-socket-address.cc
--- ns-3.45/src/network/utils/inet-socket-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/inet-socket-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -86,7 +86,8 @@
     return address.CheckCompatible(GetType(), 6);
 }
 
-InetSocketAddress::operator Address() const
+InetSocketAddress::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/ipv4-address.cc ns-3.46/src/network/utils/ipv4-address.cc
--- ns-3.45/src/network/utils/ipv4-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/ipv4-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -332,7 +332,8 @@
     return address.CheckCompatible(GetType(), 4);
 }
 
-Ipv4Address::operator Address() const
+Ipv4Address::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/ipv6-address.cc ns-3.46/src/network/utils/ipv6-address.cc
--- ns-3.45/src/network/utils/ipv6-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/ipv6-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -652,7 +652,8 @@
     return address.CheckCompatible(GetType(), 16);
 }
 
-Ipv6Address::operator Address() const
+Ipv6Address::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/mac16-address.cc ns-3.46/src/network/utils/mac16-address.cc
--- ns-3.45/src/network/utils/mac16-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/mac16-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -68,7 +68,8 @@
     return address.CheckCompatible(GetType(), 2);
 }
 
-Mac16Address::operator Address() const
+Mac16Address::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/mac48-address.cc ns-3.46/src/network/utils/mac48-address.cc
--- ns-3.45/src/network/utils/mac48-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/mac48-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -68,7 +68,8 @@
     return address.CheckCompatible(GetType(), 6);
 }
 
-Mac48Address::operator Address() const
+Mac48Address::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/mac64-address.cc ns-3.46/src/network/utils/mac64-address.cc
--- ns-3.45/src/network/utils/mac64-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/mac64-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -83,7 +83,8 @@
     return address.CheckCompatible(GetType(), 8);
 }
 
-Mac64Address::operator Address() const
+Mac64Address::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/mac8-address.cc ns-3.46/src/network/utils/mac8-address.cc
--- ns-3.45/src/network/utils/mac8-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/mac8-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -56,7 +56,8 @@
     return address.CheckCompatible(GetType(), 1);
 }
 
-Mac8Address::operator Address() const
+Mac8Address::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/packet-burst.cc ns-3.46/src/network/utils/packet-burst.cc
--- ns-3.45/src/network/utils/packet-burst.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/packet-burst.cc	2025-10-01 18:46:32.000000000 -0700
@@ -11,8 +11,8 @@
 #include "ns3/log.h"
 #include "ns3/packet.h"
 
+#include <cstdint>
 #include <list>
-#include <stdint.h>
 
 namespace ns3
 {
@@ -56,7 +56,7 @@
 PacketBurst::Copy() const
 {
     NS_LOG_FUNCTION(this);
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
+    Ptr<PacketBurst> burst = CreateObject<PacketBurst>();
 
     for (auto iter = m_packets.begin(); iter != m_packets.end(); ++iter)
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/packet-socket-address.cc ns-3.46/src/network/utils/packet-socket-address.cc
--- ns-3.45/src/network/utils/packet-socket-address.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/packet-socket-address.cc	2025-10-01 18:46:32.000000000 -0700
@@ -78,7 +78,8 @@
     return m_address;
 }
 
-PacketSocketAddress::operator Address() const
+PacketSocketAddress::
+operator Address() const
 {
     return ConvertTo();
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/radiotap-header.cc ns-3.46/src/network/utils/radiotap-header.cc
--- ns-3.45/src/network/utils/radiotap-header.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/radiotap-header.cc	2025-10-01 18:46:32.000000000 -0700
@@ -56,13 +56,13 @@
 {
     NS_LOG_FUNCTION(this << &start);
 
-    start.WriteU8(0);          // major version of radiotap header
-    start.WriteU8(0);          // pad field
-    start.WriteU16(m_length);  // entire length of radiotap data + header
-    start.WriteU32(m_present); // bits describing which fields follow header
-    if (m_presentExt)
+    start.WriteU8(0);         // major version of radiotap header
+    start.WriteU8(0);         // pad field
+    start.WriteU16(m_length); // entire length of radiotap data + header
+    NS_ASSERT(!m_present.empty());
+    for (const auto present : m_present)
     {
-        start.WriteU32(*m_presentExt); // extended bitmasks
+        start.WriteU32(present); // bits describing which fields follow header
     }
 
     //
@@ -70,16 +70,16 @@
     // arrived at the MAC)
     // Reference: https://www.radiotap.org/fields/TSFT.html
     //
-    if (m_present & RADIOTAP_TSFT) // bit 0
+    if (m_present.at(0) & RADIOTAP_TSFT) // bit 0
     {
-        start.WriteU64(m_tsft);
+        SerializeTsft(start);
     }
 
     //
     // Properties of transmitted and received frames.
     // Reference: https://www.radiotap.org/fields/Flags.html
     //
-    if (m_present & RADIOTAP_FLAGS) // bit 1
+    if (m_present.at(0) & RADIOTAP_FLAGS) // bit 1
     {
         start.WriteU8(m_flags);
     }
@@ -88,7 +88,7 @@
     // TX/RX data rate in units of 500 kbps
     // Reference: https://www.radiotap.org/fields/Rate.html
     //
-    if (m_present & RADIOTAP_RATE) // bit 2
+    if (m_present.at(0) & RADIOTAP_RATE) // bit 2
     {
         start.WriteU8(m_rate);
     }
@@ -97,7 +97,7 @@
     // Tx/Rx frequency in MHz, followed by flags.
     // Reference: https://www.radiotap.org/fields/Channel.html
     //
-    if (m_present & RADIOTAP_CHANNEL) // bit 3
+    if (m_present.at(0) & RADIOTAP_CHANNEL) // bit 3
     {
         SerializeChannel(start);
     }
@@ -107,9 +107,9 @@
     // still need to account for it.
     // Reference: https://www.radiotap.org/fields/FHSS.html
     //
-    if (m_present & RADIOTAP_FHSS) // bit 4
+    if (m_present.at(0) & RADIOTAP_FHSS) // bit 4
     {
-        start.WriteU8(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -117,7 +117,7 @@
     // reference.
     // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
     //
-    if (m_present & RADIOTAP_DBM_ANTSIGNAL) // bit 5
+    if (m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL) // bit 5
     {
         start.WriteU8(m_antennaSignal);
     }
@@ -127,7 +127,7 @@
     // reference.
     // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
     //
-    if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
+    if (m_present.at(0) & RADIOTAP_DBM_ANTNOISE) // bit 6
     {
         start.WriteU8(m_antennaNoise);
     }
@@ -136,9 +136,9 @@
     // Quality of Barker code lock.
     // Reference: https://www.radiotap.org/fields/Lock%20quality.html
     //
-    if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
+    if (m_present.at(0) & RADIOTAP_LOCK_QUALITY) // bit 7
     {
-        start.WriteU16(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -146,9 +146,9 @@
     // set at factory calibration (0 is max power).
     // Reference: https://www.radiotap.org/fields/TX%20attenuation.html
     //
-    if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
+    if (m_present.at(0) & RADIOTAP_TX_ATTENUATION) // bit 8
     {
-        start.WriteU16(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -156,9 +156,9 @@
     // set at factory calibration (0 is max power).
     // Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
     //
-    if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
+    if (m_present.at(0) & RADIOTAP_DB_TX_ATTENUATION) // bit 9
     {
-        start.WriteU16(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -166,9 +166,9 @@
     // This is the absolute power level measured at the antenna port.
     // Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
     //
-    if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
+    if (m_present.at(0) & RADIOTAP_DBM_TX_POWER) // bit 10
     {
-        start.WriteU8(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -176,43 +176,43 @@
     // The first antenna is antenna 0.
     // Reference: https://www.radiotap.org/fields/Antenna.html
     //
-    if (m_present & RADIOTAP_ANTENNA) // bit 11
+    if (m_present.at(0) & RADIOTAP_ANTENNA) // bit 11
     {
-        start.WriteU8(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
     // Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
     //
-    if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
+    if (m_present.at(0) & RADIOTAP_DB_ANTSIGNAL) // bit 12
     {
-        start.WriteU8(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
     // Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
     //
-    if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
+    if (m_present.at(0) & RADIOTAP_DB_ANTNOISE) // bit 13
     {
-        start.WriteU8(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // Properties of received frames.
     // Reference: https://www.radiotap.org/fields/RX%20flags.html
     //
-    if (m_present & RADIOTAP_RX_FLAGS) // bit 14
+    if (m_present.at(0) & RADIOTAP_RX_FLAGS) // bit 14
     {
-        start.WriteU16(0); // not yet implemented
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // MCS field.
     // Reference: https://www.radiotap.org/fields/MCS.html
     //
-    if (m_present & RADIOTAP_MCS) // bit 19
+    if (m_present.at(0) & RADIOTAP_MCS) // bit 19
     {
         SerializeMcs(start);
     }
@@ -221,7 +221,7 @@
     // A-MPDU Status, information about the received or transmitted A-MPDU.
     // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
     //
-    if (m_present & RADIOTAP_AMPDU_STATUS) // bit 20
+    if (m_present.at(0) & RADIOTAP_AMPDU_STATUS) // bit 20
     {
         SerializeAmpduStatus(start);
     }
@@ -230,7 +230,7 @@
     // Information about the received or transmitted VHT frame.
     // Reference: https://www.radiotap.org/fields/VHT.html
     //
-    if (m_present & RADIOTAP_VHT) // bit 21
+    if (m_present.at(0) & RADIOTAP_VHT) // bit 21
     {
         SerializeVht(start);
     }
@@ -239,7 +239,7 @@
     // HE field.
     // Reference: https://www.radiotap.org/fields/HE.html
     //
-    if (m_present & RADIOTAP_HE) // bit 23
+    if (m_present.at(0) & RADIOTAP_HE) // bit 23
     {
         SerializeHe(start);
     }
@@ -248,7 +248,7 @@
     // HE MU field.
     // Reference: https://www.radiotap.org/fields/HE-MU.html
     //
-    if (m_present & RADIOTAP_HE_MU) // bit 24
+    if (m_present.at(0) & RADIOTAP_HE_MU) // bit 24
     {
         SerializeHeMu(start);
     }
@@ -257,7 +257,7 @@
     // HE MU other user field.
     // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
     //
-    if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25
+    if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER) // bit 25
     {
         SerializeHeMuOtherUser(start);
     }
@@ -266,7 +266,7 @@
     // U-SIG field.
     // Reference: https://www.radiotap.org/fields/U-SIG.html
     //
-    if (m_presentExt && (*m_presentExt & RADIOTAP_USIG)) // bit 33
+    if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG) // bit 33
     {
         SerializeUsig(start);
     }
@@ -275,7 +275,7 @@
     // EHT field.
     // Reference: https://www.radiotap.org/fields/EHT.html
     //
-    if (m_presentExt && (*m_presentExt & RADIOTAP_EHT_SIG)) // bit 34
+    if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG) // bit 34
     {
         SerializeEht(start);
     }
@@ -290,14 +290,15 @@
     NS_ASSERT_MSG(tmp == 0x00, "RadiotapHeader::Deserialize(): Unexpected major version");
     start.ReadU8(); // pad field
 
-    m_length = start.ReadU16();  // entire length of radiotap data + header
-    m_present = start.ReadU32(); // bits describing which fields follow header
-    uint32_t bytesRead = 8;
+    m_length = start.ReadU16();              // entire length of radiotap data + header
+    m_present.emplace_back(start.ReadU32()); // bits describing which fields follow header
+    uint32_t bytesRead = MIN_HEADER_SIZE;
 
-    if (m_present & RADIOTAP_EXT)
+    std::size_t index{0};
+    while (m_present.at(index++) & RADIOTAP_EXT)
     {
-        // If bit 31 of the it_present field is set, an extended it_present bitmask is present.
-        m_presentExt = start.ReadU32();
+        // If bit 31 of the it_present field is set, another it_present bitmask is present.
+        m_present.emplace_back(start.ReadU32());
         bytesRead += 4;
     }
 
@@ -305,17 +306,16 @@
     // Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
     // Reference: https://www.radiotap.org/fields/TSFT.html
     //
-    if (m_present & RADIOTAP_TSFT) // bit 0
+    if (m_present.at(0) & RADIOTAP_TSFT) // bit 0
     {
-        m_tsft = start.ReadU64();
-        bytesRead += 8;
+        bytesRead += DeserializeTsft(start, bytesRead);
     }
 
     //
     // Properties of transmitted and received frames.
     // Reference: https://www.radiotap.org/fields/Flags.html
     //
-    if (m_present & RADIOTAP_FLAGS) // bit 1
+    if (m_present.at(0) & RADIOTAP_FLAGS) // bit 1
     {
         m_flags = start.ReadU8();
         ++bytesRead;
@@ -325,7 +325,7 @@
     // TX/RX data rate in units of 500 kbps
     // Reference: https://www.radiotap.org/fields/Rate.html
     //
-    if (m_present & RADIOTAP_RATE) // bit 2
+    if (m_present.at(0) & RADIOTAP_RATE) // bit 2
     {
         m_rate = start.ReadU8();
         ++bytesRead;
@@ -335,7 +335,7 @@
     // Tx/Rx frequency in MHz, followed by flags.
     // Reference: https://www.radiotap.org/fields/Channel.html
     //
-    if (m_present & RADIOTAP_CHANNEL) // bit 3
+    if (m_present.at(0) & RADIOTAP_CHANNEL) // bit 3
     {
         bytesRead += DeserializeChannel(start, bytesRead);
     }
@@ -345,11 +345,9 @@
     // still need to account for it.
     // Reference: https://www.radiotap.org/fields/FHSS.html
     //
-    if (m_present & RADIOTAP_FHSS) // bit 4
+    if (m_present.at(0) & RADIOTAP_FHSS) // bit 4
     {
-        // not yet implemented
-        start.ReadU8();
-        ++bytesRead;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -357,7 +355,7 @@
     // reference.
     // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
     //
-    if (m_present & RADIOTAP_DBM_ANTSIGNAL) // bit 5
+    if (m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL) // bit 5
     {
         m_antennaSignal = start.ReadU8();
         ++bytesRead;
@@ -368,7 +366,7 @@
     // reference.
     // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
     //
-    if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
+    if (m_present.at(0) & RADIOTAP_DBM_ANTNOISE) // bit 6
     {
         m_antennaNoise = start.ReadU8();
         ++bytesRead;
@@ -378,11 +376,9 @@
     // Quality of Barker code lock.
     // Reference: https://www.radiotap.org/fields/Lock%20quality.html
     //
-    if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
+    if (m_present.at(0) & RADIOTAP_LOCK_QUALITY) // bit 7
     {
-        // not yet implemented
-        start.ReadU16();
-        bytesRead += 2;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -390,11 +386,9 @@
     // set at factory calibration (0 is max power).
     // Reference: https://www.radiotap.org/fields/TX%20attenuation.html
     //
-    if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
+    if (m_present.at(0) & RADIOTAP_TX_ATTENUATION) // bit 8
     {
-        // not yet implemented
-        start.ReadU16();
-        bytesRead += 2;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -402,11 +396,9 @@
     // set at factory calibration (0 is max power).
     // Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
     //
-    if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
+    if (m_present.at(0) & RADIOTAP_DB_TX_ATTENUATION) // bit 9
     {
-        // not yet implemented
-        start.ReadU16();
-        bytesRead += 2;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -414,11 +406,9 @@
     // This is the absolute power level measured at the antenna port.
     // Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
     //
-    if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
+    if (m_present.at(0) & RADIOTAP_DBM_TX_POWER) // bit 10
     {
-        // not yet implemented
-        start.ReadU8();
-        ++bytesRead;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
@@ -426,51 +416,43 @@
     // The first antenna is antenna 0.
     // Reference: https://www.radiotap.org/fields/Antenna.html
     //
-    if (m_present & RADIOTAP_ANTENNA) // bit 11
+    if (m_present.at(0) & RADIOTAP_ANTENNA) // bit 11
     {
-        // not yet implemented
-        start.ReadU8();
-        ++bytesRead;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
     // Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
     //
-    if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
+    if (m_present.at(0) & RADIOTAP_DB_ANTSIGNAL) // bit 12
     {
-        // not yet implemented
-        start.ReadU8();
-        ++bytesRead;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
     // Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
     //
-    if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
+    if (m_present.at(0) & RADIOTAP_DB_ANTNOISE) // bit 13
     {
-        // not yet implemented
-        start.ReadU8();
-        ++bytesRead;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // Properties of received frames.
     // Reference: https://www.radiotap.org/fields/RX%20flags.html
     //
-    if (m_present & RADIOTAP_RX_FLAGS) // bit 14
+    if (m_present.at(0) & RADIOTAP_RX_FLAGS) // bit 14
     {
-        // not yet implemented
-        start.ReadU16();
-        bytesRead += 2;
+        NS_ASSERT(false); // not yet implemented
     }
 
     //
     // MCS field.
     // Reference: https://www.radiotap.org/fields/MCS.html
     //
-    if (m_present & RADIOTAP_MCS) // bit 19
+    if (m_present.at(0) & RADIOTAP_MCS) // bit 19
     {
         bytesRead += DeserializeMcs(start, bytesRead);
     }
@@ -479,7 +461,7 @@
     // A-MPDU Status, information about the received or transmitted A-MPDU.
     // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
     //
-    if (m_present & RADIOTAP_AMPDU_STATUS)
+    if (m_present.at(0) & RADIOTAP_AMPDU_STATUS)
     {
         bytesRead += DeserializeAmpduStatus(start, bytesRead);
     }
@@ -488,7 +470,7 @@
     // Information about the received or transmitted VHT frame.
     // Reference: https://www.radiotap.org/fields/VHT.html
     //
-    if (m_present & RADIOTAP_VHT) // bit 21
+    if (m_present.at(0) & RADIOTAP_VHT) // bit 21
     {
         bytesRead += DeserializeVht(start, bytesRead);
     }
@@ -497,7 +479,7 @@
     // HE field.
     // Reference: https://www.radiotap.org/fields/HE.html
     //
-    if (m_present & RADIOTAP_HE) // bit 23
+    if (m_present.at(0) & RADIOTAP_HE) // bit 23
     {
         bytesRead += DeserializeHe(start, bytesRead);
     }
@@ -506,7 +488,7 @@
     // HE MU field.
     // Reference: https://www.radiotap.org/fields/HE-MU.html
     //
-    if (m_present & RADIOTAP_HE_MU) // bit 24
+    if (m_present.at(0) & RADIOTAP_HE_MU) // bit 24
     {
         bytesRead += DeserializeHeMu(start, bytesRead);
     }
@@ -515,7 +497,7 @@
     // HE MU other user field.
     // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
     //
-    if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25
+    if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER) // bit 25
     {
         bytesRead += DeserializeHeMuOtherUser(start, bytesRead);
     }
@@ -524,7 +506,7 @@
     // U-SIG field.
     // Reference: https://www.radiotap.org/fields/U-SIG.html
     //
-    if (m_presentExt && (*m_presentExt & RADIOTAP_USIG)) // bit 33
+    if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG) // bit 33
     {
         bytesRead += DeserializeUsig(start, bytesRead);
     }
@@ -533,7 +515,7 @@
     // EHT field.
     // Reference: https://www.radiotap.org/fields/EHT.html
     //
-    if (m_presentExt && (*m_presentExt & RADIOTAP_EHT_SIG)) // bit 34
+    if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG) // bit 34
     {
         bytesRead += DeserializeEht(start, bytesRead);
     }
@@ -548,70 +530,104 @@
 {
     NS_LOG_FUNCTION(this << &os);
     os << " tsft=" << m_tsft << " flags=" << std::hex << m_flags << std::dec << " rate=" << +m_rate;
-    if (m_present & RADIOTAP_CHANNEL)
+    if (m_present.at(0) & RADIOTAP_CHANNEL)
     {
         PrintChannel(os);
     }
     os << std::dec << " signal=" << +m_antennaSignal << " noise=" << +m_antennaNoise;
-    if (m_present & RADIOTAP_MCS)
+    if (m_present.at(0) & RADIOTAP_MCS)
     {
         PrintMcs(os);
     }
-    if (m_present & RADIOTAP_AMPDU_STATUS)
+    if (m_present.at(0) & RADIOTAP_AMPDU_STATUS)
     {
         PrintAmpduStatus(os);
     }
-    if (m_present & RADIOTAP_VHT)
+    if (m_present.at(0) & RADIOTAP_VHT)
     {
         PrintVht(os);
     }
-    if (m_present & RADIOTAP_HE)
+    if (m_present.at(0) & RADIOTAP_HE)
     {
         PrintHe(os);
     }
-    if (m_present & RADIOTAP_HE_MU)
+    if (m_present.at(0) & RADIOTAP_HE_MU)
     {
         PrintHeMu(os);
     }
-    if (m_present & RADIOTAP_HE_MU_OTHER_USER)
+    if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER)
     {
         PrintHeMuOtherUser(os);
     }
-    if (m_presentExt && (*m_presentExt & RADIOTAP_USIG))
+    if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG)
     {
         PrintUsig(os);
     }
-    if (m_presentExt && (*m_presentExt & RADIOTAP_EHT_SIG))
+    if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG)
     {
         PrintEht(os);
     }
 }
 
 void
+RadiotapHeader::SetWifiHeader(std::size_t numPresentWords)
+{
+    NS_LOG_FUNCTION(this << numPresentWords);
+    NS_ASSERT_MSG(numPresentWords > 0,
+                  "RadiotapHeader::SetWifiHeader() requires at least one it_present word");
+    NS_ASSERT_MSG(m_length == MIN_HEADER_SIZE,
+                  "RadiotapHeader::SetWifiHeader() should be called before any other Set* method");
+    NS_ASSERT_MSG(m_present.size() == 1, "RadiotapHeader::SetWifiHeader() should be called once");
+    for (std::size_t i = 0; i < (numPresentWords - 1); ++i)
+    {
+        m_present.at(i) |= RADIOTAP_EXT;
+        m_present.emplace_back(0);
+        m_length += sizeof(RadiotapExtFlags);
+    }
+}
+
+void
 RadiotapHeader::SetTsft(uint64_t value)
 {
     NS_LOG_FUNCTION(this << value);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_TSFT), "TSFT radiotap field already present");
-    m_present |= RADIOTAP_TSFT;
-    m_length += 8;
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_TSFT), "TSFT radiotap field already present");
+    m_tsftPad = ((8 - m_length % 8) % 8);
+    m_present.at(0) |= RADIOTAP_TSFT;
+    m_length += 8 + m_tsftPad;
     m_tsft = value;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
 void
+RadiotapHeader::SerializeTsft(Buffer::Iterator& start) const
+{
+    start.WriteU8(0, m_tsftPad);
+    start.WriteU64(m_tsft);
+}
+
+uint32_t
+RadiotapHeader::DeserializeTsft(Buffer::Iterator start, uint32_t bytesRead)
+{
+    m_tsftPad = ((8 - bytesRead % 8) % 8);
+    start.Next(m_tsftPad);
+    m_tsft = start.ReadU64();
+    return sizeof(m_tsft) + m_tsftPad;
+}
+
+void
 RadiotapHeader::SetFrameFlags(uint8_t flags)
 {
     NS_LOG_FUNCTION(this << +flags);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_FLAGS), "Flags radiotap field already present");
-    m_present |= RADIOTAP_FLAGS;
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_FLAGS), "Flags radiotap field already present");
+    m_present.at(0) |= RADIOTAP_FLAGS;
     m_length += 1;
     m_flags = flags;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -620,12 +636,12 @@
 {
     NS_LOG_FUNCTION(this << +rate);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_RATE), "Rate radiotap field already present");
-    m_present |= RADIOTAP_RATE;
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_RATE), "Rate radiotap field already present");
+    m_present.at(0) |= RADIOTAP_RATE;
     m_length += 1;
     m_rate = rate;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -634,13 +650,13 @@
 {
     NS_LOG_FUNCTION(this << channelFields.frequency << channelFields.flags);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_CHANNEL), "Channel radiotap field already present");
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_CHANNEL), "Channel radiotap field already present");
     m_channelPad = ((2 - m_length % 2) % 2);
-    m_present |= RADIOTAP_CHANNEL;
+    m_present.at(0) |= RADIOTAP_CHANNEL;
     m_length += (sizeof(ChannelFields) + m_channelPad);
     m_channelFields = channelFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -674,9 +690,9 @@
 {
     NS_LOG_FUNCTION(this << signal);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_DBM_ANTSIGNAL),
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL),
                   "Antenna signal radiotap field already present");
-    m_present |= RADIOTAP_DBM_ANTSIGNAL;
+    m_present.at(0) |= RADIOTAP_DBM_ANTSIGNAL;
     m_length += 1;
 
     if (signal > 127)
@@ -692,7 +708,7 @@
         m_antennaSignal = static_cast<int8_t>(floor(signal + 0.5));
     }
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -701,9 +717,9 @@
 {
     NS_LOG_FUNCTION(this << noise);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_DBM_ANTNOISE),
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_DBM_ANTNOISE),
                   "Antenna noise radiotap field already present");
-    m_present |= RADIOTAP_DBM_ANTNOISE;
+    m_present.at(0) |= RADIOTAP_DBM_ANTNOISE;
     m_length += 1;
 
     if (noise > 127.0)
@@ -719,7 +735,7 @@
         m_antennaNoise = static_cast<int8_t>(floor(noise + 0.5));
     }
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -728,12 +744,12 @@
 {
     NS_LOG_FUNCTION(this << +mcsFields.known << +mcsFields.flags << +mcsFields.mcs);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_MCS), "MCS radiotap field already present");
-    m_present |= RADIOTAP_MCS;
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_MCS), "MCS radiotap field already present");
+    m_present.at(0) |= RADIOTAP_MCS;
     m_length += sizeof(McsFields);
     m_mcsFields = mcsFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -766,14 +782,14 @@
 {
     NS_LOG_FUNCTION(this << ampduStatusFields.referenceNumber << ampduStatusFields.flags);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_AMPDU_STATUS),
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_AMPDU_STATUS),
                   "A-MPDU status radiotap field already present");
     m_ampduStatusPad = ((4 - m_length % 4) % 4);
-    m_present |= RADIOTAP_AMPDU_STATUS;
+    m_present.at(0) |= RADIOTAP_AMPDU_STATUS;
     m_length += (sizeof(ampduStatusFields) + m_ampduStatusPad);
     m_ampduStatusFields = ampduStatusFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -813,13 +829,13 @@
                          << +vhtFields.mcsNss.at(3) << +vhtFields.coding << +vhtFields.groupId
                          << +vhtFields.partialAid);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_VHT), "VHT radiotap field already present");
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_VHT), "VHT radiotap field already present");
     m_vhtPad = ((2 - m_length % 2) % 2);
-    m_present |= RADIOTAP_VHT;
+    m_present.at(0) |= RADIOTAP_VHT;
     m_length += (sizeof(VhtFields) + m_vhtPad);
     m_vhtFields = vhtFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -875,13 +891,13 @@
     NS_LOG_FUNCTION(this << heFields.data1 << heFields.data2 << heFields.data3 << heFields.data4
                          << heFields.data5 << heFields.data6);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_HE), "HE radiotap field already present");
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE), "HE radiotap field already present");
     m_hePad = ((2 - m_length % 2) % 2);
-    m_present |= RADIOTAP_HE;
+    m_present.at(0) |= RADIOTAP_HE;
     m_length += (sizeof(heFields) + m_hePad);
     m_heFields = heFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -925,13 +941,13 @@
 {
     NS_LOG_FUNCTION(this << heMuFields.flags1 << heMuFields.flags2);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_HE_MU), "HE-MU radiotap field already present");
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE_MU), "HE-MU radiotap field already present");
     m_heMuPad = ((2 - m_length % 2) % 2);
-    m_present |= RADIOTAP_HE_MU;
+    m_present.at(0) |= RADIOTAP_HE_MU;
     m_length += (sizeof(heMuFields) + m_heMuPad);
     m_heMuFields = heMuFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -983,14 +999,14 @@
                          << +heMuOtherUserFields.perUserPosition
                          << +heMuOtherUserFields.perUserKnown);
 
-    NS_ASSERT_MSG(!(m_present & RADIOTAP_HE_MU_OTHER_USER),
+    NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER),
                   "HE-MU-other-user radiotap field already present");
     m_heMuOtherUserPad = ((2 - m_length % 2) % 2);
-    m_present |= RADIOTAP_HE_MU_OTHER_USER;
+    m_present.at(0) |= RADIOTAP_HE_MU_OTHER_USER;
     m_length += (sizeof(HeMuOtherUserFields) + m_heMuOtherUserPad);
     m_heMuOtherUserFields = heMuOtherUserFields;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
                       << std::dec);
 }
 
@@ -1030,15 +1046,12 @@
 RadiotapHeader::SetUsigFields(const UsigFields& usigFields)
 {
     NS_LOG_FUNCTION(this << usigFields.common << usigFields.mask << usigFields.value);
-    if (!m_presentExt)
-    {
-        m_present |= RADIOTAP_TLV | RADIOTAP_EXT;
-        m_presentExt = 0;
-        m_length += sizeof(RadiotapExtFlags);
-    }
+    NS_ASSERT_MSG(m_present.size() >= 2,
+                  "Number of it_present words (" << m_present.size() << ") is incorrect");
+    m_present.at(0) |= RADIOTAP_TLV;
 
-    NS_ASSERT_MSG(!(*m_presentExt & RADIOTAP_USIG), "U-SIG radiotap field already present");
-    *m_presentExt |= RADIOTAP_USIG;
+    NS_ASSERT_MSG(!(m_present.at(1) & RADIOTAP_USIG), "U-SIG radiotap field already present");
+    m_present.at(1) |= RADIOTAP_USIG;
 
     m_usigTlvPad = ((8 - m_length % 8) % 8);
     m_usigTlv.type = 32 + std::countr_zero<uint16_t>(RADIOTAP_USIG);
@@ -1049,8 +1062,8 @@
     m_usigFields = usigFields;
     m_length += m_usigTlv.length + m_usigPad;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
-                      << " m_presentExt=0x" << *m_presentExt << std::dec);
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present[0]=0x" << std::hex
+                      << m_present.at(0) << " m_present[1]=0x" << m_present.at(1) << std::dec);
 }
 
 void
@@ -1096,15 +1109,12 @@
 RadiotapHeader::SetEhtFields(const EhtFields& ehtFields)
 {
     NS_LOG_FUNCTION(this << ehtFields.known);
-    if (!m_presentExt)
-    {
-        m_present |= RADIOTAP_TLV | RADIOTAP_EXT;
-        m_presentExt = 0;
-        m_length += sizeof(RadiotapExtFlags);
-    }
+    NS_ASSERT_MSG(m_present.size() >= 2,
+                  "Number of it_present words (" << m_present.size() << ") is incorrect");
+    m_present.at(0) |= RADIOTAP_TLV;
 
-    NS_ASSERT_MSG(!(*m_presentExt & RADIOTAP_EHT_SIG), "EHT radiotap field already present");
-    *m_presentExt |= RADIOTAP_EHT_SIG;
+    NS_ASSERT_MSG(!(m_present.at(1) & RADIOTAP_EHT_SIG), "EHT radiotap field already present");
+    m_present.at(1) |= RADIOTAP_EHT_SIG;
 
     m_ehtTlvPad = ((8 - m_length % 8) % 8);
     m_ehtTlv.type = 32 + std::countr_zero<uint16_t>(RADIOTAP_EHT_SIG);
@@ -1115,8 +1125,8 @@
     m_ehtFields = ehtFields;
     m_length += m_ehtTlv.length + m_ehtPad;
 
-    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
-                      << " m_presentExt=0x" << *m_presentExt << std::dec);
+    NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present[0]=0x" << std::hex
+                      << m_present.at(0) << " m_present[1]=0x" << m_present.at(1) << std::dec);
 }
 
 void
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/network/utils/radiotap-header.h ns-3.46/src/network/utils/radiotap-header.h
--- ns-3.45/src/network/utils/radiotap-header.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/network/utils/radiotap-header.h	2025-10-01 18:46:32.000000000 -0700
@@ -83,6 +83,14 @@
     void Print(std::ostream& os) const override;
 
     /**
+     * @brief Set the ieee80211_radiotap_header. This method must be called
+     * before any other Set* method.
+     *
+     * @param numPresentWords Number of it_present words in the radiotap header.
+     */
+    void SetWifiHeader(std::size_t numPresentWords);
+
+    /**
      * @brief Set the Time Synchronization Function Timer (TSFT) value.  Valid for
      * received frames only.
      *
@@ -773,6 +781,25 @@
     void SetEhtFields(const EhtFields& ehtFields);
 
   private:
+    static constexpr int MIN_HEADER_SIZE{8}; //!< the minimum size of the radiotap header
+
+    /**
+     * Serialize the TSFT radiotap header.
+     *
+     * @param start An iterator which points to where the header should be written.
+     */
+    void SerializeTsft(Buffer::Iterator& start) const;
+
+    /**
+     * Deserialize the TSFT radiotap header.
+     *
+     * @param start An iterator which points to where the header should be read.
+     * @param bytesRead the number of bytes already read.
+
+     * @returns The number of bytes read.
+     */
+    uint32_t DeserializeTsft(Buffer::Iterator start, uint32_t bytesRead);
+
     /**
      * Serialize the Channel radiotap header.
      *
@@ -1031,12 +1058,12 @@
         RADIOTAP_EHT_SIG = 0x00000004
     };
 
-    uint16_t m_length{8};                   //!< entire length of radiotap data + header
-    uint32_t m_present{0};                  //!< bits describing which fields follow header
-    std::optional<uint32_t> m_presentExt{}; //!< optional extended present bitmask
+    uint16_t m_length{MIN_HEADER_SIZE}; //!< entire length of radiotap data + header
+    std::vector<uint32_t> m_present{0}; //!< bits describing which fields follow header
 
-    uint64_t m_tsft{0}; //!< Time Synchronization Function Timer (when the first bit of the MPDU
-                        //!< arrived at the MAC)
+    uint8_t m_tsftPad{0}; //!< TSFT padding.
+    uint64_t m_tsft{0};   //!< Time Synchronization Function Timer (when the first bit of the MPDU
+                          //!< arrived at the MAC)
 
     uint8_t m_flags{FRAME_FLAG_NONE}; //!< Properties of transmitted and received frames.
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/olsr/examples/olsr-hna.cc ns-3.46/src/olsr/examples/olsr-hna.cc
--- ns-3.45/src/olsr/examples/olsr-hna.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/olsr/examples/olsr-hna.cc	2025-10-01 18:46:32.000000000 -0700
@@ -237,7 +237,7 @@
     {
         // Create a special Ipv4StaticRouting instance for RoutingTableAssociation
         // Even the Ipv4StaticRouting instance added to list may be used
-        Ptr<Ipv4StaticRouting> hnaEntries = Create<Ipv4StaticRouting>();
+        Ptr<Ipv4StaticRouting> hnaEntries = CreateObject<Ipv4StaticRouting>();
 
         // Add the required routes into the Ipv4StaticRouting Protocol instance
         // and have the node generate HNA messages for all these routes
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/olsr/model/olsr-routing-protocol.cc ns-3.46/src/olsr/model/olsr-routing-protocol.cc
--- ns-3.45/src/olsr/model/olsr-routing-protocol.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/olsr/model/olsr-routing-protocol.cc	2025-10-01 18:46:32.000000000 -0700
@@ -252,7 +252,7 @@
 {
     m_uniformRandomVariable = CreateObject<UniformRandomVariable>();
 
-    m_hnaRoutingTable = Create<Ipv4StaticRouting>();
+    m_hnaRoutingTable = CreateObject<Ipv4StaticRouting>();
 }
 
 RoutingProtocol::~RoutingProtocol()
@@ -3032,6 +3032,7 @@
         NS_LOG_LOGIC("No dynamic route, check network routes");
         if (m_hnaRoutingTable->RouteInput(p, header, idev, ucb, mcb, lcb, ecb))
         {
+            // NOLINTNEXTLINE(readability-simplify-boolean-expr)
             return true;
         }
         else
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/model/channel-condition-model.cc ns-3.46/src/propagation/model/channel-condition-model.cc
--- ns-3.45/src/propagation/model/channel-condition-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/model/channel-condition-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -983,4 +983,4 @@
     return SuburbanRuralLOSProb.at(quantizedElevAngle);
 }
 
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/model/probabilistic-v2v-channel-condition-model.cc ns-3.46/src/propagation/model/probabilistic-v2v-channel-condition-model.cc
--- ns-3.45/src/propagation/model/probabilistic-v2v-channel-condition-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/model/probabilistic-v2v-channel-condition-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -228,4 +228,4 @@
     return pNlos;
 }
 
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/model/propagation-loss-model.cc ns-3.46/src/propagation/model/propagation-loss-model.cc
--- ns-3.45/src/propagation/model/propagation-loss-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/model/propagation-loss-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,6 +15,7 @@
 #include "ns3/double.h"
 #include "ns3/log.h"
 #include "ns3/mobility-model.h"
+#include "ns3/node.h"
 #include "ns3/pointer.h"
 #include "ns3/string.h"
 
@@ -863,7 +864,8 @@
 {
     NS_ASSERT(ma && mb);
 
-    MobilityPair p = std::make_pair(ma, mb);
+    uint64_t p = ((uint64_t)ma->GetObject<Node>()->GetId()) << 32 |
+                 ((uint64_t)mb->GetObject<Node>()->GetId());
     auto i = m_loss.find(p);
 
     if (i == m_loss.end())
@@ -886,7 +888,9 @@
                                           Ptr<MobilityModel> a,
                                           Ptr<MobilityModel> b) const
 {
-    auto i = m_loss.find(std::make_pair(a, b));
+    uint64_t p =
+        ((uint64_t)a->GetObject<Node>()->GetId()) << 32 | ((uint64_t)b->GetObject<Node>()->GetId());
+    auto i = m_loss.find(p);
 
     if (i != m_loss.end())
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/model/propagation-loss-model.h ns-3.46/src/propagation/model/propagation-loss-model.h
--- ns-3.45/src/propagation/model/propagation-loss-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/model/propagation-loss-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -734,30 +734,7 @@
 
     double m_default; //!< default loss
 
-    /// Typedef: Mobility models pair
-    typedef std::pair<const Ptr<MobilityModel>, const Ptr<MobilityModel>> MobilityPair;
-
-    /**
-     * @ingroup propagation
-     *
-     * @brief Hasher for a pair of mobility models.
-     */
-    class MobilityPairHasher
-    {
-      public:
-        /**
-         * @brief Get the hash for a MobilityPair.
-         * @param key MobilityPair reference to hash
-         * @return the MobilityPair hash
-         */
-        size_t operator()(const MobilityPair& key) const
-        {
-            return uint64_t(key.first.operator->()) ^ uint64_t(key.second.operator->());
-        }
-    };
-
-    std::unordered_map<MobilityPair, double, MobilityPairHasher>
-        m_loss; //!< Propagation loss between pair of nodes
+    std::unordered_map<uint64_t, double> m_loss; //!< Propagation loss between pair of nodes
 };
 
 /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/model/three-gpp-propagation-loss-model.cc ns-3.46/src/propagation/model/three-gpp-propagation-loss-model.cc
--- ns-3.45/src/propagation/model/three-gpp-propagation-loss-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/model/three-gpp-propagation-loss-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -263,9 +263,6 @@
 
 NS_OBJECT_ENSURE_REGISTERED(ThreeGppPropagationLossModel);
 
-std::function<Ptr<MobilityModel>(Ptr<const MobilityModel>, Ptr<const MobilityModel>)>
-    ThreeGppPropagationLossModel::m_doCalcRxPowerPrologueFunction;
-
 TypeId
 ThreeGppPropagationLossModel::GetTypeId()
 {
@@ -378,19 +375,11 @@
 
 double
 ThreeGppPropagationLossModel::DoCalcRxPower(double txPowerDbm,
-                                            Ptr<MobilityModel> c,
+                                            Ptr<MobilityModel> a,
                                             Ptr<MobilityModel> b) const
 {
     NS_LOG_FUNCTION(this);
 
-    // if there is a prologue function installed, call it and replace the transmitter mobility model
-    auto a = m_doCalcRxPowerPrologueFunction ? m_doCalcRxPowerPrologueFunction(b, c) : c;
-    if (a->GetPosition() != c->GetPosition())
-    {
-        NS_LOG_DEBUG("Prologue function replaced source position "
-                     << c->GetPosition() << " with position " << a->GetPosition());
-    }
-
     // check if the model is initialized
     NS_ASSERT_MSG(m_frequency != 0.0, "First set the centre frequency");
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/model/three-gpp-propagation-loss-model.h ns-3.46/src/propagation/model/three-gpp-propagation-loss-model.h
--- ns-3.45/src/propagation/model/three-gpp-propagation-loss-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/model/three-gpp-propagation-loss-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -75,26 +75,6 @@
      */
     bool IsO2iLowPenetrationLoss(Ptr<const ChannelCondition> cond) const;
 
-    /**
-     * @brief Stop-gap solution for wraparound model
-     *
-     * Stop-gap solution for support of wraparound model in the 5G NR module. This
-     * method was introduced for ns-3.45 but will be removed in a future release once
-     * a more general solution is added elsewhere (most likely in the spectrum channel). The
-     * callback method registered here will be executed at the beginning of DoCalcRxPower, and the
-     * returned pointer to a mobility model will be subsequently used as the (replacement) source
-     * mobility model for the rest of DoCalcRxPower() processing.
-     *
-     * @param prologueFunction Function that receives two mobility models and compute a third, based
-     * on the wrapped position of the second model in respect to the first
-     */
-    static void InstallDoCalcRxPowerPrologueFunction(
-        std::function<Ptr<MobilityModel>(Ptr<const MobilityModel>, Ptr<const MobilityModel>)>
-            prologueFunction)
-    {
-        m_doCalcRxPowerPrologueFunction = prologueFunction;
-    }
-
   private:
     /**
      * Computes the received power by applying the pathloss model described in
@@ -320,10 +300,6 @@
     Ptr<NormalRandomVariable>
         m_normalO2iHighLossVar; //!< a normal random variable for the calculation of 02i high loss,
                                 //!< see TR38.901 Table 7.4.3-2
-
-    /// Optional prologue function that can be used to implement wraparound models
-    static std::function<Ptr<MobilityModel>(Ptr<const MobilityModel>, Ptr<const MobilityModel>)>
-        m_doCalcRxPowerPrologueFunction;
 };
 
 /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/propagation/test/propagation-loss-model-test-suite.cc ns-3.46/src/propagation/test/propagation-loss-model-test-suite.cc
--- ns-3.45/src/propagation/test/propagation-loss-model-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/propagation/test/propagation-loss-model-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -9,6 +9,7 @@
 #include "ns3/constant-position-mobility-model.h"
 #include "ns3/double.h"
 #include "ns3/log.h"
+#include "ns3/node-container.h"
 #include "ns3/propagation-loss-model.h"
 #include "ns3/simulator.h"
 #include "ns3/test.h"
@@ -407,10 +408,12 @@
 void
 MatrixPropagationLossModelTestCase::DoRun()
 {
+    NodeContainer nc(3);
     Ptr<MobilityModel> m[3];
     for (int i = 0; i < 3; ++i)
     {
         m[i] = CreateObject<ConstantPositionMobilityModel>();
+        nc.Get(i)->AggregateObject(m[i]);
     }
 
     MatrixPropagationLossModel loss;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/CMakeLists.txt ns-3.46/src/spectrum/CMakeLists.txt
--- ns-3.45/src/spectrum/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -10,12 +10,13 @@
     model/friis-spectrum-propagation-loss.cc
     model/half-duplex-ideal-phy-signal-parameters.cc
     model/half-duplex-ideal-phy.cc
+    model/hexagonal-wraparound-model.cc
     model/ism-spectrum-value-helper.cc
     model/matrix-based-channel-model.cc
     model/microwave-oven-spectrum-value-helper.cc
-    model/two-ray-spectrum-propagation-loss-model.cc
     model/multi-model-spectrum-channel.cc
     model/non-communicating-net-device.cc
+    model/phased-array-spectrum-propagation-loss-model.cc
     model/single-model-spectrum-channel.cc
     model/spectrum-analyzer.cc
     model/spectrum-channel.cc
@@ -27,15 +28,16 @@
     model/spectrum-model.cc
     model/spectrum-phy.cc
     model/spectrum-propagation-loss-model.cc
-    model/spectrum-transmit-filter.cc
-    model/phased-array-spectrum-propagation-loss-model.cc
     model/spectrum-signal-parameters.cc
+    model/spectrum-transmit-filter.cc
     model/spectrum-value.cc
     model/three-gpp-channel-model.cc
     model/three-gpp-spectrum-propagation-loss-model.cc
     model/trace-fading-loss-model.cc
     model/tv-spectrum-transmitter.cc
+    model/two-ray-spectrum-propagation-loss-model.cc
     model/waveform-generator.cc
+    model/wraparound-model.cc
 )
 
 set(header_files
@@ -50,12 +52,13 @@
     model/friis-spectrum-propagation-loss.h
     model/half-duplex-ideal-phy-signal-parameters.h
     model/half-duplex-ideal-phy.h
+    model/hexagonal-wraparound-model.h
     model/ism-spectrum-value-helper.h
     model/matrix-based-channel-model.h
     model/microwave-oven-spectrum-value-helper.h
-    model/two-ray-spectrum-propagation-loss-model.h
     model/multi-model-spectrum-channel.h
     model/non-communicating-net-device.h
+    model/phased-array-spectrum-propagation-loss-model.h
     model/single-model-spectrum-channel.h
     model/spectrum-analyzer.h
     model/spectrum-channel.h
@@ -67,26 +70,28 @@
     model/spectrum-model.h
     model/spectrum-phy.h
     model/spectrum-propagation-loss-model.h
-    model/spectrum-transmit-filter.h
-    model/phased-array-spectrum-propagation-loss-model.h
     model/spectrum-signal-parameters.h
+    model/spectrum-transmit-filter.h
     model/spectrum-value.h
     model/three-gpp-channel-model.h
     model/three-gpp-spectrum-propagation-loss-model.h
     model/trace-fading-loss-model.h
     model/tv-spectrum-transmitter.h
+    model/two-ray-spectrum-propagation-loss-model.h
     model/waveform-generator.h
-    test/spectrum-test.h
+    model/wraparound-model.h
+    utils/spectrum-test.h
 )
 
 build_lib(
   LIBNAME spectrum
   SOURCE_FILES ${source_files}
   HEADER_FILES ${header_files}
-  LIBRARIES_TO_LINK ${libpropagation}
-                    ${libantenna}
+  LIBRARIES_TO_LINK
+    ${libpropagation}
+    ${libantenna}
+    ${libbuildings}
   TEST_SOURCES
-    test/two-ray-splm-test-suite.cc
     test/spectrum-ideal-phy-test.cc
     test/spectrum-interference-test.cc
     test/spectrum-value-test.cc
@@ -94,4 +99,6 @@
     test/three-gpp-channel-test-suite.cc
     test/tv-helper-distribution-test.cc
     test/tv-spectrum-transmitter-test.cc
+    test/two-ray-splm-test-suite.cc
+    test/wraparound-model-test.cc
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/doc/spectrum.rst ns-3.46/src/spectrum/doc/spectrum.rst
--- ns-3.45/src/spectrum/doc/spectrum.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/doc/spectrum.rst	2025-10-01 18:46:32.000000000 -0700
@@ -64,6 +64,9 @@
 
 * a reference to the transmitting PHY device
 
+* a reference to the transmitting mobility model, which should be used in StartRx
+  instead of retrieving it from PHY in order to wraparound models to work
+
 * a reference to the antenna model used by the transmitting PHY device
   to transmit this signal
 
@@ -140,6 +143,9 @@
 ``SingleModelSpectrumChannel`` and ``MultiModelSpectrumChannel``. They
 both provide this functionality:
 
+ * If a wraparound model is aggregated to the channel, automatically apply it
+   to transmitting nodes.
+
  * Propagation loss modeling, in three forms:
 
    - you can plug models based on ``PropagationLossModel`` on these
@@ -1139,3 +1145,135 @@
    100 GHz. V.15.0.0. (2018-06).
 
 .. [3GPPTR38811] 3GPP. 2018. TR 38.811, Study on New Radio (NR) to support non-terrestrial networks, V15.4.0. (2020-09).
+
+
+Wraparound Models
+=================
+The wrap around mechanism is a simulation technique used in cellular network modeling to eliminate
+edge effects and create a more realistic interference environment. The most common setup used by 3GPP
+is the hexagonal deployment wraparound, which transforms a finite hexagonal cellular cluster into what
+appears to be an infinite network by creating virtual copies of the cluster around the original one.
+
+This also can significantly reduce memory and computational requirements of simulations to achieve similar
+results in respect to interference, avoiding the simulation of additional rings and then filtering only
+central rings with equivalent interference.
+
+WraparoundModel Implementation
+##############################
+When a wraparound model is aggregated to the ``SingleModelSpectrumChannel`` or ``MultiModelSpectrumChannel``,
+the base class ``WraparoundModel`` creates a virtual ``MobilityModel`` for the transmitter, in respect to each
+receiver.
+
+The virtual ``MobilityModel`` is carried via the ``SpectrumSignalParameters`` to the receiver, which
+must use that model to retrieve the transmitter position, ``NodeId`` and buildings related information during ``StartRx``.
+
+The base ``WraparoundModel`` only reuses the existing transmitter mobility model, while its children classes may
+implement different wraparound techniques.
+
+HexagonalWraparoundModel Implementation
+########################################
+
+``HexagonalWraparoundModel`` implements wraparound for the standard cellular network setups using hexagonal clusters,
+and is based on [Panwar]_. Without wraparound, only the central cells experience symmetric interference from all
+directions. Edge cells receive unrealistic interference patterns because they lack neighboring cells on certain sides,
+making their performance data statistically invalid for real-world analysis. The wrap around mechanism addresses
+this "edge effect" problem by ensuring all cells in the simulation experience equivalent interference conditions.
+For this reason, wraparound is mandatory for 5G NR calibration of selected scenarios, as defined in [TR38901]_.
+
+.. figure:: figures/hexagonal-wraparound-cdf-comparison.png
+    :align: center
+    :width: 600
+
+    Ring 1 setup with 7 tri-sector cell clusters, with (orange) and without wraparound (blue),
+    plus ring 3 setup with 19 tri-sector cell clusters without wraparound (green).
+
+Interference with ring 1 and wraparound (orange) is higher than even ring 3 (green). This, in spite
+of only simulating 7 tri-cell clusters of ring 1 versus the 19 clusters of ring 3. The interference of
+both ring 1 with wraparound and ring 3 have much much higher than ring 1 without wraparound (blue).
+As a result, throughput without wraparound is unrealistically high (indicated by lower curves
+shifted to the right). This is confirmed in the following right figure.
+
+.. figure:: figures/hexagonal-wraparound-execution-and-median-thr.png
+    :align: center
+    :width: 800
+
+    Left: Execution times of ring 1 setup with and without wraparound,
+    plus ring 3 setup without wraparound in an AMD Ryzen Threadripper PRO 7965WX.
+    Right: Median throughput of the different configurations.
+
+Since the computational cost of wireless simulations scales quadratically with the number of nodes in the channel,
+we significantly reduce computational costs by cutting the number of simulated clusters. For this particular
+5G-NR outdoor calibration example with different number of rings and wraparound, the speedup of ring 1 with
+wraparound against ring 3 without wraparound is of 6x, for comparable results.
+
+Note: ring 3 simulations without wraparound require the user to manually filtering results to only cells and UEs
+that are part of the ring 1 cell clusters. This is because they suffer first and second tier interference.
+The remaining results for 12 out of 19 cells, and their respective UEs, would be discarded.
+
+The wrap around mechanism operates by creating six additional virtual copies of the original hexagonal cluster,
+positioned symmetrically around the central cluster. It usually follows these steps:
+
+* Virtual Cluster Creation: Six copies of the original cluster are mathematically placed around the central cluster to simulate an infinite grid
+* Distance Calculation: For each signal transmission, the system calculates seven different distances - one to the actual transmitter and six to the virtual transmitter positions
+* Minimum Distance Selection: The shortest distance is used for path loss and signal strength calculations, ensuring realistic propagation effects
+* UE Mobility Handling: When a user device moves to connect with a virtual cell, it's automatically repositioned within the central cluster while maintaining the same relative position to its serving cell (moving UE to central cluster is not currently implemented)
+
+
+.. figure:: figures/hexagonal-wraparound-topology.png
+    :align: center
+    :width: 400
+
+    Virtual cell clusters (white and green) around real cell cluster (red). Virtual distances are shown as dashed arrows.
+    The virtual transmitter position that results in the smallest distance to receiver is used
+    in the virtual mobility model. [`Panwar`_]
+
+The technique is implemented using geometric distance calculations with specific equations for different cluster sizes:
+- ring 3: 19-site clusters: Standard configuration with 2-tier interference (57 cells for tri-sector antennas)
+- ring 1: 7-site clusters: Smaller configuration with 1-tier interference (21 cells for tri-sector antennas)
+- ring 0: 3-site clusters: Minimal configuration for quick testing (9 cells for tri-sector antennas)
+
+Before start transmitting, each site position needs to be registered to the ``HexagonalWraparoundModel`` via
+``AddSitePosition(Vector3D position)``. The number of sites should also be set via ``SetNumSites(uint8_t sites)``.
+Finally, the inter-site distance (ISD) must be set via ``SetSiteDistance(double isd_in_meters)``.
+
+This can be automatically done by hexagonal deployment helpers of LTE and NR, by setting the ``EnableWraparound``
+attribute to true. After setting up the hexagonal deployment, the user should call ``GetWraparoundModel`` method
+of the hexagonal deployment helper, and then aggregate that model to the spectrum channel model.
+
+Caveats and Limitations
+#######################
+
+This implementation does not simply model edge interference in a localized or realistic way.
+Instead, because all signals are routed through higher-layer protocols, the effect resembles
+a "wormhole" model where transmissions can unrealistically appear at distant points in the topology.
+The transmitter itself stays fixed, but its signals may propagate as if emerging from arbitrary locations,
+depending on geometry and inter-site distances.
+
+A side-effect is that mobility and handover do not strictly reflect physical adjacency.
+Simulations may misleadingly suggest a larger or denser deployment, allowing handover not
+just to neighboring cells but also to virtually adjacent ones (including cells that are physically
+on opposite sides of the layout). Plots can therefore be confusing: devices that look widely separated
+in absolute position might be treated as if they were close in virtual space.
+
+The use of virtual mobility inside the spectrum channel models further complicates interpretation.
+Transmitters are treated as if they relocate, and any additional attenuation (such as building
+shadowing modeled through ns-3 propagation loss and buildings modules) is applied even though
+the device itself never actually moved. The buildings themselves are not virtualized,
+but buildings deployed into the non-virtualized topology still affect virtual transmissions.
+
+[Panwar]_ discusses the use of wraparound for mobility models also, such that a
+node that left the physical site boundaries would wormhole around and reappear
+within the site at the mirror location. This means replacing the physical position
+with the virtual position when going out of physical cell areas, so the node stays
+within the physical topology throughout the simulation. This is not currently implemented.
+As such, nodes may appear outside of physical cells, but still are considered as transmitting
+from within the virtual cells.
+
+References
+##########
+
+.. [Panwar] R. S. Panwar and K. M. Sivalingam, "Implementation of wrap
+    around mechanism for system level simulation of LTE cellular
+    networks in NS3," 2017 IEEE 18th International Symposium on
+    A World of Wireless, Mobile and Multimedia Networks (WoWMoM),
+    Macau, 2017, pp. 1-9, doi: 10.1109/WoWMoM.2017.7974289
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/hexagonal-wraparound-model.cc ns-3.46/src/spectrum/model/hexagonal-wraparound-model.cc
--- ns-3.45/src/spectrum/model/hexagonal-wraparound-model.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/spectrum/model/hexagonal-wraparound-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2025 CTTC
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "hexagonal-wraparound-model.h"
+
+#include "ns3/log.h"
+
+#include <algorithm>
+
+constexpr double M_SQRT3 = 1.732050807568877; // sqrt(3)
+
+namespace ns3
+{
+/**
+ * Coefficients used to wraparound a cluster with 7 sites (1 ring)
+ */
+std::vector<Vector2D> WRAPPING_COEFF_CLUSTER7 =
+    {{0.0, 0.0}, {-3.0, 2.0}, {3.0, -2.0}, {-1.5, -2.5}, {1.5, 2.5}, {-4.5, -0.5}, {4.5, 0.5}};
+
+/**
+ * Coefficients used to wraparound a cluster with 19 sites (3 rings)
+ */
+std::vector<Vector2D> WRAPPING_COEFF_CLUSTER19 =
+    {{0.0, 0.0}, {-3.0, -4.0}, {3.0, 4.0}, {-4.5, 3.5}, {4.5, -3.5}, {-7.5, -0.5}, {7.5, 0.5}};
+
+NS_LOG_COMPONENT_DEFINE("HexagonalWraparoundModel");
+
+NS_OBJECT_ENSURE_REGISTERED(HexagonalWraparoundModel);
+
+TypeId
+HexagonalWraparoundModel::GetTypeId()
+{
+    static TypeId tid = TypeId("ns3::HexagonalWraparoundModel")
+                            .SetParent<WraparoundModel>()
+                            .SetGroupName("Spectrum")
+                            .AddConstructor<HexagonalWraparoundModel>();
+    return tid;
+}
+
+HexagonalWraparoundModel::HexagonalWraparoundModel()
+    : m_numSites(1)
+{
+}
+
+HexagonalWraparoundModel::HexagonalWraparoundModel(double isd, size_t numSites)
+    : m_numSites(numSites)
+{
+    SetSiteDistance(isd);
+}
+
+void
+HexagonalWraparoundModel::SetSiteDistance(double isd)
+{
+    m_isd = isd;
+    m_radius = isd / M_SQRT3;
+}
+
+void
+HexagonalWraparoundModel::SetNumSites(uint8_t numSites)
+{
+    NS_ASSERT((numSites == 1) || (numSites == 7) || (numSites == 19));
+    m_numSites = numSites;
+}
+
+void
+HexagonalWraparoundModel::AddSitePosition(const Vector3D& pos)
+{
+    NS_LOG_FUNCTION(this << pos);
+    NS_ASSERT(m_sitePositions.size() < m_numSites);
+    m_sitePositions.push_back(pos);
+}
+
+void
+HexagonalWraparoundModel::SetSitePositions(const std::vector<Vector3D>& positions)
+{
+    NS_ASSERT(positions.size() == m_numSites);
+    m_sitePositions = positions;
+}
+
+double
+HexagonalWraparoundModel::CalculateDistance(const Vector3D& a, const Vector3D& b) const
+{
+    return (a - GetVirtualPosition(b, a)).GetLength();
+}
+
+// Wraparound calculation is based on
+// R. S. Panwar and K. M. Sivalingam, "Implementation of wrap
+// around mechanism for system level simulation of LTE cellular
+// networks in NS3," 2017 IEEE 18th International Symposium on
+// A World of Wireless, Mobile and Multimedia Networks (WoWMoM),
+// Macau, 2017, pp. 1-9, doi: 10.1109/WoWMoM.2017.7974289.
+Vector3D
+HexagonalWraparoundModel::GetSitePosition(const Vector3D& pos) const
+{
+    NS_ASSERT(m_numSites == m_sitePositions.size());
+
+    std::vector<double> virtDists;
+    virtDists.resize(m_numSites);
+    std::transform(m_sitePositions.begin(),
+                   m_sitePositions.end(),
+                   virtDists.begin(),
+                   [&](const Vector3D& sitePos) {
+                       return (this->GetVirtualPosition(pos, sitePos) - sitePos).GetLength();
+                   });
+    auto idx = std::min_element(virtDists.begin(), virtDists.end()) - virtDists.begin();
+    return m_sitePositions[idx];
+}
+
+Vector3D
+HexagonalWraparoundModel::GetVirtualPosition(const Vector3D txPos, const Vector3D rxPos) const
+{
+    NS_ASSERT_MSG((m_numSites == 1) || (m_numSites == 7) || (m_numSites == 19),
+                  "invalid numSites: " << m_numSites);
+
+    if (m_numSites == 1)
+    {
+        return txPos;
+    }
+
+    auto& coeffs = (m_numSites == 7) ? WRAPPING_COEFF_CLUSTER7 : WRAPPING_COEFF_CLUSTER19;
+
+    std::vector<double> virtDists;
+    virtDists.resize(coeffs.size());
+    std::transform(coeffs.begin(), coeffs.end(), virtDists.begin(), [&](const Vector2D& coeff) {
+        Vector3D virtPos2 = txPos;
+        virtPos2.x += coeff.x * m_radius;
+        virtPos2.y += coeff.y * m_isd;
+        return static_cast<double>((virtPos2 - rxPos).GetLength());
+    });
+
+    auto idx = std::min_element(virtDists.begin(), virtDists.end()) - virtDists.begin();
+    Vector3D offset(m_radius * coeffs[idx].x, m_isd * coeffs[idx].y, 0.0);
+    return txPos + offset;
+}
+
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/hexagonal-wraparound-model.h ns-3.46/src/spectrum/model/hexagonal-wraparound-model.h
--- ns-3.45/src/spectrum/model/hexagonal-wraparound-model.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/spectrum/model/hexagonal-wraparound-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2025 CTTC
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef HEXAGONAL_WRAPAROUND_H
+#define HEXAGONAL_WRAPAROUND_H
+
+#include "wraparound-model.h"
+
+#include "ns3/vector.h"
+
+#include <map>
+#include <vector>
+
+namespace ns3
+{
+/**
+ * @ingroup propagation
+ * @brief Hexagonal wraparound model wraps nodes around in space based on an
+ * hexagonal deployment. It is used to determine a virtual position after
+ * wraparound and calculate the distance between a point of reference and
+ * the virtual position.
+ *
+ * This model is used for the hexagonal deployments typical of mobile networks.
+ * It supports rings 0 (1 site), 1 (7 sites) and 3 rings (19 sites).
+ * To use it, set the inter-site distance (isd) and the number of sites.
+ * Then, add the position coordinates of the sites.
+ * All space coordinates in this class and its subclasses are understood
+ * to be meters or meters/s. i.e., they are all metric international units.
+ *
+ * When GetRelativeVirtualPosition (absPos1, absPos2) is called,
+ * the relative position of the absPos2 is calculated respective to the
+ * reference coordinate absPos1, applying the wrapping based on the model
+ * described in:
+ *
+ * R. S. Panwar and K. M. Sivalingam, "Implementation of wrap
+ * around mechanism for system level simulation of LTE cellular
+ * networks in NS3," 2017 IEEE 18th International Symposium on
+ * A World of Wireless, Mobile and Multimedia Networks (WoWMoM),
+ * Macau, 2017, pp. 1-9, doi: 10.1109/WoWMoM.2017.7974289.
+ */
+class HexagonalWraparoundModel : public WraparoundModel
+{
+  public:
+    /**
+     * Register this type with the TypeId system.
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId();
+
+    /**
+     * @brief Default constructor
+     */
+    HexagonalWraparoundModel();
+
+    /**
+     * @brief Constructor
+     * @param isd inter-site distance
+     * @param numSites number of sites
+     */
+    HexagonalWraparoundModel(double isd, size_t numSites);
+
+    /**
+     * @brief Set site distance
+     * @param isd site distance
+     */
+    void SetSiteDistance(double isd);
+
+    /**
+     * @brief Set number of sites
+     * @param numSites number of sites
+     */
+    void SetNumSites(uint8_t numSites);
+
+    /**
+     * @brief Add a site position
+     * @param pos position of a site
+     */
+    void AddSitePosition(const Vector3D& pos);
+
+    /**
+     * @brief Set site positions
+     * @param positions positions of all sites
+     */
+    void SetSitePositions(const std::vector<Vector3D>& positions);
+
+    /**
+     * @brief Calculate the site position
+     * @param pos original position
+     * @return closest cell center based on wraparound distance
+     */
+    Vector3D GetSitePosition(const Vector3D& pos) const;
+
+    /**
+     * @brief Calculate distance after wraparound between two points
+     * @param a position of point a
+     * @param b position of point b
+     * @return wraparound distance between a and b
+     */
+    double CalculateDistance(const Vector3D& a, const Vector3D& b) const;
+    /**
+     * @brief Get virtual position of txPos with respect to rxPos
+     * @param txPos
+     * @param rxPos
+     * @return virtual position of txPos
+     */
+    Vector3D GetVirtualPosition(const Vector3D txPos, const Vector3D rxPos) const override;
+
+  private:
+    double m_isd;                          //!< distance between sites
+    double m_radius;                       //!< site radius
+    uint8_t m_numSites;                    //!< number of sites
+    std::vector<Vector3D> m_sitePositions; //!< site positions
+};
+} // namespace ns3
+
+#endif /* HEXAGONAL_WRAPAROUND_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/multi-model-spectrum-channel.cc ns-3.46/src/spectrum/model/multi-model-spectrum-channel.cc
--- ns-3.45/src/spectrum/model/multi-model-spectrum-channel.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/multi-model-spectrum-channel.cc	2025-10-01 18:46:32.000000000 -0700
@@ -12,6 +12,7 @@
 #include "spectrum-phy.h"
 #include "spectrum-propagation-loss-model.h"
 #include "spectrum-transmit-filter.h"
+#include "wraparound-model.h"
 
 #include "ns3/angles.h"
 #include "ns3/antenna-model.h"
@@ -225,7 +226,9 @@
                                            // potential underlying DynamicCasts)
     m_txSigParamsTrace(txParamsTrace);
 
-    auto txMobility = txParams->txPhy->GetMobility();
+    auto wraparound = GetObject<WraparoundModel>();
+    auto refTxMobility = txParams->txPhy->GetMobility();
+    auto txMobility = refTxMobility;
     const auto txSpectrumModelUid = txParams->psd->GetSpectrumModelUid();
     NS_LOG_LOGIC("txSpectrumModelUid " << txSpectrumModelUid);
 
@@ -321,6 +324,14 @@
 
                 if (txMobility && receiverMobility)
                 {
+                    if (wraparound)
+                    {
+                        // Use virtual mobility model instead
+                        txMobility =
+                            wraparound->GetVirtualMobilityModel(refTxMobility, receiverMobility);
+                    }
+                    rxParams->txMobility = txMobility;
+
                     if (rxParams->txAntenna)
                     {
                         Angles txAngles(receiverMobility->GetPosition(), txMobility->GetPosition());
@@ -413,7 +424,7 @@
         }
     }
 
-    auto txMobility = params->txPhy->GetMobility();
+    auto txMobility = params->txMobility;
     auto rxMobility = receiver->GetMobility();
     if (txMobility && rxMobility)
     {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/single-model-spectrum-channel.cc ns-3.46/src/spectrum/model/single-model-spectrum-channel.cc
--- ns-3.45/src/spectrum/model/single-model-spectrum-channel.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/single-model-spectrum-channel.cc	2025-10-01 18:46:32.000000000 -0700
@@ -11,6 +11,7 @@
 #include "spectrum-phy.h"
 #include "spectrum-propagation-loss-model.h"
 #include "spectrum-transmit-filter.h"
+#include "wraparound-model.h"
 
 #include "ns3/angles.h"
 #include "ns3/antenna-model.h"
@@ -111,7 +112,9 @@
         NS_ASSERT(*(txParams->psd->GetSpectrumModel()) == *m_spectrumModel);
     }
 
-    Ptr<MobilityModel> senderMobility = txParams->txPhy->GetMobility();
+    auto wraparound = GetObject<WraparoundModel>();
+    Ptr<MobilityModel> refSenderMobility = txParams->txPhy->GetMobility();
+    Ptr<MobilityModel> senderMobility = refSenderMobility;
 
     for (auto rxPhyIterator = m_phyList.begin(); rxPhyIterator != m_phyList.end(); ++rxPhyIterator)
     {
@@ -144,6 +147,14 @@
 
             if (senderMobility && receiverMobility)
             {
+                if (wraparound)
+                {
+                    // Use virtual mobility model instead
+                    senderMobility =
+                        wraparound->GetVirtualMobilityModel(refSenderMobility, receiverMobility);
+                }
+                rxParams->txMobility = senderMobility;
+
                 double txAntennaGain = 0;
                 double rxAntennaGain = 0;
                 double propagationGainDb = 0;
@@ -228,7 +239,7 @@
     {
         params->psd =
             m_spectrumPropagationLoss->CalcRxPowerSpectralDensity(params,
-                                                                  params->txPhy->GetMobility(),
+                                                                  params->txMobility,
                                                                   receiver->GetMobility());
     }
     receiver->StartRx(params);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/spectrum-model.cc ns-3.46/src/spectrum/model/spectrum-model.cc
--- ns-3.45/src/spectrum/model/spectrum-model.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/spectrum-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2009 CTTC
  *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/spectrum-signal-parameters.cc ns-3.46/src/spectrum/model/spectrum-signal-parameters.cc
--- ns-3.45/src/spectrum/model/spectrum-signal-parameters.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/spectrum-signal-parameters.cc	2025-10-01 18:46:32.000000000 -0700
@@ -13,6 +13,7 @@
 
 #include "ns3/antenna-model.h"
 #include "ns3/log.h"
+#include "ns3/mobility-model.h"
 
 namespace ns3
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/spectrum-signal-parameters.h ns-3.46/src/spectrum/model/spectrum-signal-parameters.h
--- ns-3.45/src/spectrum/model/spectrum-signal-parameters.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/spectrum-signal-parameters.h	2025-10-01 18:46:32.000000000 -0700
@@ -18,6 +18,7 @@
 class SpectrumPhy;
 class SpectrumValue;
 class AntennaModel;
+class MobilityModel;
 
 /**
  * @ingroup spectrum
@@ -113,6 +114,13 @@
      * the number of TX streams, the number of RBs.
      */
     Ptr<const ComplexMatrixArray> precodingMatrix;
+
+    /**
+     * The transmitter mobility model
+     * This should be used at StartRx instead of retrieving the mobility model directly from the
+     * PHY. This allows wraparound models to replace the real mobility model with a virtual one.
+     */
+    Ptr<MobilityModel> txMobility;
 };
 
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/spectrum-value.cc ns-3.46/src/spectrum/model/spectrum-value.cc
--- ns-3.45/src/spectrum/model/spectrum-value.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/spectrum-value.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2009 CTTC
  *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/three-gpp-channel-model.h ns-3.46/src/spectrum/model/three-gpp-channel-model.h
--- ns-3.45/src/spectrum/model/three-gpp-channel-model.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/model/three-gpp-channel-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -228,21 +228,6 @@
 
     /**
      * Get the parameters needed to apply the channel generation procedure
-     * @param channelCondition the channel condition
-     * @param hBS the height of the BS
-     * @param hUT the height of the UT
-     * @param distance2D the 2D distance between tx and rx
-     * @return the parameters table
-     */
-    NS_DEPRECATED_3_41("Use GetThreeGppTable(const Ptr<const MobilityModel>, const Ptr<const "
-                       "MobilityModel>, Ptr<const ChannelCondition>) instead")
-    Ptr<const ParamsTable> GetThreeGppTable(Ptr<const ChannelCondition> channelCondition,
-                                            double hBS,
-                                            double hUT,
-                                            double distance2D) const;
-
-    /**
-     * Get the parameters needed to apply the channel generation procedure
      * @param aMob the mobility model of node A
      * @param bMob the mobility model of node B
      * @param channelCondition the channel condition
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/wraparound-model.cc ns-3.46/src/spectrum/model/wraparound-model.cc
--- ns-3.45/src/spectrum/model/wraparound-model.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/spectrum/model/wraparound-model.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025 CTTC
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
+ */
+
+#include "wraparound-model.h"
+
+#include "ns3/log.h"
+#include "ns3/mobility-building-info.h"
+#include "ns3/node.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("WraparoundModel");
+NS_OBJECT_ENSURE_REGISTERED(WraparoundModel);
+
+TypeId
+WraparoundModel::GetTypeId()
+{
+    static TypeId tid = TypeId("ns3::WraparoundModel")
+                            .SetParent<Object>()
+                            .SetGroupName("Spectrum")
+                            .AddConstructor<WraparoundModel>();
+    return tid;
+}
+
+Ptr<MobilityModel>
+WraparoundModel::GetVirtualMobilityModel(Ptr<const MobilityModel> tx,
+                                         Ptr<const MobilityModel> rx) const
+{
+    NS_LOG_DEBUG("Transmitter using virtual mobility model. Real position "
+                 << tx->GetPosition() << ", receiver position " << rx->GetPosition()
+                 << ", wrapped position "
+                 << GetVirtualPosition(tx->GetPosition(), rx->GetPosition()) << ".");
+    auto virtualMm = tx->Copy();
+    // Set the transmitter to its virtual position respective to receiver
+    virtualMm->SetPosition(GetVirtualPosition(tx->GetPosition(), rx->GetPosition()));
+
+    // Unidirectionally aggregate NodeId to it, so it can be fetched later by
+    // propagation models
+    auto node = tx->GetObject<Node>();
+    if (node)
+    {
+        virtualMm->UnidirectionalAggregateObject(node);
+    }
+
+    // Some mobility models access building info related to mobility model
+    auto mbi = tx->GetObject<MobilityBuildingInfo>();
+    if (mbi)
+    {
+        virtualMm->UnidirectionalAggregateObject(mbi);
+    }
+    return virtualMm;
+}
+
+Vector3D
+WraparoundModel::GetVirtualPosition(const Vector3D tx, const Vector3D rx) const
+{
+    return tx; // Placeholder, you are supposed to implement whatever wraparound model you want
+}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/model/wraparound-model.h ns-3.46/src/spectrum/model/wraparound-model.h
--- ns-3.45/src/spectrum/model/wraparound-model.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/spectrum/model/wraparound-model.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 CTTC
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
+ */
+
+#ifndef WRAPAROUNDMODEL_H
+#define WRAPAROUNDMODEL_H
+
+#include "ns3/mobility-model.h"
+
+namespace ns3
+{
+class WraparoundModel : public Object
+{
+  public:
+    /**
+     * @brief Default constructor
+     */
+    WraparoundModel() = default;
+
+    /**
+     * Register this type with the TypeId system.
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId();
+
+    /**
+     * @brief Creates a disposable virtual mobility model for tx based on rx distance and
+     * a wraparound model
+     * @param tx Transmitter mobility model
+     * @param rx Receiver Mobility model
+     * @return virtual mobility model for transmitter
+     */
+    Ptr<MobilityModel> GetVirtualMobilityModel(Ptr<const MobilityModel> tx,
+                                               Ptr<const MobilityModel> rx) const;
+    /**
+     * @brief Get virtual position of txPos with respect to rxPos. Each wraparound model
+     * should override this function with their own implementation
+     * @param tx Transmitter position
+     * @param rx Receiver position
+     * @return virtual position of transmitter in respect to receiver position
+     */
+    virtual Vector3D GetVirtualPosition(const Vector3D tx, const Vector3D rx) const;
+};
+} // namespace ns3
+
+#endif // WRAPAROUNDMODEL_H
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/test/spectrum-test.h ns-3.46/src/spectrum/test/spectrum-test.h
--- ns-3.45/src/spectrum/test/spectrum-test.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/test/spectrum-test.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2009 University of Washington
- * Copyright (c) 2011 CTTC
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Nicola Baldo <nbaldo@cttc.es>
- * part of the code copied from test.h
- */
-
-#ifndef SPECTRUM_TEST_H
-#define SPECTRUM_TEST_H
-
-#include "ns3/spectrum-value.h"
-#include "ns3/test.h"
-
-/**
- * @ingroup spectrum
- * @defgroup spectrum-test Spectrum module tests
- */
-
-/**
- * @ingroup spectrum-tests
- *
- * @brief Test if two SpectrumModel instances are equal within a given tolerance.
- *
- * This test compares component-by-component the two SpectrumModel
- * instances; if any pair of components differs by more than the given
- * tolerance, the test fails.
- *
- * @param actual the actual value obtained by the simulator
- * @param expected the expected value obtained by off-line calculations
- * @param tol the tolerance
- * @param msg the message to print if the test fails
- *
- */
-#define NS_TEST_ASSERT_MSG_SPECTRUM_MODEL_EQ_TOL(actual, expected, tol, msg)                       \
-    do                                                                                             \
-    {                                                                                              \
-        auto i = (actual).Begin();                                                                 \
-        auto j = (expected).Begin();                                                               \
-        uint32_t k = 0;                                                                            \
-        while (i != (actual).End() && j != (expected).End())                                       \
-        {                                                                                          \
-            if ((i->fl > j->fl + (tol)) || (i->fl < j->fl - (tol)) || (i->fc > j->fc + (tol)) ||   \
-                (i->fc < j->fc - (tol)) || (i->fh > j->fh + (tol)) || (i->fh < j->fh - (tol)))     \
-            {                                                                                      \
-                ASSERT_ON_FAILURE;                                                                 \
-                std::ostringstream indexStream;                                                    \
-                indexStream << "[" << k << "]";                                                    \
-                std::ostringstream msgStream;                                                      \
-                msgStream << (msg);                                                                \
-                std::ostringstream actualStream;                                                   \
-                actualStream << i->fl << " <-- " << i->fc << " --> " << i->fh;                     \
-                std::ostringstream expectedStream;                                                 \
-                expectedStream << j->fl << " <-- " << j->fc << " --> " << j->fh;                   \
-                ReportTestFailure(std::string(#actual) + indexStream.str() +                       \
-                                      " == " + std::string(#expected) + indexStream.str(),         \
-                                  actualStream.str(),                                              \
-                                  expectedStream.str(),                                            \
-                                  msgStream.str(),                                                 \
-                                  (__FILE__),                                                      \
-                                  (__LINE__));                                                     \
-                CONTINUE_ON_FAILURE;                                                               \
-            }                                                                                      \
-            ++i;                                                                                   \
-            ++j;                                                                                   \
-            ++k;                                                                                   \
-        }                                                                                          \
-        if (i != (actual).End() || j != (expected).End())                                          \
-        {                                                                                          \
-            std::ostringstream msgStream;                                                          \
-            msgStream << (msg);                                                                    \
-            std::ostringstream actualStream;                                                       \
-            actualStream << (i != (actual).End());                                                 \
-            std::ostringstream expectedStream;                                                     \
-            expectedStream << (j != (expected).End());                                             \
-            ReportTestFailure("Bands::iterator == End ()",                                         \
-                              actualStream.str(),                                                  \
-                              expectedStream.str(),                                                \
-                              msgStream.str(),                                                     \
-                              (__FILE__),                                                          \
-                              (__LINE__));                                                         \
-        }                                                                                          \
-    } while (false);
-
-/**
- * @ingroup spectrum-tests
- *
- * @brief Test if two SpectrumValue instances are equal within a given tolerance.
- *
- * This test compares component-by-component the two SpectrumValue
- * instances; if any pair of components differs by more than the given
- * tolerance, the test fails.
- *
- * @param actual the actual value obtained by the simulator
- * @param expected the expected value obtained by off-line calculations
- * @param tol the tolerance
- * @param msg the message to print if the test fails
- *
- */
-#define NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL(actual, expected, tol, msg)                       \
-    do                                                                                             \
-    {                                                                                              \
-        auto i = (actual).ConstValuesBegin();                                                      \
-        auto j = (expected).ConstValuesBegin();                                                    \
-        uint32_t k = 0;                                                                            \
-        while (i != (actual).ConstValuesEnd() && j != (expected).ConstValuesEnd())                 \
-        {                                                                                          \
-            if ((*i) > (*j) + (tol) || (*i) < (*j) - (tol))                                        \
-            {                                                                                      \
-                ASSERT_ON_FAILURE;                                                                 \
-                std::ostringstream indexStream;                                                    \
-                indexStream << "[" << k << "]";                                                    \
-                std::ostringstream msgStream;                                                      \
-                msgStream << msg;                                                                  \
-                std::ostringstream actualStream;                                                   \
-                actualStream << actual;                                                            \
-                std::ostringstream expectedStream;                                                 \
-                expectedStream << expected;                                                        \
-                ReportTestFailure(std::string(#actual) + indexStream.str() +                       \
-                                      " == " + std::string(#expected) + indexStream.str(),         \
-                                  actualStream.str(),                                              \
-                                  expectedStream.str(),                                            \
-                                  msgStream.str(),                                                 \
-                                  __FILE__,                                                        \
-                                  __LINE__);                                                       \
-                CONTINUE_ON_FAILURE;                                                               \
-            }                                                                                      \
-            ++i;                                                                                   \
-            ++j;                                                                                   \
-            ++k;                                                                                   \
-        }                                                                                          \
-        if (i != (actual).ConstValuesEnd() || j != (expected).ConstValuesEnd())                    \
-        {                                                                                          \
-            std::ostringstream msgStream;                                                          \
-            msgStream << (msg);                                                                    \
-            std::ostringstream actualStream;                                                       \
-            actualStream << (i != (actual).ConstValuesEnd());                                      \
-            std::ostringstream expectedStream;                                                     \
-            expectedStream << (j != (expected).ConstValuesEnd());                                  \
-            ReportTestFailure("Values::const_iterator == ConstValuesEnd ()",                       \
-                              actualStream.str(),                                                  \
-                              expectedStream.str(),                                                \
-                              msgStream.str(),                                                     \
-                              (__FILE__),                                                          \
-                              (__LINE__));                                                         \
-        }                                                                                          \
-    } while (false);
-
-#endif // SPECTRUM_TEST_H
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/test/spectrum-value-test.cc ns-3.46/src/spectrum/test/spectrum-value-test.cc
--- ns-3.45/src/spectrum/test/spectrum-value-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/spectrum/test/spectrum-value-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -6,11 +6,10 @@
  * Author: Nicola Baldo <nbaldo@cttc.es>
  */
 
-#include "spectrum-test.h"
-
 #include "ns3/log.h"
 #include "ns3/object.h"
 #include "ns3/spectrum-converter.h"
+#include "ns3/spectrum-test.h"
 #include "ns3/spectrum-value.h"
 #include "ns3/test.h"
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/test/wraparound-model-test.cc ns-3.46/src/spectrum/test/wraparound-model-test.cc
--- ns-3.45/src/spectrum/test/wraparound-model-test.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/spectrum/test/wraparound-model-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2025 CTTC
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
+ */
+
+#include "ns3/boolean.h"
+#include "ns3/config.h"
+#include "ns3/hexagonal-wraparound-model.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/node-container.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/waypoint-mobility-model.h"
+
+using namespace ns3;
+
+/**
+ * @ingroup propagation-test
+ *
+ * @brief Wraparound Model Test
+ */
+class WraparoundModelTest : public TestCase
+{
+  public:
+    /**
+     * Constructor for test case
+     * @param name description of test case
+     * @param numRings number of rings used in the deployment
+     * @param alternativeConfig wraparound is configured manually when false, or via constructor
+     * when true.
+     */
+    WraparoundModelTest(std::string name, int numRings, bool alternativeConfig)
+        : TestCase(name),
+          m_numRings(numRings),
+          m_alternativeConfig(alternativeConfig)
+    {
+    }
+
+  private:
+    int m_numRings;           ///< number of wrings to wraparound
+    bool m_alternativeConfig; ///< indicate whether to configure isd and numSites via constructor or
+                              ///< manually
+  private:
+    void DoRun() override;
+};
+
+size_t
+GetNearestSite(std::vector<Vector3D>& sites, size_t numSites, Vector3D virtualPos)
+{
+    double minDist = std::numeric_limits<double>::max();
+    size_t minSite = 0;
+    for (size_t siteI = 0; siteI < sites.size() && siteI < numSites; siteI++)
+    {
+        auto dist = CalculateDistance(sites.at(siteI), virtualPos);
+        if (dist < minDist)
+        {
+            minDist = dist;
+            minSite = siteI;
+        }
+    }
+    return minSite;
+}
+
+void
+WraparoundModelTest::DoRun()
+{
+    int numSites = 0;
+    switch (m_numRings)
+    {
+    case 0:
+        numSites = 1;
+        break;
+    case 1:
+        numSites = 7;
+        break;
+    case 3:
+        numSites = 19;
+        break;
+    default:
+        NS_TEST_EXPECT_MSG_EQ(false,
+                              true,
+                              "Wraparound does not support " << m_numRings << " rings");
+        break;
+    }
+
+    NodeContainer userNodes(1);
+    NodeContainer siteNodes(numSites);
+
+    MobilityHelper mobilityHelper;
+    mobilityHelper.SetMobilityModel("ns3::ConstantPositionMobilityModel");
+
+    // Site positions
+    // clang-format off
+    std::vector<Vector3D> sitePositions = {
+        Vector3D(    0,     0, 30), // Site 01
+        Vector3D( 1000,     0, 30), // Site 02
+        Vector3D(  500,   866, 30), // Site 03
+        Vector3D( -500,   866, 30), // Site 04
+        Vector3D(-1000,     0, 30), // Site 05
+        Vector3D( -500,  -866, 30), // Site 06
+        Vector3D(  500,  -866, 30), // Site 07
+        Vector3D( 2000,     0, 30), // Site 08
+        Vector3D( 1500,   866, 30), // Site 09
+        Vector3D(  500,  1732, 30), // Site 10
+        Vector3D( -500,  1732, 30), // Site 11
+        Vector3D(-1500,   866, 30), // Site 12
+        Vector3D(-2000,     0, 30), // Site 13
+        Vector3D(-1500,  -866, 30), // Site 14
+        Vector3D( -500, -1732, 30), // Site 15
+        Vector3D(  500, -1732, 30), // Site 16
+        Vector3D( 1500,  -866, 30), // Site 17
+        Vector3D( 1000,  1732, 30), // Site 18
+        Vector3D(-1000,  1732, 30), // Site 19
+    };
+    // clang-format on
+
+    Ptr<HexagonalWraparoundModel> wraparoundModel =
+        m_alternativeConfig ? CreateObject<HexagonalWraparoundModel>()
+                            : CreateObject<HexagonalWraparoundModel>(1000, numSites);
+
+    if (m_alternativeConfig)
+    {
+        wraparoundModel->SetSiteDistance(1000);
+        wraparoundModel->SetNumSites(numSites);
+        auto sitePositionsSlice =
+            std::vector<Vector3D>(sitePositions.begin(), sitePositions.begin() + numSites);
+        wraparoundModel->SetSitePositions(sitePositionsSlice);
+    }
+
+    // Install mobility models
+    mobilityHelper.Install(userNodes);
+    mobilityHelper.Install(siteNodes);
+
+    // Add site positions and wraparound model
+    for (auto i = 0; i < numSites; i++)
+    {
+        auto siteMm = siteNodes.Get(i)->GetObject<MobilityModel>();
+        siteMm->SetPosition(sitePositions.at(i));
+        if (!m_alternativeConfig)
+        {
+            wraparoundModel->AddSitePosition(sitePositions.at(i));
+        }
+    }
+
+    // Retrieve user node mobility to move it around
+    auto userMm = userNodes.Get(0)->GetObject<MobilityModel>();
+
+    // Test cases (target site number, expected UE virtual site, real user position, expected
+    // wrapped position)
+    std::vector<std::tuple<size_t, size_t, Vector3D, Vector3D>> testPoint;
+    // clang-format off
+    switch (m_numRings)
+    {
+    case 3: // Cases involving sites 8-19
+        testPoint.emplace_back( 7,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back( 8,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back( 9,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(10,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(11,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(12,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(13,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(14,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(15,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(16,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(17,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(18,  0, Vector3D(    0,     0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back( 7,  0, Vector3D(  100,     0, 0), Vector3D(  100,     0, 0));
+        testPoint.emplace_back( 8,  0, Vector3D(  500,     0, 0), Vector3D(  500,     0, 0));
+        testPoint.emplace_back( 9,  1, Vector3D( 1000,     0, 0), Vector3D( 1000,     0, 0));
+        testPoint.emplace_back(10,  2, Vector3D( 1000,  1000, 0), Vector3D( 1000,  1000, 0));
+        testPoint.emplace_back(11,  0, Vector3D( -500,     0, 0), Vector3D( -500,     0, 0));
+        testPoint.emplace_back(12,  0, Vector3D(    0,  -500, 0), Vector3D(    0,  -500, 0));
+        testPoint.emplace_back(13,  5, Vector3D(-1000, -1000, 0), Vector3D(-1000, -1000, 0));
+        testPoint.emplace_back(14, 13, Vector3D( 2000, -1000, 0), Vector3D(-2330, -1500, 0));
+        testPoint.emplace_back(15, 16, Vector3D(-1000,  2000, 0), Vector3D( 1598, -1500, 0));
+        testPoint.emplace_back(16, 15, Vector3D( 2000,  2000, 0), Vector3D(  267, -2000, 0));
+        testPoint.emplace_back(17, 10, Vector3D(-2000, -2000, 0), Vector3D( -268,  2000, 0));
+        testPoint.emplace_back(18, 11, Vector3D(-2000,  1500, 0), Vector3D(-2000,  1500, 0));
+        break;
+    case 1: // Cases involving sites 2-7
+        testPoint.emplace_back(1, 0, Vector3D(    0,    0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(2, 0, Vector3D(    0,    0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(3, 0, Vector3D(    0,    0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(4, 0, Vector3D(    0,    0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(5, 0, Vector3D(    0,    0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(6, 0, Vector3D(    0,    0, 0), Vector3D(    0,     0, 0));
+        testPoint.emplace_back(1, 1, Vector3D( 1000,    0, 0), Vector3D( 1000,     0, 0));
+        testPoint.emplace_back(2, 3, Vector3D( 1000, -500, 0), Vector3D( -732,  1500, 0));
+        testPoint.emplace_back(3, 4, Vector3D( 1000,  500, 0), Vector3D(-1598,     0, 0));
+        testPoint.emplace_back(4, 4, Vector3D(-1000,    0, 0), Vector3D(-1000,     0, 0));
+        testPoint.emplace_back(5, 6, Vector3D(-1000,  500, 0), Vector3D(  732, -1500, 0));
+        testPoint.emplace_back(6, 1, Vector3D(-1000, -500, 0), Vector3D( 1598,     0, 0));
+        break;
+    case 0: // Cases involving site 1. No wraparound.
+        testPoint.emplace_back(0, 0, Vector3D(    0,     0, 0), Vector3D(   0,      0, 0));
+        testPoint.emplace_back(0, 0, Vector3D( 1000,  1000, 0), Vector3D( 1000,  1000, 0));
+        testPoint.emplace_back(0, 0, Vector3D( 1000, -1000, 0), Vector3D( 1000, -1000, 0));
+        testPoint.emplace_back(0, 0, Vector3D(-1000,  1000, 0), Vector3D(-1000,  1000, 0));
+        testPoint.emplace_back(0, 0, Vector3D(-1000, -1000, 0), Vector3D(-1000, -1000, 0));
+        testPoint.emplace_back(0, 0, Vector3D( 2000,  2000, 0), Vector3D( 2000,  2000, 0));
+        testPoint.emplace_back(0, 0, Vector3D( 2000, -2000, 0), Vector3D( 2000, -2000, 0));
+        testPoint.emplace_back(0, 0, Vector3D(-2000,  2000, 0), Vector3D(-2000,  2000, 0));
+        testPoint.emplace_back(0, 0, Vector3D(-2000, -2000, 0), Vector3D(-2000, -2000, 0));
+    default:
+        break;
+    }
+    // clang-format on
+
+    for (auto [siteNumber, expectedVirtualUserSite, realUserPos, expectedVirtualPos] : testPoint)
+    {
+        userMm->SetPosition(realUserPos);
+        auto siteMm = siteNodes.Get(siteNumber)->GetObject<MobilityModel>();
+        auto virtualPos =
+            wraparoundModel->GetVirtualPosition(userMm->GetPosition(), siteMm->GetPosition());
+        auto nearestSiteToVirtualUser = GetNearestSite(sitePositions, numSites, virtualPos);
+        NS_TEST_EXPECT_MSG_EQ(nearestSiteToVirtualUser,
+                              expectedVirtualUserSite,
+                              "Virtual position leads to from real site "
+                                  << GetNearestSite(sitePositions, numSites, realUserPos)
+                                  << " to incorrect site " << nearestSiteToVirtualUser);
+        NS_TEST_EXPECT_MSG_LT_OR_EQ(CalculateDistance(virtualPos, expectedVirtualPos),
+                                    5,
+                                    "Expected " << expectedVirtualPos << " and obtained "
+                                                << virtualPos << " virtual positions differ");
+    }
+    // Move user node and check virtual positions correspond to the expected sites
+    Simulator::Stop(MilliSeconds(1));
+    Simulator::Run();
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup propagation-test
+ *
+ * @brief Wraparound Model Test Suite
+ */
+static struct WraparoundModelTestSuite : public TestSuite
+{
+    WraparoundModelTestSuite()
+        : TestSuite("wraparound-model", Type::UNIT)
+    {
+        std::vector<bool> alternativeConfig{false, true};
+        for (auto altConf : alternativeConfig)
+        {
+            // Supported ring numbers
+            AddTestCase(new WraparoundModelTest("Check wraparound with 0 rings", 0, altConf),
+                        TestCase::Duration::QUICK);
+            AddTestCase(new WraparoundModelTest("Check wraparound with 1 rings", 1, altConf),
+                        TestCase::Duration::QUICK);
+            AddTestCase(new WraparoundModelTest("Check wraparound with 3 rings", 3, altConf),
+                        TestCase::Duration::QUICK);
+        }
+    }
+} g_WraparoundModelTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/spectrum/utils/spectrum-test.h ns-3.46/src/spectrum/utils/spectrum-test.h
--- ns-3.45/src/spectrum/utils/spectrum-test.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/spectrum/utils/spectrum-test.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2009 University of Washington
+ * Copyright (c) 2011 CTTC
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ * part of the code copied from test.h
+ */
+
+#ifndef SPECTRUM_TEST_H
+#define SPECTRUM_TEST_H
+
+#include "ns3/spectrum-value.h"
+#include "ns3/test.h"
+
+/**
+ * @ingroup spectrum
+ * @defgroup spectrum-test Spectrum module tests
+ */
+
+/**
+ * @ingroup spectrum-tests
+ *
+ * @brief Test if two SpectrumModel instances are equal within a given tolerance.
+ *
+ * This test compares component-by-component the two SpectrumModel
+ * instances; if any pair of components differs by more than the given
+ * tolerance, the test fails.
+ *
+ * @param actual the actual value obtained by the simulator
+ * @param expected the expected value obtained by off-line calculations
+ * @param tol the tolerance
+ * @param msg the message to print if the test fails
+ *
+ */
+#define NS_TEST_ASSERT_MSG_SPECTRUM_MODEL_EQ_TOL(actual, expected, tol, msg)                       \
+    do                                                                                             \
+    {                                                                                              \
+        auto i = (actual).Begin();                                                                 \
+        auto j = (expected).Begin();                                                               \
+        uint32_t k = 0;                                                                            \
+        while (i != (actual).End() && j != (expected).End())                                       \
+        {                                                                                          \
+            if ((i->fl > j->fl + (tol)) || (i->fl < j->fl - (tol)) || (i->fc > j->fc + (tol)) ||   \
+                (i->fc < j->fc - (tol)) || (i->fh > j->fh + (tol)) || (i->fh < j->fh - (tol)))     \
+            {                                                                                      \
+                ASSERT_ON_FAILURE;                                                                 \
+                std::ostringstream indexStream;                                                    \
+                indexStream << "[" << k << "]";                                                    \
+                std::ostringstream msgStream;                                                      \
+                msgStream << (msg);                                                                \
+                std::ostringstream actualStream;                                                   \
+                actualStream << i->fl << " <-- " << i->fc << " --> " << i->fh;                     \
+                std::ostringstream expectedStream;                                                 \
+                expectedStream << j->fl << " <-- " << j->fc << " --> " << j->fh;                   \
+                ReportTestFailure(std::string(#actual) + indexStream.str() +                       \
+                                      " == " + std::string(#expected) + indexStream.str(),         \
+                                  actualStream.str(),                                              \
+                                  expectedStream.str(),                                            \
+                                  msgStream.str(),                                                 \
+                                  (__FILE__),                                                      \
+                                  (__LINE__));                                                     \
+                CONTINUE_ON_FAILURE;                                                               \
+            }                                                                                      \
+            ++i;                                                                                   \
+            ++j;                                                                                   \
+            ++k;                                                                                   \
+        }                                                                                          \
+        if (i != (actual).End() || j != (expected).End())                                          \
+        {                                                                                          \
+            std::ostringstream msgStream;                                                          \
+            msgStream << (msg);                                                                    \
+            std::ostringstream actualStream;                                                       \
+            actualStream << (i != (actual).End());                                                 \
+            std::ostringstream expectedStream;                                                     \
+            expectedStream << (j != (expected).End());                                             \
+            ReportTestFailure("Bands::iterator == End ()",                                         \
+                              actualStream.str(),                                                  \
+                              expectedStream.str(),                                                \
+                              msgStream.str(),                                                     \
+                              (__FILE__),                                                          \
+                              (__LINE__));                                                         \
+        }                                                                                          \
+    } while (false);
+
+/**
+ * @ingroup spectrum-tests
+ *
+ * @brief Test if two SpectrumValue instances are equal within a given tolerance.
+ *
+ * This test compares component-by-component the two SpectrumValue
+ * instances; if any pair of components differs by more than the given
+ * tolerance, the test fails.
+ *
+ * @param actual the actual value obtained by the simulator
+ * @param expected the expected value obtained by off-line calculations
+ * @param tol the tolerance
+ * @param msg the message to print if the test fails
+ *
+ */
+#define NS_TEST_ASSERT_MSG_SPECTRUM_VALUE_EQ_TOL(actual, expected, tol, msg)                       \
+    do                                                                                             \
+    {                                                                                              \
+        auto i = (actual).ConstValuesBegin();                                                      \
+        auto j = (expected).ConstValuesBegin();                                                    \
+        uint32_t k = 0;                                                                            \
+        while (i != (actual).ConstValuesEnd() && j != (expected).ConstValuesEnd())                 \
+        {                                                                                          \
+            if ((*i) > (*j) + (tol) || (*i) < (*j) - (tol))                                        \
+            {                                                                                      \
+                ASSERT_ON_FAILURE;                                                                 \
+                std::ostringstream indexStream;                                                    \
+                indexStream << "[" << k << "]";                                                    \
+                std::ostringstream msgStream;                                                      \
+                msgStream << msg;                                                                  \
+                std::ostringstream actualStream;                                                   \
+                actualStream << actual;                                                            \
+                std::ostringstream expectedStream;                                                 \
+                expectedStream << expected;                                                        \
+                ReportTestFailure(std::string(#actual) + indexStream.str() +                       \
+                                      " == " + std::string(#expected) + indexStream.str(),         \
+                                  actualStream.str(),                                              \
+                                  expectedStream.str(),                                            \
+                                  msgStream.str(),                                                 \
+                                  __FILE__,                                                        \
+                                  __LINE__);                                                       \
+                CONTINUE_ON_FAILURE;                                                               \
+            }                                                                                      \
+            ++i;                                                                                   \
+            ++j;                                                                                   \
+            ++k;                                                                                   \
+        }                                                                                          \
+        if (i != (actual).ConstValuesEnd() || j != (expected).ConstValuesEnd())                    \
+        {                                                                                          \
+            std::ostringstream msgStream;                                                          \
+            msgStream << (msg);                                                                    \
+            std::ostringstream actualStream;                                                       \
+            actualStream << (i != (actual).ConstValuesEnd());                                      \
+            std::ostringstream expectedStream;                                                     \
+            expectedStream << (j != (expected).ConstValuesEnd());                                  \
+            ReportTestFailure("Values::const_iterator == ConstValuesEnd ()",                       \
+                              actualStream.str(),                                                  \
+                              expectedStream.str(),                                                \
+                              msgStream.str(),                                                     \
+                              (__FILE__),                                                          \
+                              (__LINE__));                                                         \
+        }                                                                                          \
+    } while (false);
+
+#endif // SPECTRUM_TEST_H
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/stats/model/sqlite-output.cc ns-3.46/src/stats/model/sqlite-output.cc
--- ns-3.45/src/stats/model/sqlite-output.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/stats/model/sqlite-output.cc	2025-10-01 18:46:32.000000000 -0700
@@ -22,6 +22,7 @@
 {
     int rc = sqlite3_open(name.c_str(), &m_db);
     NS_ABORT_MSG_UNLESS(rc == SQLITE_OK, "Failed to open DB");
+    sqlite3_busy_timeout(m_db, 100); // set 100 ms timeout for sqlite3 operations
 }
 
 SQLiteOutput::~SQLiteOutput()
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/stats/test/double-probe-test-suite.cc ns-3.46/src/stats/test/double-probe-test-suite.cc
--- ns-3.45/src/stats/test/double-probe-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/stats/test/double-probe-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 // Include a header file from your module to test.
 #include "ns3/double-probe.h"
 #include "ns3/names.h"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/tap-bridge/model/tap-creator.cc ns-3.46/src/tap-bridge/model/tap-creator.cc
--- ns-3.45/src/tap-bridge/model/tap-creator.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/tap-bridge/model/tap-creator.cc	2025-10-01 18:46:32.000000000 -0700
@@ -9,6 +9,7 @@
 #include "ns3/mac48-address.h"
 
 #include <cerrno>
+#include <cstdint>
 #include <cstdlib>
 #include <cstring> // for strerror
 #include <fcntl.h>
@@ -19,7 +20,6 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #include <sstream>
-#include <stdint.h>
 #include <string>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/tap-bridge/model/tap-encode-decode.cc ns-3.46/src/tap-bridge/model/tap-encode-decode.cc
--- ns-3.45/src/tap-bridge/model/tap-encode-decode.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/tap-bridge/model/tap-encode-decode.cc	2025-10-01 18:46:32.000000000 -0700
@@ -4,10 +4,10 @@
  * SPDX-License-Identifier: GPL-2.0-only
  */
 
+#include <cstdint>
 #include <iomanip>
 #include <iostream>
 #include <sstream>
-#include <stdint.h>
 #include <string>
 
 namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/test/CMakeLists.txt ns-3.46/src/test/CMakeLists.txt
--- ns-3.45/src/test/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/test/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -38,6 +38,7 @@
         ns3wifi/wifi-issue-211-test-suite.cc
         ns3wifi/wifi-ac-mapping-test-suite.cc
         ns3wifi/wifi-msdu-aggregator-test-suite.cc
+        # ns3wifi/wifi-mlo-udp-test-suite.cc
     )
   endif()
   if((csma-layout
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/test/traced/traced-callback-typedef-test-suite.cc ns-3.46/src/test/traced/traced-callback-typedef-test-suite.cc
--- ns-3.45/src/test/traced/traced-callback-typedef-test-suite.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/test/traced/traced-callback-typedef-test-suite.cc	2025-10-01 18:46:32.000000000 -0700
@@ -53,6 +53,16 @@
 class TracedCallbackTypedefTestCase : public TestCase
 {
   public:
+    /// @return the TypeId for the callback checkers
+    static TypeId GetCheckerTypeId()
+    {
+        static TypeId tid = TypeId("ns3::TracedCallbackTypedefTestCaseChecker")
+                                .SetParent<Object>()
+                                .SetGroupName("Test")
+                                .HideFromDocumentation();
+        return tid;
+    }
+
     TracedCallbackTypedefTestCase();
 
     ~TracedCallbackTypedefTestCase() override
@@ -268,6 +278,12 @@
     TracedCallback<Ts...> m_cb;
 
   public:
+    /// @return the TypeId for this checker
+    static TypeId GetTypeId()
+    {
+        return TracedCallbackTypedefTestCase::GetCheckerTypeId();
+    }
+
     Checker()
     {
     }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/topology-read/examples/topology-example-sim.cc ns-3.46/src/topology-read/examples/topology-example-sim.cc
--- ns-3.45/src/topology-read/examples/topology-example-sim.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/topology-read/examples/topology-example-sim.cc	2025-10-01 18:46:32.000000000 -0700
@@ -27,13 +27,13 @@
  * Example of TopologyReader: read in a topology in a specified format.
  *
  * This example can be used with the following parameters:
- *   - <tt>--format=Inet --input=src/topology-read/examples/Inet_small_toposample.txt</tt>
- *   - <tt>--format=Inet --input=src/topology-read/examples/Inet_toposample.txt</tt>
- *   - <tt>--format=Orbis --input=src/topology-read/examples/Orbis_toposample.txt</tt>
- *   - <tt>--format=Rocket
- *     --input=src/topology-read/examples/RocketFuel_sample_4755.r0.cch_maps.txt</tt>
- *   - <tt>--format=Rocket
- *     --input=src/topology-read/examples/RocketFuel_toposample_1239_weights.txt</tt>
+ *   - ``--format=Inet --input=src/topology-read/examples/Inet_small_toposample.txt``
+ *   - ``--format=Inet --input=src/topology-read/examples/Inet_toposample.txt``
+ *   - ``--format=Orbis --input=src/topology-read/examples/Orbis_toposample.txt``
+ *   - ``--format=Rocket
+ *     --input=src/topology-read/examples/RocketFuel_sample_4755.r0.cch_maps.txt``
+ *   - ``--format=Rocket
+ *     --input=src/topology-read/examples/RocketFuel_toposample_1239_weights.txt``
  */
 
 using namespace ns3;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/traffic-control/examples/adaptive-red-tests.cc ns-3.46/src/traffic-control/examples/adaptive-red-tests.cc
--- ns-3.45/src/traffic-control/examples/adaptive-red-tests.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/traffic-control/examples/adaptive-red-tests.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2015 NITK Surathkal
  *
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/uan/helper/uan-helper.cc ns-3.46/src/uan/helper/uan-helper.cc
--- ns-3.45/src/uan/helper/uan-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/uan/helper/uan-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -195,4 +195,4 @@
     return (currentStream - stream);
 }
 
-} // end namespace ns3
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/uan/helper/uan-helper.h ns-3.46/src/uan/helper/uan-helper.h
--- ns-3.45/src/uan/helper/uan-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/uan/helper/uan-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -202,6 +202,6 @@
     m_transducer = ObjectFactory(type, std::forward<Ts>(args)...);
 }
 
-} // end namespace ns3
+} // namespace ns3
 
 #endif /* UAN_HELPER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/uan/model/uan-phy-dual.cc ns-3.46/src/uan/model/uan-phy-dual.cc
--- ns-3.45/src/uan/model/uan-phy-dual.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/uan/model/uan-phy-dual.cc	2025-10-01 18:46:32.000000000 -0700
@@ -226,7 +226,7 @@
                             MakeTraceSourceAccessor(&UanPhyDual::m_rxOkLogger),
                             "ns3::UanPhy::TracedCallback")
             .AddTraceSource("RxError",
-                            "A packet was received unsuccessfuly.",
+                            "A packet was received unsuccessfully.",
                             MakeTraceSourceAccessor(&UanPhyDual::m_rxErrLogger),
                             "ns3::UanPhy::TracedCallback")
             .AddTraceSource("Tx",
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/uan/model/uan-phy-dual.h ns-3.46/src/uan/model/uan-phy-dual.h
--- ns-3.45/src/uan/model/uan-phy-dual.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/uan/model/uan-phy-dual.h	2025-10-01 18:46:32.000000000 -0700
@@ -230,7 +230,7 @@
 
     /** A packet was received successfully. */
     ns3::TracedCallback<Ptr<const Packet>, double, UanTxMode> m_rxOkLogger;
-    /** A packet was received unsuccessfuly. */
+    /** A packet was received unsuccessfully. */
     ns3::TracedCallback<Ptr<const Packet>, double, UanTxMode> m_rxErrLogger;
     /** A packet was sent from this Phy. */
     ns3::TracedCallback<Ptr<const Packet>, double, UanTxMode> m_txLogger;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/uan/model/uan-phy-gen.cc ns-3.46/src/uan/model/uan-phy-gen.cc
--- ns-3.45/src/uan/model/uan-phy-gen.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/uan/model/uan-phy-gen.cc	2025-10-01 18:46:32.000000000 -0700
@@ -609,7 +609,7 @@
                             MakeTraceSourceAccessor(&UanPhyGen::m_rxOkLogger),
                             "ns3::UanPhy::TracedCallback")
             .AddTraceSource("RxError",
-                            "A packet was received unsuccessfuly.",
+                            "A packet was received unsuccessfully.",
                             MakeTraceSourceAccessor(&UanPhyGen::m_rxErrLogger),
                             "ns3::UanPhy::TracedCallback")
             .AddTraceSource("Tx",
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/visualizer/model/pyviz.cc ns-3.46/src/visualizer/model/pyviz.cc
--- ns-3.45/src/visualizer/model/pyviz.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/visualizer/model/pyviz.cc	2025-10-01 18:46:32.000000000 -0700
@@ -154,13 +154,6 @@
     Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacRx",
                             MakeCallback(&PyViz::TraceNetDevRxPointToPoint, this));
 
-    // WiMax
-    Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Tx",
-                            MakeCallback(&PyViz::TraceNetDevTxWimax, this));
-
-    Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Rx",
-                            MakeCallback(&PyViz::TraceNetDevRxWimax, this));
-
     // LTE
     Config::ConnectFailSafe("/NodeList/*/DeviceList/*/$ns3::LteNetDevice/Tx",
                             MakeCallback(&PyViz::TraceNetDevTxLte, this));
@@ -631,7 +624,7 @@
     else
     {
         // NS_ASSERT (0);
-        NS_LOG_WARN("Packet has no byte tag; wimax link?");
+        NS_LOG_WARN("Packet has no byte tag");
         uid = packet->GetUid();
     }
 
@@ -797,22 +790,6 @@
 }
 
 void
-PyViz::TraceNetDevTxWimax(std::string context,
-                          Ptr<const Packet> packet,
-                          const Mac48Address& destination)
-{
-    NS_LOG_FUNCTION(context);
-    TraceNetDevTxCommon(context, packet, destination);
-}
-
-void
-PyViz::TraceNetDevRxWimax(std::string context, Ptr<const Packet> packet, const Mac48Address& source)
-{
-    NS_LOG_FUNCTION(context);
-    TraceNetDevRxCommon(context, packet, source);
-}
-
-void
 PyViz::TraceNetDevTxLte(std::string context,
                         Ptr<const Packet> packet,
                         const Mac48Address& destination)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/visualizer/model/pyviz.h ns-3.46/src/visualizer/model/pyviz.h
--- ns-3.45/src/visualizer/model/pyviz.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/visualizer/model/pyviz.h	2025-10-01 18:46:32.000000000 -0700
@@ -393,25 +393,6 @@
     void TraceNetDevRxPointToPoint(std::string context, Ptr<const Packet> packet);
 
     /**
-     * WiMax transmit trace callback function
-     * @param context the context
-     * @param packet the packet
-     * @param destination the destination MAC address
-     */
-    void TraceNetDevTxWimax(std::string context,
-                            Ptr<const Packet> packet,
-                            const Mac48Address& destination);
-    /**
-     * WiMax transmit trace callback function
-     * @param context the context
-     * @param packet the packet
-     * @param source the source MAC address
-     */
-    void TraceNetDevRxWimax(std::string context,
-                            Ptr<const Packet> packet,
-                            const Mac48Address& source);
-
-    /**
      * LTE transmit trace callback function
      * @param context the context
      * @param packet the packet
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/visualizer/visualizer/base.py ns-3.46/src/visualizer/visualizer/base.py
--- ns-3.45/src/visualizer/visualizer/base.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/visualizer/visualizer/base.py	2025-10-01 18:46:32.000000000 -0700
@@ -59,8 +59,6 @@
     ns.BridgeNetDevice: NetDeviceTraits(is_virtual=True),
     ns.LoopbackNetDevice: NetDeviceTraits(is_virtual=True, is_wireless=False),
     ns.MeshPointDevice: NetDeviceTraits(is_virtual=True),
-    ns.SubscriberStationNetDevice: NetDeviceTraits(is_wireless=True),
-    ns.BaseStationNetDevice: NetDeviceTraits(is_wireless=True),
     ns.LteUeNetDevice: NetDeviceTraits(is_wireless=True),
     ns.LteEnbNetDevice: NetDeviceTraits(is_wireless=True),
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/CMakeLists.txt ns-3.46/src/wifi/CMakeLists.txt
--- ns-3.45/src/wifi/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -14,6 +14,7 @@
     helper/wifi-radio-energy-model-helper.cc
     helper/yans-wifi-helper.cc
     helper/wifi-phy-rx-trace-helper.cc
+    helper/wifi-static-setup-helper.cc
     helper/wifi-tx-stats-helper.cc
     model/addba-extension.cc
     model/adhoc-wifi-mac.cc
@@ -137,7 +138,6 @@
     model/wifi-acknowledgment.cc
     model/wifi-assoc-manager.cc
     model/wifi-bandwidth-filter.cc
-    model/wifi-constants.cc
     model/wifi-default-ack-manager.cc
     model/wifi-default-assoc-manager.cc
     model/wifi-default-gcr-manager.cc
@@ -167,11 +167,13 @@
     model/wifi-ru.cc
     model/wifi-spectrum-phy-interface.cc
     model/wifi-spectrum-signal-parameters.cc
+    model/wifi-standard-constants.cc
     model/wifi-standards.cc
     model/wifi-tx-current-model.cc
     model/wifi-tx-parameters.cc
     model/wifi-tx-timer.cc
     model/wifi-tx-vector.cc
+    model/wifi-types.cc
     model/wifi-utils.cc
     model/yans-error-rate-model.cc
     model/yans-wifi-channel.cc
@@ -188,6 +190,7 @@
     helper/wifi-radio-energy-model-helper.h
     helper/yans-wifi-helper.h
     helper/wifi-phy-rx-trace-helper.h
+    helper/wifi-static-setup-helper.h
     helper/wifi-tx-stats-helper.h
     model/addba-extension.h
     model/adhoc-wifi-mac.h
@@ -310,7 +313,6 @@
     model/wifi-acknowledgment.h
     model/wifi-assoc-manager.h
     model/wifi-bandwidth-filter.h
-    model/wifi-constants.h
     model/wifi-default-ack-manager.h
     model/wifi-default-assoc-manager.h
     model/wifi-default-gcr-manager.h
@@ -328,6 +330,7 @@
     model/wifi-mode.h
     model/wifi-mpdu.h
     model/wifi-net-device.h
+    model/wifi-ns3-constants.h
     model/wifi-opt-field.h
     model/wifi-phy-band.h
     model/wifi-phy-common.h
@@ -346,6 +349,7 @@
     model/wifi-ru.h
     model/wifi-spectrum-phy-interface.h
     model/wifi-spectrum-signal-parameters.h
+    model/wifi-standard-constants.h
     model/wifi-standards.h
     model/wifi-tx-current-model.h
     model/wifi-tx-parameters.h
@@ -403,6 +407,8 @@
     test/wifi-retransmit-test.cc
     test/wifi-ru-allocation-test.cc
     test/wifi-channel-switching-test.cc
+    test/wifi-static-emlsr-test.cc
+    test/wifi-static-infra-bss-test.cc
     test/wifi-test.cc
     test/wifi-transmit-mask-test.cc
     test/wifi-txop-test.cc
@@ -411,4 +417,5 @@
     test/wifi-phy-mu-mimo-test.cc
     test/wifi-operating-channel-test.cc
     test/wifi-tx-stats-helper-test.cc
+  GENERATE_EXPORT_HEADER
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/doc/Makefile ns-3.46/src/wifi/doc/Makefile
--- ns-3.45/src/wifi/doc/Makefile	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/doc/Makefile	2025-10-01 18:46:32.000000000 -0700
@@ -1,7 +1,4 @@
-EPSTOPDF = epstopdf
-DIA = dia
-DOT = dot
-CONVERT = convert -density 120
+include $(CURDIR)/../../../doc/sphinx/defines.mk
 
 SOURCE = source
 FIGURES = $(SOURCE)/figures
@@ -64,16 +61,7 @@
 	$(EPSTOPDF) $< -o=$@
 	if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi
 
-
-# You can set these variables from the command line.
-SPHINXOPTS    = -W --keep-going
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = build
-
 # Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
 ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)
 
 .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/doc/source/wifi-user.rst ns-3.46/src/wifi/doc/source/wifi-user.rst
--- ns-3.45/src/wifi/doc/source/wifi-user.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/doc/source/wifi-user.rst	2025-10-01 18:46:32.000000000 -0700
@@ -264,7 +264,7 @@
 
 .. sourcecode:: cpp
 
-  AttributeContainerValue<TupleValue<UintegerValue, UintegerValue, EnumValue, UintegerValue>, ';'> value;
+  WifiPhy::ChannelSettingsValue value;
   value.Set(WifiPhy::ChannelSegments{{38, 40, WIFI_PHY_BAND_5GHZ, 0}});
 
 In both cases, the operating channel will be channel 38 in the 5 GHz band, which
@@ -283,7 +283,7 @@
 
 .. sourcecode:: cpp
 
-  AttributeContainerValue<TupleValue<UintegerValue, UintegerValue, EnumValue, UintegerValue>, ';'> value;
+  WifiPhy::ChannelSettingsValue value;
   value.Set(WifiPhy::ChannelSegments{{38, 40, WIFI_PHY_BAND_5GHZ, 0}});
   YansWifiPhyHelper wifiPhyHelper = YansWifiPhyHelper::Default();
   wifiPhyHelper.Set("ChannelSettings", value);
@@ -1341,6 +1341,66 @@
 
 You can refer an example program in ``src/wifi/examples/wifi-co-trace-example.cc`` on how to use these APIs.
 
+WifiStaticSetupHelper
+=====================
+
+Wi-Fi devices normally exchange management frames over the air to perform association or setup
+various features. In many simulations, users are not interested in the actual exchange of such
+management frames because they want to evaluate the performance of the network when the requested
+features are already established. In such cases, actually exchanging management frames not only
+constitutes a waste of computing resources, but it could also lead to unexpected results due to
+collisions among the required management frames.
+
+The purpose of the ``WifiStaticSetupHelper`` is to statically setup wifi devices at the exact time
+the simulation starts without actually exchanging management frames over the air. Currently, the
+following operations can be statically setup:
+
+* legacy association/ML setup (note that channel scanning is automatically disabled by the helper)
+* establishment of block ack agreements
+* enabling EMLSR mode on EMLSR client links
+
+The ``WifiStaticSetupHelper`` is made of various static functions to perform the operations above,
+which can be called once the installation and configuration of the wifi is completed.
+For example, the following line of code:
+
+.. sourcecode:: cpp
+
+    WifiStaticSetupHelper::SetStaticAssociation(apDev, staDevices);
+
+performs association or ML setup (depending on whether involved devices are single-link or multi-link)
+between the AP ``apDev`` and the non-AP STAs included in the ``staDevices`` container of devices.
+Additionally, the following line of code:
+
+.. sourcecode:: cpp
+
+    WifiStaticSetupHelper::SetStaticBlockAck(apDev, staDev, 0);
+
+establishes a Block Ack agreement for TID 0 between the AP ``apDev`` and the non-AP STA ``staDev``,
+with the AP being the originator and the non-AP STA the recipient.
+
+To enable EMLSR mode on the links specified via the ``EmlsrManager::EmlsrLinkSet`` attribute, the
+following line of code can be used:
+
+.. sourcecode:: cpp
+
+    WifiStaticSetupHelper::SetStaticEmlsr(apDev, staDev);
+
+where ``apDev`` is the AP device and ``staDev`` is the EMLSR client device.
+
+In case wifi devices exchange IPv4 or IPv6 traffic, it is also convenient to statically setup their
+ARP or NDISC cache, so that ARP Request/Response frames do not need to be actually exchanged. This
+can be achieved by calling:
+
+.. sourcecode:: cpp
+
+    NeighborCacheHelper nbCache;
+    nbCache.PopulateNeighborCache();
+
+after assigning IP addresses to the devices in the network.
+
+For an example usage of these static helpers, you can refer to the
+``/examples/wireless/wifi-{ht,vht,he,eht}-network.cc`` example programs.
+
 HT configuration
 ================
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/examples/wifi-bianchi.cc ns-3.46/src/wifi/examples/wifi-bianchi.cc
--- ns-3.45/src/wifi/examples/wifi-bianchi.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/examples/wifi-bianchi.cc	2025-10-01 18:46:32.000000000 -0700
@@ -69,14 +69,14 @@
 std::map<Mac48Address, uint64_t>
     packetsTransmitted; ///< Map that stores the total packets transmitted per STA
 std::map<Mac48Address, uint64_t>
-    psduFailed; ///< Map that stores the total number of unsuccessfuly received PSDUS (for which
+    psduFailed; ///< Map that stores the total number of unsuccessfully received PSDUS (for which
                 ///< the PHY header was successfully received)  per STA (including PSDUs not
                 ///< addressed to that STA)
 std::map<Mac48Address, uint64_t>
     psduSucceeded; ///< Map that stores the total number of successfully received PSDUs per STA
                    ///< (including PSDUs not addressed to that STA)
 std::map<Mac48Address, uint64_t> phyHeaderFailed; ///< Map that stores the total number of
-                                                  ///< unsuccessfuly received PHY headers per STA
+                                                  ///< unsuccessfully received PHY headers per STA
 std::map<Mac48Address, uint64_t>
     rxEventWhileTxing; ///< Map that stores the number of reception events per STA that occurred
                        ///< while PHY was already transmitting a PPDU
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/examples/wifi-manager-example.cc ns-3.46/src/wifi/examples/wifi-manager-example.cc
--- ns-3.45/src/wifi/examples/wifi-manager-example.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/examples/wifi-manager-example.cc	2025-10-01 18:46:32.000000000 -0700
@@ -746,10 +746,7 @@
     NetDeviceContainer serverDevice;
     NetDeviceContainer clientDevice;
 
-    AttributeContainerValue<
-        TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
-        ';'>
-        channelValue;
+    WifiPhy::ChannelSettingsValue channelValue;
 
     WifiMacHelper wifiMac;
     if (infrastructure)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/examples/wifi-test-interference-helper.cc ns-3.46/src/wifi/examples/wifi-test-interference-helper.cc
--- ns-3.45/src/wifi/examples/wifi-test-interference-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/examples/wifi-test-interference-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -81,8 +81,8 @@
         dBm_u txPowerLevelB;   ///< transmit power level B
         uint32_t packetSizeA;  ///< packet size A
         uint32_t packetSizeB;  ///< packet size B
-        uint16_t channelA;     ///< channel number A
-        uint16_t channelB;     ///< channel number B
+        uint8_t channelA;      ///< channel number A
+        uint8_t channelB;      ///< channel number B
         MHz_u widthA;          ///< channel width A
         MHz_u widthB;          ///< channel width B
         WifiStandard standard; ///< standard
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/helper/wifi-helper.cc ns-3.46/src/wifi/helper/wifi-helper.cc
--- ns-3.45/src/wifi/helper/wifi-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/helper/wifi-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,14 +15,17 @@
 #include "ns3/config.h"
 #include "ns3/eht-configuration.h"
 #include "ns3/eht-ppdu.h"
+#include "ns3/frame-capture-model.h"
 #include "ns3/he-configuration.h"
 #include "ns3/ht-configuration.h"
+#include "ns3/interference-helper.h"
 #include "ns3/log.h"
 #include "ns3/mobility-model.h"
 #include "ns3/names.h"
 #include "ns3/net-device-queue-interface.h"
 #include "ns3/obss-pd-algorithm.h"
 #include "ns3/pointer.h"
+#include "ns3/preamble-detection-model.h"
 #include "ns3/qos-txop.h"
 #include "ns3/qos-utils.h"
 #include "ns3/radiotap-header.h"
@@ -30,6 +33,7 @@
 #include "ns3/vht-configuration.h"
 #include "ns3/wifi-mac-queue.h"
 #include "ns3/wifi-mac-trailer.h"
+#include "ns3/wifi-radio-energy-model.h"
 
 #include <bit>
 #include <memory>
@@ -275,14 +279,12 @@
     }
     case PcapHelper::DLT_IEEE802_11_RADIO: {
         Ptr<Packet> p = packet->Copy();
-        RadiotapHeader header;
-        GetRadiotapHeader(header,
-                          p,
-                          channelFreqMhz,
-                          info->device->GetPhy(phyId)->GetPrimary20Index(),
-                          txVector,
-                          aMpdu,
-                          staId);
+        const auto header = GetRadiotapHeader(p,
+                                              channelFreqMhz,
+                                              info->device->GetPhy(phyId)->GetPrimary20Index(),
+                                              txVector,
+                                              aMpdu,
+                                              staId);
         p->AddHeader(header);
         file->Write(Simulator::Now(), p);
         return;
@@ -318,15 +320,13 @@
     }
     case PcapHelper::DLT_IEEE802_11_RADIO: {
         Ptr<Packet> p = packet->Copy();
-        RadiotapHeader header;
-        GetRadiotapHeader(header,
-                          p,
-                          channelFreqMhz,
-                          info->device->GetPhy(phyId)->GetPrimary20Index(),
-                          txVector,
-                          aMpdu,
-                          staId,
-                          signalNoise);
+        const auto header = GetRadiotapHeader(p,
+                                              channelFreqMhz,
+                                              info->device->GetPhy(phyId)->GetPrimary20Index(),
+                                              txVector,
+                                              aMpdu,
+                                              staId,
+                                              signalNoise);
         p->AddHeader(header);
         file->Write(Simulator::Now(), p);
         return;
@@ -336,35 +336,30 @@
     }
 }
 
-void
-WifiPhyHelper::GetRadiotapHeader(RadiotapHeader& header,
-                                 Ptr<Packet> packet,
+RadiotapHeader
+WifiPhyHelper::GetRadiotapHeader(Ptr<Packet> packet,
                                  uint16_t channelFreqMhz,
                                  uint8_t p20Index,
                                  const WifiTxVector& txVector,
                                  MpduInfo aMpdu,
                                  uint16_t staId,
-                                 SignalNoiseDbm signalNoise)
+                                 std::optional<SignalNoiseDbm> signalNoise)
 {
-    header.SetAntennaSignalPower(signalNoise.signal);
-    header.SetAntennaNoisePower(signalNoise.noise);
-    GetRadiotapHeader(header, packet, channelFreqMhz, p20Index, txVector, aMpdu, staId);
-}
+    RadiotapHeader header;
 
-void
-WifiPhyHelper::GetRadiotapHeader(RadiotapHeader& header,
-                                 Ptr<Packet> packet,
-                                 uint16_t channelFreqMhz,
-                                 uint8_t p20Index,
-                                 const WifiTxVector& txVector,
-                                 MpduInfo aMpdu,
-                                 uint16_t staId)
-{
     const auto preamble = txVector.GetPreambleType();
     const auto modClass = txVector.GetModulationClass();
     const auto channelWidth = txVector.GetChannelWidth();
     const auto gi = txVector.GetGuardInterval();
 
+    header.SetWifiHeader(IsEht(preamble) ? 2 : 1);
+
+    if (signalNoise)
+    {
+        header.SetAntennaSignalPower(signalNoise->signal);
+        header.SetAntennaNoisePower(signalNoise->noise);
+    }
+
     header.SetTsft(Simulator::Now().GetMicroSeconds());
 
     uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
@@ -815,6 +810,8 @@
         ehtFields.userInfo.push_back(userInfo);
         header.SetEhtFields(ehtFields);
     }
+
+    return header;
 }
 
 void
@@ -1301,6 +1298,7 @@
     LogComponentEnable("WifiSpectrumPhyInterface", logLevel);
     LogComponentEnable("WifiSpectrumSignalParameters", logLevel);
     LogComponentEnable("WifiSpectrumValueHelper", logLevel);
+    LogComponentEnable("WifiStaticSetupHelper", logLevel);
     LogComponentEnable("WifiTxCurrentModel", logLevel);
     LogComponentEnable("WifiTxParameters", logLevel);
     LogComponentEnable("WifiTxTimer", logLevel);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/helper/wifi-helper.h ns-3.46/src/wifi/helper/wifi-helper.h
--- ns-3.45/src/wifi/helper/wifi-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/helper/wifi-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -20,6 +20,7 @@
 
 #include <functional>
 #include <map>
+#include <optional>
 #include <vector>
 
 namespace ns3
@@ -310,44 +311,25 @@
                                                     uint8_t phyId);
 
     /**
-     * Get the Radiotap header for a transmitted packet.
-     *
-     * @param header the radiotap header to be filled in
-     * @param packet the packet
-     * @param channelFreqMhz the channel frequency
-     * @param p20Index the index of the primary20 channel
-     * @param txVector the TXVECTOR
-     * @param aMpdu the A-MPDU information
-     * @param staId the STA-ID
-     */
-    static void GetRadiotapHeader(RadiotapHeader& header,
-                                  Ptr<Packet> packet,
-                                  uint16_t channelFreqMhz,
-                                  uint8_t p20Index,
-                                  const WifiTxVector& txVector,
-                                  MpduInfo aMpdu,
-                                  uint16_t staId);
-
-    /**
      * Get the Radiotap header for a received packet.
      *
-     * @param header the radiotap header to be filled in
      * @param packet the packet
      * @param channelFreqMhz the channel frequency
      * @param p20Index the index of the primary20 channel
      * @param txVector the TXVECTOR
      * @param aMpdu the A-MPDU information
      * @param staId the STA-ID
-     * @param signalNoise the rx signal and noise information
+     * @param signalNoise the rx signal and noise information (for receiver only)
+     * @return the radiotap header
      */
-    static void GetRadiotapHeader(RadiotapHeader& header,
-                                  Ptr<Packet> packet,
-                                  uint16_t channelFreqMhz,
-                                  uint8_t p20Index,
-                                  const WifiTxVector& txVector,
-                                  MpduInfo aMpdu,
-                                  uint16_t staId,
-                                  SignalNoiseDbm signalNoise);
+    static RadiotapHeader GetRadiotapHeader(
+        Ptr<Packet> packet,
+        uint16_t channelFreqMhz,
+        uint8_t p20Index,
+        const WifiTxVector& txVector,
+        MpduInfo aMpdu,
+        uint16_t staId,
+        std::optional<SignalNoiseDbm> signalNoise = std::nullopt);
 
     /**
      * @brief Enable pcap output the indicated net device.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/helper/wifi-radio-energy-model-helper.h ns-3.46/src/wifi/helper/wifi-radio-energy-model-helper.h
--- ns-3.45/src/wifi/helper/wifi-radio-energy-model-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/helper/wifi-radio-energy-model-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,6 +10,7 @@
 #define WIFI_RADIO_ENERGY_MODEL_HELPER_H
 
 #include "ns3/energy-model-helper.h"
+#include "ns3/wifi-export.h"
 #include "ns3/wifi-radio-energy-model.h"
 
 namespace ns3
@@ -22,7 +23,7 @@
  * This installer installs WifiRadioEnergyModel for only WifiNetDevice objects.
  *
  */
-class WifiRadioEnergyModelHelper : public DeviceEnergyModelHelper
+class WIFI_EXPORT WifiRadioEnergyModelHelper : public DeviceEnergyModelHelper
 {
   public:
     /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/helper/wifi-static-setup-helper.cc ns-3.46/src/wifi/helper/wifi-static-setup-helper.cc
--- ns-3.45/src/wifi/helper/wifi-static-setup-helper.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/helper/wifi-static-setup-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2025
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sharan Naribole <sharan.naribole@gmail.com>
+ */
+
+#include "wifi-static-setup-helper.h"
+
+#include "ns3/adhoc-wifi-mac.h"
+#include "ns3/ap-wifi-mac.h"
+#include "ns3/assert.h"
+#include "ns3/boolean.h"
+#include "ns3/emlsr-manager.h"
+#include "ns3/ht-configuration.h"
+#include "ns3/ht-frame-exchange-manager.h"
+#include "ns3/log.h"
+#include "ns3/mgt-action-headers.h"
+#include "ns3/mgt-headers.h"
+#include "ns3/net-device-container.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/sta-wifi-mac.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-utils.h"
+
+NS_LOG_COMPONENT_DEFINE("WifiStaticSetupHelper");
+
+namespace ns3
+{
+
+void
+WifiStaticSetupHelper::SetStaticAssociation(Ptr<WifiNetDevice> bssDev,
+                                            const NetDeviceContainer& clientDevs)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    for (auto i = clientDevs.Begin(); i != clientDevs.End(); ++i)
+    {
+        auto clientDev = DynamicCast<WifiNetDevice>(*i);
+        NS_ASSERT_MSG(clientDev, "WifiNetDevice expected");
+        SetStaticAssociation(bssDev, clientDev);
+    }
+}
+
+void
+WifiStaticSetupHelper::SetStaticAssociation(Ptr<WifiNetDevice> bssDev, Ptr<WifiNetDevice> clientDev)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    Simulator::ScheduleNow(
+        [=] { WifiStaticSetupHelper::SetStaticAssocPostInit(bssDev, clientDev); });
+}
+
+void
+WifiStaticSetupHelper::SetStaticAssocPostInit(Ptr<WifiNetDevice> bssDev,
+                                              Ptr<WifiNetDevice> clientDev)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    auto clientMac = DynamicCast<StaWifiMac>(clientDev->GetMac());
+    auto apMac = DynamicCast<ApWifiMac>(bssDev->GetMac());
+
+    NS_ABORT_MSG_IF(!apMac || !clientMac, "Invalid static capabilities exchange case");
+    SetStaticAssocPostInit(apMac, clientMac);
+}
+
+void
+WifiStaticSetupHelper::SetStaticAssocPostInit(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    NS_ASSERT_MSG(apMac, "Expected ApWifiMac");
+    NS_ASSERT_MSG(clientMac, "Expected StaWifiMac");
+
+    // disable scanning
+    clientMac->SetAttribute("EnableScanning", BooleanValue(false));
+
+    const auto linkIdMap = GetLinkIdMap(apMac, clientMac);
+    const auto nClientLinks = clientMac->GetNLinks();
+    const auto isMldAssoc = nClientLinks > 1;
+    const auto apMldAddr = apMac->GetAddress();
+    const auto clientMldAddr = clientMac->GetAddress();
+
+    // Swap links at client MAC to match with AP (MLD)
+    clientMac->SwapLinks(linkIdMap);
+    const auto clientLinkIds = clientMac->GetLinkIds();
+    const auto assocLinkId = *clientLinkIds.cbegin();
+    std::optional<MultiLinkElement> apMle;
+    if (isMldAssoc)
+    {
+        apMle = apMac->GetMultiLinkElement(assocLinkId, WIFI_MAC_MGT_BEACON);
+    }
+    std::shared_ptr<CommonInfoBasicMle> mleCommonInfo;
+    for (const auto clientLinkId : clientLinkIds)
+    {
+        // AP Link ID matches with non-AP MLD Link ID after swap operation
+        // using WifiMac::SwapLinks performed above
+        const auto apLinkId = clientLinkId;
+        auto& clientLink = clientMac->GetLink(clientLinkId);
+
+        // Set BSSID
+        auto apLinkAddr = apMac->GetFrameExchangeManager(apLinkId)->GetAddress();
+        clientMac->SetBssid(apLinkAddr, clientLinkId);
+        clientLink.bssid = apLinkAddr;
+        if (!isMldAssoc)
+        {
+            continue;
+        }
+        NS_ASSERT_MSG(apMle.has_value(), "Expected Multi-link Element");
+        if (!mleCommonInfo)
+        {
+            mleCommonInfo = std::make_shared<CommonInfoBasicMle>(apMle->GetCommonInfoBasic());
+        }
+        auto clientManager = clientMac->GetWifiRemoteStationManager(clientLinkId);
+        clientManager->AddStationMleCommonInfo(apLinkAddr, mleCommonInfo);
+    }
+
+    // Association Request
+    auto assocReq = GetAssocReq(clientMac, assocLinkId, isMldAssoc);
+    auto clientLinkAddr = clientMac->GetFrameExchangeManager(assocLinkId)->GetAddress();
+    WifiMacHeader assocReqHdr(WIFI_MAC_MGT_ASSOCIATION_REQUEST);
+    assocReqHdr.SetAddr2(clientLinkAddr);
+    auto assocSuccess = apMac->ReceiveAssocRequest(assocReq, clientLinkAddr, assocLinkId);
+    apMac->ParseReportedStaInfo(assocReq, clientLinkAddr, assocLinkId);
+    NS_ASSERT_MSG(assocSuccess,
+                  "Static Association failed AP: " << apMldAddr << ", STA: " << clientMldAddr);
+
+    // Association Response
+    clientMac->SetState(StaWifiMac::WAIT_ASSOC_RESP);
+    auto assocResp = GetAssocResp(clientLinkAddr, apMac, assocLinkId, isMldAssoc);
+    auto assocRespMacHdr = GetAssocRespMacHdr(clientLinkAddr, apMac, assocLinkId);
+    auto linkIdStaAddrMap = apMac->GetLinkIdStaAddrMap(assocResp, clientLinkAddr, assocLinkId);
+    apMac->SetAid(assocResp, linkIdStaAddrMap);
+    auto packet = Create<Packet>();
+    packet->AddHeader(assocResp);
+    auto mpdu = Create<WifiMpdu>(packet, assocRespMacHdr);
+    clientMac->ReceiveAssocResp(mpdu, assocLinkId);
+
+    // Record Association success in Remote STA manager
+    for (auto clientLinkId : clientLinkIds)
+    {
+        const auto apLinkId = clientLinkId;
+        clientLinkAddr = clientMac->GetFrameExchangeManager(clientLinkId)->GetAddress();
+        apMac->GetWifiRemoteStationManager(apLinkId)->RecordGotAssocTxOk(clientLinkAddr);
+        const auto aid = apMac->GetAssociationId(clientLinkAddr, apLinkId);
+        if (const auto gcrMgr = apMac->GetGcrManager())
+        {
+            const auto extendedCapabilities =
+                apMac->GetWifiRemoteStationManager(apLinkId)->GetStationExtendedCapabilities(
+                    clientLinkAddr);
+            gcrMgr->NotifyStaAssociated(clientLinkAddr,
+                                        extendedCapabilities &&
+                                            (extendedCapabilities->m_robustAvStreaming > 0));
+        }
+        apMac->m_assocLogger(aid, clientLinkAddr);
+    }
+
+    NS_LOG_DEBUG("Assoc success AP addr=" << apMldAddr << ", STA addr=" << clientMldAddr);
+
+    if (isMldAssoc)
+    {
+        // Update TID-to-Link Mapping in MAC queues
+        apMac->ApplyTidLinkMapping(clientMldAddr, WifiDirection::DOWNLINK);
+        clientMac->ApplyTidLinkMapping(apMldAddr, WifiDirection::UPLINK);
+    }
+}
+
+std::map<linkId_t, linkId_t>
+WifiStaticSetupHelper::GetLinkIdMap(Ptr<WifiNetDevice> apDev, Ptr<WifiNetDevice> clientDev)
+{
+    auto apMac = DynamicCast<ApWifiMac>(apDev->GetMac());
+    NS_ASSERT_MSG(apMac, "Expected ApWifiMac");
+    auto clientMac = DynamicCast<StaWifiMac>(clientDev->GetMac());
+    NS_ASSERT_MSG(clientMac, "Expected StaWifiMac");
+    return GetLinkIdMap(apMac, clientMac);
+}
+
+std::map<linkId_t, linkId_t>
+WifiStaticSetupHelper::GetLinkIdMap(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac)
+{
+    NS_ASSERT(apMac && clientMac);
+    const auto nApLinks = apMac->GetNLinks();
+    const auto nClientLinks = clientMac->GetNLinks();
+    // Assumed all links of non-AP MLD need to be associated
+    NS_ASSERT_MSG(
+        nApLinks >= nClientLinks,
+        "Expected AP MLD to have at least the same number of links than non-AP MLD, nApLinks="
+            << nApLinks << ", nClientLinks=" << nClientLinks);
+
+    std::map<linkId_t, linkId_t> linkIdMap{};
+    auto apCandidateLinks = apMac->GetLinkIds();
+
+    for (const auto clientLinkId : clientMac->GetLinkIds())
+    {
+        for (const auto apLinkId : apCandidateLinks)
+        {
+            const auto apPhy = apMac->GetWifiPhy(apLinkId);
+            const auto clientPhy = clientMac->GetWifiPhy(clientLinkId);
+            if (!apPhy || !clientPhy)
+            {
+                continue;
+            }
+            NS_LOG_DEBUG("AP channel: " << apPhy->GetOperatingChannel());
+            NS_LOG_DEBUG("Client channel: " << clientPhy->GetOperatingChannel());
+            const auto isMatch = (apPhy->GetOperatingChannel().GetPrimaryChannel(MHz_u{20}) ==
+                                  clientPhy->GetOperatingChannel().GetPrimaryChannel(MHz_u{20}));
+            NS_LOG_DEBUG("Client Link ID = " << +clientLinkId << ", AP Link ID Candidate="
+                                             << +apLinkId << ", isMatch=" << isMatch);
+            if (isMatch)
+            {
+                linkIdMap[clientLinkId] = apLinkId;
+                break;
+            }
+        }
+
+        NS_ASSERT_MSG(linkIdMap.contains(clientLinkId),
+                      "No matching AP found for STA PHY setting link ID=" << +clientLinkId);
+        apCandidateLinks.erase(linkIdMap.at(clientLinkId));
+    }
+
+    return linkIdMap;
+}
+
+WifiMacHeader
+WifiStaticSetupHelper::GetAssocRespMacHdr(Mac48Address clientLinkAddr,
+                                          Ptr<ApWifiMac> apMac,
+                                          linkId_t apLinkId)
+{
+    WifiMacHeader hdr(WIFI_MAC_MGT_ASSOCIATION_RESPONSE);
+    hdr.SetAddr1(clientLinkAddr);
+    auto apLinkAddr = apMac->GetFrameExchangeManager(apLinkId)->GetAddress();
+    hdr.SetAddr2(apLinkAddr);
+    hdr.SetAddr3(apLinkAddr);
+    return hdr;
+}
+
+MgtAssocResponseHeader
+WifiStaticSetupHelper::GetAssocResp(Mac48Address clientLinkAddr,
+                                    Ptr<ApWifiMac> apMac,
+                                    linkId_t apLinkId,
+                                    bool isMldAssoc)
+{
+    auto assocResp = apMac->GetAssocResp(clientLinkAddr, apLinkId);
+    if (!isMldAssoc)
+    {
+        return assocResp;
+    }
+    auto mle =
+        apMac->GetMultiLinkElement(apLinkId, WIFI_MAC_MGT_ASSOCIATION_RESPONSE, clientLinkAddr);
+    assocResp.Get<MultiLinkElement>() = mle;
+    return assocResp;
+}
+
+MgtAssocRequestHeader
+WifiStaticSetupHelper::GetAssocReq(Ptr<StaWifiMac> clientMac, linkId_t linkId, bool isMldAssoc)
+{
+    auto frame = clientMac->GetAssociationRequest(false, linkId);
+    auto assocReq = std::get<MgtAssocRequestHeader>(frame);
+    if (!isMldAssoc)
+    {
+        return assocReq;
+    }
+
+    auto mle = clientMac->GetBasicMultiLinkElement(false, linkId);
+    assocReq.Get<MultiLinkElement>() = mle;
+    auto& link = clientMac->GetLink(linkId);
+    auto bssid = *link.bssid;
+    auto remoteManager = clientMac->GetWifiRemoteStationManager(linkId);
+    const auto& mldCap = remoteManager->GetStationMldCapabilities(bssid);
+    NS_ASSERT_MSG(mldCap, "Expected MLD Capabilities info for AP MLD");
+    auto apNegSupport = mldCap->get().tidToLinkMappingSupport;
+    if (apNegSupport > 0)
+    {
+        assocReq.Get<TidToLinkMapping>() = clientMac->GetTidToLinkMappingElements(
+            static_cast<WifiTidToLinkMappingNegSupport>(apNegSupport));
+    }
+
+    return assocReq;
+}
+
+void
+WifiStaticSetupHelper::SetStaticBlockAck(Ptr<WifiNetDevice> apDev,
+                                         const NetDeviceContainer& clientDevs,
+                                         const std::set<tid_t>& tids,
+                                         std::optional<Mac48Address> gcrGroupAddr)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    for (auto i = clientDevs.Begin(); i != clientDevs.End(); ++i)
+    {
+        auto clientDev = DynamicCast<WifiNetDevice>(*i);
+        NS_ASSERT_MSG(clientDev, "WifiNetDevice expected");
+        if (!clientDev->GetHtConfiguration())
+        {
+            // Block Ack requires HT support
+            continue;
+        }
+        for (const auto tid : tids)
+        {
+            SetStaticBlockAck(apDev, clientDev, tid, gcrGroupAddr); // Downlink setup
+            SetStaticBlockAck(clientDev, apDev, tid, gcrGroupAddr); // Uplink setup
+        }
+    }
+}
+
+void
+WifiStaticSetupHelper::SetStaticBlockAck(Ptr<WifiNetDevice> originatorDev,
+                                         Ptr<WifiNetDevice> recipientDev,
+                                         tid_t tid,
+                                         std::optional<Mac48Address> gcrGroupAddr)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    Simulator::ScheduleNow(&WifiStaticSetupHelper::SetStaticBlockAckPostInit,
+                           originatorDev,
+                           recipientDev,
+                           tid,
+                           gcrGroupAddr);
+}
+
+void
+WifiStaticSetupHelper::SetStaticBlockAckPostInit(Ptr<WifiNetDevice> originatorDev,
+                                                 Ptr<WifiNetDevice> recipientDev,
+                                                 tid_t tid,
+                                                 std::optional<Mac48Address> gcrGroupAddr)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    // Originator Device
+    const auto originatorMac = originatorDev->GetMac();
+    const auto originatorLinkId = *(originatorMac->GetLinkIds().begin());
+    const auto originatorFem = DynamicCast<HtFrameExchangeManager>(
+        originatorMac->GetFrameExchangeManager(originatorLinkId));
+    NS_ASSERT_MSG(originatorFem, "Block ACK setup requires HT support");
+    const auto originatorBaManager = originatorMac->GetQosTxop(tid)->GetBaManager();
+
+    // Recipient Device
+    const auto recipientMac = recipientDev->GetMac();
+    const auto recipientLinkId = *(recipientMac->GetLinkIds().begin());
+    const auto recipientFem =
+        DynamicCast<HtFrameExchangeManager>(recipientMac->GetFrameExchangeManager(recipientLinkId));
+    NS_ASSERT_MSG(recipientFem, "Block ACK setup requires HT support");
+    const auto recipientBaManager = recipientMac->GetQosTxop(tid)->GetBaManager();
+
+    const auto originatorAddr = GetBaOriginatorAddr(originatorMac, recipientMac);
+    const auto recipientAddr = GetBaRecipientAddr(originatorMac, recipientMac);
+
+    // Early return if BA Agreement already exists
+    if (originatorMac->GetBaAgreementEstablishedAsOriginator(recipientAddr, tid, gcrGroupAddr))
+    {
+        return;
+    }
+
+    // ADDBA Request
+    MgtAddBaRequestHeader reqHdr;
+    reqHdr.SetAmsduSupport(true);
+    reqHdr.SetImmediateBlockAck();
+    reqHdr.SetTid(tid);
+    reqHdr.SetBufferSize(originatorMac->GetMpduBufferSize());
+    reqHdr.SetTimeout(0);
+    reqHdr.SetStartingSequence(0);
+    if (gcrGroupAddr)
+    {
+        reqHdr.SetGcrGroupAddress(gcrGroupAddr.value());
+    }
+
+    // ADDBA Response
+    MgtAddBaResponseHeader respHdr;
+    StatusCode code;
+    code.SetSuccess();
+    respHdr.SetStatusCode(code);
+    respHdr.SetAmsduSupport(true);
+    respHdr.SetImmediateBlockAck();
+    respHdr.SetTid(tid);
+    auto agrBufferSize = std::min(reqHdr.GetBufferSize(), recipientMac->GetMpduBufferSize());
+    respHdr.SetBufferSize(agrBufferSize);
+    respHdr.SetTimeout(0);
+    if (auto gcrGroupAddr = reqHdr.GetGcrGroupAddress())
+    {
+        respHdr.SetGcrGroupAddress(gcrGroupAddr.value());
+    }
+
+    originatorBaManager->CreateOriginatorAgreement(reqHdr, recipientAddr);
+    recipientBaManager->CreateRecipientAgreement(respHdr,
+                                                 originatorAddr,
+                                                 reqHdr.GetStartingSequence(),
+                                                 recipientMac->m_rxMiddle);
+    auto recipientAgr [[maybe_unused]] =
+        recipientBaManager->GetAgreementAsRecipient(originatorAddr,
+                                                    tid,
+                                                    reqHdr.GetGcrGroupAddress());
+    NS_ASSERT_MSG(recipientAgr.has_value(),
+                  "No agreement as recipient found for originator " << originatorAddr << ", TID "
+                                                                    << +tid);
+    originatorBaManager->UpdateOriginatorAgreement(respHdr,
+                                                   recipientAddr,
+                                                   reqHdr.GetStartingSequence());
+    auto originatorAgr [[maybe_unused]] =
+        originatorBaManager->GetAgreementAsOriginator(recipientAddr,
+                                                      tid,
+                                                      reqHdr.GetGcrGroupAddress());
+    NS_ASSERT_MSG(originatorAgr.has_value(),
+                  "No agreement as originator found for recipient " << recipientAddr << ", TID "
+                                                                    << +tid);
+}
+
+Mac48Address
+WifiStaticSetupHelper::GetBaOriginatorAddr(Ptr<WifiMac> originatorMac, Ptr<WifiMac> recipientMac)
+{
+    // Originator is AdhocWifiMac type
+    // FIXME Restricted to single link operation, as AdHocWifiMac does not support multi-link yet
+    if (const auto origAdhoc = DynamicCast<AdhocWifiMac>(originatorMac))
+    {
+        return origAdhoc->GetAddress();
+    }
+
+    // Recipient is AdhocWifiMac type
+    // Return MAC address of link communicating with recipient
+    if (const auto recAdhoc = DynamicCast<AdhocWifiMac>(recipientMac))
+    {
+        const auto origSta = DynamicCast<StaWifiMac>(originatorMac);
+        NS_ASSERT_MSG(origSta, "Expected originator StaWifiMac type");
+        return origSta->GetLocalAddress(recAdhoc->GetAddress());
+    }
+
+    // Infra WLAN case
+    auto isOriginatorClient{true};
+    auto staMac = DynamicCast<StaWifiMac>(originatorMac);
+    if (!staMac)
+    {
+        staMac = DynamicCast<StaWifiMac>(recipientMac);
+        isOriginatorClient = false;
+    }
+    NS_ASSERT_MSG(staMac, "Expected one of the MACs to be StaWifiMac type");
+
+    const auto setupLinks = staMac->GetSetupLinkIds();
+    const auto nSetupLinks = setupLinks.size();
+    if (nSetupLinks != 1)
+    { // Handle cases other than single link association
+        return originatorMac->GetAddress();
+    }
+
+    // Handle case where one device is MLD and other is single link device
+    // Link MAC address to be used for Block ACK agreement
+    // Required for one device to be StaWifiMac type
+    const auto linkId = *(setupLinks.cbegin());
+    if (isOriginatorClient)
+    {
+        const auto fem = originatorMac->GetFrameExchangeManager(linkId);
+        return fem->GetAddress();
+    }
+    else
+    {
+        const auto fem = recipientMac->GetFrameExchangeManager(linkId);
+        return fem->GetBssid();
+    }
+}
+
+Mac48Address
+WifiStaticSetupHelper::GetBaRecipientAddr(Ptr<WifiMac> originatorMac, Ptr<WifiMac> recipientMac)
+{
+    return GetBaOriginatorAddr(recipientMac, originatorMac);
+}
+
+void
+WifiStaticSetupHelper::SetStaticEmlsr(Ptr<WifiNetDevice> apDev, Ptr<WifiNetDevice> clientDev)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    Simulator::ScheduleNow(&WifiStaticSetupHelper::SetStaticEmlsrPostInit, apDev, clientDev);
+}
+
+void
+WifiStaticSetupHelper::SetStaticEmlsrPostInit(Ptr<WifiNetDevice> apDev,
+                                              Ptr<WifiNetDevice> clientDev)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    auto clientMac = DynamicCast<StaWifiMac>(clientDev->GetMac());
+    NS_ASSERT_MSG(clientMac, "Expected StaWifiMac");
+    NS_ASSERT_MSG(clientMac->IsAssociated(), "Expected Association complete");
+    auto setupLinks = clientMac->GetSetupLinkIds();
+
+    if (const auto isMldAssoc = (setupLinks.size() > 1); !isMldAssoc)
+    {
+        NS_LOG_DEBUG("Multi-link setup not performed, skipping EMLSR static setup");
+        return;
+    }
+    if (!clientDev->IsEmlsrActivated())
+    {
+        NS_LOG_DEBUG("Non-AP MLD does not support EMLSR, not performing EMLSR static setup");
+        return;
+    }
+
+    auto emlsrManager = clientMac->GetEmlsrManager();
+    NS_ASSERT_MSG(emlsrManager, "EMLSR Manager not set");
+    emlsrManager->ComputeOperatingChannels();
+    auto emlOmnReq = emlsrManager->GetEmlOmn();
+    auto emlsrLinkId = emlsrManager->GetLinkToSendEmlOmn();
+    emlsrManager->ChangeEmlsrMode();
+    auto clientLinkAddr = clientMac->GetFrameExchangeManager(emlsrLinkId)->GetAddress();
+    auto apMac = DynamicCast<ApWifiMac>(apDev->GetMac());
+    NS_ASSERT_MSG(apMac, "Expected ApWifiMac");
+    apMac->ReceiveEmlOmn(emlOmnReq, clientLinkAddr, emlsrLinkId);
+    apMac->EmlOmnExchangeCompleted(emlOmnReq, clientLinkAddr, emlsrLinkId);
+}
+
+void
+WifiStaticSetupHelper::SetStaticEmlsr(Ptr<WifiNetDevice> apDev,
+                                      const NetDeviceContainer& clientDevs)
+{
+    NS_LOG_FUNCTION_NOARGS();
+
+    auto apMac = DynamicCast<ApWifiMac>(apDev->GetMac());
+    NS_ASSERT_MSG(apMac, "Expected ApWifiMac");
+    // Check if AP supports EMLSR
+    if ((!apMac->GetEhtSupported()) || (apMac->GetNLinks() == 1))
+    {
+        NS_LOG_DEBUG("AP does not support MLD, not performing EMLSR static setup");
+        return;
+    }
+
+    if (!apDev->IsEmlsrActivated())
+    {
+        NS_LOG_DEBUG("AP MLD does not support EMLSR, not performing EMLSR static setup");
+        return;
+    }
+
+    for (auto i = clientDevs.Begin(); i != clientDevs.End(); ++i)
+    {
+        auto clientDev = DynamicCast<WifiNetDevice>(*i);
+        NS_ASSERT_MSG(clientDev, "WifiNetDevice expected");
+        SetStaticEmlsr(apDev, clientDev);
+    }
+}
+
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/helper/wifi-static-setup-helper.h ns-3.46/src/wifi/helper/wifi-static-setup-helper.h
--- ns-3.45/src/wifi/helper/wifi-static-setup-helper.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/helper/wifi-static-setup-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2025
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sharan Naribole <sharan.naribole@gmail.com>
+ */
+
+#ifndef WIFI_STATIC_SETUP_HELPER_H
+#define WIFI_STATIC_SETUP_HELPER_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-utils.h"
+
+#include <optional>
+#include <set>
+
+namespace ns3
+{
+
+class ApWifiMac;
+class MgtAssocRequestHeader;
+class MgtAssocResponseHeader;
+class NetDeviceContainer;
+class WifiNetDevice;
+class StaWifiMac;
+class WifiMacHeader;
+
+/**
+ * Helper to statically setup wifi devices without actually exchanging management frames over the
+ * air:
+ *
+ * - association/ML setup (note that scanning is disabled for this purpose)
+ * - block ack agreement(s)
+ * - enabling EMLSR mode on EMLSR client links
+ */
+class WifiStaticSetupHelper
+{
+  public:
+    /// Bypass static capabilities exchange for input devices
+    /// @param bssDev BSS advertising device (AP)
+    /// @param clientDevs client devices
+    static void SetStaticAssociation(Ptr<WifiNetDevice> bssDev,
+                                     const NetDeviceContainer& clientDevs);
+
+    /// Bypass static capabilities exchange for input devices
+    /// @param bssDev BSS advertising device (AP)
+    /// @param clientDev client device
+    static void SetStaticAssociation(Ptr<WifiNetDevice> bssDev, Ptr<WifiNetDevice> clientDev);
+
+    /// Perform static Association Request/Response exchange for input devices post initialization
+    /// at runtime begin
+    /// @param bssDev BSS advertising device (AP)
+    /// @param clientDev client device
+    static void SetStaticAssocPostInit(Ptr<WifiNetDevice> bssDev, Ptr<WifiNetDevice> clientDev);
+
+    /// Perform static Association Request/Response exchange for input devices post initialization
+    /// at runtime begin
+    /// @param apMac AP MAC
+    /// @param clientMac client MAC
+    static void SetStaticAssocPostInit(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac);
+
+    /// Construct non-AP MLD link ID to AP MLD link ID mapping based on PHY channel settings.
+    /// It is required that for each STA affiliated with the non-AP MLD there exists an AP
+    /// affiliated with the AP MLD that operates on a channel having the same primary20 as the
+    /// channel on which the STA operates.
+    /// @param apDev AP NetDevice
+    /// @param clientDev STA NetDevice
+    /// @return link ID mapping
+    static std::map<linkId_t, linkId_t> GetLinkIdMap(Ptr<WifiNetDevice> apDev,
+                                                     Ptr<WifiNetDevice> clientDev);
+
+    /// Construct non-AP MLD link ID to AP MLD link ID mapping based on PHY channel settings
+    /// It is required that for each STA affiliated with the non-AP MLD there exists an AP
+    /// affiliated with the AP MLD that operates on a channel having the same primary20 as the
+    /// channel on which the STA operates.
+    /// @param apMac AP MAC
+    /// @param staMac STA MAC
+    /// @return link ID mapping
+    static std::map<linkId_t, linkId_t> GetLinkIdMap(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> staMac);
+
+    /// Get Association Request for input STA link address
+    /// @param staMac STA MAC
+    /// @param staLinkId ID of link used for Assoc request
+    /// @param isMldAssoc true if MLD association, false otherwise
+    /// @return association request
+    static MgtAssocRequestHeader GetAssocReq(Ptr<StaWifiMac> staMac,
+                                             linkId_t staLinkId,
+                                             bool isMldAssoc);
+
+    /// Get Association Response for input STA link address from
+    /// AP MAC including Multi-link Element if MLD Association
+    /// @param staLinkAddr STA link MAC address
+    /// @param apMac AP MAC
+    /// @param apLinkId ID of link used for Assoc response
+    /// @param isMldAssoc true if MLD association, false otherwise
+    /// @return association response
+    static MgtAssocResponseHeader GetAssocResp(Mac48Address staLinkAddr,
+                                               Ptr<ApWifiMac> apMac,
+                                               linkId_t apLinkId,
+                                               bool isMldAssoc);
+
+    /// Get Association Response MAC Header for input STA link address from
+    /// AP MAC including Multi-link Element if MLD Association
+    /// @param staLinkAddr STA link MAC address
+    /// @param apMac AP MAC
+    /// @param apLinkId Link ID of link used for Assoc response
+    /// @return MAC header
+    static WifiMacHeader GetAssocRespMacHdr(Mac48Address staLinkAddr,
+                                            Ptr<ApWifiMac> apMac,
+                                            linkId_t apLinkId);
+
+    /// Bypass ADDBA Request-Response exchange sequence between AP and STAs for given TIDs.
+    /// Static setup will be performed in both uplink and downlink.
+    /// @param apDev AP device
+    /// @param clientDevs STA devices
+    /// @param tids the set of TIDs corresponding to Block ACK agreements
+    /// @param gcrGroupAddr MAC address of the GCR group (GCR Group Address)
+    static void SetStaticBlockAck(Ptr<WifiNetDevice> apDev,
+                                  const NetDeviceContainer& clientDevs,
+                                  const std::set<tid_t>& tids,
+                                  std::optional<Mac48Address> gcrGroupAddr = std::nullopt);
+
+    /// Bypass ADDBA Request-Response exchange sequence between input devices for given TID.
+    /// @param originatorDev originator device of Block ACK agreement
+    /// @param recipientDev recipient device of Block ACK agreement
+    /// @param tid TID corresponding to Block ACK agreement
+    /// @param gcrGroupAddr MAC address of the GCR group (GCR Group Address)
+    static void SetStaticBlockAck(Ptr<WifiNetDevice> originatorDev,
+                                  Ptr<WifiNetDevice> recipientDev,
+                                  tid_t tid,
+                                  std::optional<Mac48Address> gcrGroupAddr = std::nullopt);
+
+    /// Perform ADDBA Request-Response exchange sequence between input devices for given TID
+    /// post initialization at runtime begin
+    /// @param originatorDev originator device of Block ACK agreement
+    /// @param recipientDev recipient device of Block ACK agreement
+    /// @param tid TID corresponding to Block ACK agreement
+    /// @param gcrGroupAddr MAC address of the GCR group (GCR Group Address)
+    static void SetStaticBlockAckPostInit(Ptr<WifiNetDevice> originatorDev,
+                                          Ptr<WifiNetDevice> recipientDev,
+                                          tid_t tid,
+                                          std::optional<Mac48Address> gcrGroupAddr = std::nullopt);
+
+    /// Get Block ACK originator address based on devices MAC config
+    /// @param originatorMac originator MAC
+    /// @param recipientMac recipient MAC
+    /// @return the Block Ack originator address
+    static Mac48Address GetBaOriginatorAddr(Ptr<WifiMac> originatorMac, Ptr<WifiMac> recipientMac);
+
+    /// Get Block ACK recipient address based on devices MAC config
+    /// @param originatorMac originator MAC
+    /// @param recipientMac recipient MAC
+    /// @return the Block Ack recipient address
+    static Mac48Address GetBaRecipientAddr(Ptr<WifiMac> originatorMac, Ptr<WifiMac> recipientMac);
+
+    /// Bypass EML Operating Mode Notification exchange sequence between AP MLD
+    /// and input non-AP devices
+    /// @param apDev AP MLD
+    /// @param clientDevs Non-AP devices
+    static void SetStaticEmlsr(Ptr<WifiNetDevice> apDev, const NetDeviceContainer& clientDevs);
+
+    /// Bypass EML Operating Mode Notification exchange sequence between AP MLD and non-AP MLD
+    /// to enable EMLSR mode on the links specified via the EmlsrManager::EmlsrLinkSet attribute
+    /// @param apDev AP MLD
+    /// @param clientDev Non-AP MLD
+    static void SetStaticEmlsr(Ptr<WifiNetDevice> apDev, Ptr<WifiNetDevice> clientDev);
+
+    /// Perform EML Operating Mode Notification exchange sequence between AP MLD and non-AP MLD
+    /// to enable EMLSR mode on the links specified via the EmlsrManager::EmlsrLinkSet attribute
+    /// post initialization at runtime begin
+    /// @param apDev AP MLD
+    /// @param clientDev Non-AP MLD
+    static void SetStaticEmlsrPostInit(Ptr<WifiNetDevice> apDev, Ptr<WifiNetDevice> clientDev);
+};
+
+} // namespace ns3
+
+#endif // WIFI_STATIC_SETUP_HELPER_H
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/ap-wifi-mac.cc ns-3.46/src/wifi/model/ap-wifi-mac.cc
--- ns-3.45/src/wifi/model/ap-wifi-mac.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/ap-wifi-mac.cc	2025-10-01 18:46:32.000000000 -0700
@@ -2148,6 +2148,7 @@
                     MgtEmlOmn frame;
                     pkt->RemoveHeader(frame);
                     ReceiveEmlOmn(frame, hdr->GetAddr2(), linkId);
+                    RespondToEmlOmn(frame, hdr->GetAddr2(), linkId);
                     return;
                 }
                 break;
@@ -2488,7 +2489,7 @@
 }
 
 void
-ApWifiMac::ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId)
+ApWifiMac::ReceiveEmlOmn(const MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId)
 {
     NS_LOG_FUNCTION(this << frame << sender << linkId);
 
@@ -2512,11 +2513,12 @@
         emlCapabilities->get().emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay;
         emlCapabilities->get().emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay;
     }
+}
 
-    auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender);
-    NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender);
-    auto emlsrLinks =
-        frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list<uint8_t>{};
+void
+ApWifiMac::RespondToEmlOmn(MgtEmlOmn frame, const Mac48Address& sender, uint8_t linkId)
+{
+    NS_LOG_FUNCTION(this << frame << sender << linkId);
 
     // The AP MLD has to consider the changes carried by the received EML Notification frame
     // as effective at the same time as the non-AP MLD. Therefore, we need to start a time
@@ -2532,65 +2534,13 @@
             auto ackDuration =
                 WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand());
 
-            m_transitionTimeoutEvents[sender] = Simulator::Schedule(
-                ackDuration + ehtConfiguration->m_transitionTimeout,
-                [=, this]() {
-                    for (uint8_t id = 0; id < GetNLinks(); id++)
-                    {
-                        auto linkAddress =
-                            GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress);
-                        if (!linkAddress)
-                        {
-                            // this link has not been setup by the non-AP MLD
-                            continue;
-                        }
-
-                        if (!emlsrLinks.empty())
-                        {
-                            // the non-AP MLD is enabling EMLSR mode
-                            /**
-                             * After the successful transmission of the EML Operating Mode
-                             * Notification frame by the non-AP STA affiliated with the non-AP MLD,
-                             * the non-AP MLD shall operate in the EMLSR mode and the other non-AP
-                             * STAs operating on the corresponding EMLSR links shall transition to
-                             * active mode after the transition delay indicated in the Transition
-                             * Timeout subfield in the EML Capabilities subfield of the Basic
-                             * Multi-Link element or immediately after receiving an EML Operating
-                             * Mode Notification frame from one of the APs operating on the EMLSR
-                             * links and affiliated with the AP MLD (Sec. 35.3.17 of 802.11be D3.0)
-                             */
-                            auto enabled = std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) !=
-                                           emlsrLinks.cend();
-                            if (enabled)
-                            {
-                                StaSwitchingToActiveModeOrDeassociated(*linkAddress, id);
-                            }
-                            GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled);
-                        }
-                        else
-                        {
-                            // the non-AP MLD is disabling EMLSR mode
-                            /**
-                             * After the successful transmission of the EML Operating Mode
-                             * Notification frame by the non-AP STA affiliated with the non-AP MLD,
-                             * the non-AP MLD shall disable the EMLSR mode and the other non-AP
-                             * STAs operating on the corresponding EMLSR links shall transition to
-                             * power save mode after the transition delay indicated in the
-                             * Transition Timeout subfield in the EML Capabilities subfield of the
-                             * Basic Multi-Link element or immediately after receiving an EML
-                             * Operating Mode Notification frame from one of the APs operating on
-                             * the EMLSR links and affiliated with the AP MLD. (Sec. 35.3.17 of
-                             * 802.11be D3.0)
-                             */
-                            if (id != linkId &&
-                                GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress))
-                            {
-                                StaSwitchingToPsMode(*linkAddress, id);
-                            }
-                            GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false);
-                        }
-                    }
-                });
+            m_transitionTimeoutEvents[sender] =
+                Simulator::Schedule(ackDuration + GetEhtConfiguration()->m_transitionTimeout,
+                                    &ApWifiMac::EmlOmnExchangeCompleted,
+                                    this,
+                                    frame,
+                                    sender,
+                                    linkId);
         });
 
     // connect the callback to the PHY TX begin trace to catch the Ack and disconnect
@@ -2621,6 +2571,73 @@
 }
 
 void
+ApWifiMac::EmlOmnExchangeCompleted(const MgtEmlOmn& frame,
+                                   const Mac48Address& sender,
+                                   uint8_t linkId)
+{
+    NS_LOG_FUNCTION(this << frame << sender << linkId);
+
+    auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender);
+    NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender);
+    auto emlsrLinks =
+        frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list<uint8_t>{};
+
+    for (uint8_t id = 0; id < GetNLinks(); id++)
+    {
+        auto linkAddress = GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress);
+        if (!linkAddress)
+        {
+            // this link has not been setup by the non-AP MLD
+            continue;
+        }
+
+        if (!emlsrLinks.empty())
+        {
+            // the non-AP MLD is enabling EMLSR mode
+            /**
+             * After the successful transmission of the EML Operating Mode
+             * Notification frame by the non-AP STA affiliated with the non-AP MLD,
+             * the non-AP MLD shall operate in the EMLSR mode and the other non-AP
+             * STAs operating on the corresponding EMLSR links shall transition to
+             * active mode after the transition delay indicated in the Transition
+             * Timeout subfield in the EML Capabilities subfield of the Basic
+             * Multi-Link element or immediately after receiving an EML Operating
+             * Mode Notification frame from one of the APs operating on the EMLSR
+             * links and affiliated with the AP MLD (Sec. 35.3.17 of 802.11be D3.0)
+             */
+            auto enabled =
+                std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) != emlsrLinks.cend();
+            if (enabled)
+            {
+                StaSwitchingToActiveModeOrDeassociated(*linkAddress, id);
+            }
+            GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled);
+        }
+        else
+        {
+            // the non-AP MLD is disabling EMLSR mode
+            /**
+             * After the successful transmission of the EML Operating Mode
+             * Notification frame by the non-AP STA affiliated with the non-AP MLD,
+             * the non-AP MLD shall disable the EMLSR mode and the other non-AP
+             * STAs operating on the corresponding EMLSR links shall transition to
+             * power save mode after the transition delay indicated in the
+             * Transition Timeout subfield in the EML Capabilities subfield of the
+             * Basic Multi-Link element or immediately after receiving an EML
+             * Operating Mode Notification frame from one of the APs operating on
+             * the EMLSR links and affiliated with the AP MLD. (Sec. 35.3.17 of
+             * 802.11be D3.0)
+             */
+            if (id != linkId && GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress))
+            {
+                StaSwitchingToPsMode(*linkAddress, id);
+            }
+            GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false);
+        }
+    }
+}
+
+void
 ApWifiMac::DeaggregateAmsduAndForward(Ptr<const WifiMpdu> mpdu)
 {
     NS_LOG_FUNCTION(this << *mpdu);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/ap-wifi-mac.h ns-3.46/src/wifi/model/ap-wifi-mac.h
--- ns-3.45/src/wifi/model/ap-wifi-mac.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/ap-wifi-mac.h	2025-10-01 18:46:32.000000000 -0700
@@ -59,6 +59,8 @@
 class ApWifiMac : public WifiMac
 {
   public:
+    friend class WifiStaticSetupHelper;
+
     /**
      * @brief Get the type ID.
      * @return the object TypeId
@@ -329,14 +331,36 @@
     void ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address from, uint8_t linkId);
 
     /**
-     * Take necessary actions upon receiving the given EML Operating Mode Notification frame
-     * from the given station on the given link.
+     * Process the EML Operating Mode Notification frame received from the given station on the
+     * given link.
+     *
+     * @param frame the received EML Operating Mode Notification frame
+     * @param sender the MAC address of the sender of the frame
+     * @param linkId the ID of the link over which the frame was received
+     */
+    void ReceiveEmlOmn(const MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId);
+
+    /**
+     * Respond to the EML Operating Mode Notification frame received from the given station on the
+     * given link.
+     *
+     * @param frame the received EML Operating Mode Notification frame
+     * @param sender the MAC address of the sender of the frame
+     * @param linkId the ID of the link over which the frame was received
+     */
+    void RespondToEmlOmn(MgtEmlOmn frame, const Mac48Address& sender, uint8_t linkId);
+
+    /**
+     * Take necessary actions upon completion of an exchange of EML Operating Mode Notification
+     * frames.
      *
      * @param frame the received EML Operating Mode Notification frame
      * @param sender the MAC address of the sender of the frame
      * @param linkId the ID of the link over which the frame was received
      */
-    void ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId);
+    void EmlOmnExchangeCompleted(const MgtEmlOmn& frame,
+                                 const Mac48Address& sender,
+                                 uint8_t linkId);
 
     /**
      * The packet we sent was successfully received by the receiver
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/block-ack-manager.cc ns-3.46/src/wifi/model/block-ack-manager.cc
--- ns-3.45/src/wifi/model/block-ack-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/block-ack-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1000,7 +1000,10 @@
 
     uint8_t tid = reqHdr.GetTidInfo();
 
-    WifiContainerQueueId queueId(WIFI_CTL_QUEUE, WIFI_UNICAST, hdr.GetAddr1(), std::nullopt);
+    WifiContainerQueueId queueId(WIFI_CTL_QUEUE,
+                                 WifiRcvAddr::UNICAST,
+                                 hdr.GetAddr1(),
+                                 std::nullopt);
     auto pkt = Create<Packet>();
     pkt->AddHeader(reqHdr);
     Ptr<WifiMpdu> item = nullptr;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/block-ack-manager.h ns-3.46/src/wifi/model/block-ack-manager.h
--- ns-3.45/src/wifi/model/block-ack-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/block-ack-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -414,7 +414,7 @@
     void SetTxOkCallback(TxOk callback);
     /**
      * @param callback the callback to invoke when a
-     * packet transmission was completed unsuccessfuly.
+     * packet transmission was completed unsuccessfully.
      */
     void SetTxFailedCallback(TxFailed callback);
     /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/channel-access-manager.cc ns-3.46/src/wifi/model/channel-access-manager.cc
--- ns-3.45/src/wifi/model/channel-access-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/channel-access-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -17,6 +17,7 @@
 #include "ns3/log.h"
 #include "ns3/simulator.h"
 
+#include <cmath>
 #include <sstream>
 
 #undef NS_LOG_APPEND_CONTEXT
@@ -189,7 +190,8 @@
                           MakeBooleanAccessor(&ChannelAccessManager::m_proactiveBackoff),
                           MakeBooleanChecker())
             .AddAttribute("ResetBackoffThreshold",
-                          "If no PHY operates on this link for a period greater than this "
+                          "If no PHY operates on this link, or the PHY operating on this link "
+                          "stays in sleep mode or off mode, for a period greater than this "
                           "threshold, all the backoffs are reset.",
                           TimeValue(Time{0}),
                           MakeTimeAccessor(&ChannelAccessManager::m_resetBackoffThreshold),
@@ -225,8 +227,6 @@
       m_lastRxReceivedOk(true),
       m_lastTxEnd(0),
       m_lastSwitchingEnd(0),
-      m_lastSleepEnd(0),
-      m_lastOffEnd(0),
       m_linkId(0)
 {
     NS_LOG_FUNCTION(this);
@@ -249,11 +249,7 @@
 ChannelAccessManager::DoDispose()
 {
     NS_LOG_FUNCTION(this);
-    for (Ptr<Txop> i : m_txops)
-    {
-        i->Dispose();
-        i = nullptr;
-    }
+    m_txops.clear();
     m_phy = nullptr;
     m_feManager = nullptr;
     m_phyListeners.clear();
@@ -591,13 +587,13 @@
      */
     Time accessGrantStart = GetAccessGrantStart() + (txop->GetAifsn(m_linkId) * GetSlot());
 
-    if (txop->IsQosTxop() && txop->GetBackoffStart(m_linkId) > accessGrantStart)
+    if (const auto diff = txop->GetBackoffStart(m_linkId) - accessGrantStart;
+        txop->IsQosTxop() && diff.IsStrictlyPositive())
     {
-        // The backoff start time reported by the EDCAF is more recent than the last
-        // time the medium was busy plus an AIFS, hence we need to align it to the
-        // next slot boundary.
-        Time diff = txop->GetBackoffStart(m_linkId) - accessGrantStart;
-        uint32_t nIntSlots = (diff / GetSlot()).GetHigh() + 1;
+        // The backoff start time reported by the EDCAF is more recent than the last time the medium
+        // was busy plus an AIFS, hence we need to align it to the next slot boundary.
+        const auto div = diff / GetSlot();
+        const uint32_t nIntSlots = div.GetHigh() + (div.GetLow() > 0 ? 1 : 0);
         txop->UpdateBackoffSlotsNow(0, accessGrantStart + (nIntSlots * GetSlot()), m_linkId);
     }
 
@@ -615,6 +611,12 @@
     uint32_t k = 0;
     const auto now = Simulator::Now();
     const auto accessGrantStart = GetAccessGrantStart();
+    if (accessGrantStart > now)
+    {
+        NS_LOG_DEBUG("access cannot be granted yet");
+        return;
+    }
+
     for (auto i = m_txops.begin(); i != m_txops.end(); k++)
     {
         Ptr<Txop> txop = *i;
@@ -697,7 +699,14 @@
 {
     NS_LOG_FUNCTION(this);
 
-    if (!m_phy && Simulator::Now() - m_lastNoPhy.start > m_resetBackoffThreshold)
+    const auto now = Simulator::Now();
+    const auto noPhyForTooLong = (!m_phy && now - m_lastNoPhy.start > m_resetBackoffThreshold);
+    const auto sleepForTooLong =
+        (m_phy && m_phy->IsStateSleep() && now - m_lastSleep.start > m_resetBackoffThreshold);
+    const auto offForTooLong =
+        (m_phy && m_phy->IsStateOff() && now - m_lastOff.start > m_resetBackoffThreshold);
+
+    if (noPhyForTooLong || sleepForTooLong || offForTooLong)
     {
         ResetAllBackoffs();
         return;
@@ -740,8 +749,11 @@
     const auto noPhyStart = m_phy ? m_lastNoPhy.end : now;
     ret.emplace(noPhyStart, WifiExpectedAccessReason::NO_PHY_END);
 
-    ret.emplace(m_lastSleepEnd, WifiExpectedAccessReason::SLEEP_END);
-    ret.emplace(m_lastOffEnd, WifiExpectedAccessReason::OFF_END);
+    const auto lastSleepEnd = (m_lastSleep.start > m_lastSleep.end ? now : m_lastSleep.end);
+    ret.emplace(lastSleepEnd, WifiExpectedAccessReason::SLEEP_END);
+
+    const auto lastOffEnd = (m_lastOff.start > m_lastOff.end ? now : m_lastOff.end);
+    ret.emplace(lastOffEnd, WifiExpectedAccessReason::OFF_END);
 
     NS_LOG_INFO("rx access start=" << rxAccessStart.As(Time::US)
                                    << ", busy access start=" << busyAccessStart.As(Time::US)
@@ -749,8 +761,8 @@
                                    << ", nav access start=" << navAccessStart.As(Time::US)
                                    << ", switching access start=" << m_lastSwitchingEnd.As(Time::US)
                                    << ", no PHY start=" << noPhyStart.As(Time::US)
-                                   << ", sleep access start=" << m_lastSleepEnd.As(Time::US)
-                                   << ", off access start=" << m_lastOffEnd.As(Time::US));
+                                   << ", sleep access start=" << lastSleepEnd.As(Time::US)
+                                   << ", off access start=" << lastOffEnd.As(Time::US));
     return ret;
 }
 
@@ -1220,6 +1232,8 @@
     m_lastAckTimeoutEnd = std::min(m_lastAckTimeoutEnd, now);
     m_lastCtsTimeoutEnd = std::min(m_lastCtsTimeoutEnd, now);
     m_lastNoPhy.end = std::min(m_lastNoPhy.end, now);
+    m_lastSleep.end = std::min(m_lastSleep.end, now);
+    m_lastOff.end = std::min(m_lastOff.end, now);
 
     InitLastBusyStructs();
 }
@@ -1255,8 +1269,9 @@
 ChannelAccessManager::NotifySleepNow()
 {
     NS_LOG_FUNCTION(this);
-    // Reset backoffs
-    ResetAllBackoffs();
+    UpdateBackoff();
+    UpdateLastIdlePeriod();
+    m_lastSleep.start = Simulator::Now();
     m_feManager->NotifySleepNow();
     for (auto txop : m_txops)
     {
@@ -1268,16 +1283,13 @@
 ChannelAccessManager::NotifyOffNow()
 {
     NS_LOG_FUNCTION(this);
-    // Cancel timeout
-    if (m_accessTimeout.IsPending())
-    {
-        m_accessTimeout.Cancel();
-    }
-
-    // Reset backoffs
+    UpdateBackoff();
+    UpdateLastIdlePeriod();
+    m_lastOff.start = Simulator::Now();
+    m_feManager->NotifyOffNow();
     for (auto txop : m_txops)
     {
-        txop->NotifyOff();
+        txop->NotifyOff(m_linkId);
     }
 }
 
@@ -1285,10 +1297,14 @@
 ChannelAccessManager::NotifyWakeupNow()
 {
     NS_LOG_FUNCTION(this);
-    m_lastSleepEnd = Simulator::Now();
+    const auto now = Simulator::Now();
+    m_lastSleep.end = now;
+    if (now - m_lastSleep.start > m_resetBackoffThreshold)
+    {
+        ResetAllBackoffs();
+    }
     for (auto txop : m_txops)
     {
-        ResetBackoff(txop);
         txop->NotifyWakeUp(m_linkId);
     }
 }
@@ -1297,10 +1313,14 @@
 ChannelAccessManager::NotifyOnNow()
 {
     NS_LOG_FUNCTION(this);
-    m_lastOffEnd = Simulator::Now();
+    const auto now = Simulator::Now();
+    m_lastOff.end = now;
+    if (now - m_lastOff.start > m_resetBackoffThreshold)
+    {
+        ResetAllBackoffs();
+    }
     for (auto txop : m_txops)
     {
-        ResetBackoff(txop);
         txop->NotifyOn();
     }
 }
@@ -1377,8 +1397,8 @@
                                m_lastRx.end,
                                m_lastSwitchingEnd,
                                m_lastNoPhy.end,
-                               m_lastSleepEnd,
-                               m_lastOffEnd});
+                               m_lastSleep.end,
+                               m_lastOff.end});
     Time now = Simulator::Now();
 
     if (idleStart >= now)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/channel-access-manager.h ns-3.46/src/wifi/model/channel-access-manager.h
--- ns-3.45/src/wifi/model/channel-access-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/channel-access-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -275,7 +275,7 @@
     void NotifyRxEndOkNow();
     /**
      * Notify the Txop that a packet reception was just
-     * completed unsuccessfuly.
+     * completed unsuccessfully.
      *
      * @param txVector the TXVECTOR used for transmission
      */
@@ -536,8 +536,8 @@
     std::map<WifiChannelListType, Timespan>
         m_lastIdle;               //!< the last idle start and end time for each channel type
     Time m_lastSwitchingEnd;      //!< the last switching end time
-    Time m_lastSleepEnd;          //!< the last sleep end time
-    Time m_lastOffEnd;            //!< the last off end time
+    Timespan m_lastSleep;         //!< the last sleep start and end time
+    Timespan m_lastOff;           //!< the last off start and end time
     Time m_eifsNoDifs;            //!< EIFS no DIFS time
     Timespan m_lastNoPhy;         //!< the last start and end time no PHY was operating on the link
     mutable Time m_cachedSifs;    //!< cached value for SIFS, to be only used without a PHY
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/ctrl-headers.cc ns-3.46/src/wifi/model/ctrl-headers.cc
--- ns-3.45/src/wifi/model/ctrl-headers.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/ctrl-headers.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1188,7 +1188,7 @@
       m_ulMcs(0),
       m_ulDcm(false),
       m_ps160(false),
-      m_ulTargetRssi(0),
+      m_ulTargetRxPower(0),
       m_triggerType(triggerType),
       m_basicTriggerDependentUserInfo(0)
 {
@@ -1218,7 +1218,7 @@
     m_ulDcm = userInfo.m_ulDcm;
     m_ps160 = userInfo.m_ps160;
     m_bits26To31 = userInfo.m_bits26To31;
-    m_ulTargetRssi = userInfo.m_ulTargetRssi;
+    m_ulTargetRxPower = userInfo.m_ulTargetRxPower;
     m_basicTriggerDependentUserInfo = userInfo.m_basicTriggerDependentUserInfo;
     m_muBarTriggerDependentUserInfo = userInfo.m_muBarTriggerDependentUserInfo;
     return *this;
@@ -1291,7 +1291,7 @@
     i.WriteHtolsbU32(userInfo);
     // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and B39, which is
     // reserved in the HE variant and the PS160 subfield in the EHT variant.
-    uint8_t bit32To39 = m_ulTargetRssi;
+    uint8_t bit32To39 = m_ulTargetRxPower;
     if (m_variant == TriggerFrameVariant::EHT)
     {
         bit32To39 |= (m_ps160 ? 1 << 7 : 0);
@@ -1348,7 +1348,7 @@
     }
 
     uint8_t bit32To39 = i.ReadU8();
-    m_ulTargetRssi = bit32To39 & 0x7f; // B39 is reserved in HE variant
+    m_ulTargetRxPower = bit32To39 & 0x7f; // B39 is reserved in HE variant
     if (m_variant == TriggerFrameVariant::EHT)
     {
         m_ps160 = (bit32To39 >> 7) == 1;
@@ -1677,31 +1677,31 @@
 }
 
 void
-CtrlTriggerUserInfoField::SetUlTargetRssiMaxTxPower()
+CtrlTriggerUserInfoField::SetUlTargetRxPowerMaxTxPower()
 {
-    m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
+    m_ulTargetRxPower = 127; // see Table 9-54 of 802.11-2024
 }
 
 void
-CtrlTriggerUserInfoField::SetUlTargetRssi(int8_t dBm)
+CtrlTriggerUserInfoField::SetUlTargetRxPower(int8_t dBm)
 {
     NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
 
-    m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
+    m_ulTargetRxPower = static_cast<uint8_t>(110 + dBm);
 }
 
 bool
-CtrlTriggerUserInfoField::IsUlTargetRssiMaxTxPower() const
+CtrlTriggerUserInfoField::IsUlTargetRxPowerMaxTxPower() const
 {
-    return (m_ulTargetRssi == 127);
+    return (m_ulTargetRxPower == 127);
 }
 
 int8_t
-CtrlTriggerUserInfoField::GetUlTargetRssi() const
+CtrlTriggerUserInfoField::GetUlTargetRxPower() const
 {
-    NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
+    NS_ABORT_MSG_IF(m_ulTargetRxPower == 127, "STA must use its max TX power");
 
-    return static_cast<int8_t>(m_ulTargetRssi) - 110;
+    return static_cast<int8_t>(m_ulTargetRxPower) - 110;
 }
 
 void
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/ctrl-headers.h ns-3.46/src/wifi/model/ctrl-headers.h
--- ns-3.45/src/wifi/model/ctrl-headers.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/ctrl-headers.h	2025-10-01 18:46:32.000000000 -0700
@@ -803,32 +803,32 @@
      */
     bool GetMoreRaRu() const;
     /**
-     * Set the UL Target RSSI subfield to indicate to the station to transmit an
+     * Set the UL Target Receive Power subfield to indicate to the station to transmit an
      * HE TB PPDU response at its maximum transmit power for the assigned MCS
      */
-    void SetUlTargetRssiMaxTxPower();
+    void SetUlTargetRxPowerMaxTxPower();
     /**
-     * Set the UL Target RSSI subfield to indicate the expected receive signal
+     * Set the UL Target Receive Power subfield to indicate the expected receive signal
      * power in dBm
      *
      * @param dBm the expected receive signal power (a value between -110 and -20)
      */
-    void SetUlTargetRssi(int8_t dBm);
+    void SetUlTargetRxPower(int8_t dBm);
     /**
-     * Return true if the UL Target RSSI subfield indicates to the station to transmit
+     * Return true if the UL Target Receive Power subfield indicates to the station to transmit
      * an HE TB PPDU response at its maximum transmit power for the assigned MCS
      *
-     * @return true if the UL Target RSSI subfield indicates to the station to transmit
+     * @return true if the UL Target Receive Power subfield indicates to the station to transmit
      * an HE TB PPDU response at its maximum transmit power for the assigned MCS
      */
-    bool IsUlTargetRssiMaxTxPower() const;
+    bool IsUlTargetRxPowerMaxTxPower() const;
     /**
      * Get the expected receive signal power for the solicited HE TB PPDU. This
-     * method can only be called if IsUlTargetRssiMaxTxPower returns false.
+     * method can only be called if IsUlTargetRxPowerMaxTxPower returns false.
      *
      * @return the expected receive signal power in dBm
      */
-    int8_t GetUlTargetRssi() const;
+    int8_t GetUlTargetRxPower() const;
     /**
      * Set the Trigger Dependent User Info subfield for Basic Trigger frames.
      *
@@ -903,7 +903,7 @@
         } raRuInformation; //!< Used when AID12 is 0 or 2045
     } m_bits26To31;        //!< Fields occupying bits 26-31 in the User Info field
 
-    uint8_t m_ulTargetRssi;                  //!< Expected receive signal power
+    uint8_t m_ulTargetRxPower;               //!< Expected receive signal power
     TriggerFrameType m_triggerType;          //!< Trigger frame type
     uint8_t m_basicTriggerDependentUserInfo; //!< Basic Trigger variant of Trigger Dependent User
                                              //!< Info subfield
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/advanced-emlsr-manager.cc ns-3.46/src/wifi/model/eht/advanced-emlsr-manager.cc
--- ns-3.45/src/wifi/model/eht/advanced-emlsr-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/advanced-emlsr-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -329,9 +329,10 @@
     NS_LOG_FUNCTION(this << *linkId << macHdr << txVector << psduDuration.As(Time::MS));
 
     auto& ongoingTxopEnd = GetEhtFem(*linkId)->GetOngoingTxopEndEvent();
+    const auto isMainPhy = (phy->GetPhyId() == GetMainPhyId());
 
     if (ongoingTxopEnd.IsPending() && macHdr.GetAddr1() != GetEhtFem(*linkId)->GetAddress() &&
-        !macHdr.GetAddr1().IsBroadcast() &&
+        !macHdr.IsTrigger() && !macHdr.IsBlockAck() &&
         !(macHdr.IsCts() && macHdr.GetAddr1() == GetEhtFem(*linkId)->GetBssid() /* CTS-to-self */))
     {
         // the EMLSR client is no longer involved in the TXOP and switching to listening mode
@@ -346,13 +347,30 @@
         Simulator::ScheduleNow(&AdvancedEmlsrManager::NotifyTxopEnd, this, *linkId, nullptr);
     }
 
+    if (!ongoingTxopEnd.IsPending() && GetStaMac()->IsEmlsrLink(*linkId) && isMainPhy &&
+        !GetEhtFem(*linkId)->UsingOtherEmlsrLink() &&
+        (macHdr.IsRts() || macHdr.IsBlockAckReq() || macHdr.IsData()) &&
+        (macHdr.GetAddr1() == GetEhtFem(*linkId)->GetAddress()))
+    {
+        // a frame that is starting a DL TXOP is being received by the main PHY; start blocking
+        // transmission on other links (which is normally done later on by PostProcessFrame()) to
+        // avoid starting an UL TXOP before the end of the MPDU
+        for (auto id : GetStaMac()->GetLinkIds())
+        {
+            if (id != *linkId && GetStaMac()->IsEmlsrLink(id))
+            {
+                GetStaMac()->BlockTxOnLink(id, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK);
+            }
+        }
+        return;
+    }
+
     // if the MAC header has been received on the link on which the main PHY is operating (or on
     // the link the main PHY is switching to), the switch main PHY back timer is running and channel
     // access is not expected to be gained by the main PHY before the switch main PHY back timer
     // expires (plus a channel switch delay), try to switch the main PHY back to the preferred link
     const auto mainPhyInvolved =
-        (phy->GetPhyId() == GetMainPhyId()) ||
-        (m_mainPhySwitchInfo.disconnected && m_mainPhySwitchInfo.to == *linkId);
+        isMainPhy || (m_mainPhySwitchInfo.disconnected && m_mainPhySwitchInfo.to == *linkId);
     const auto delay =
         Simulator::GetDelayLeft(m_switchMainPhyBackEvent) + phy->GetChannelSwitchDelay();
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/eht-configuration.h ns-3.46/src/wifi/model/eht/eht-configuration.h
--- ns-3.45/src/wifi/model/eht/eht-configuration.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/eht-configuration.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,7 +10,6 @@
 #ifndef EHT_CONFIGURATION_H
 #define EHT_CONFIGURATION_H
 
-#include "ns3/deprecated.h"
 #include "ns3/nstime.h"
 #include "ns3/object.h"
 #include "ns3/wifi-utils.h"
@@ -41,23 +40,6 @@
 };
 
 /**
- * Deprecated link mapping support enums.
- *
- * Use `WifiTidToLinkMappingNegSupport` class enum values instead.
- * @{
- */
-NS_DEPRECATED_3_42("Use WifiTidToLinkMappingNegSupport::NOT_SUPPORTED instead")
-static constexpr auto WIFI_TID_TO_LINK_MAPPING_NOT_SUPPORTED =
-    WifiTidToLinkMappingNegSupport::NOT_SUPPORTED;
-NS_DEPRECATED_3_42("Use WifiTidToLinkMappingNegSupport::SAME_LINK_SET instead")
-static constexpr auto WIFI_TID_TO_LINK_MAPPING_SAME_LINK_SET =
-    WifiTidToLinkMappingNegSupport::SAME_LINK_SET;
-NS_DEPRECATED_3_42("Use WifiTidToLinkMappingNegSupport::ANY_LINK_SET instead")
-static constexpr auto WIFI_TID_TO_LINK_MAPPING_ANY_LINK_SET =
-    WifiTidToLinkMappingNegSupport::ANY_LINK_SET;
-/**@}*/
-
-/**
  * @brief Stream insertion operator.
  * @param [in] os The reference to the output stream.
  * @param [in] negsupport The WifiTidToLinkMappingNegSupport.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/eht-frame-exchange-manager.cc ns-3.46/src/wifi/model/eht/eht-frame-exchange-manager.cc
--- ns-3.45/src/wifi/model/eht/eht-frame-exchange-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/eht-frame-exchange-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -53,10 +53,17 @@
 TypeId
 EhtFrameExchangeManager::GetTypeId()
 {
-    static TypeId tid = TypeId("ns3::EhtFrameExchangeManager")
-                            .SetParent<HeFrameExchangeManager>()
-                            .AddConstructor<EhtFrameExchangeManager>()
-                            .SetGroupName("Wifi");
+    static TypeId tid =
+        TypeId("ns3::EhtFrameExchangeManager")
+            .SetParent<HeFrameExchangeManager>()
+            .AddConstructor<EhtFrameExchangeManager>()
+            .SetGroupName("Wifi")
+            .AddAttribute("EarlyTxopEndDetect",
+                          "Whether the Duration/ID value of the frame being transmitted "
+                          "or received can be used to early detect an ongoing TXOP end.",
+                          BooleanValue(true),
+                          MakeBooleanAccessor(&EhtFrameExchangeManager::m_earlyTxopEndDetect),
+                          MakeBooleanChecker());
     return tid;
 }
 
@@ -213,7 +220,10 @@
                 }
 
                 // check that this link is blocked as expected
-                WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, *mldAddress, 0);
+                WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE,
+                                             WifiRcvAddr::UNICAST,
+                                             *mldAddress,
+                                             0);
                 auto mask =
                     m_apMac->GetMacQueueScheduler()->GetQueueLinkMask(AC_BE, queueId, m_linkId);
                 NS_ASSERT_MSG(mask,
@@ -234,8 +244,6 @@
         }
     }
 
-    std::optional<Time> timeToCtsEnd;
-
     if (m_staMac && m_staMac->IsEmlsrLink(m_linkId))
     {
         // Cannot start a transmission on a link blocked because another EMLSR link is being used
@@ -335,7 +343,7 @@
     // EHT-SIG, the equivalent of HE-SIG-B, is present in EHT SU transmissions, too
     if (txVector.GetPreambleType() == WIFI_PREAMBLE_EHT_MU)
     {
-        auto phy = StaticCast<EhtPhy>(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT));
+        auto phy = std::static_pointer_cast<EhtPhy>(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT));
         auto sigBMode = phy->GetSigBMode(txVector);
         txVector.SetSigBMode(sigBMode);
     }
@@ -464,7 +472,7 @@
             const auto psduMapIt = psduMap.find(aid);
             const auto aidNotFoundAndNotTf = (psduMapIt == psduMap.cend()) && !IsTrigger(psduMap);
             // the PSDU to process: the one addressed to the given AID (if any) or the unique one
-            const auto psdu = (psduMapIt != psduMap.cend() ? psduMapIt : psduMap.cbegin())->second;
+            const auto psdu = (psduMapIt != psduMap.cend() ? psduMapIt : psduMap.begin())->second;
 
             if (GetWifiRemoteStationManager()->GetEmlsrEnabled(*clientIt) &&
                 (aidNotFoundAndNotTf || GetEmlsrSwitchToListening(psdu, aid, *clientIt)))
@@ -1111,7 +1119,10 @@
                 m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
             {
                 // check that other links are blocked as expected
-                WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, *mldAddress, 0);
+                WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE,
+                                             WifiRcvAddr::UNICAST,
+                                             *mldAddress,
+                                             0);
                 auto mask =
                     m_apMac->GetMacQueueScheduler()->GetQueueLinkMask(AC_BE, queueId, linkId);
                 NS_ASSERT_MSG(mask, "No mask for client " << *mldAddress << " on link " << +linkId);
@@ -1505,7 +1516,7 @@
             m_staMac->IsEmlsrLink(m_linkId))
         {
             // this is an initial Control frame
-            if (DropReceivedIcf())
+            if (DropReceivedIcf(mpdu))
             {
                 return;
             }
@@ -1515,10 +1526,29 @@
     }
     else if (m_staMac && m_staMac->IsEmlsrLink(m_linkId) && !m_ongoingTxopEnd.IsPending() &&
              m_phy->GetPhyId() == m_staMac->GetEmlsrManager()->GetMainPhyId() &&
-             (hdr.IsRts() || hdr.IsBlockAckReq() || (hdr.IsData() && hdr.GetAddr1() == m_self)))
+             (hdr.IsRts() || hdr.IsBlockAckReq() || hdr.IsData()) && hdr.GetAddr1() == m_self)
     {
-        // a frame that is starting a DL TXOP has been received by the main PHY
+        // a frame that is starting a DL TXOP has been received by the main PHY, check if the frame
+        // shall be dropped
+        if (DropReceivedIcf(mpdu))
+        {
+            return;
+        }
+
         m_dlTxopStart = true;
+
+        if (inAmpdu)
+        {
+            // start blocking transmission on other links (which is normally done later on by
+            // PostProcessFrame()) to avoid starting an UL TXOP before end of A-MPDU
+            for (auto id : m_staMac->GetLinkIds())
+            {
+                if (id != m_linkId && m_staMac->IsEmlsrLink(id))
+                {
+                    m_staMac->BlockTxOnLink(id, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK);
+                }
+            }
+        }
     }
 
     if (!m_dlTxopStart && ShallDropReceivedMpdu(mpdu))
@@ -1544,33 +1574,6 @@
     }
 }
 
-void
-EhtFrameExchangeManager::EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
-                                         const RxSignalInfo& rxSignalInfo,
-                                         const WifiTxVector& txVector,
-                                         const std::vector<bool>& perMpduStatus)
-{
-    NS_LOG_FUNCTION(
-        this << *psdu << rxSignalInfo << txVector << perMpduStatus.size()
-             << std::all_of(perMpduStatus.begin(), perMpduStatus.end(), [](bool v) { return v; }));
-
-    const auto& hdr = psdu->GetHeader(0);
-    if (m_staMac && m_staMac->IsEmlsrLink(m_linkId) && !m_ongoingTxopEnd.IsPending() &&
-        m_phy->GetPhyId() == m_staMac->GetEmlsrManager()->GetMainPhyId() &&
-        (hdr.IsData() && hdr.GetAddr1() == m_self))
-    {
-        // a frame that is starting a DL TXOP has been received by the main PHY
-        m_dlTxopStart = true;
-    }
-
-    if (!m_dlTxopStart && ShallDropReceivedMpdu(*psdu->begin()))
-    {
-        return;
-    }
-
-    HeFrameExchangeManager::EndReceiveAmpdu(psdu, rxSignalInfo, txVector, perMpduStatus);
-}
-
 bool
 EhtFrameExchangeManager::ShallDropReceivedMpdu(Ptr<const WifiMpdu> mpdu) const
 {
@@ -1639,9 +1642,9 @@
 }
 
 bool
-EhtFrameExchangeManager::DropReceivedIcf()
+EhtFrameExchangeManager::DropReceivedIcf(Ptr<const WifiMpdu> icf)
 {
-    NS_LOG_FUNCTION(this);
+    NS_LOG_FUNCTION(this << *icf);
 
     auto emlsrManager = m_staMac->GetEmlsrManager();
     NS_ASSERT(emlsrManager);
@@ -1650,8 +1653,10 @@
     {
         // we received an ICF on a link that is blocked because another EMLSR link is
         // being used. Check if there is an ongoing DL TXOP on the other EMLSR link
-        auto apMldAddress = GetWifiRemoteStationManager()->GetMldAddress(m_bssid);
-        NS_ASSERT_MSG(apMldAddress, "MLD address not found for " << m_bssid);
+        auto addr2 = icf->GetHeader().GetAddr2();
+        const auto sender = GetWifiRemoteStationManager()->GetMldAddress(addr2).value_or(addr2);
+        NS_ASSERT_MSG(addr2 != m_bssid || sender != m_bssid,
+                      "If the ICF is not sent by an adhoc peer, it must be sent by an (AP) MLD");
 
         if (auto it = std::find_if(
                 m_staMac->GetLinkIds().cbegin(),
@@ -1662,27 +1667,29 @@
                         StaticCast<EhtFrameExchangeManager>(m_mac->GetFrameExchangeManager(linkId));
                     return linkId != m_linkId && m_staMac->IsEmlsrLink(linkId) &&
                            ehtFem->m_ongoingTxopEnd.IsPending() && ehtFem->m_txopHolder &&
-                           m_mac->GetWifiRemoteStationManager(linkId)->GetMldAddress(
-                               *ehtFem->m_txopHolder) == apMldAddress;
+                           m_mac->GetWifiRemoteStationManager(linkId)
+                                   ->GetMldAddress(*ehtFem->m_txopHolder)
+                                   .value_or(*ehtFem->m_txopHolder) == sender;
                 });
             it != m_staMac->GetLinkIds().cend())
         {
-            // AP is not expected to send ICFs on two links. If an ICF
-            // has been received on this link, it means that the DL TXOP
-            // on the other link terminated (e.g., the AP did not
-            // receive our response)
+            // A device is not expected to send ICFs on two links. If an ICF has been received on
+            // this link, it means that the DL TXOP on the other link terminated (e.g., the device
+            // did not receive our response)
             StaticCast<EhtFrameExchangeManager>(m_mac->GetFrameExchangeManager(*it))
                 ->m_ongoingTxopEnd.Cancel();
-            // we are going to start a TXOP on this link; unblock
-            // transmissions on this link, the other links will be
-            // blocked subsequently
+            // we are going to start a TXOP on this link; unblock transmissions on this link, the
+            // other links will be blocked subsequently
             m_staMac->UnblockTxOnLink({m_linkId}, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK);
         }
         else
         {
-            // We get here likely because transmission on the other EMLSR link
-            // started before the reception of the ICF ended. We drop this ICF and let the
-            // UL TXOP continue.
+            // We get here if either there is an ongoing DL TXOP on another EMLSR link but the
+            // TXOP holder is not the sender of the ICF (this may happen when the EMLSR client
+            // receives ICFs from the AP and a peer adhoc STA) or there is an ongoing UL TXOP on
+            // the other EMLSR link (which likely happens when a transmission on the other EMLSR
+            // link started before the reception of the ICF ended). In both cases, we drop this ICF
+            // and let the TXOP on the other EMLSR link continue.
             NS_LOG_DEBUG("Drop ICF because another EMLSR link is being used");
             m_icfDropCallback({WifiIcfDrop::USING_OTHER_LINK, m_linkId, m_bssid});
             return true;
@@ -1776,7 +1783,7 @@
         // the response)
         delay = m_txTimer.GetDelayLeft();
     }
-    else if (durationId <= m_phy->GetSifs())
+    else if (m_earlyTxopEndDetect && durationId <= m_phy->GetSifs())
     {
         // the TX timer is not running, hence no response is expected, and the Duration/ID value
         // is less than or equal to a SIFS; the TXOP will end after this transmission
@@ -1790,8 +1797,11 @@
         // after the end of this PPDU, hence we need to postpone the TXOP end in order to
         // get the PHY-RXSTART.indication
         delay = txDuration + m_phy->GetSifs() + m_phy->GetSlot() + EMLSR_RX_PHY_START_DELAY;
-        // TXOP end cannot be beyond the period protected via Duration/ID
-        delay = Min(delay, txDuration + durationId);
+        if (m_earlyTxopEndDetect)
+        {
+            // TXOP end cannot be beyond the period protected via Duration/ID
+            delay = Min(delay, txDuration + durationId);
+        }
     }
 
     NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
@@ -1835,7 +1845,7 @@
 
     // if the Duration/ID of the received frame is less than a SIFS, the TXOP
     // is terminated
-    if (durationId <= m_phy->GetSifs())
+    if (m_earlyTxopEndDetect && durationId <= m_phy->GetSifs())
     {
         NS_LOG_DEBUG("Assume TXOP ended based on Duration/ID value");
         TxopEnd(m_txopHolder);
@@ -1845,8 +1855,11 @@
     // we may send a response after a SIFS or we may receive another frame after a SIFS.
     // Postpone the TXOP end by considering the latter (which takes longer)
     auto delay = m_phy->GetSifs() + m_phy->GetSlot() + EMLSR_RX_PHY_START_DELAY;
-    // TXOP end cannot be beyond the period protected via Duration/ID
-    delay = Min(delay, durationId);
+    if (m_earlyTxopEndDetect)
+    {
+        // TXOP end cannot be beyond the period protected via Duration/ID
+        delay = Min(delay, durationId);
+    }
     NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
     m_ongoingTxopEnd =
         Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this, m_txopHolder);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/eht-frame-exchange-manager.h ns-3.46/src/wifi/model/eht/eht-frame-exchange-manager.h
--- ns-3.45/src/wifi/model/eht/eht-frame-exchange-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/eht-frame-exchange-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -189,10 +189,6 @@
                      RxSignalInfo rxSignalInfo,
                      const WifiTxVector& txVector,
                      bool inAmpdu) override;
-    void EndReceiveAmpdu(Ptr<const WifiPsdu> psdu,
-                         const RxSignalInfo& rxSignalInfo,
-                         const WifiTxVector& txVector,
-                         const std::vector<bool>& perMpduStatus) override;
     void NavResetTimeout() override;
     void IntraBssNavResetTimeout() override;
     void SendCtsAfterRts(const WifiMacHeader& rtsHdr,
@@ -247,12 +243,16 @@
      */
     bool UnblockEmlsrLinksIfAllowed(Mac48Address address, bool checkThisLink);
 
+    bool m_earlyTxopEndDetect; ///< whether the Duration/ID value of the frame being transmitted
+                               ///< or received can be used to early detect an ongoing TXOP end
+
   private:
     /**
+     * @param icf the received ICF
      * @return whether the received ICF must be dropped because we are unable to process it
      *         (e.g., another EMLSR link is being used or there is no time for main PHY switch)
      */
-    bool DropReceivedIcf();
+    bool DropReceivedIcf(Ptr<const WifiMpdu> icf);
 
     /**
      * For each EMLSR client in the given set of clients that did not respond to a frame requesting
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/eht-phy.cc ns-3.46/src/wifi/model/eht/eht-phy.cc
--- ns-3.45/src/wifi/model/eht/eht-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/eht-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -565,7 +565,7 @@
     ConstructorEht()
     {
         ns3::EhtPhy::InitializeModes();
-        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_EHT, ns3::Create<ns3::EhtPhy>());
+        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_EHT, std::make_shared<ns3::EhtPhy>());
     }
 } g_constructor_eht; ///< the constructor for EHT modes
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/eht-ru.cc ns-3.46/src/wifi/model/eht/eht-ru.cc
--- ns-3.45/src/wifi/model/eht/eht-ru.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/eht-ru.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1064,6 +1064,9 @@
 {
     const auto it = m_ruSubcarrierGroups.find({bw, ruType});
     NS_ABORT_MSG_IF(it == m_ruSubcarrierGroups.cend(), "RU not found");
+    NS_ABORT_MSG_IF(phyIndex == 0 || phyIndex > it->second.size(),
+                    "Invalid PHY index " << phyIndex << " for RU type " << ruType
+                                         << " and bandwidth " << bw);
     return it->second.at(phyIndex - 1);
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/eht/emlsr-manager.h ns-3.46/src/wifi/model/eht/emlsr-manager.h
--- ns-3.45/src/wifi/model/eht/emlsr-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/eht/emlsr-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -80,6 +80,7 @@
 {
     /// Allow test cases to access private members
     friend class ::EmlsrCcaBusyTest;
+    friend class WifiStaticSetupHelper;
 
   public:
     /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/he/constant-obss-pd-algorithm.cc ns-3.46/src/wifi/model/he/constant-obss-pd-algorithm.cc
--- ns-3.45/src/wifi/model/he/constant-obss-pd-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/he/constant-obss-pd-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -48,11 +48,12 @@
     auto phy = device->GetPhy();
     if (phy->GetStandard() >= WIFI_STANDARD_80211be)
     {
-        auto ehtPhy = DynamicCast<EhtPhy>(device->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_EHT));
+        auto ehtPhy =
+            std::dynamic_pointer_cast<EhtPhy>(device->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_EHT));
         NS_ASSERT(ehtPhy);
         ehtPhy->SetEndOfHeSigACallback(MakeCallback(&ConstantObssPdAlgorithm::ReceiveHeSigA, this));
     }
-    auto hePhy = DynamicCast<HePhy>(phy->GetPhyEntity(WIFI_MOD_CLASS_HE));
+    auto hePhy = std::dynamic_pointer_cast<HePhy>(phy->GetPhyEntity(WIFI_MOD_CLASS_HE));
     NS_ASSERT(hePhy);
     hePhy->SetEndOfHeSigACallback(MakeCallback(&ConstantObssPdAlgorithm::ReceiveHeSigA, this));
     ObssPdAlgorithm::ConnectWifiNetDevice(device);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/he/he-frame-exchange-manager.cc ns-3.46/src/wifi/model/he/he-frame-exchange-manager.cc
--- ns-3.45/src/wifi/model/he/he-frame-exchange-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/he/he-frame-exchange-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -644,8 +644,8 @@
             ForwardPsduDown(triggerPsdu, acknowledgment->muBarTxVector);
 
             // Pass TRIGVECTOR to HE PHY (equivalent to PHY-TRIGGER.request primitive)
-            auto hePhy =
-                StaticCast<HePhy>(m_phy->GetPhyEntity(responseTxVector->GetModulationClass()));
+            auto hePhy = std::static_pointer_cast<HePhy>(
+                m_phy->GetPhyEntity(responseTxVector->GetModulationClass()));
             hePhy->SetTrigVector(m_trigVector, timeout);
 
             return;
@@ -892,7 +892,8 @@
         timerType == WifiTxTimer::WAIT_QOS_NULL_AFTER_BSRP_TF)
     {
         // Pass TRIGVECTOR to HE PHY (equivalent to PHY-TRIGGER.request primitive)
-        auto hePhy = StaticCast<HePhy>(m_phy->GetPhyEntity(responseTxVector->GetModulationClass()));
+        auto hePhy = std::static_pointer_cast<HePhy>(
+            m_phy->GetPhyEntity(responseTxVector->GetModulationClass()));
         hePhy->SetTrigVector(m_trigVector, m_txTimer.GetDelayLeft());
     }
     else if (timerType == WifiTxTimer::NOT_RUNNING &&
@@ -929,7 +930,8 @@
 
     if (ns3::IsDlMu(txVector.GetPreambleType()))
     {
-        auto hePhy = StaticCast<HePhy>(m_phy->GetPhyEntity(txVector.GetModulationClass()));
+        auto hePhy =
+            std::static_pointer_cast<HePhy>(m_phy->GetPhyEntity(txVector.GetModulationClass()));
         auto sigBMode = hePhy->GetSigBMode(txVector);
         txVector.SetSigBMode(sigBMode);
     }
@@ -1510,7 +1512,7 @@
     NS_ASSERT_MSG(heConfiguration, "This STA has to be an HE station to send an HE TB PPDU");
     v.SetBssColor(heConfiguration->m_bssColor);
 
-    if (userInfoIt->IsUlTargetRssiMaxTxPower())
+    if (userInfoIt->IsUlTargetRxPowerMaxTxPower())
     {
         NS_LOG_LOGIC("AP requested using the max transmit power (" << m_phy->GetTxPowerEnd()
                                                                    << " dBm)");
@@ -1542,7 +1544,7 @@
         trigger.GetApTxPower() -
         static_cast<int8_t>(
             *optRssi); // cast RSSI to be on equal footing with AP Tx power information
-    auto reqTxPower = dBm_u{static_cast<double>(userInfoIt->GetUlTargetRssi() + pathLossDb)};
+    auto reqTxPower = dBm_u{static_cast<double>(userInfoIt->GetUlTargetRxPower() + pathLossDb)};
 
     // Convert the transmit power to a power level
     uint8_t numPowerLevels = m_phy->GetNTxPower();
@@ -1594,12 +1596,20 @@
         auto itAidAddr = staList.find(userInfo.GetAid12());
         NS_ASSERT(itAidAddr != staList.end());
         auto optRssi = GetMostRecentRssi(itAidAddr->second);
+        if (!optRssi.has_value())
+        {
+            // This might happen after static setup where the AP has not received any
+            // frame from the client yet.
+            userInfo.SetUlTargetRxPowerMaxTxPower();
+            continue;
+        }
+
         NS_ASSERT(optRssi);
         auto rssi = static_cast<int8_t>(*optRssi);
         rssi = (rssi >= -20)
                    ? -20
                    : ((rssi <= -110) ? -110 : rssi); // cap so as to keep within [-110; -20] dBm
-        userInfo.SetUlTargetRssi(rssi);
+        userInfo.SetUlTargetRxPower(rssi);
     }
 }
 
@@ -1899,7 +1909,7 @@
     // TR3: Sequence numbers for transmitted QoS (+)Null frames may be set
     // to any value. (Table 10-3 of 802.11-2016)
     header.SetSequenceNumber(0);
-    // Set the EOSP bit so that NotifyTxToEdca will add the Queue Size
+    // Set the EOSP bit so that HtFEM::FinalizeMacHeader will add the Queue Size
     header.SetQosEosp();
 
     WifiTxParameters txParams;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/he/he-phy.cc ns-3.46/src/wifi/model/he/he-phy.cc
--- ns-3.45/src/wifi/model/he/he-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/he/he-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -992,6 +992,7 @@
                             channelWidth,
                             m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(MHz_u{20})),
         mc);
+    NS_ABORT_MSG_IF(group.empty(), "No subcarrier group found");
     // for a TX spectrum, the guard bandwidth is a function of the transmission channel width
     // and the spectrum width equals the transmission channel width (hence bandIndex equals 0)
     const auto indices = ConvertRuSubcarriers({channelWidth,
@@ -1027,6 +1028,7 @@
                             channelWidth,
                             m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(MHz_u{20})),
         mc);
+    NS_ABORT_MSG_IF(group.empty(), "No subcarrier group found");
     // for an RX spectrum, the guard bandwidth is a function of the operating channel width
     // and the spectrum width equals the operating channel width
     const auto indices = ConvertRuSubcarriers(
@@ -1888,7 +1890,7 @@
     ConstructorHe()
     {
         ns3::HePhy::InitializeModes();
-        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_HE, ns3::Create<ns3::HePhy>());
+        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_HE, std::make_shared<ns3::HePhy>());
     }
 } g_constructor_he; ///< the constructor for HE modes
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/he/obss-pd-algorithm.cc ns-3.46/src/wifi/model/he/obss-pd-algorithm.cc
--- ns-3.45/src/wifi/model/he/obss-pd-algorithm.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/he/obss-pd-algorithm.cc	2025-10-01 18:46:32.000000000 -0700
@@ -76,11 +76,13 @@
     auto phy = device->GetPhy();
     if (phy->GetStandard() >= WIFI_STANDARD_80211be)
     {
-        auto ehtPhy = DynamicCast<EhtPhy>(device->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_EHT));
+        auto ehtPhy =
+            std::dynamic_pointer_cast<EhtPhy>(device->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_EHT));
         NS_ASSERT(ehtPhy);
         ehtPhy->SetObssPdAlgorithm(this);
     }
-    auto hePhy = DynamicCast<HePhy>(device->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
+    auto hePhy =
+        std::dynamic_pointer_cast<HePhy>(device->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
     NS_ASSERT(hePhy);
     hePhy->SetObssPdAlgorithm(this);
 }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/he/rr-multi-user-scheduler.cc ns-3.46/src/wifi/model/he/rr-multi-user-scheduler.cc
--- ns-3.45/src/wifi/model/he/rr-multi-user-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/he/rr-multi-user-scheduler.cc	2025-10-01 18:46:32.000000000 -0700
@@ -320,11 +320,11 @@
     // check if the station is an EMLSR client that is using another link
     if (GetWifiRemoteStationManager(m_linkId)->GetEmlsrEnabled(info.address) &&
         (m_apMac->GetTxBlockedOnLink(AC_BE,
-                                     {WIFI_QOSDATA_QUEUE, WIFI_UNICAST, *mldAddr, 0},
+                                     {WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, *mldAddr, 0},
                                      m_linkId,
                                      WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK) ||
          m_apMac->GetTxBlockedOnLink(AC_BE,
-                                     {WIFI_QOSDATA_QUEUE, WIFI_UNICAST, *mldAddr, 0},
+                                     {WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, *mldAddr, 0},
                                      m_linkId,
                                      WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY)))
     {
@@ -1118,4 +1118,10 @@
     return UlMuInfo{m_trigger, m_triggerMacHdr, std::move(m_txParams)};
 }
 
+const std::list<RrMultiUserScheduler::MasterInfo>&
+RrMultiUserScheduler::GetUlMuStas() const
+{
+    return m_staListUl;
+}
+
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/he/rr-multi-user-scheduler.h ns-3.46/src/wifi/model/he/rr-multi-user-scheduler.h
--- ns-3.45/src/wifi/model/he/rr-multi-user-scheduler.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/he/rr-multi-user-scheduler.h	2025-10-01 18:46:32.000000000 -0700
@@ -44,6 +44,23 @@
 
     Time GetExtraTimeForBsrpTfDurationId(uint8_t linkId) const override;
 
+    /**
+     * Information used to sort stations
+     */
+    struct MasterInfo
+    {
+        uint16_t aid{0};      //!< station's AID
+        Mac48Address address; //!< station's MAC Address
+        double credits{0.};   //!< credits accumulated by the station
+    };
+
+    /**
+     * @brief Get UL MU eligible stations list
+     *
+     * @return list of UL MU eligible stations
+     */
+    virtual const std::list<MasterInfo>& GetUlMuStas() const;
+
   protected:
     void DoDispose() override;
     void DoInitialize() override;
@@ -56,16 +73,6 @@
                                    WifiTxParameters& txParams) const override;
 
     /**
-     * Information used to sort stations
-     */
-    struct MasterInfo
-    {
-        uint16_t aid;         //!< station's AID
-        Mac48Address address; //!< station's MAC Address
-        double credits;       //!< credits accumulated by the station
-    };
-
-    /**
      * Determine whether the given STA can be solicited via a Basic Trigger Frame.
      *
      * @param info the information about the given STA
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/ht/ht-frame-exchange-manager.cc ns-3.46/src/wifi/model/ht/ht-frame-exchange-manager.cc
--- ns-3.45/src/wifi/model/ht/ht-frame-exchange-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/ht/ht-frame-exchange-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -126,7 +126,7 @@
     // NOLINTEND(bugprone-branch-clone)
     else
     {
-        WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WIFI_UNICAST, recipient, tid};
+        WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, recipient, tid};
         uint32_t packets = qosTxop->GetWifiMacQueue()->GetNPackets(queueId);
         establish =
             (m_mac->Is6GhzBand(m_linkId) ||
@@ -152,7 +152,7 @@
         m_mpduAggregator->GetMaxAmpduSize(groupAddress, tid, WIFI_MOD_CLASS_HT);
     const auto isGcrBa = (m_apMac->GetGcrManager()->GetRetransmissionPolicy() ==
                           GroupAddressRetransmissionPolicy::GCR_BLOCK_ACK);
-    WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WIFI_GROUPCAST, groupAddress, tid};
+    WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WifiRcvAddr::GROUPCAST, groupAddress, tid};
 
     for (const auto& recipients =
              m_apMac->GetGcrManager()->GetMemberStasForGroupAddress(groupAddress);
@@ -570,7 +570,7 @@
             if (bar->GetHeader().GetAddr2() == m_self && recipientMld)
             {
                 WifiContainerQueueId queueId{WIFI_CTL_QUEUE,
-                                             WIFI_UNICAST,
+                                             WifiRcvAddr::UNICAST,
                                              *recipientMld,
                                              std::nullopt};
                 Ptr<WifiMpdu> otherBar;
@@ -606,7 +606,7 @@
         {
             WifiContainerQueueId queueId(
                 WIFI_QOSDATA_QUEUE,
-                WIFI_UNICAST,
+                WifiRcvAddr::UNICAST,
                 GetWifiRemoteStationManager()->GetMldAddress(recipient).value_or(recipient),
                 tid);
             // check if data is queued and can be transmitted on this link
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/ht/ht-phy.cc ns-3.46/src/wifi/model/ht/ht-phy.cc
--- ns-3.45/src/wifi/model/ht/ht-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/ht/ht-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -262,7 +262,6 @@
                         << +nDataLtf << ")  and extension (" << +nExtensionLtf
                         << ")  LTFs numbers for HT"); // see IEEE 802.11-2016, section 19.3.9.4.6
                                                       // "HT-LTF definition"
-    Time duration = MicroSeconds(4) * (nDataLtf + nExtensionLtf);
     return MicroSeconds(4) * (1 /* HT-STF */ + nDataLtf + nExtensionLtf);
 }
 
@@ -939,7 +938,7 @@
     {
         ns3::HtPhy::InitializeModes();
         ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_HT,
-                                         ns3::Create<ns3::HtPhy>()); // dummy Nss
+                                         std::make_shared<ns3::HtPhy>()); // dummy Nss
     }
 } g_constructor_ht; ///< the constructor for HT modes
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/interference-helper.cc ns-3.46/src/wifi/model/interference-helper.cc
--- ns-3.45/src/wifi/model/interference-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/interference-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -10,6 +10,7 @@
 #include "interference-helper.h"
 
 #include "error-rate-model.h"
+#include "phy-entity.h"
 #include "wifi-phy-operating-channel.h"
 #include "wifi-phy.h"
 #include "wifi-psdu.h"
@@ -134,11 +135,6 @@
 {
 }
 
-InterferenceHelper::NiChange::~NiChange()
-{
-    m_event = nullptr;
-}
-
 Watt_u
 InterferenceHelper::NiChange::GetPower() const
 {
@@ -471,14 +467,13 @@
     {
         ;
     }
-    NiChanges ni;
+    auto& ni = nis[band];
     ni.emplace(event->GetStartTime(), NiChange(Watt_u{0}, event));
     while (++it != niIt->second.end() && it->second.GetEvent() != event)
     {
         ni.insert(*it);
     }
     ni.emplace(event->GetEndTime(), NiChange(Watt_u{0}, event));
-    nis.insert({band, ni});
     NS_ASSERT_MSG(noiseInterference >= Watt_u{0.0},
                   "CalculateNoiseInterferenceW returns negative value " << noiseInterference);
     return noiseInterference;
@@ -646,12 +641,11 @@
 }
 
 double
-InterferenceHelper::CalculatePhyHeaderSectionPsr(
-    Ptr<const Event> event,
-    NiChangesPerBand* nis,
-    MHz_u channelWidth,
-    const WifiSpectrumBandInfo& band,
-    PhyEntity::PhyHeaderSections phyHeaderSections) const
+InterferenceHelper::CalculatePhyHeaderSectionPsr(Ptr<const Event> event,
+                                                 NiChangesPerBand* nis,
+                                                 MHz_u channelWidth,
+                                                 const WifiSpectrumBandInfo& band,
+                                                 PhyHeaderSections phyHeaderSections) const
 {
     NS_LOG_FUNCTION(this << band);
     double psr = 1.0; /* Packet Success Rate */
@@ -721,7 +715,7 @@
     auto phyEntity =
         WifiPhy::GetStaticPhyEntity(event->GetPpdu()->GetTxVector().GetModulationClass());
 
-    PhyEntity::PhyHeaderSections sections;
+    PhyHeaderSections sections;
     for (const auto& section :
          phyEntity->GetPhyHeaderSections(event->GetPpdu()->GetTxVector(), niIt.begin()->first))
     {
@@ -739,7 +733,7 @@
     return 1 - psr;
 }
 
-PhyEntity::SnrPer
+SnrPer
 InterferenceHelper::CalculatePayloadSnrPer(Ptr<Event> event,
                                            MHz_u channelWidth,
                                            const WifiSpectrumBandInfo& band,
@@ -761,7 +755,7 @@
     const auto per =
         CalculatePayloadPer(event, channelWidth, &ni, band, staId, relativeMpduStartStop);
 
-    return PhyEntity::SnrPer(snr, per);
+    return SnrPer(snr, per);
 }
 
 double
@@ -775,7 +769,7 @@
     return CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, nss);
 }
 
-PhyEntity::SnrPer
+SnrPer
 InterferenceHelper::CalculatePhyHeaderSnrPer(Ptr<Event> event,
                                              MHz_u channelWidth,
                                              const WifiSpectrumBandInfo& band,
@@ -791,7 +785,7 @@
      */
     const auto per = CalculatePhyHeaderPer(event, &ni, channelWidth, band, header);
 
-    return PhyEntity::SnrPer(snr, per);
+    return SnrPer(snr, per);
 }
 
 InterferenceHelper::NiChanges::iterator
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/interference-helper.h ns-3.46/src/wifi/model/interference-helper.h
--- ns-3.45/src/wifi/model/interference-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/interference-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -9,10 +9,14 @@
 #ifndef INTERFERENCE_HELPER_H
 #define INTERFERENCE_HELPER_H
 
-#include "phy-entity.h"
+#include "wifi-phy-common.h"
+#include "wifi-ppdu.h"
+#include "wifi-tx-vector.h"
 
 #include "ns3/object.h"
 
+#include <map>
+
 namespace ns3
 {
 
@@ -21,6 +25,11 @@
 class ErrorRateModel;
 
 /**
+ * A map of the received power for each band
+ */
+using RxPowerWattPerChannelBand = std::map<WifiSpectrumBandInfo, Watt_u>;
+
+/**
  * @ingroup wifi
  * @brief handles interference calculations
  * @brief signal event for a PPDU.
@@ -241,11 +250,11 @@
      *
      * @return struct of SNR and PER (with PER being evaluated over the provided time window)
      */
-    PhyEntity::SnrPer CalculatePayloadSnrPer(Ptr<Event> event,
-                                             MHz_u channelWidth,
-                                             const WifiSpectrumBandInfo& band,
-                                             uint16_t staId,
-                                             std::pair<Time, Time> relativeMpduStartStop) const;
+    SnrPer CalculatePayloadSnrPer(Ptr<Event> event,
+                                  MHz_u channelWidth,
+                                  const WifiSpectrumBandInfo& band,
+                                  uint16_t staId,
+                                  std::pair<Time, Time> relativeMpduStartStop) const;
     /**
      * Calculate the SNIR for the event (starting from now until the event end).
      *
@@ -271,10 +280,10 @@
      *
      * @return struct of SNR and PER
      */
-    PhyEntity::SnrPer CalculatePhyHeaderSnrPer(Ptr<Event> event,
-                                               MHz_u channelWidth,
-                                               const WifiSpectrumBandInfo& band,
-                                               WifiPpduField header) const;
+    SnrPer CalculatePhyHeaderSnrPer(Ptr<Event> event,
+                                    MHz_u channelWidth,
+                                    const WifiSpectrumBandInfo& band,
+                                    WifiPpduField header) const;
 
     /**
      * Notify that RX has started.
@@ -365,7 +374,7 @@
          * @param event causes this NI change
          */
         NiChange(Watt_u power, Ptr<Event> event);
-        ~NiChange();
+
         /**
          * Return the power
          *
@@ -505,7 +514,7 @@
      * @param nis the NiChanges
      * @param channelWidth the channel width for header measurement
      * @param band the band
-     * @param phyHeaderSections the map of PHY header sections (\see PhyEntity::PhyHeaderSections)
+     * @param phyHeaderSections the map of PHY header sections (\see PhyHeaderSections)
      *
      * @return the success rate of the PHY header sections
      */
@@ -513,7 +522,7 @@
                                         NiChangesPerBand* nis,
                                         MHz_u channelWidth,
                                         const WifiSpectrumBandInfo& band,
-                                        PhyEntity::PhyHeaderSections phyHeaderSections) const;
+                                        PhyHeaderSections phyHeaderSections) const;
 
     double m_noiseFigure;                 //!< noise figure (linear)
     Ptr<ErrorRateModel> m_errorRateModel; //!< error rate model
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/mgt-action-headers.cc ns-3.46/src/wifi/model/mgt-action-headers.cc
--- ns-3.45/src/wifi/model/mgt-action-headers.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/mgt-action-headers.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1641,6 +1641,7 @@
     }
     if (m_frameCtl.m_capPresenceInd)
     {
+        m_fdCap = FilsDiscHeader::FdCapability{};
         nOctets = m_fdCap->Deserialize(i);
         i.Next(nOctets);
     }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/non-ht/dsss-phy.cc ns-3.46/src/wifi/model/non-ht/dsss-phy.cc
--- ns-3.45/src/wifi/model/non-ht/dsss-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/non-ht/dsss-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -404,7 +404,7 @@
     ConstructorDsss()
     {
         ns3::DsssPhy::InitializeModes();
-        ns3::Ptr<ns3::DsssPhy> phyEntity = ns3::Create<ns3::DsssPhy>();
+        auto phyEntity = std::make_shared<ns3::DsssPhy>();
         ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_HR_DSSS, phyEntity);
         ns3::WifiPhy::AddStaticPhyEntity(
             ns3::WIFI_MOD_CLASS_DSSS,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/non-ht/erp-ofdm-phy.cc ns-3.46/src/wifi/model/non-ht/erp-ofdm-phy.cc
--- ns-3.45/src/wifi/model/non-ht/erp-ofdm-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/non-ht/erp-ofdm-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -252,7 +252,7 @@
     {
         ns3::ErpOfdmPhy::InitializeModes();
         ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_ERP_OFDM,
-                                         ns3::Create<ns3::ErpOfdmPhy>());
+                                         std::make_shared<ns3::ErpOfdmPhy>());
     }
 } g_constructor_erp_ofdm; ///< the constructor for ERP-OFDM modes
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/non-ht/ofdm-phy.cc ns-3.46/src/wifi/model/non-ht/ofdm-phy.cc
--- ns-3.45/src/wifi/model/non-ht/ofdm-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/non-ht/ofdm-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -709,8 +709,9 @@
     ConstructorOfdm()
     {
         ns3::OfdmPhy::InitializeModes();
-        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_OFDM,
-                                         ns3::Create<ns3::OfdmPhy>()); // default variant will do
+        ns3::WifiPhy::AddStaticPhyEntity(
+            ns3::WIFI_MOD_CLASS_OFDM,
+            std::make_shared<ns3::OfdmPhy>()); // default variant will do
     }
 } g_constructor_ofdm; ///< the constructor for OFDM modes
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/phy-entity.cc ns-3.46/src/wifi/model/phy-entity.cc
--- ns-3.45/src/wifi/model/phy-entity.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/phy-entity.cc	2025-10-01 18:46:32.000000000 -0700
@@ -15,13 +15,16 @@
 #include "interference-helper.h"
 #include "preamble-detection-model.h"
 #include "spectrum-wifi-phy.h"
+#include "wifi-net-device.h"
 #include "wifi-psdu.h"
+#include "wifi-radio-energy-model.h"
 #include "wifi-spectrum-signal-parameters.h"
 #include "wifi-utils.h"
 
 #include "ns3/assert.h"
 #include "ns3/data-rate.h"
 #include "ns3/log.h"
+#include "ns3/mobility-model.h"
 #include "ns3/packet.h"
 #include "ns3/simulator.h"
 
@@ -212,7 +215,7 @@
     return ppdu->GetPsdu();
 }
 
-PhyEntity::PhyHeaderSections
+PhyHeaderSections
 PhyEntity::GetPhyHeaderSections(const WifiTxVector& txVector, Time ppduStart) const
 {
     PhyHeaderSections map;
@@ -257,7 +260,7 @@
         .first; // return the start time of field relatively to the beginning of the PPDU
 }
 
-PhyEntity::SnrPer
+SnrPer
 PhyEntity::GetPhyHeaderSnrPer(WifiPpduField field, Ptr<Event> event) const
 {
     const auto measurementChannelWidth = GetMeasurementChannelWidth(event->GetPpdu());
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/phy-entity.h ns-3.46/src/wifi/model/phy-entity.h
--- ns-3.45/src/wifi/model/phy-entity.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/phy-entity.h	2025-10-01 18:46:32.000000000 -0700
@@ -13,6 +13,8 @@
 #define PHY_ENTITY_H
 
 #include "wifi-phy-band.h"
+#include "wifi-phy-state-helper.h"
+#include "wifi-phy.h"
 #include "wifi-ppdu.h"
 #include "wifi-tx-vector.h"
 #include "wifi-types.h"
@@ -20,6 +22,7 @@
 #include "ns3/event-id.h"
 #include "ns3/nstime.h"
 #include "ns3/simple-ref-count.h"
+#include "ns3/wifi-export.h"
 
 #include <list>
 #include <map>
@@ -60,7 +63,7 @@
  * to be used by each PHY entity, corresponding to
  * the different amendments of the IEEE 802.11 standard.
  */
-class PhyEntity : public SimpleRefCount<PhyEntity>
+class WIFI_EXPORT PhyEntity
 {
   public:
     /**
@@ -109,34 +112,6 @@
     };
 
     /**
-     * A struct for both SNR and PER
-     */
-    struct SnrPer
-    {
-        double snr{0.0}; ///< SNR in linear scale
-        double per{1.0}; ///< PER
-
-        /**
-         * Default constructor.
-         */
-        SnrPer()
-        {
-        }
-
-        /**
-         * Constructor for SnrPer.
-         *
-         * @param s the SNR in linear scale
-         * @param p the PER
-         */
-        SnrPer(double s, double p)
-            : snr(s),
-              per(p)
-        {
-        }
-    };
-
-    /**
      * Destructor for PHY entity
      */
     virtual ~PhyEntity();
@@ -283,16 +258,6 @@
     virtual uint32_t GetMaxPsduSize() const = 0;
 
     /**
-     * A pair containing information on the PHY header chunk, namely
-     * the start and stop times of the chunk and the WifiMode used.
-     */
-    typedef std::pair<std::pair<Time /* start */, Time /* stop */>, WifiMode> PhyHeaderChunkInfo;
-    /**
-     * A map of PhyHeaderChunkInfo elements per PPDU field.
-     * @see PhyHeaderChunkInfo
-     */
-    typedef std::map<WifiPpduField, PhyHeaderChunkInfo> PhyHeaderSections;
-    /**
      * Return a map of PHY header chunk information per PPDU field.
      * This map will contain the PPDU fields that are actually present based
      * on the \p txVector information.
@@ -716,7 +681,7 @@
                                     uint16_t staId,
                                     const std::vector<bool>& statusPerMpdu);
     /**
-     * Perform amendment-specific actions when the payload is unsuccessfuly received.
+     * Perform amendment-specific actions when the payload is unsuccessfully received.
      *
      * @param psdu the PSDU that we failed to received
      * @param snr the SNR of the received PSDU in linear scale
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/qos-txop.cc ns-3.46/src/wifi/model/qos-txop.cc
--- ns-3.45/src/wifi/model/qos-txop.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/qos-txop.cc	2025-10-01 18:46:32.000000000 -0700
@@ -177,7 +177,7 @@
 uint8_t
 QosTxop::GetQosQueueSize(uint8_t tid, Mac48Address receiver) const
 {
-    WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WIFI_UNICAST, receiver, tid};
+    WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, receiver, tid};
     uint32_t bufferSize = m_queue->GetNBytes(queueId);
     // A queue size value of 254 is used for all sizes greater than 64 768 octets.
     uint8_t queueSize = static_cast<uint8_t>(std::ceil(std::min(bufferSize, 64769U) / 256.0));
@@ -393,7 +393,8 @@
             return m_queue->PeekFirstAvailable(linkId, mpdu);
         }
         WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE,
-                                     recipient.IsGroup() ? WIFI_GROUPCAST : WIFI_UNICAST,
+                                     recipient.IsGroup() ? WifiRcvAddr::GROUPCAST
+                                                         : WifiRcvAddr::UNICAST,
                                      recipient,
                                      tid);
         if (auto mask = m_mac->GetMacQueueScheduler()->GetQueueLinkMask(m_ac, queueId, linkId);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/qos-utils.h ns-3.46/src/wifi/model/qos-utils.h
--- ns-3.45/src/wifi/model/qos-utils.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/qos-utils.h	2025-10-01 18:46:32.000000000 -0700
@@ -11,6 +11,7 @@
 
 #include "ns3/fatal-error.h"
 #include "ns3/ptr.h"
+#include "ns3/wifi-export.h"
 
 #include <map>
 
@@ -195,7 +196,7 @@
  * Map containing the four ACs in increasing order of priority (according to
  * Table 10-1 "UP-to-AC Mappings" of 802.11-2016)
  */
-extern const std::map<AcIndex, WifiAc> wifiAcList;
+WIFI_EXPORT extern const std::map<AcIndex, WifiAc> wifiAcList;
 
 /**
  * @ingroup wifi
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/sta-wifi-mac.cc ns-3.46/src/wifi/model/sta-wifi-mac.cc
--- ns-3.45/src/wifi/model/sta-wifi-mac.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/sta-wifi-mac.cc	2025-10-01 18:46:32.000000000 -0700
@@ -74,6 +74,12 @@
                           UintegerValue(10),
                           MakeUintegerAccessor(&StaWifiMac::m_maxMissedBeacons),
                           MakeUintegerChecker<uint32_t>())
+            .AddAttribute("EnableScanning",
+                          "If false, STA does not perform channel scanning. This may be useful in "
+                          "case of static configuration via the static setup helper.",
+                          BooleanValue(true),
+                          MakeBooleanAccessor(&StaWifiMac::m_enableScanning),
+                          MakeBooleanChecker())
             .AddAttribute(
                 "ActiveProbing",
                 "If true, we send probe requests. If false, we don't."
@@ -823,6 +829,11 @@
 StaWifiMac::StartScanning()
 {
     NS_LOG_FUNCTION(this);
+    if (!m_enableScanning)
+    {
+        NS_LOG_DEBUG("Scanning disabled");
+        return;
+    }
     SetState(SCANNING);
     NS_ASSERT(m_assocManager);
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/sta-wifi-mac.h ns-3.46/src/wifi/model/sta-wifi-mac.h
--- ns-3.45/src/wifi/model/sta-wifi-mac.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/sta-wifi-mac.h	2025-10-01 18:46:32.000000000 -0700
@@ -148,6 +148,7 @@
     friend class ::AmpduAggregationTest;
     friend class ::MultiLinkOperationsTestBase;
     friend class ::ProbeExchTest;
+    friend class WifiStaticSetupHelper;
 
     /**
      * Struct to hold information regarding observed AP through
@@ -662,6 +663,7 @@
     uint32_t m_maxMissedBeacons;                  ///< maximum missed beacons
     EventId m_beaconWatchdog;                     //!< beacon watchdog
     Time m_beaconWatchdogEnd{0};                  //!< beacon watchdog end
+    bool m_enableScanning;                        //!< enable channel scanning
     bool m_activeProbing;                         ///< active probing
     Ptr<RandomVariableStream> m_probeDelay;       ///< RandomVariable used to randomize the time
                                                   ///< of the first Probe Response on each channel
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/tim.cc ns-3.46/src/wifi/model/tim.cc
--- ns-3.45/src/wifi/model/tim.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/tim.cc	2025-10-01 18:46:32.000000000 -0700
@@ -8,7 +8,7 @@
 
 #include "tim.h"
 
-#include "wifi-constants.h"
+#include "wifi-standard-constants.h"
 
 #include <algorithm>
 #include <cstdint>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/txop.cc ns-3.46/src/wifi/model/txop.cc
--- ns-3.45/src/wifi/model/txop.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/txop.cc	2025-10-01 18:46:32.000000000 -0700
@@ -65,18 +65,6 @@
                                           "AC_BEACON",
                                           AC_UNDEF,
                                           "AC_UNDEF"))
-            // NS_DEPRECATED_3_42
-            .AddAttribute(
-                "MinCw",
-                "The minimum value of the contention window (just for the first link, "
-                "in case of 11be multi-link devices).",
-                TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
-                UintegerValue(15),
-                MakeUintegerAccessor(static_cast<void (Txop::*)(uint32_t)>(&Txop::SetMinCw),
-                                     static_cast<uint32_t (Txop::*)() const>(&Txop::GetMinCw)),
-                MakeUintegerChecker<uint32_t>(),
-                TypeId::SupportLevel::OBSOLETE,
-                "Use MinCws attribute instead of MinCw")
             .AddAttribute(
                 "MinCws",
                 "The minimum values of the contention window for all the links (sorted in "
@@ -87,18 +75,6 @@
                 AttributeContainerValue<UintegerValue>(),
                 MakeAttributeContainerAccessor<UintegerValue>(&Txop::SetMinCws, &Txop::GetMinCws),
                 MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint32_t>()))
-            // NS_DEPRECATED_3_42
-            .AddAttribute(
-                "MaxCw",
-                "The maximum value of the contention window (just for the first link, "
-                "in case of 11be multi-link devices).",
-                TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
-                UintegerValue(1023),
-                MakeUintegerAccessor(static_cast<void (Txop::*)(uint32_t)>(&Txop::SetMaxCw),
-                                     static_cast<uint32_t (Txop::*)() const>(&Txop::GetMaxCw)),
-                MakeUintegerChecker<uint32_t>(),
-                TypeId::SupportLevel::OBSOLETE,
-                "Use MaxCws attribute instead of MaxCw")
             .AddAttribute(
                 "MaxCws",
                 "The maximum values of the contention window for all the links (sorted in "
@@ -109,18 +85,6 @@
                 AttributeContainerValue<UintegerValue>(),
                 MakeAttributeContainerAccessor<UintegerValue>(&Txop::SetMaxCws, &Txop::GetMaxCws),
                 MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint32_t>()))
-            // NS_DEPRECATED_3_42
-            .AddAttribute(
-                "Aifsn",
-                "The AIFSN: the default value conforms to non-QOS (just for the first link, "
-                "in case of 11be multi-link devices).",
-                TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
-                UintegerValue(2),
-                MakeUintegerAccessor(static_cast<void (Txop::*)(uint8_t)>(&Txop::SetAifsn),
-                                     static_cast<uint8_t (Txop::*)() const>(&Txop::GetAifsn)),
-                MakeUintegerChecker<uint8_t>(),
-                TypeId::SupportLevel::OBSOLETE,
-                "Use Aifsns attribute instead of Aifsn")
             .AddAttribute(
                 "Aifsns",
                 "The values of AIFSN for all the links (sorted in increasing order "
@@ -131,18 +95,6 @@
                 AttributeContainerValue<UintegerValue>(),
                 MakeAttributeContainerAccessor<UintegerValue>(&Txop::SetAifsns, &Txop::GetAifsns),
                 MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint8_t>()))
-            // NS_DEPRECATED_3_42
-            .AddAttribute(
-                "TxopLimit",
-                "The TXOP limit: the default value conforms to non-QoS "
-                "(just for the first link, in case of 11be multi-link devices).",
-                TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
-                TimeValue(MilliSeconds(0)),
-                MakeTimeAccessor(static_cast<void (Txop::*)(Time)>(&Txop::SetTxopLimit),
-                                 static_cast<Time (Txop::*)() const>(&Txop::GetTxopLimit)),
-                MakeTimeChecker(),
-                TypeId::SupportLevel::OBSOLETE,
-                "Use TxopLimits attribute instead of TxopLimit")
             .AddAttribute(
                 "TxopLimits",
                 "The values of TXOP limit for all the links (sorted in increasing order "
@@ -810,10 +762,9 @@
 }
 
 void
-Txop::NotifyOff()
+Txop::NotifyOff(uint8_t linkId)
 {
-    NS_LOG_FUNCTION(this);
-    m_queue->Flush();
+    NS_LOG_FUNCTION(this << linkId);
 }
 
 void
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/txop.h ns-3.46/src/wifi/model/txop.h
--- ns-3.45/src/wifi/model/txop.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/txop.h	2025-10-01 18:46:32.000000000 -0700
@@ -330,9 +330,11 @@
      */
     virtual void NotifySleep(uint8_t linkId);
     /**
-     * When off operation occurs, the queue gets cleaned up.
+     * Notify that the given link is switched off.
+     *
+     * @param linkId the ID of the given link
      */
-    virtual void NotifyOff();
+    virtual void NotifyOff(uint8_t linkId);
     /**
      * When wake up operation occurs on a link, channel access on that link
      * will be restarted.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/vht/vht-phy.cc ns-3.46/src/wifi/model/vht/vht-phy.cc
--- ns-3.45/src/wifi/model/vht/vht-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/vht/vht-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -583,7 +583,7 @@
     ConstructorVht()
     {
         ns3::VhtPhy::InitializeModes();
-        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_VHT, ns3::Create<ns3::VhtPhy>());
+        ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_VHT, std::make_shared<ns3::VhtPhy>());
     }
 } g_constructor_vht; ///< the constructor for VHT modes
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-constants.cc ns-3.46/src/wifi/model/wifi-constants.cc
--- ns-3.45/src/wifi/model/wifi-constants.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-constants.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2024 DERONNE SOFTWARE ENGINEERING
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
- */
-
-#include "wifi-constants.h"
-
-namespace ns3
-{
-
-const Time WIFI_TU = MicroSeconds(1024);
-
-const Time EMLSR_RX_PHY_START_DELAY = MicroSeconds(20);
-
-const Time OFDM_SIFS_TIME_20MHZ = MicroSeconds(16);
-
-const Time OFDM_SLOT_TIME_20MHZ = MicroSeconds(9);
-
-const Time OFDM_SIFS_TIME_10MHZ = MicroSeconds(32);
-
-const Time OFDM_SLOT_TIME_10MHZ = MicroSeconds(13);
-
-const Time OFDM_SIFS_TIME_5MHZ = MicroSeconds(64);
-
-const Time OFDM_SLOT_TIME_5MHZ = MicroSeconds(21);
-
-const Time DSSS_SIFS_TIME = MicroSeconds(10);
-
-const Time DSSS_SLOT_TIME = MicroSeconds(20);
-
-const Time MAX_PROPAGATION_DELAY = MicroSeconds(1);
-
-const Time MEDIUM_SYNC_THRESHOLD = MicroSeconds(72);
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-constants.h ns-3.46/src/wifi/model/wifi-constants.h
--- ns-3.45/src/wifi/model/wifi-constants.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-constants.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2024 DERONNE SOFTWARE ENGINEERING
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
- */
-
-#ifndef WIFI_CONSTANTS_H
-#define WIFI_CONSTANTS_H
-
-#include "ns3/nstime.h"
-
-/**
- * @file
- * @ingroup wifi
- * Declaration of the constants used across wifi module
- */
-
-namespace ns3
-{
-
-/// Wi-Fi Time Unit value in microseconds (see IEEE 802.11-2020 sec. 3.1)
-/// Used to initialize WIFI_TU
-extern const Time WIFI_TU;
-
-/// aRxPHYStartDelay value to use when waiting for a new frame in the context of EMLSR operations
-/// (Sec. 35.3.17 of 802.11be D3.1)
-extern const Time EMLSR_RX_PHY_START_DELAY;
-
-/// aSIFSTime value for OFDM (20 MHz channel spacing)
-/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
-extern const Time OFDM_SIFS_TIME_20MHZ;
-
-/// aSlotTime duration for OFDM (20 MHz channel spacing)
-/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
-extern const Time OFDM_SLOT_TIME_20MHZ;
-
-/// aSIFSTime value for OFDM (10 MHz channel spacing)
-/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
-extern const Time OFDM_SIFS_TIME_10MHZ;
-
-/// aSlotTime duration for OFDM (10 MHz channel spacing)
-/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
-extern const Time OFDM_SLOT_TIME_10MHZ;
-
-/// aSIFSTime value for OFDM (5 MHz channel spacing)
-/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
-extern const Time OFDM_SIFS_TIME_5MHZ;
-
-/// aSlotTime duration for OFDM (5 MHz channel spacing)
-/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
-extern const Time OFDM_SLOT_TIME_5MHZ;
-
-/// aSIFSTime duration for DSSS (Table 16-4 "HR/DSSS PHY characteristics" of 802.11-2020)
-extern const Time DSSS_SIFS_TIME;
-
-/// aSlotTime duration for DSSS (Table 16-4 "HR/DSSS PHY characteristics" of 802.11-2020)
-extern const Time DSSS_SLOT_TIME;
-
-/// maximum propagation delay
-extern const Time MAX_PROPAGATION_DELAY;
-
-/// The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0
-extern const Time MEDIUM_SYNC_THRESHOLD;
-
-/// Subcarrier frequency spacing in Hz (Table 19-6 "Timing-related constants" of 802.11-2020)
-static constexpr uint32_t SUBCARRIER_FREQUENCY_SPACING{312500};
-
-/// Subcarrier frequency spacing for the HE modulated fields in Hz (Table 27-12 "Timing-related
-/// constants" of 802.11ax-2021)
-static constexpr uint32_t SUBCARRIER_FREQUENCY_SPACING_HE{78125};
-
-/// Size of the space of sequence numbers
-static constexpr uint16_t SEQNO_SPACE_SIZE{4096};
-
-/// Size of the half the space of sequence numbers (used to determine old packets)
-static constexpr uint16_t SEQNO_SPACE_HALF_SIZE{SEQNO_SPACE_SIZE / 2};
-
-/// This value conforms to the 802.11 specification
-static constexpr uint16_t MAX_MSDU_SIZE{2304};
-
-/// The length in octets of the IEEE 802.11 MAC FCS field
-static constexpr uint16_t WIFI_MAC_FCS_LENGTH{4};
-
-/// The minimum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
-static constexpr uint32_t WIFI_MIN_RTS_THRESHOLD{0};
-
-/// The maximum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
-static constexpr uint32_t WIFI_MAX_RTS_THRESHOLD{4692480};
-
-/// The default value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
-static constexpr uint32_t WIFI_DEFAULT_RTS_THRESHOLD{WIFI_MAX_RTS_THRESHOLD};
-
-/// The minimum value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
-static constexpr uint32_t WIFI_MIN_FRAG_THRESHOLD{256};
-
-/// The maximum value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
-static constexpr uint32_t WIFI_MAX_FRAG_THRESHOLD{65535};
-
-/// The default value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
-static constexpr uint32_t WIFI_DEFAULT_FRAG_THRESHOLD{WIFI_MAX_FRAG_THRESHOLD};
-
-/// STA_ID to identify a single user (SU)
-static constexpr uint16_t SU_STA_ID{65535};
-
-/// Empty 242-tone RU identifier for HE (Section 26.11.7 802.11ax-2021)
-static constexpr uint8_t EMPTY_242_TONE_HE_RU{113};
-
-/// The minimum value for the association ID (Sec. 9.4.1.8 of 802.11-2020)
-static constexpr uint16_t MIN_AID{1};
-
-/// The maximum value for the association ID (Sec. 9.4.1.8 of 802.11-2020)
-static constexpr uint16_t MAX_AID{2007};
-
-/// STA_ID for a RU that is intended for no user (Section 26.11.1 802.11ax-2021)
-static constexpr uint16_t NO_USER_STA_ID{2046};
-
-/// Unassigned 242-tone RU identifier for EHT (Table Table 36-34 IEEE 802.11be D7.0)
-static constexpr uint8_t UNASSIGNED_242_TONE_EHT_RU{27};
-
-/// The maximum value for the association ID updated since 802.11be (Sec. 9.4.1.8 of 802.11be D7.0)
-static constexpr uint16_t EHT_MAX_AID{2006};
-
-/// AID value for Special User Info field in trigger frames (Sec. 9.3.1.22.3 of 802.11be D7.0)
-static constexpr uint16_t AID_SPECIAL_USER{2007};
-
-} // namespace ns3
-
-#endif /* WIFI_CONSTANTS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-default-ack-manager.cc ns-3.46/src/wifi/model/wifi-default-ack-manager.cc
--- ns-3.45/src/wifi/model/wifi-default-ack-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-default-ack-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -152,7 +152,8 @@
     }
     // * no other frame belonging to this BA agreement is queued (because, in such
     //   a case, a Block Ack is not going to be requested anytime soon)
-    if (auto queueId = WifiContainerQueueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, origReceiver, tid);
+    if (auto queueId =
+            WifiContainerQueueId(WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, origReceiver, tid);
         edca->GetWifiMacQueue()->GetNPackets(queueId) -
             edca->GetBaManager()->GetNBufferedPackets(origReceiver, tid) - seqNumbers.size() <
         1)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac.h ns-3.46/src/wifi/model/wifi-mac.h
--- ns-3.45/src/wifi/model/wifi-mac.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac.h	2025-10-01 18:46:32.000000000 -0700
@@ -89,6 +89,8 @@
 class WifiMac : public Object
 {
   public:
+    friend class WifiStaticSetupHelper;
+
     /**
      * @brief Get the type ID.
      * @return the object TypeId
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac-queue.cc ns-3.46/src/wifi/model/wifi-mac-queue.cc
--- ns-3.45/src/wifi/model/wifi-mac-queue.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac-queue.cc	2025-10-01 18:46:32.000000000 -0700
@@ -318,7 +318,7 @@
     NS_LOG_FUNCTION(this << +tid << dest << item);
     NS_ABORT_IF(dest.IsBroadcast());
     WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE,
-                                 dest.IsGroup() ? WIFI_GROUPCAST : WIFI_UNICAST,
+                                 dest.IsGroup() ? WifiRcvAddr::GROUPCAST : WifiRcvAddr::UNICAST,
                                  dest,
                                  tid);
     return PeekByQueueId(queueId, item);
@@ -387,7 +387,13 @@
 Ptr<WifiMpdu>
 WifiMacQueue::Remove()
 {
-    return Remove(Peek());
+    if (auto queueId = m_scheduler->GetNext(m_ac, std::nullopt, false))
+    {
+        return Remove(GetContainer().GetQueue(queueId.value()).cbegin()->mpdu);
+    }
+
+    NS_LOG_DEBUG("The queue is empty");
+    return nullptr;
 }
 
 Ptr<WifiMpdu>
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac-queue-container.cc ns-3.46/src/wifi/model/wifi-mac-queue-container.cc
--- ns-3.45/src/wifi/model/wifi-mac-queue-container.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac-queue-container.cc	2025-10-01 18:46:32.000000000 -0700
@@ -70,21 +70,21 @@
 {
     const WifiMacHeader& hdr = mpdu->GetHeader();
 
-    WifiReceiverAddressType addrType;
+    WifiRcvAddr addrType;
     Mac48Address address;
     if (hdr.GetAddr1().IsBroadcast())
     {
-        addrType = WIFI_BROADCAST;
+        addrType = WifiRcvAddr::BROADCAST;
         address = hdr.GetAddr2();
     }
     else if (hdr.GetAddr1().IsGroup())
     {
-        addrType = WIFI_GROUPCAST;
+        addrType = WifiRcvAddr::GROUPCAST;
         address = hdr.IsQosAmsdu() ? mpdu->begin()->second.GetDestinationAddr() : hdr.GetAddr1();
     }
     else
     {
-        addrType = WIFI_UNICAST;
+        addrType = WifiRcvAddr::UNICAST;
         address = hdr.GetAddr1();
     }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac-queue-container.h ns-3.46/src/wifi/model/wifi-mac-queue-container.h
--- ns-3.45/src/wifi/model/wifi-mac-queue-container.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac-queue-container.h	2025-10-01 18:46:32.000000000 -0700
@@ -11,6 +11,7 @@
 
 #include "wifi-mac-queue-elem.h"
 
+#include "ns3/deprecated.h"
 #include "ns3/mac48-address.h"
 
 #include <list>
@@ -30,15 +31,30 @@
     WIFI_DATA_QUEUE = 3
 };
 
-/// enumeration of frame directions
-enum WifiReceiverAddressType : uint8_t
+/// enumeration of frame types based on receiver address
+enum class WifiRcvAddr : uint8_t
 {
-    WIFI_UNICAST = 0,
-    WIFI_BROADCAST,
-    WIFI_GROUPCAST
+    UNICAST = 0,
+    BROADCAST,
+    GROUPCAST,
+    COUNT
 };
 
 /**
+ * Deprecated frame types enums.
+ *
+ * Use `WifiRcvAddr` class enum values instead.
+ * @{
+ */
+NS_DEPRECATED_3_46("Use WifiRcvAddr::UNICAST instead")
+static constexpr auto WIFI_UNICAST = WifiRcvAddr::UNICAST;
+NS_DEPRECATED_3_46("Use WifiRcvAddr::BROADCAST instead")
+static constexpr auto WIFI_BROADCAST = WifiRcvAddr::BROADCAST;
+NS_DEPRECATED_3_46("Use WifiRcvAddr::GROUPCAST instead")
+static constexpr auto WIFI_GROUPCAST = WifiRcvAddr::GROUPCAST;
+/**@}*/
+
+/**
  * Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
  *
  * @note that Address has a different meaning depending on container queue type:
@@ -65,8 +81,8 @@
  *
  * The TID is only specified for container queue types holding QoS data frames.
  */
-using WifiContainerQueueId = std::
-    tuple<WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional<uint8_t>>;
+using WifiContainerQueueId =
+    std::tuple<WifiContainerQueueType, WifiRcvAddr, Mac48Address, std::optional<uint8_t>>;
 
 } // namespace ns3
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac-queue-scheduler.h ns-3.46/src/wifi/model/wifi-mac-queue-scheduler.h
--- ns-3.45/src/wifi/model/wifi-mac-queue-scheduler.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac-queue-scheduler.h	2025-10-01 18:46:32.000000000 -0700
@@ -91,32 +91,38 @@
     virtual void SetWifiMac(Ptr<WifiMac> mac);
 
     /**
-     * Get the next queue to serve, which is guaranteed to contain at least an MPDU
-     * whose lifetime has not expired. Queues containing MPDUs that cannot be sent
-     * over the given link (if any) are ignored.
+     * Get the next queue to serve, which is guaranteed to contain at least an MPDU whose lifetime
+     * has not expired. Queues containing MPDUs that cannot be sent over the given link, if any, or
+     * on any link, otherwise, are ignored if and only if <i>skipBlockedQueues</i> is true.
      *
      * @param ac the Access Category that we want to serve
      * @param linkId the ID of the link on which MPDUs contained in the returned queue must be
      *               allowed to be sent
+     * @param skipBlockedQueues whether queues containing MPDUs that cannot be sent over the given
+     *                          link, if any, or on any link, otherwise, must be ignored
      * @return the ID of the selected container queue (if any)
      */
     virtual std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
-                                                        std::optional<uint8_t> linkId) = 0;
+                                                        std::optional<uint8_t> linkId,
+                                                        bool skipBlockedQueues = true) = 0;
     /**
-     * Get the next queue to serve after the given one. The returned queue is
-     * guaranteed to contain at least an MPDU whose lifetime has not expired.
-     * Queues containing MPDUs that cannot be sent over the given link (if any) are ignored.
+     * Get the next queue to serve after the given one. The returned queue is guaranteed to contain
+     * at least an MPDU whose lifetime has not expired. Queues containing MPDUs that cannot be sent
+     * over the given link, if any, or on any link, otherwise, are ignored if and only if
+     * <i>skipBlockedQueues</i> is true.
      *
      * @param ac the Access Category that we want to serve
      * @param linkId the ID of the link on which MPDUs contained in the returned queue must be
      *               allowed to be sent
      * @param prevQueueId the ID of the container queue served previously
+     * @param skipBlockedQueues whether queues containing MPDUs that cannot be sent over the given
+     *                          link, if any, or on any link, otherwise, must be ignored
      * @return the ID of the selected container queue (if any)
      */
-    virtual std::optional<WifiContainerQueueId> GetNext(
-        AcIndex ac,
-        std::optional<uint8_t> linkId,
-        const WifiContainerQueueId& prevQueueId) = 0;
+    virtual std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
+                                                        std::optional<uint8_t> linkId,
+                                                        const WifiContainerQueueId& prevQueueId,
+                                                        bool skipBlockedQueues = true) = 0;
 
     /**
      * Get the list of the IDs of the links the given MPDU (belonging to the given
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac-queue-scheduler-impl.h ns-3.46/src/wifi/model/wifi-mac-queue-scheduler-impl.h
--- ns-3.45/src/wifi/model/wifi-mac-queue-scheduler-impl.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac-queue-scheduler-impl.h	2025-10-01 18:46:32.000000000 -0700
@@ -24,6 +24,7 @@
 #include <vector>
 
 class WifiMacQueueDropOldestTest;
+class WifiMacQueueFlushTest;
 
 namespace ns3
 {
@@ -42,8 +43,9 @@
 class WifiMacQueueSchedulerImpl : public WifiMacQueueScheduler
 {
   public:
-    /// allow WifiMacQueueDropOldestTest class access
+    /// allow test classes access
     friend class ::WifiMacQueueDropOldestTest;
+    friend class ::WifiMacQueueFlushTest;
 
     /**
      * @brief Get the type ID.
@@ -58,15 +60,18 @@
 
     /** @copydoc ns3::WifiMacQueueScheduler::SetWifiMac */
     void SetWifiMac(Ptr<WifiMac> mac) final;
-    /** @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>) */
-    std::optional<WifiContainerQueueId> GetNext(AcIndex ac, std::optional<uint8_t> linkId) final;
+    /** @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>,bool) */
+    std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
+                                                std::optional<uint8_t> linkId,
+                                                bool skipBlockedQueues = true) final;
     /**
      *  @copydoc ns3::WifiMacQueueScheduler::GetNext(AcIndex,std::optional<uint8_t>,
-     *           const WifiContainerQueueId&)
+     *           const WifiContainerQueueId&,bool)
      */
     std::optional<WifiContainerQueueId> GetNext(AcIndex ac,
                                                 std::optional<uint8_t> linkId,
-                                                const WifiContainerQueueId& prevQueueId) final;
+                                                const WifiContainerQueueId& prevQueueId,
+                                                bool skipBlockedQueues = true) final;
     /** @copydoc ns3::WifiMacQueueScheduler::GetLinkIds */
     std::list<uint8_t> GetLinkIds(AcIndex ac,
                                   Ptr<const WifiMpdu> mpdu,
@@ -200,19 +205,23 @@
     typename QueueInfoMap::iterator InitQueueInfo(AcIndex ac, Ptr<const WifiMpdu> mpdu);
 
     /**
-     * Get the next queue to serve. The search starts from the given one. The returned
-     * queue is guaranteed to contain at least an MPDU whose lifetime has not expired.
-     * Queues containing MPDUs that cannot be sent over the given link are ignored.
+     * Get the next queue to serve. The search starts from the given one. The returned queue is
+     * guaranteed to contain at least an MPDU whose lifetime has not expired. Queues containing
+     * MPDUs that cannot be sent over the given link, if any, or on any link, otherwise, are ignored
+     * if and only if <i>skipBlockedQueues</i> is true.
      *
      * @param ac the Access Category that we want to serve
      * @param linkId the ID of the link on which MPDUs contained in the returned queue must be
      *               allowed to be sent
      * @param sortedQueuesIt iterator pointing to the queue we start the search from
+     * @param skipBlockedQueues whether queues containing MPDUs that cannot be sent over the given
+     *                          link, if any, or on any link, otherwise, must be ignored
      * @return the ID of the selected container queue (if any)
      */
     std::optional<WifiContainerQueueId> DoGetNext(AcIndex ac,
                                                   std::optional<uint8_t> linkId,
-                                                  typename SortedQueues::iterator sortedQueuesIt);
+                                                  typename SortedQueues::iterator sortedQueuesIt,
+                                                  bool skipBlockedQueues);
 
     /**
      * Check whether an MPDU has to be dropped before enqueuing the given MPDU.
@@ -703,19 +712,22 @@
 
 template <class Priority, class Compare>
 std::optional<WifiContainerQueueId>
-WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac, std::optional<uint8_t> linkId)
+WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac,
+                                                      std::optional<uint8_t> linkId,
+                                                      bool skipBlockedQueues)
 {
-    NS_LOG_FUNCTION(this << +ac << linkId.has_value());
-    return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin());
+    NS_LOG_FUNCTION(this << +ac << linkId.has_value() << skipBlockedQueues);
+    return DoGetNext(ac, linkId, m_perAcInfo[ac].sortedQueues.begin(), skipBlockedQueues);
 }
 
 template <class Priority, class Compare>
 std::optional<WifiContainerQueueId>
 WifiMacQueueSchedulerImpl<Priority, Compare>::GetNext(AcIndex ac,
                                                       std::optional<uint8_t> linkId,
-                                                      const WifiContainerQueueId& prevQueueId)
+                                                      const WifiContainerQueueId& prevQueueId,
+                                                      bool skipBlockedQueues)
 {
-    NS_LOG_FUNCTION(this << +ac << linkId.has_value());
+    NS_LOG_FUNCTION(this << +ac << linkId.has_value() << skipBlockedQueues);
 
     auto queueInfoIt = m_perAcInfo[ac].queueInfoMap.find(prevQueueId);
     NS_ABORT_IF(queueInfoIt == m_perAcInfo[ac].queueInfoMap.end() ||
@@ -724,7 +736,7 @@
     auto sortedQueuesIt = queueInfoIt->second.priorityIt.value();
     NS_ABORT_IF(sortedQueuesIt == m_perAcInfo[ac].sortedQueues.end());
 
-    return DoGetNext(ac, linkId, ++sortedQueuesIt);
+    return DoGetNext(ac, linkId, ++sortedQueuesIt, skipBlockedQueues);
 }
 
 template <class Priority, class Compare>
@@ -732,9 +744,10 @@
 WifiMacQueueSchedulerImpl<Priority, Compare>::DoGetNext(
     AcIndex ac,
     std::optional<uint8_t> linkId,
-    typename SortedQueues::iterator sortedQueuesIt)
+    typename SortedQueues::iterator sortedQueuesIt,
+    bool skipBlockedQueues)
 {
-    NS_LOG_FUNCTION(this << +ac << linkId.has_value());
+    NS_LOG_FUNCTION(this << +ac << linkId.has_value() << skipBlockedQueues);
     NS_ASSERT(static_cast<uint8_t>(ac) < AC_UNDEF);
 
     while (sortedQueuesIt != m_perAcInfo[ac].sortedQueues.end())
@@ -743,11 +756,13 @@
         const auto& linkIds = queueInfoPair.second.linkIds;
         typename std::decay_t<decltype(linkIds)>::const_iterator linkIt;
 
-        if (!linkId.has_value() ||
-            ((linkIt = linkIds.find(*linkId)) != linkIds.cend() && linkIt->second.none()))
+        if (!skipBlockedQueues ||
+            std::any_of(linkIds.cbegin(), linkIds.cend(), [&linkId](const auto& linkIdMask) {
+                return (!linkId.has_value() || linkId == linkIdMask.first) &&
+                       linkIdMask.second.none();
+            }))
         {
-            // Packets in this queue can be sent over the link we got channel access on.
-            // Now remove packets with expired lifetime from this queue.
+            // Remove packets with expired lifetime from this queue.
             // In case the queue becomes empty, the queue is removed from the sorted
             // list and sortedQueuesIt is invalidated; thus, store an iterator to the
             // previous queue in the sorted list (if any) to resume the search afterwards.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mac-trailer.h ns-3.46/src/wifi/model/wifi-mac-trailer.h
--- ns-3.45/src/wifi/model/wifi-mac-trailer.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mac-trailer.h	2025-10-01 18:46:32.000000000 -0700
@@ -9,7 +9,7 @@
 #ifndef WIFI_MAC_TRAILER_H
 #define WIFI_MAC_TRAILER_H
 
-#include "wifi-constants.h"
+#include "wifi-standard-constants.h"
 
 #include "ns3/trailer.h"
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-mode.h ns-3.46/src/wifi/model/wifi-mode.h
--- ns-3.45/src/wifi/model/wifi-mode.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-mode.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,8 +10,8 @@
 #ifndef WIFI_MODE_H
 #define WIFI_MODE_H
 
-#include "wifi-constants.h"
 #include "wifi-phy-common.h"
+#include "wifi-standard-constants.h"
 
 #include "ns3/attribute-helper.h"
 #include "ns3/callback.h"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-net-device.cc ns-3.46/src/wifi/model/wifi-net-device.cc
--- ns-3.45/src/wifi/model/wifi-net-device.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-net-device.cc	2025-10-01 18:46:32.000000000 -0700
@@ -12,6 +12,7 @@
 #include "sta-wifi-mac.h"
 #include "wifi-phy.h"
 
+#include "ns3/boolean.h"
 #include "ns3/channel.h"
 #include "ns3/eht-configuration.h"
 #include "ns3/he-configuration.h"
@@ -655,4 +656,20 @@
     return (m_standard >= WIFI_STANDARD_80211be ? m_ehtConfiguration : nullptr);
 }
 
+bool
+WifiNetDevice::IsEmlsrActivated() const
+{
+    if (!m_ehtConfiguration)
+    {
+        return false;
+    }
+
+    BooleanValue emlsrActivated;
+    if (!m_ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated))
+    {
+        return false;
+    }
+    return emlsrActivated.Get();
+}
+
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-net-device.h ns-3.46/src/wifi/model/wifi-net-device.h
--- ns-3.45/src/wifi/model/wifi-net-device.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-net-device.h	2025-10-01 18:46:32.000000000 -0700
@@ -169,6 +169,11 @@
      */
     Ptr<EhtConfiguration> GetEhtConfiguration() const;
 
+    /**
+     *  @return true if device supports EMLSR, otherwise false
+     */
+    bool IsEmlsrActivated() const;
+
     void SetIfIndex(const uint32_t index) override;
     uint32_t GetIfIndex() const override;
     Ptr<Channel> GetChannel() const override;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-ns3-constants.h ns-3.46/src/wifi/model/wifi-ns3-constants.h
--- ns-3.45/src/wifi/model/wifi-ns3-constants.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/model/wifi-ns3-constants.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2025
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sharan Naribole <sharan.naribole@gmail.com>
+ */
+
+#ifndef WIFI_NS3_CONSTANTS_H
+#define WIFI_NS3_CONSTANTS_H
+
+/**
+ * @file
+ * @ingroup wifi
+ * Declaration of default values used across wifi module
+ */
+
+namespace ns3
+{
+
+/// UL MU Data Disable flag at non-AP STA
+static constexpr bool DEFAULT_WIFI_UL_MU_DATA_DISABLE{false};
+
+/// UL MU Data Disable Rx support at AP
+static constexpr bool DEFAULT_WIFI_UL_MU_DATA_DISABLE_RX{true};
+
+} // namespace ns3
+
+#endif /* WIFI_NS3_CONSTANTS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy.cc ns-3.46/src/wifi/model/wifi-phy.cc
--- ns-3.45/src/wifi/model/wifi-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy.cc	2025-10-01 18:46:32.000000000 -0700
@@ -12,6 +12,7 @@
 #include "error-rate-model.h"
 #include "frame-capture-model.h"
 #include "interference-helper.h"
+#include "phy-entity.h"
 #include "preamble-detection-model.h"
 #include "wifi-net-device.h"
 #include "wifi-ppdu.h"
@@ -19,7 +20,6 @@
 #include "wifi-radio-energy-model.h"
 #include "wifi-utils.h"
 
-#include "ns3/attribute-container.h"
 #include "ns3/channel.h"
 #include "ns3/dsss-phy.h"
 #include "ns3/eht-phy.h" //also includes OFDM, HT, VHT and HE
@@ -32,7 +32,6 @@
 #include "ns3/random-variable-stream.h"
 #include "ns3/simulator.h"
 #include "ns3/string.h"
-#include "ns3/tuple.h"
 #include "ns3/vht-configuration.h"
 
 #include <algorithm>
@@ -88,27 +87,10 @@
                 "Note that the channel width can be left unspecified (0) if the channel "
                 "number uniquely identify a frequency channel for the given standard and band.",
                 StringValue("{0, 0, BAND_UNSPECIFIED, 0}"),
-                MakeAttributeContainerAccessor<
-                    TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
-                    ';'>(static_cast<void (WifiPhy::*)(const ChannelSegments&)>(
-                    &WifiPhy::SetOperatingChannel)),
-                MakeAttributeContainerChecker<
-                    TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
-                    ';'>(MakeTupleChecker<UintegerValue,
-                                          UintegerValue,
-                                          EnumValue<WifiPhyBand>,
-                                          UintegerValue>(
-                    MakeUintegerChecker<uint8_t>(0, 233),
-                    MakeUintegerChecker<MHz_u>(0, 320),
-                    MakeEnumChecker(WifiPhyBand::WIFI_PHY_BAND_2_4GHZ,
-                                    "BAND_2_4GHZ",
-                                    WifiPhyBand::WIFI_PHY_BAND_5GHZ,
-                                    "BAND_5GHZ",
-                                    WifiPhyBand::WIFI_PHY_BAND_6GHZ,
-                                    "BAND_6GHZ",
-                                    WifiPhyBand::WIFI_PHY_BAND_UNSPECIFIED,
-                                    "BAND_UNSPECIFIED"),
-                    MakeUintegerChecker<uint8_t>(0, 15))))
+                MakeAttributeContainerAccessor<ChannelTupleValue, ';'>(
+                    static_cast<void (WifiPhy::*)(const ChannelSegments&)>(
+                        &WifiPhy::SetOperatingChannel)),
+                GetChannelSegmentsChecker())
             .AddAttribute("Frequency",
                           "The center frequency (MHz) of the current operating channel.",
                           TypeId::ATTR_GET,
@@ -385,6 +367,24 @@
     return tid;
 }
 
+Ptr<const AttributeChecker>
+WifiPhy::GetChannelSegmentsChecker()
+{
+    return MakeAttributeContainerChecker<ChannelTupleValue, ';'>(
+        MakeTupleChecker<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>(
+            MakeUintegerChecker<uint8_t>(0, 233),
+            MakeUintegerChecker<uint16_t>(0, 320),
+            MakeEnumChecker(WifiPhyBand::WIFI_PHY_BAND_2_4GHZ,
+                            "BAND_2_4GHZ",
+                            WifiPhyBand::WIFI_PHY_BAND_5GHZ,
+                            "BAND_5GHZ",
+                            WifiPhyBand::WIFI_PHY_BAND_6GHZ,
+                            "BAND_6GHZ",
+                            WifiPhyBand::WIFI_PHY_BAND_UNSPECIFIED,
+                            "BAND_UNSPECIFIED"),
+            MakeUintegerChecker<uint8_t>(0, 15)));
+}
+
 WifiPhy::WifiPhy()
     : m_phyId(0),
       m_txMpduReferenceNumber(0xffffffff),
@@ -470,10 +470,10 @@
     m_phyEntities.clear();
 }
 
-std::map<WifiModulationClass, Ptr<PhyEntity>>&
+std::map<WifiModulationClass, std::shared_ptr<PhyEntity>>&
 WifiPhy::GetStaticPhyEntities()
 {
-    static std::map<WifiModulationClass, Ptr<PhyEntity>> g_staticPhyEntities;
+    static std::map<WifiModulationClass, std::shared_ptr<PhyEntity>> g_staticPhyEntities;
     return g_staticPhyEntities;
 }
 
@@ -756,7 +756,7 @@
     return m_interference->GetErrorRateModel()->CalculateSnr(txVector, ber);
 }
 
-const Ptr<const PhyEntity>
+const std::shared_ptr<const PhyEntity>
 WifiPhy::GetStaticPhyEntity(WifiModulationClass modulation)
 {
     const auto it = GetStaticPhyEntities().find(modulation);
@@ -765,7 +765,7 @@
     return it->second;
 }
 
-Ptr<PhyEntity>
+std::shared_ptr<PhyEntity>
 WifiPhy::GetPhyEntity(WifiModulationClass modulation) const
 {
     const auto it = m_phyEntities.find(modulation);
@@ -774,19 +774,19 @@
     return it->second;
 }
 
-Ptr<PhyEntity>
+std::shared_ptr<PhyEntity>
 WifiPhy::GetPhyEntity(WifiStandard standard) const
 {
     return GetPhyEntity(GetModulationClassForStandard(standard));
 }
 
-Ptr<PhyEntity>
+std::shared_ptr<PhyEntity>
 WifiPhy::GetLatestPhyEntity() const
 {
     return GetPhyEntity(m_standard);
 }
 
-Ptr<PhyEntity>
+std::shared_ptr<PhyEntity>
 WifiPhy::GetPhyEntityForPpdu(const Ptr<const WifiPpdu> ppdu) const
 {
     NS_ABORT_IF(!ppdu);
@@ -807,7 +807,7 @@
 }
 
 void
-WifiPhy::AddStaticPhyEntity(WifiModulationClass modulation, Ptr<PhyEntity> phyEntity)
+WifiPhy::AddStaticPhyEntity(WifiModulationClass modulation, std::shared_ptr<PhyEntity> phyEntity)
 {
     NS_ASSERT_MSG(!GetStaticPhyEntities().contains(modulation),
                   "The PHY entity has already been added. The setting should only be done once per "
@@ -816,7 +816,7 @@
 }
 
 void
-WifiPhy::AddPhyEntity(WifiModulationClass modulation, Ptr<PhyEntity> phyEntity)
+WifiPhy::AddPhyEntity(WifiModulationClass modulation, std::shared_ptr<PhyEntity> phyEntity)
 {
     NS_LOG_FUNCTION(this << modulation);
     NS_ABORT_MSG_IF(!GetStaticPhyEntities().contains(modulation),
@@ -868,7 +868,7 @@
 WifiPhy::Configure80211a()
 {
     NS_LOG_FUNCTION(this);
-    AddPhyEntity(WIFI_MOD_CLASS_OFDM, Create<OfdmPhy>());
+    AddPhyEntity(WIFI_MOD_CLASS_OFDM, std::make_shared<OfdmPhy>());
 
     // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016
     SetSifs(OFDM_SIFS_TIME_20MHZ);
@@ -882,7 +882,7 @@
 WifiPhy::Configure80211b()
 {
     NS_LOG_FUNCTION(this);
-    Ptr<DsssPhy> phyEntity = Create<DsssPhy>();
+    std::shared_ptr<DsssPhy> phyEntity = std::make_shared<DsssPhy>();
     AddPhyEntity(WIFI_MOD_CLASS_HR_DSSS, phyEntity);
     AddPhyEntity(WIFI_MOD_CLASS_DSSS, phyEntity); // when plain DSSS modes are used
 
@@ -903,7 +903,7 @@
     // if the user sets the ShortSlotTimeSupported flag to true and when the BSS
     // consists of only ERP STAs capable of supporting this option.
     Configure80211b();
-    AddPhyEntity(WIFI_MOD_CLASS_ERP_OFDM, Create<ErpOfdmPhy>());
+    AddPhyEntity(WIFI_MOD_CLASS_ERP_OFDM, std::make_shared<ErpOfdmPhy>());
 }
 
 void
@@ -912,7 +912,7 @@
     NS_LOG_FUNCTION(this);
     if (GetChannelWidth() == MHz_u{10})
     {
-        AddPhyEntity(WIFI_MOD_CLASS_OFDM, Create<OfdmPhy>(OFDM_PHY_10_MHZ));
+        AddPhyEntity(WIFI_MOD_CLASS_OFDM, std::make_shared<OfdmPhy>(OFDM_PHY_10_MHZ));
 
         // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016
         SetSifs(OFDM_SIFS_TIME_10MHZ);
@@ -921,7 +921,7 @@
     }
     else if (GetChannelWidth() == MHz_u{5})
     {
-        AddPhyEntity(WIFI_MOD_CLASS_OFDM, Create<OfdmPhy>(OFDM_PHY_5_MHZ));
+        AddPhyEntity(WIFI_MOD_CLASS_OFDM, std::make_shared<OfdmPhy>(OFDM_PHY_5_MHZ));
 
         // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016
         SetSifs(OFDM_SIFS_TIME_5MHZ);
@@ -946,7 +946,7 @@
     {
         Configure80211a();
     }
-    AddPhyEntity(WIFI_MOD_CLASS_HT, Create<HtPhy>(m_txSpatialStreams));
+    AddPhyEntity(WIFI_MOD_CLASS_HT, std::make_shared<HtPhy>(m_txSpatialStreams));
 }
 
 void
@@ -954,7 +954,7 @@
 {
     NS_LOG_FUNCTION(this);
     Configure80211n();
-    AddPhyEntity(WIFI_MOD_CLASS_VHT, Create<VhtPhy>());
+    AddPhyEntity(WIFI_MOD_CLASS_VHT, std::make_shared<VhtPhy>());
 }
 
 void
@@ -969,7 +969,7 @@
     {
         Configure80211ac();
     }
-    AddPhyEntity(WIFI_MOD_CLASS_HE, Create<HePhy>());
+    AddPhyEntity(WIFI_MOD_CLASS_HE, std::make_shared<HePhy>());
 }
 
 void
@@ -977,7 +977,7 @@
 {
     NS_LOG_FUNCTION(this);
     Configure80211ax();
-    AddPhyEntity(WIFI_MOD_CLASS_EHT, Create<EhtPhy>());
+    AddPhyEntity(WIFI_MOD_CLASS_EHT, std::make_shared<EhtPhy>());
 }
 
 void
@@ -1011,7 +1011,7 @@
     if (!m_operatingChannel.IsSet())
     {
         NS_LOG_DEBUG("Setting the operating channel first");
-        SetOperatingChannel(m_channelSettings);
+        SetOperatingChannel(m_channelCfg);
         // return because we are called back by SetOperatingChannel
         return;
     }
@@ -1123,36 +1123,39 @@
 WifiPhy::SetOperatingChannel(const WifiPhyOperatingChannel& channel)
 {
     NS_LOG_FUNCTION(this << channel);
-    ChannelSegments segments{};
+    WifiChannelConfig cfg;
     for (std::size_t segmentId = 0; segmentId < channel.GetNSegments(); ++segmentId)
     {
-        segments.emplace_back(channel.GetNumber(segmentId),
-                              channel.GetWidth(segmentId),
-                              channel.GetPhyBand(),
-                              channel.GetPrimaryChannelIndex(MHz_u{20}));
+        cfg.segments.emplace_back(channel.GetNumber(segmentId),
+                                  channel.GetWidth(segmentId),
+                                  channel.GetPhyBand(),
+                                  channel.GetPrimaryChannelIndex(MHz_u{20}));
     }
-    SetOperatingChannel(segments);
+    SetOperatingChannel(cfg);
 }
 
 void
-WifiPhy::SetOperatingChannel(const ChannelTuple& tuple)
+WifiPhy::SetOperatingChannel(const ChannelSegments& channelSegments)
 {
-    SetOperatingChannel(ChannelSegments{tuple});
+    SetOperatingChannel(WifiChannelConfig(channelSegments));
 }
 
 void
-WifiPhy::SetOperatingChannel(const ChannelSegments& channelSegments)
+WifiPhy::SetOperatingChannel(const WifiChannelConfig& channelCfg)
 {
-    NS_LOG_FUNCTION(this << +std::get<0>(channelSegments.front())
-                         << std::get<1>(channelSegments.front())
-                         << static_cast<WifiPhyBand>(std::get<2>(channelSegments.front()))
-                         << +std::get<3>(channelSegments.front()));
+    NS_LOG_FUNCTION(this << +channelCfg.front().number << channelCfg.front().width
+                         << channelCfg.front().band << +channelCfg.front().p20Index);
 
-    m_channelSettings = channelSegments;
+    if (IsInitialized() && m_operatingChannel.IsSet() && (m_channelCfg == channelCfg))
+    {
+        NS_LOG_DEBUG("Already operating on requested channel");
+        return;
+    }
 
     if (m_standard == WIFI_STANDARD_UNSPECIFIED)
     {
         NS_LOG_DEBUG("Channel information will be applied when a standard is configured");
+        m_channelCfg = channelCfg;
         return;
     }
 
@@ -1167,12 +1170,13 @@
         if (delay.value().IsStrictlyPositive())
         {
             // switching channel has been postponed
-            void (WifiPhy::*fp)(const ChannelSegments&) = &WifiPhy::SetOperatingChannel;
-            Simulator::Schedule(delay.value(), fp, this, channelSegments);
+            Simulator::Schedule(delay.value(), [=, this] { SetOperatingChannel(channelCfg); });
             return;
         }
     }
 
+    m_channelCfg = channelCfg;
+
     // channel can be switched now.
     DoChannelSwitch();
 }
@@ -1219,60 +1223,61 @@
 }
 
 void
-WifiPhy::DoChannelSwitch()
+WifiPhy::SetUnspecifiedChannelParams(WifiChannelConfig& channelCfg, WifiStandard standard)
 {
-    NS_LOG_FUNCTION(this);
-
-    m_powerRestricted = false;
-    m_channelAccessRequested = false;
-
-    // Update unspecified parameters with default values
     std::optional<uint8_t> prevChannelNumber{};
-    for (auto& [number, width, band, primary20] : m_channelSettings)
+    for (auto& [number, width, band, primary20] : channelCfg.segments)
     {
         if (band == WIFI_PHY_BAND_UNSPECIFIED)
         {
-            band = GetDefaultPhyBand(m_standard);
+            band = GetDefaultPhyBand(standard);
         }
         if (width == MHz_u{0} && number == 0)
         {
-            width = GetDefaultChannelWidth(m_standard, static_cast<WifiPhyBand>(band));
+            width = GetDefaultChannelWidth(standard, static_cast<WifiPhyBand>(band));
         }
         if (number == 0)
         {
-            number =
-                WifiPhyOperatingChannel::GetDefaultChannelNumber(width,
-                                                                 m_standard,
-                                                                 static_cast<WifiPhyBand>(band),
-                                                                 prevChannelNumber);
+            number = WifiPhyOperatingChannel::GetDefaultChannelNumber(width,
+                                                                      standard,
+                                                                      band,
+                                                                      prevChannelNumber);
         }
         prevChannelNumber = number;
     }
+}
+
+void
+WifiPhy::DoChannelSwitch()
+{
+    NS_LOG_FUNCTION(this);
+
+    m_powerRestricted = false;
+    m_channelAccessRequested = false;
+
+    // Update unspecified parameters with default values
+    SetUnspecifiedChannelParams(m_channelCfg, m_standard);
 
     // We need to call SetStandard if this is the first time we set a channel or we
     // are changing PHY band. Checking if the new PHY band is different than the
     // previous one covers both cases because initially the PHY band is unspecified
-    bool changingPhyBand =
-        (static_cast<WifiPhyBand>(std::get<2>(m_channelSettings.front())) != m_band);
+    const auto changingPhyBand = (m_channelCfg.front().band != m_band);
 
     NS_ABORT_MSG_IF(IsInitialized() && m_fixedPhyBand && changingPhyBand,
                     "Trying to change PHY band while prohibited.");
 
-    m_band = static_cast<WifiPhyBand>(std::get<2>(m_channelSettings.front()));
+    m_band = m_channelCfg.front().band;
 
     NS_LOG_DEBUG("switching channel");
     std::vector<FrequencyChannelInfo> segments{};
-    std::transform(m_channelSettings.cbegin(),
-                   m_channelSettings.cend(),
+    std::transform(m_channelCfg.segments.cbegin(),
+                   m_channelCfg.segments.cend(),
                    std::back_inserter(segments),
-                   [this](const auto& channelTuple) {
-                       return FrequencyChannelInfo{std::get<0>(channelTuple),
-                                                   MHz_u{0},
-                                                   std::get<1>(channelTuple),
-                                                   m_band};
+                   [this](const auto& segment) {
+                       return FrequencyChannelInfo{segment.number, MHz_u{0}, segment.width, m_band};
                    });
     m_operatingChannel.Set(segments, m_standard);
-    m_operatingChannel.SetPrimary20Index(std::get<3>(m_channelSettings.front()));
+    m_operatingChannel.SetPrimary20Index(m_channelCfg.front().p20Index);
 
     // check that the channel width is supported
     if (const auto chWidth = GetChannelWidth();
@@ -1335,7 +1340,7 @@
         auto phyEntity = m_phyEntities.find(WIFI_MOD_CLASS_HT);
         if (phyEntity != m_phyEntities.end())
         {
-            Ptr<HtPhy> htPhy = DynamicCast<HtPhy>(phyEntity->second);
+            std::shared_ptr<HtPhy> htPhy = std::dynamic_pointer_cast<HtPhy>(phyEntity->second);
             if (htPhy)
             {
                 htPhy->SetMaxSupportedNss(
@@ -1380,7 +1385,7 @@
     std::list<uint8_t> list;
     for (const auto& phyEntity : m_phyEntities)
     {
-        Ptr<HtPhy> htPhy = DynamicCast<HtPhy>(phyEntity.second);
+        std::shared_ptr<HtPhy> htPhy = std::dynamic_pointer_cast<HtPhy>(phyEntity.second);
         if (htPhy)
         {
             list.emplace_back(htPhy->GetBssMembershipSelector());
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy-common.h ns-3.46/src/wifi/model/wifi-phy-common.h
--- ns-3.45/src/wifi/model/wifi-phy-common.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy-common.h	2025-10-01 18:46:32.000000000 -0700
@@ -728,6 +728,45 @@
     {WIFI_CHANLIST_SECONDARY160, 12.0},
 };
 
+/**
+ * A struct for both SNR and PER
+ */
+struct SnrPer
+{
+    double snr{0.0}; ///< SNR in linear scale
+    double per{1.0}; ///< PER
+
+    /**
+     * Default constructor.
+     */
+    SnrPer()
+    {
+    }
+
+    /**
+     * Constructor for SnrPer.
+     *
+     * @param s the SNR in linear scale
+     * @param p the PER
+     */
+    SnrPer(double s, double p)
+        : snr(s),
+          per(p)
+    {
+    }
+};
+
+/**
+ * A pair containing information on the PHY header chunk, namely
+ * the start and stop times of the chunk and the WifiMode used.
+ */
+typedef std::pair<std::pair<Time /* start */, Time /* stop */>, WifiMode> PhyHeaderChunkInfo;
+/**
+ * A map of PhyHeaderChunkInfo elements per PPDU field.
+ * @see PhyHeaderChunkInfo
+ */
+typedef std::map<WifiPpduField, PhyHeaderChunkInfo> PhyHeaderSections;
+
 } // namespace ns3
 
 #endif /* WIFI_PHY_COMMON_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy.h ns-3.46/src/wifi/model/wifi-phy.h
--- ns-3.45/src/wifi/model/wifi-phy.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,12 +10,22 @@
 #ifndef WIFI_PHY_H
 #define WIFI_PHY_H
 
-#include "phy-entity.h"
+#include "frame-capture-model.h"
+#include "interference-helper.h"
+#include "preamble-detection-model.h"
+#include "wifi-net-device.h"
 #include "wifi-phy-operating-channel.h"
 #include "wifi-phy-state-helper.h"
+#include "wifi-radio-energy-model.h"
 #include "wifi-standards.h"
 
+#include "ns3/attribute-container.h"
+#include "ns3/enum.h"
 #include "ns3/error-model.h"
+#include "ns3/mobility-model.h"
+#include "ns3/tuple.h"
+#include "ns3/uinteger.h"
+#include "ns3/wifi-export.h"
 
 #include <limits>
 
@@ -35,6 +45,7 @@
 {
 
 class Channel;
+class PhyEntity;
 class WifiNetDevice;
 class MobilityModel;
 class WifiPhyStateHelper;
@@ -51,7 +62,7 @@
  * @ingroup wifi
  *
  */
-class WifiPhy : public Object
+class WIFI_EXPORT WifiPhy : public Object
 {
   public:
     friend class PhyEntity;
@@ -934,14 +945,45 @@
      */
     Ptr<MobilityModel> GetMobility() const;
 
-    using ChannelTuple = std::tuple<uint8_t /* channel number */,
-                                    MHz_u /* channel width */,
-                                    WifiPhyBand /* WifiPhyBand */,
-                                    uint8_t /* primary20 index*/>; //!< Tuple identifying a segment
-                                                                   //!< of an operating channel
+    /// kept for backward compatibility, can be deprecated when using strong types
+    using ChannelTuple = WifiChannelConfig::SegmentWithoutUnits;
 
-    using ChannelSegments =
-        std::vector<ChannelTuple>; //!< segments identifying an operating channel
+    /// segments identifying an operating channel
+    using ChannelSegments = std::list<WifiChannelConfig::TupleWithoutUnits>;
+
+    /// AttributeValue type of a ChannelTuple object
+    using ChannelTupleValue =
+        TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>;
+
+    /// AttributeValue type of a ChannelSegments object
+    using ChannelSettingsValue = AttributeContainerValue<ChannelTupleValue, ';'>;
+
+    /**
+     * Get a checker for the ChannelSettings attribute, which can be used to deserialize a
+     * ChannelSegments object from a string:
+     *
+     * @code
+     *   WifiPhy::ChannelSettingsValue value;
+     *   value.DeserializeFromString("{36,0,BAND_5GHZ,0}", WifiPhy::GetChannelSegmentsChecker());
+     *   ChannelSettings channel = value.Get();
+     * @endcode
+     *
+     * Note that the WifiChannelConfig::FromString() static function uses the code above to return
+     * a WifiChannelConfig object starting from a string.
+     *
+     * @return a checker for the ChannelSettings attribute
+     */
+    static Ptr<const AttributeChecker> GetChannelSegmentsChecker();
+
+    /**
+     * The ChannelSettings attribute allows users to leave some parameters (e.g., the channel width)
+     * unspecified. This function is used to set such unspecified parameters to their default values
+     * in the given channel config.
+     *
+     * @param channelCfg the given channel settings
+     * @param standard the supported standard
+     */
+    static void SetUnspecifiedChannelParams(WifiChannelConfig& channelCfg, WifiStandard standard);
 
     /**
      * If the standard for this object has not been set yet, store the channel settings
@@ -967,12 +1009,12 @@
     void SetOperatingChannel(const ChannelSegments& channelSegments);
 
     /**
-     * This overloaded function is used when the operating channel
-     * consists of a single segment, identified by a tuple.
+     * This overloaded function is used to pass a WifiChannelConfig object from which
+     * the operating channel can be deduced.
      *
-     * @param tuple the segment identifying the operating channel
+     * @param channelCfg the channel config object
      */
-    void SetOperatingChannel(const ChannelTuple& tuple);
+    void SetOperatingChannel(const WifiChannelConfig& channelCfg);
 
     /**
      * Configure whether it is prohibited to change PHY band after initialization.
@@ -1162,7 +1204,8 @@
      * @param modulation the modulation class
      * @param phyEntity the PHY entity
      */
-    static void AddStaticPhyEntity(WifiModulationClass modulation, Ptr<PhyEntity> phyEntity);
+    static void AddStaticPhyEntity(WifiModulationClass modulation,
+                                   std::shared_ptr<PhyEntity> phyEntity);
 
     /**
      * Get the __implemented__ PHY entity corresponding to the modulation class.
@@ -1172,7 +1215,8 @@
      * @param modulation the modulation class
      * @return the pointer to the static implemented PHY entity
      */
-    static const Ptr<const PhyEntity> GetStaticPhyEntity(WifiModulationClass modulation);
+    static const std::shared_ptr<const PhyEntity> GetStaticPhyEntity(
+        WifiModulationClass modulation);
 
     /**
      * Get the supported PHY entity to use for a received PPDU.
@@ -1185,7 +1229,7 @@
      * @param ppdu the received PPDU
      * @return the pointer to the supported PHY entity
      */
-    Ptr<PhyEntity> GetPhyEntityForPpdu(const Ptr<const WifiPpdu> ppdu) const;
+    std::shared_ptr<PhyEntity> GetPhyEntityForPpdu(const Ptr<const WifiPpdu> ppdu) const;
 
     /**
      * Get the supported PHY entity corresponding to the modulation class.
@@ -1193,20 +1237,20 @@
      * @param modulation the modulation class
      * @return the pointer to the supported PHY entity
      */
-    Ptr<PhyEntity> GetPhyEntity(WifiModulationClass modulation) const;
+    std::shared_ptr<PhyEntity> GetPhyEntity(WifiModulationClass modulation) const;
     /**
      * Get the supported PHY entity corresponding to the wifi standard.
      *
      * @param standard the wifi standard
      * @return the pointer to the supported PHY entity
      */
-    Ptr<PhyEntity> GetPhyEntity(WifiStandard standard) const;
+    std::shared_ptr<PhyEntity> GetPhyEntity(WifiStandard standard) const;
     /**
      * Get the latest PHY entity supported by this PHY instance.
      *
      * @return the latest PHY entity supported by this PHY instance
      */
-    Ptr<PhyEntity> GetLatestPhyEntity() const;
+    std::shared_ptr<PhyEntity> GetLatestPhyEntity() const;
 
     /**
      * @return the UID of the previously received PPDU (reset to UINT64_MAX upon transmission)
@@ -1335,7 +1379,7 @@
      * @param modulation the modulation class
      * @param phyEntity the PHY entity
      */
-    void AddPhyEntity(WifiModulationClass modulation, Ptr<PhyEntity> phyEntity);
+    void AddPhyEntity(WifiModulationClass modulation, std::shared_ptr<PhyEntity> phyEntity);
 
     uint8_t m_phyId; //!< the index of the PHY in the vector of PHYs held by the WifiNetDevice
 
@@ -1378,7 +1422,7 @@
      * looking for WifiMode objects for which
      * WifiMode::IsMandatory() is true.
      */
-    std::map<WifiModulationClass, Ptr<PhyEntity>> m_phyEntities;
+    std::map<WifiModulationClass, std::shared_ptr<PhyEntity>> m_phyEntities;
 
     TracedCallback<Ptr<const WifiPpdu>, const WifiTxVector&>
         m_signalTransmissionCb; //!< Signal Transmission callback
@@ -1599,12 +1643,12 @@
      * For PHY entities supported by a given WifiPhy instance,
      * @see m_phyEntities.
      */
-    static std::map<WifiModulationClass, Ptr<PhyEntity>>& GetStaticPhyEntities();
+    static std::map<WifiModulationClass, std::shared_ptr<PhyEntity>>& GetStaticPhyEntities();
 
     WifiStandard m_standard;                    //!< WifiStandard
     WifiModulationClass m_maxModClassSupported; //!< max modulation class supported
     WifiPhyBand m_band;                         //!< WifiPhyBand
-    ChannelSegments m_channelSettings; //!< Store operating channel settings until initialization
+    WifiChannelConfig m_channelCfg; //!< Store operating channel config until initialization
     WifiPhyOperatingChannel m_operatingChannel; //!< Operating channel
     bool m_fixedPhyBand; //!< True to prohibit changing PHY band after initialization
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy-operating-channel.cc ns-3.46/src/wifi/model/wifi-phy-operating-channel.cc
--- ns-3.45/src/wifi/model/wifi-phy-operating-channel.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy-operating-channel.cc	2025-10-01 18:46:32.000000000 -0700
@@ -276,6 +276,12 @@
     return os;
 }
 
+const std::set<FrequencyChannelInfo>&
+WifiPhyOperatingChannel::GetFrequencyChannels()
+{
+    return m_frequencyChannels;
+}
+
 bool
 WifiPhyOperatingChannel::Compare::operator()(const ConstIterator& first,
                                              const ConstIterator& second) const
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy-operating-channel.h ns-3.46/src/wifi/model/wifi-phy-operating-channel.h
--- ns-3.45/src/wifi/model/wifi-phy-operating-channel.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy-operating-channel.h	2025-10-01 18:46:32.000000000 -0700
@@ -14,6 +14,8 @@
 #include "wifi-phy-common.h"
 #include "wifi-ru.h"
 
+#include "ns3/wifi-export.h"
+
 #include <optional>
 #include <set>
 #include <tuple>
@@ -25,7 +27,7 @@
 /**
  * A structure containing the information about a frequency channel
  */
-struct FrequencyChannelInfo
+struct WIFI_EXPORT FrequencyChannelInfo
 {
     /**
      * @brief spaceship operator.
@@ -57,7 +59,7 @@
  *
  * Class that keeps track of all information about the current PHY operating channel.
  */
-class WifiPhyOperatingChannel
+class WIFI_EXPORT WifiPhyOperatingChannel
 {
   public:
     /// Typedef for a const iterator pointing to a channel in the set of available channels
@@ -128,6 +130,13 @@
         m_frequencyChannels; //!< Available frequency channels
 
     /**
+     * Return a reference to the set of all available frequency channels
+     *
+     * @return reference to the set of frequency channels
+     */
+    static const std::set<FrequencyChannelInfo>& GetFrequencyChannels();
+
+    /**
      * Return true if a valid channel has been set, false otherwise.
      *
      * @return true if a valid channel has been set, false otherwise
@@ -359,7 +368,7 @@
                                    MHz_u width,
                                    WifiStandard standard,
                                    WifiPhyBand band,
-                                   ConstIterator start = m_frequencyChannels.begin());
+                                   ConstIterator start = GetFrequencyChannels().begin());
 
     /**
      * Get channel number of the primary channel
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy-state.h ns-3.46/src/wifi/model/wifi-phy-state.h
--- ns-3.45/src/wifi/model/wifi-phy-state.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy-state.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,7 +10,6 @@
 #ifndef WIFI_PHY_STATE_H
 #define WIFI_PHY_STATE_H
 
-#include "ns3/deprecated.h"
 #include "ns3/fatal-error.h"
 
 namespace ns3
@@ -86,26 +85,4 @@
 
 } // namespace ns3
 
-/**
- * Deprecated WifiPhyState enums.
- *
- * Use WifiPhyState class enum symbols instead.
- * @{
- */
-NS_DEPRECATED_3_42("Use WifiPhyState::IDLE instead")
-static constexpr auto IDLE = ns3::WifiPhyState::IDLE;
-NS_DEPRECATED_3_42("Use WifiPhyState::CCA_BUSY instead")
-static constexpr auto CCA_BUSY = ns3::WifiPhyState::CCA_BUSY;
-NS_DEPRECATED_3_42("Use WifiPhyState::TX instead")
-static constexpr auto TX = ns3::WifiPhyState::TX;
-NS_DEPRECATED_3_42("Use WifiPhyState::RX instead")
-static constexpr auto RX = ns3::WifiPhyState::RX;
-NS_DEPRECATED_3_42("Use WifiPhyState::SWITCHING instead")
-static constexpr auto SWITCHING = ns3::WifiPhyState::SWITCHING;
-NS_DEPRECATED_3_42("Use WifiPhyState::SLEEP instead")
-static constexpr auto SLEEP = ns3::WifiPhyState::SLEEP;
-NS_DEPRECATED_3_42("Use WifiPhyState::OFF instead")
-static constexpr auto OFF = ns3::WifiPhyState::OFF;
-/**@}*/
-
 #endif /* WIFI_PHY_STATE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy-state-helper.cc ns-3.46/src/wifi/model/wifi-phy-state-helper.cc
--- ns-3.45/src/wifi/model/wifi-phy-state-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy-state-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -51,7 +51,7 @@
                 MakeTraceSourceAccessor(&WifiPhyStateHelper::m_rxOutcomeTrace),
                 "ns3::WifiPhyStateHelper::RxOutcomeTracedCallback")
             .AddTraceSource("RxError",
-                            "A packet has been received unsuccessfuly.",
+                            "A packet has been received unsuccessfully.",
                             MakeTraceSourceAccessor(&WifiPhyStateHelper::m_rxErrorTrace),
                             "ns3::WifiPhyStateHelper::RxEndErrorTracedCallback")
             .AddTraceSource("Tx",
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-phy-state-helper.h ns-3.46/src/wifi/model/wifi-phy-state-helper.h
--- ns-3.45/src/wifi/model/wifi-phy-state-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-phy-state-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -9,7 +9,6 @@
 #ifndef WIFI_PHY_STATE_HELPER_H
 #define WIFI_PHY_STATE_HELPER_H
 
-#include "phy-entity.h"
 #include "wifi-phy-common.h"
 #include "wifi-phy-state.h"
 #include "wifi-ppdu.h"
@@ -18,6 +17,7 @@
 #include "ns3/nstime.h"
 #include "ns3/object.h"
 #include "ns3/traced-callback.h"
+#include "ns3/wifi-export.h"
 
 #include <algorithm>
 #include <list>
@@ -51,9 +51,9 @@
                  const std::vector<bool>&>
     RxOkCallback;
 /**
- * Callback if PSDU unsuccessfuly received
+ * Callback if PSDU unsuccessfully received
  *
- * arg1: PSDU received unsuccessfuly
+ * arg1: PSDU received unsuccessfully
  */
 typedef Callback<void, Ptr<const WifiPsdu>> RxErrorCallback;
 
@@ -62,7 +62,7 @@
  *
  * This objects implements the PHY state machine of the Wifi device.
  */
-class WifiPhyStateHelper : public Object
+class WIFI_EXPORT WifiPhyStateHelper : public Object
 {
   public:
     /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-remote-station-manager.cc ns-3.46/src/wifi/model/wifi-remote-station-manager.cc
--- ns-3.45/src/wifi/model/wifi-remote-station-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-remote-station-manager.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1168,9 +1168,9 @@
     const auto& hdr = psdu->GetHeader(0);
 
     if (hdr.IsMgt() || (hdr.IsData() && !hdr.IsQosData()) ||
-        (hdr.IsQosData() && (!m_wifiMac->GetBaAgreementEstablishedAsOriginator(
-                                hdr.GetAddr1(),
-                                hdr.GetQosTid() || m_incrRetryCountUnderBa))))
+        (hdr.IsQosData() &&
+         (!m_wifiMac->GetBaAgreementEstablishedAsOriginator(hdr.GetAddr1(), hdr.GetQosTid()) ||
+          m_incrRetryCountUnderBa)))
     {
         psdu->IncrementRetryCount();
     }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-remote-station-manager.h ns-3.46/src/wifi/model/wifi-remote-station-manager.h
--- ns-3.45/src/wifi/model/wifi-remote-station-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-remote-station-manager.h	2025-10-01 18:46:32.000000000 -0700
@@ -1055,7 +1055,7 @@
      * @param address the address of the receiver
      * @param nSuccessfulMpdus number of successfully transmitted MPDUs
      * A value of 0 means that the Block ACK was missed.
-     * @param nFailedMpdus number of unsuccessfuly transmitted MPDUs
+     * @param nFailedMpdus number of unsuccessfully transmitted MPDUs
      * @param rxSnr received SNR of the block ack frame itself
      * @param dataSnr data SNR reported by remote station
      * @param dataTxVector the TXVECTOR of the MPDUs we sent
@@ -1540,7 +1540,7 @@
      * @param station the station that sent the DATA to us
      * @param nSuccessfulMpdus number of successfully transmitted MPDUs.
      *        A value of 0 means that the Block ACK was missed.
-     * @param nFailedMpdus number of unsuccessfuly transmitted MPDUs.
+     * @param nFailedMpdus number of unsuccessfully transmitted MPDUs.
      * @param rxSnr received SNR of the block ack frame itself
      * @param dataSnr data SNR reported by remote station
      * @param dataChannelWidth the channel width of the A-MPDU we sent
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-standard-constants.cc ns-3.46/src/wifi/model/wifi-standard-constants.cc
--- ns-3.45/src/wifi/model/wifi-standard-constants.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/model/wifi-standard-constants.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 DERONNE SOFTWARE ENGINEERING
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
+ */
+
+#include "wifi-standard-constants.h"
+
+namespace ns3
+{
+
+const Time WIFI_TU = MicroSeconds(1024);
+
+const Time EMLSR_RX_PHY_START_DELAY = MicroSeconds(20);
+
+const Time OFDM_SIFS_TIME_20MHZ = MicroSeconds(16);
+
+const Time OFDM_SLOT_TIME_20MHZ = MicroSeconds(9);
+
+const Time OFDM_SIFS_TIME_10MHZ = MicroSeconds(32);
+
+const Time OFDM_SLOT_TIME_10MHZ = MicroSeconds(13);
+
+const Time OFDM_SIFS_TIME_5MHZ = MicroSeconds(64);
+
+const Time OFDM_SLOT_TIME_5MHZ = MicroSeconds(21);
+
+const Time DSSS_SIFS_TIME = MicroSeconds(10);
+
+const Time DSSS_SLOT_TIME = MicroSeconds(20);
+
+const Time MAX_PROPAGATION_DELAY = MicroSeconds(1);
+
+const Time MEDIUM_SYNC_THRESHOLD = MicroSeconds(72);
+
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-standard-constants.h ns-3.46/src/wifi/model/wifi-standard-constants.h
--- ns-3.45/src/wifi/model/wifi-standard-constants.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/model/wifi-standard-constants.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024 DERONNE SOFTWARE ENGINEERING
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
+ */
+
+#ifndef WIFI_STANDARD_CONSTANTS_H
+#define WIFI_STANDARD_CONSTANTS_H
+
+#include "ns3/nstime.h"
+#include "ns3/wifi-export.h"
+
+/**
+ * @file
+ * @ingroup wifi
+ * Declaration of the constants used across wifi module
+ */
+
+namespace ns3
+{
+
+/// Wi-Fi Time Unit value in microseconds (see IEEE 802.11-2020 sec. 3.1)
+/// Used to initialize WIFI_TU
+WIFI_EXPORT extern const Time WIFI_TU;
+
+/// aRxPHYStartDelay value to use when waiting for a new frame in the context of EMLSR operations
+/// (Sec. 35.3.17 of 802.11be D3.1)
+extern const Time EMLSR_RX_PHY_START_DELAY;
+
+/// aSIFSTime value for OFDM (20 MHz channel spacing)
+/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
+extern const Time OFDM_SIFS_TIME_20MHZ;
+
+/// aSlotTime duration for OFDM (20 MHz channel spacing)
+/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
+extern const Time OFDM_SLOT_TIME_20MHZ;
+
+/// aSIFSTime value for OFDM (10 MHz channel spacing)
+/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
+extern const Time OFDM_SIFS_TIME_10MHZ;
+
+/// aSlotTime duration for OFDM (10 MHz channel spacing)
+/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
+extern const Time OFDM_SLOT_TIME_10MHZ;
+
+/// aSIFSTime value for OFDM (5 MHz channel spacing)
+/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
+extern const Time OFDM_SIFS_TIME_5MHZ;
+
+/// aSlotTime duration for OFDM (5 MHz channel spacing)
+/// (Table 17-21 "OFDM PHY characteristics" of 802.11-2020)
+extern const Time OFDM_SLOT_TIME_5MHZ;
+
+/// aSIFSTime duration for DSSS (Table 16-4 "HR/DSSS PHY characteristics" of 802.11-2020)
+extern const Time DSSS_SIFS_TIME;
+
+/// aSlotTime duration for DSSS (Table 16-4 "HR/DSSS PHY characteristics" of 802.11-2020)
+extern const Time DSSS_SLOT_TIME;
+
+/// maximum propagation delay
+WIFI_EXPORT extern const Time MAX_PROPAGATION_DELAY;
+
+/// The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0
+WIFI_EXPORT extern const Time MEDIUM_SYNC_THRESHOLD;
+
+/// Subcarrier frequency spacing in Hz (Table 19-6 "Timing-related constants" of 802.11-2020)
+static constexpr uint32_t SUBCARRIER_FREQUENCY_SPACING{312500};
+
+/// Subcarrier frequency spacing for the HE modulated fields in Hz (Table 27-12 "Timing-related
+/// constants" of 802.11ax-2021)
+static constexpr uint32_t SUBCARRIER_FREQUENCY_SPACING_HE{78125};
+
+/// Size of the space of sequence numbers
+static constexpr uint16_t SEQNO_SPACE_SIZE{4096};
+
+/// Size of the half the space of sequence numbers (used to determine old packets)
+static constexpr uint16_t SEQNO_SPACE_HALF_SIZE{SEQNO_SPACE_SIZE / 2};
+
+/// This value conforms to the 802.11 specification
+static constexpr uint16_t MAX_MSDU_SIZE{2304};
+
+/// The length in octets of the IEEE 802.11 MAC FCS field
+static constexpr uint16_t WIFI_MAC_FCS_LENGTH{4};
+
+/// The minimum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
+static constexpr uint32_t WIFI_MIN_RTS_THRESHOLD{0};
+
+/// The maximum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
+static constexpr uint32_t WIFI_MAX_RTS_THRESHOLD{4692480};
+
+/// The default value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
+static constexpr uint32_t WIFI_DEFAULT_RTS_THRESHOLD{WIFI_MAX_RTS_THRESHOLD};
+
+/// The minimum value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
+static constexpr uint32_t WIFI_MIN_FRAG_THRESHOLD{256};
+
+/// The maximum value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
+static constexpr uint32_t WIFI_MAX_FRAG_THRESHOLD{65535};
+
+/// The default value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
+static constexpr uint32_t WIFI_DEFAULT_FRAG_THRESHOLD{WIFI_MAX_FRAG_THRESHOLD};
+
+/// STA_ID to identify a single user (SU)
+static constexpr uint16_t SU_STA_ID{65535};
+
+/// Empty 242-tone RU identifier for HE (Section 26.11.7 802.11ax-2021)
+static constexpr uint8_t EMPTY_242_TONE_HE_RU{113};
+
+/// The minimum value for the association ID (Sec. 9.4.1.8 of 802.11-2020)
+static constexpr uint16_t MIN_AID{1};
+
+/// The maximum value for the association ID (Sec. 9.4.1.8 of 802.11-2020)
+static constexpr uint16_t MAX_AID{2007};
+
+/// STA_ID for a RU that is intended for no user (Section 26.11.1 802.11ax-2021)
+static constexpr uint16_t NO_USER_STA_ID{2046};
+
+/// Unassigned 242-tone RU identifier for EHT (Table Table 36-34 IEEE 802.11be D7.0)
+static constexpr uint8_t UNASSIGNED_242_TONE_EHT_RU{27};
+
+/// The maximum value for the association ID updated since 802.11be (Sec. 9.4.1.8 of 802.11be D7.0)
+static constexpr uint16_t EHT_MAX_AID{2006};
+
+/// AID value for Special User Info field in trigger frames (Sec. 9.3.1.22.3 of 802.11be D7.0)
+static constexpr uint16_t AID_SPECIAL_USER{2007};
+
+} // namespace ns3
+
+#endif /* WIFI_STANDARD_CONSTANTS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-standards.h ns-3.46/src/wifi/model/wifi-standards.h
--- ns-3.45/src/wifi/model/wifi-standards.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-standards.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,10 +10,10 @@
 #define WIFI_STANDARD_H
 
 #include "wifi-phy-band.h"
-#include "wifi-types.h"
 #include "wifi-units.h"
 
 #include "ns3/abort.h"
+#include "ns3/wifi-export.h"
 
 #include <list>
 #include <map>
@@ -78,7 +78,18 @@
 /**
  * @brief map a given standard configured by the user to the allowed PHY bands
  */
-extern const std::map<WifiStandard, std::list<WifiPhyBand>> wifiStandards;
+WIFI_EXPORT extern const std::map<WifiStandard, std::list<WifiPhyBand>> wifiStandards;
+
+/**
+ * @ingroup wifi
+ * @brief Enumeration of frequency channel types
+ */
+enum class FrequencyChannelType : uint8_t
+{
+    DSSS = 0,
+    OFDM,
+    CH_80211P
+};
 
 /**
  * Get the type of the frequency channel for the given standard
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-types.cc ns-3.46/src/wifi/model/wifi-types.cc
--- ns-3.45/src/wifi/model/wifi-types.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/model/wifi-types.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2025 Universita' degli Studi di Napoli Federico II
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Stefano Avallone <stavallo@unina.it>
+ */
+
+#include "wifi-types.h"
+
+#include "wifi-phy.h"
+
+namespace ns3
+{
+
+WifiChannelConfig::WifiChannelConfig(const std::list<TupleWithoutUnits>& tuples)
+{
+    std::for_each(tuples.cbegin(), tuples.cend(), [this](auto&& t) {
+        segments.emplace_back(std::make_from_tuple<SegmentWithoutUnits>(t));
+    });
+}
+
+WifiChannelConfig
+WifiChannelConfig::FromString(const std::string& settings, WifiStandard standard)
+{
+    WifiPhy::ChannelSettingsValue value;
+    value.DeserializeFromString(settings, WifiPhy::GetChannelSegmentsChecker());
+    auto channelCfg = WifiChannelConfig(value.Get());
+    if (standard != WIFI_STANDARD_UNSPECIFIED)
+    {
+        WifiPhy::SetUnspecifiedChannelParams(channelCfg, standard);
+    }
+    return channelCfg;
+}
+
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-types.h ns-3.46/src/wifi/model/wifi-types.h
--- ns-3.45/src/wifi/model/wifi-types.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-types.h	2025-10-01 18:46:32.000000000 -0700
@@ -9,13 +9,18 @@
 #ifndef WIFI_TYPES_H
 #define WIFI_TYPES_H
 
+#include "wifi-phy-band.h"
+#include "wifi-standards.h"
 #include "wifi-units.h"
 
 #include "ns3/fatal-error.h"
 
 #include <compare>
+#include <list>
 #include <map>
 #include <ostream>
+#include <tuple>
+#include <vector>
 
 namespace ns3
 {
@@ -82,14 +87,150 @@
 };
 
 /**
- * @ingroup wifi
- * @brief Enumeration of frequency channel types
+ * Struct defining the configuration of a wifi channel, which can be made of one or multiple
+ * channel segments.
  */
-enum class FrequencyChannelType : uint8_t
+struct WifiChannelConfig
 {
-    DSSS = 0,
-    OFDM,
-    CH_80211P
+    /// a channel segment, as a struct without units for channel width (to be deprecated when using
+    /// strong types)
+    struct SegmentWithoutUnits
+    {
+        uint8_t number{};                            ///< channel number
+        double width{};                              ///< channel width in MHz
+        WifiPhyBand band{WIFI_PHY_BAND_UNSPECIFIED}; ///< PHY band
+        uint8_t p20Index{};                          ///< primary20 index
+
+        /**
+         * Constructor.
+         *
+         * @param n the channel number
+         * @param w the channel width
+         * @param b the PHY band
+         * @param i the primary20 index
+         */
+        SegmentWithoutUnits(uint8_t n, double w, WifiPhyBand b, uint8_t i)
+            : number(n),
+              width(w),
+              band(b),
+              p20Index(i)
+        {
+        }
+    };
+
+    /// a channel segment, as a struct with units for channel width
+    struct Segment
+    {
+        uint8_t number{};                            ///< channel number
+        MHz_u width{};                               ///< channel width
+        WifiPhyBand band{WIFI_PHY_BAND_UNSPECIFIED}; ///< PHY band
+        uint8_t p20Index{};                          ///< primary20 index
+
+        /**
+         * Constructor.
+         *
+         * @param n the channel number
+         * @param w the channel width
+         * @param b the PHY band
+         * @param i the primary20 index
+         */
+        Segment(uint8_t n, MHz_u w, WifiPhyBand b, uint8_t i)
+            : number(n),
+              width(w),
+              band(b),
+              p20Index(i)
+        {
+        }
+
+        /**
+         * Converting constructor (to be deprecated when using strong types)
+         *
+         * @param s a channel segment as a struct without units for channel width
+         */
+        Segment(const SegmentWithoutUnits& s)
+            : number(s.number),
+              width(MHz_u{s.width}),
+              band(s.band),
+              p20Index(s.p20Index)
+        {
+        }
+
+        /**
+         * Three-way comparison operator
+         *
+         * @param rhs right hand side
+         * @return deduced comparison type
+         */
+        auto operator<=>(const Segment& rhs) const = default;
+    };
+
+    std::vector<Segment> segments; ///< channel config
+
+    WifiChannelConfig() = default;
+
+    /**
+     * Construct a channel config from a channel segment
+     *
+     * @param segment the channel segment
+     */
+    WifiChannelConfig(const Segment& segment)
+        : segments(std::vector<Segment>{segment})
+    {
+    }
+
+    /**
+     * Construct a channel config from a segment without units for channel width
+     *
+     * @param s the segment without units for channel width
+     */
+    WifiChannelConfig(const SegmentWithoutUnits& s)
+        : WifiChannelConfig(Segment(s))
+    {
+    }
+
+    /// a channel segment, as a tuple without units for channel width (to be deprecated when using
+    /// strong types)
+    using TupleWithoutUnits = std::tuple<uint64_t /* channel number */,
+                                         uint64_t /* channel width in MHz */,
+                                         WifiPhyBand /* PHY band */,
+                                         uint64_t /* primary20 index*/>;
+
+    /**
+     * Construct a channel config from a list of tuples without units for channel width
+     *
+     * @param tuples the list of tuples without units for channel width
+     */
+    WifiChannelConfig(const std::list<TupleWithoutUnits>& tuples);
+
+    /**
+     * Get the wifi channel config from a WifiPhy::ChannelSettings string
+     *
+     * @param settings the WifiPhy::ChannelSettings string
+     * @param standard the Wi-Fi standard
+     * @return the wifi channel config object
+     */
+    static WifiChannelConfig FromString(const std::string& settings,
+                                        WifiStandard standard = WIFI_STANDARD_UNSPECIFIED);
+
+    /// @return a const reference to the first channel segment
+    const Segment& front() const
+    {
+        return segments.front();
+    }
+
+    /// @return a reference to the first channel segment
+    Segment& front()
+    {
+        return segments.front();
+    }
+
+    /**
+     * Three-way comparison operator
+     *
+     * @param rhs right hand side
+     * @return deduced comparison type
+     */
+    auto operator<=>(const WifiChannelConfig& rhs) const = default;
 };
 
 /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-utils.cc ns-3.46/src/wifi/model/wifi-utils.cc
--- ns-3.45/src/wifi/model/wifi-utils.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-utils.cc	2025-10-01 18:46:32.000000000 -0700
@@ -253,4 +253,21 @@
     return apMac->GetGcrManager()->GetIndividuallyAddressedRecipient(addr1);
 }
 
+FrequencyRange
+GetFrequencyRange(WifiPhyBand band)
+{
+    switch (band)
+    {
+    case WIFI_PHY_BAND_2_4GHZ:
+        return WIFI_SPECTRUM_2_4_GHZ;
+    case WIFI_PHY_BAND_5GHZ:
+        return WIFI_SPECTRUM_5_GHZ;
+    case WIFI_PHY_BAND_6GHZ:
+        return WIFI_SPECTRUM_6_GHZ;
+    default:
+        NS_FATAL_ERROR("Undefined frequency range for " << band);
+        return {};
+    }
+}
+
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/model/wifi-utils.h ns-3.46/src/wifi/model/wifi-utils.h
--- ns-3.45/src/wifi/model/wifi-utils.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/model/wifi-utils.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,7 +10,8 @@
 #define WIFI_UTILS_H
 
 #include "block-ack-type.h"
-#include "wifi-constants.h"
+#include "wifi-spectrum-value-helper.h"
+#include "wifi-standard-constants.h"
 #include "wifi-types.h"
 
 #include "ns3/fatal-error.h"
@@ -66,8 +67,14 @@
     }
 }
 
+/// @brief IEEE 802.11-2020 9.2.4.5.2 TID subfield
+using tid_t = uint8_t;
+
+/// @brief IEEE 802.11be D7.0 Figure 9-207e—Link ID Info field format
+using linkId_t = uint8_t;
+
 /// @brief TID-indexed map of the link set to which the TID is mapped
-using WifiTidLinkMapping = std::map<uint8_t, std::set<uint8_t>>;
+using WifiTidLinkMapping = std::map<tid_t, std::set<linkId_t>>;
 
 /**
  * Convert from dBm to Watts.
@@ -275,6 +282,14 @@
  */
 Mac48Address GetIndividuallyAddressedRecipient(Ptr<WifiMac> mac, const WifiMacHeader& hdr);
 
+/**
+ * Get the frequency range corresponding to the given PHY band.
+ *
+ * @param band the given PHY band
+ * @return the frequency range corresponding to the given PHY band
+ */
+FrequencyRange GetFrequencyRange(WifiPhyBand band);
+
 /// Link ID for single link operations (helps tracking places where correct link
 /// ID is to be used to support multi-link operations)
 static constexpr uint8_t SINGLE_LINK_OP_ID = 0;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/channel-access-manager-test.cc ns-3.46/src/wifi/test/channel-access-manager-test.cc
--- ns-3.45/src/wifi/test/channel-access-manager-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/channel-access-manager-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -76,10 +76,6 @@
     void NotifyChannelAccessed(uint8_t linkId, Time txopDuration = Seconds(0)) override;
     /// @copydoc ns3::Txop::HasFramesToTransmit
     bool HasFramesToTransmit(uint8_t linkId) override;
-    /// @copydoc ns3::Txop::NotifySleep
-    void NotifySleep(uint8_t linkId) override;
-    /// @copydoc ns3::Txop::NotifyWakeUp
-    void NotifyWakeUp(uint8_t linkId) override;
     /// @copydoc ns3::Txop::GenerateBackoff
     void GenerateBackoff(uint8_t linkId) override;
 
@@ -117,8 +113,18 @@
 class ChannelAccessManagerStub : public ChannelAccessManager
 {
   public:
-    ChannelAccessManagerStub()
+    /**
+     * @brief Get the type ID.
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId()
     {
+        static TypeId tid = TypeId("ns3::ChannelAccessManagerStub")
+                                .SetParent<ns3::ChannelAccessManager>()
+                                .SetGroupName("Wifi")
+                                .AddConstructor<ChannelAccessManagerStub>()
+                                .HideFromDocumentation();
+        return tid;
     }
 
     /**
@@ -232,6 +238,17 @@
 class ChannelAccessManagerTest : public TestCase
 {
   public:
+    /// Input parameters for the StartTest function
+    struct Params
+    {
+        uint64_t slotTime{4};          ///< the slot time in microseconds
+        uint64_t sifs{6};              ///< the SIFS in microseconds
+        uint64_t eifsNoDifsNoSifs{10}; ///< the EIFS no DIFS no SIFS in microseconds
+        uint32_t ackTimeoutValue{20};  ///< the Ack timeout value in microseconds
+        MHz_u chWidth{20};             ///< the channel width
+        uint64_t resetBackoffThr{};    ///< reset backoff threshold
+    };
+
     ChannelAccessManagerTest();
     void DoRun() override;
 
@@ -258,17 +275,9 @@
   private:
     /**
      * Start test function
-     * @param slotTime the slot time
-     * @param sifs the SIFS
-     * @param eifsNoDifsNoSifs the EIFS no DIFS no SIFS
-     * @param ackTimeoutValue the Ack timeout value
-     * @param chWidth the channel width
-     */
-    void StartTest(uint64_t slotTime,
-                   uint64_t sifs,
-                   uint64_t eifsNoDifsNoSifs,
-                   uint32_t ackTimeoutValue = 20,
-                   MHz_u chWidth = MHz_u{20});
+     * @param params the parameters for this function
+     */
+    void StartTest(const Params& params);
     /**
      * Add Txop function
      * @param aifsn the AIFSN
@@ -418,10 +427,9 @@
      *
      * @param at the event time
      * @param duration the duration of the interval during which no PHY is connected
-     * @param threshold the value for the ResetBackoffThreshold attribute
      * @param from the index of the Txop that has to request channel access when PHY is reconnected
      */
-    void AddPhyDisconnectEvt(uint64_t at, uint64_t duration, uint64_t threshold, uint32_t from);
+    void AddPhyDisconnectEvt(uint64_t at, uint64_t duration, uint32_t from);
 
     /**
      * Add a PHY reconnect event consisting in another PHY operating on the link for the given time.
@@ -431,6 +439,22 @@
      */
     void AddPhyReconnectEvt(uint64_t at, uint64_t duration);
 
+    /**
+     * Add PHY sleep/resume events.
+     *
+     * @param at the event time
+     * @param duration the duration of the interval during which the PHY is in sleep state
+     */
+    void AddPhySleepEvt(uint64_t at, uint64_t duration);
+
+    /**
+     * Add PHY off/on events.
+     *
+     * @param at the event time
+     * @param duration the duration of the interval during which the PHY is in off state
+     */
+    void AddPhyOffEvt(uint64_t at, uint64_t duration);
+
     typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests; //!< the TXOP tests typedef
 
     Ptr<FrameExchangeManagerStub<TxopType>> m_feManager;  //!< the Frame Exchange Manager stubbed
@@ -485,18 +509,6 @@
 }
 
 template <typename TxopType>
-void
-TxopTest<TxopType>::NotifySleep(uint8_t linkId)
-{
-}
-
-template <typename TxopType>
-void
-TxopTest<TxopType>::NotifyWakeUp(uint8_t linkId)
-{
-}
-
-template <typename TxopType>
 ChannelAccessManagerTest<TxopType>::ChannelAccessManagerTest()
     : TestCase("ChannelAccessManager")
 {
@@ -628,19 +640,17 @@
 
 template <typename TxopType>
 void
-ChannelAccessManagerTest<TxopType>::StartTest(uint64_t slotTime,
-                                              uint64_t sifs,
-                                              uint64_t eifsNoDifsNoSifs,
-                                              uint32_t ackTimeoutValue,
-                                              MHz_u chWidth)
+ChannelAccessManagerTest<TxopType>::StartTest(const Params& params)
 {
-    m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub>();
+    m_ChannelAccessManager = CreateObjectWithAttributes<ChannelAccessManagerStub>(
+        "ResetBackoffThreshold",
+        TimeValue(MicroSeconds(params.resetBackoffThr)));
     m_feManager = CreateObject<FrameExchangeManagerStub<TxopType>>(this);
     m_ChannelAccessManager->SetupFrameExchangeManager(m_feManager);
-    m_ChannelAccessManager->SetSlot(MicroSeconds(slotTime));
-    m_ChannelAccessManager->SetSifs(MicroSeconds(sifs));
-    m_ChannelAccessManager->SetEifsNoDifs(MicroSeconds(eifsNoDifsNoSifs + sifs));
-    m_ackTimeoutValue = ackTimeoutValue;
+    m_ChannelAccessManager->SetSlot(MicroSeconds(params.slotTime));
+    m_ChannelAccessManager->SetSifs(MicroSeconds(params.sifs));
+    m_ChannelAccessManager->SetEifsNoDifs(MicroSeconds(params.eifsNoDifsNoSifs + params.sifs));
+    m_ackTimeoutValue = params.ackTimeoutValue;
     // the purpose of the following operations is to initialize the last busy struct
     // of the ChannelAccessManager. Indeed, InitLastBusyStructs(), which is called by
     // SetupPhyListener(), requires an attached PHY to determine the channel types
@@ -648,7 +658,7 @@
     m_phy = CreateObject<SpectrumWifiPhy>();
     m_phy->SetInterferenceHelper(CreateObject<InterferenceHelper>());
     m_phy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
-    m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{0, chWidth, WIFI_PHY_BAND_6GHZ, 0});
+    m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{0, params.chWidth, WIFI_PHY_BAND_6GHZ, 0});
     m_phy->ConfigureStandard(WIFI_STANDARD_80211be); // required to use 320 MHz channels
     m_ChannelAccessManager->SetupPhyListener(m_phy);
 }
@@ -664,7 +674,8 @@
     auto mac = CreateObjectWithAttributes<AdhocWifiMac>(
         "Txop",
         PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
-    mac->SetWifiPhys({nullptr});
+    mac->SetWifiPhys({m_phy});
+    mac->SetChannelAccessManagers({m_ChannelAccessManager});
     txop->SetWifiMac(mac);
     txop->SetAifsn(aifsn);
 }
@@ -910,11 +921,10 @@
 void
 ChannelAccessManagerTest<TxopType>::AddPhyDisconnectEvt(uint64_t at,
                                                         uint64_t duration,
-                                                        uint64_t threshold,
                                                         uint32_t from)
 {
-    m_ChannelAccessManager->SetAttribute("ResetBackoffThreshold",
-                                         TimeValue(MicroSeconds(threshold)));
+    TimeValue threshold;
+    m_ChannelAccessManager->GetAttribute("ResetBackoffThreshold", threshold);
 
     Simulator::Schedule(MicroSeconds(at) - Now(),
                         &ChannelAccessManager::RemovePhyListener,
@@ -925,7 +935,7 @@
         auto txop = m_txop[from];
         auto hadFramesToTransmit = txop->HasFramesToTransmit(SINGLE_LINK_OP_ID);
         m_ChannelAccessManager->SetupPhyListener(m_phy);
-        if (duration > threshold)
+        if (MicroSeconds(duration) > threshold.Get())
         {
             // request channel access again because all backoffs have been reset
             if (m_ChannelAccessManager->NeedBackoffUponAccess(txop, hadFramesToTransmit, true))
@@ -960,6 +970,22 @@
     });
 }
 
+template <typename TxopType>
+void
+ChannelAccessManagerTest<TxopType>::AddPhySleepEvt(uint64_t at, uint64_t duration)
+{
+    Simulator::Schedule(MicroSeconds(at) - Now(), &WifiPhy::SetSleepMode, m_phy, false);
+    Simulator::Schedule(MicroSeconds(at + duration) - Now(), &WifiPhy::ResumeFromSleep, m_phy);
+}
+
+template <typename TxopType>
+void
+ChannelAccessManagerTest<TxopType>::AddPhyOffEvt(uint64_t at, uint64_t duration)
+{
+    Simulator::Schedule(MicroSeconds(at) - Now(), &WifiPhy::SetOffMode, m_phy);
+    Simulator::Schedule(MicroSeconds(at + duration) - Now(), &WifiPhy::ResumeFromOff, m_phy);
+}
+
 /*
  * Specialization of DoRun () method for DCF
  */
@@ -971,7 +997,7 @@
     //  1      4       5    6      8     11      12
     //  | sifs | aifsn | tx | idle | sifs | aifsn | tx |
     //
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddAccessRequest(1, 1, 5, 0);
     AddAccessRequest(8, 2, 12, 0);
@@ -983,7 +1009,7 @@
     //                        7 start rx
     //
 
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddAccessRequest(1, 1, 5, 0);
     AddRxInsideSifsEvt(7, 10);
@@ -1002,7 +1028,7 @@
     //        |
     //       30 request access. backoff slots: 4
 
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddRxOkEvt(80, 20);
@@ -1016,7 +1042,7 @@
     //        |
     //       30 request access. backoff slots: 0
 
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddAccessRequest(30, 2, 70, 0);
@@ -1029,7 +1055,7 @@
     //        |
     //       30 request access. backoff slots: 0
 
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddRxOkEvt(60, 40);
@@ -1042,7 +1068,7 @@
     //  20    60     62     68      72
     //   | rx  | idle | sifs | aifsn | tx |
     //
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddAccessRequest(62, 2, 72, 0);
@@ -1053,7 +1079,7 @@
     //   20   60     70     76      80
     //   | rx  | idle | sifs | aifsn | tx |
     //
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddAccessRequest(70, 2, 80, 0);
@@ -1065,7 +1091,7 @@
     //   |    rx     | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
     //        |      | <------eifs------>|
     //       30 request access. backoff slots: 4
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10});
     AddTxop(1);
     AddRxErrorEvt(20, 40);
     AddAccessRequest(30, 2, 102, 0);
@@ -1079,7 +1105,7 @@
     //   |    rx     | sifs | acktxttime | sifs + aifsn | tx |
     //                             | sifs + aifsn |
     //             request access 70             80
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10});
     AddTxop(1);
     AddRxErrorEvt(20, 40);
     AddAccessRequest(70, 2, 86, 0);
@@ -1091,7 +1117,7 @@
     //   |    rx     |
     //        |
     //       40 force Rx error
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10});
     AddTxop(1);
     AddRxErrorEvt(20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
     ExpectBusy(41, true);      // channel should remain busy for remaining duration
@@ -1105,7 +1131,7 @@
     //   |    rx     | sifs  |   |  rx  | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
     //        |      | <--eifs-->|
     //       30 request access. backoff slots: 4
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10});
     AddTxop(1);
     AddRxErrorEvt(20, 40);
     AddAccessRequest(30, 2, 101, 0);
@@ -1122,7 +1148,7 @@
     // bslot |  tx  |
     //                                                                 94      98     102     106
     //                                                                 110    112
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1); // high priority DCF
     AddTxop(3); // low priority DCF
     AddRxOkEvt(20, 40);
@@ -1140,7 +1166,7 @@
     // DCF1 - low  | sifs | aifsn |   tx   | Ack timeout | sifs |       |
     // DCF0 - high |                              |      | sifs |  tx   |
     //                                            ^ request access
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(0); // high priority DCF
     AddTxop(2); // low priority DCF
     AddAccessRequestWithAckTimeout(20, 20, 34, 1);
@@ -1156,7 +1182,7 @@
     // DCF1 - low  | sifs | aifsn |     tx     | got Ack | sifs |       |
     // DCF0 - high |                                |    | sifs |  tx   |
     //                                              ^ request access
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(0); // high priority DCF
     AddTxop(2); // low priority DCF
     AddAccessRequestWithSuccessfulAck(20, 20, 34, 2, 1);
@@ -1167,7 +1193,7 @@
     //       20     26      34         54     60    62     68      76       80
     //  DCF0  | sifs | aifsn |    tx    | sifs | Ack | sifs | aifsn | bslot0 | tx |
     //                                            ^ request access
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(2);
     AddAccessRequest(20, 20, 34, 0);
     AddRxOkEvt(60, 2); // Ack
@@ -1178,7 +1204,7 @@
     // test simple NAV count. This scenario models a simple Data+Ack handshake
     // where the data rate used for the Ack is higher than expected by the Data source
     // so, the data exchange completes before the end of NAV.
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddNavStart(60, 15);
@@ -1191,7 +1217,7 @@
     // test more complex NAV handling by a CF-poll. This scenario models a
     // simple Data+Ack handshake interrupted by a CF-poll which resets the
     // NAV counter.
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddNavStart(60, 15);
@@ -1204,13 +1230,13 @@
     //  20         60         80     86      94
     //   |    rx    |   idle   | sifs | aifsn |    tx    |
     //                         ^ request access
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(2);
     AddRxOkEvt(20, 40);
     AddAccessRequest(80, 10, 94, 0);
     EndTest();
 
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(2);
     AddRxOkEvt(20, 40);
     AddRxOkEvt(78, 8);
@@ -1223,7 +1249,7 @@
     //  0          20     21     24      25   26
     //  | switching | idle | sifs | aifsn | tx |
     //                     ^ access request.
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddSwitchingEvt(0, 20);
     AddAccessRequest(21, 1, 25, 0);
@@ -1234,7 +1260,7 @@
     //         |          |
     //        30 busy.   45 access request.
     //
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddSwitchingEvt(20, 20);
     AddCcaBusyEvt(30, 20);
@@ -1246,7 +1272,7 @@
     //   |  rx  | switching | idle | sifs | aifsn | tx |
     //                             ^ access request.
     //
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddRxStartEvt(20, 40);
     AddSwitchingEvt(30, 20);
@@ -1257,7 +1283,7 @@
     //   | busy | switching | idle | sifs | aifsn | tx |
     //                             ^ access request.
     //
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddCcaBusyEvt(20, 40);
     AddSwitchingEvt(30, 20);
@@ -1268,7 +1294,7 @@
     //   |  nav  | switching | idle | sifs | aifsn | tx |
     //                              ^ access request.
     //
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddNavStart(20, 40);
     AddSwitchingEvt(30, 20);
@@ -1280,7 +1306,7 @@
     //                                 |                          |
     //                                49 access request.          ^ access request.
     //
-    StartTest(1, 3, 10);
+    StartTest({.slotTime = 1, .sifs = 3});
     AddTxop(1);
     AddAccessRequestWithAckTimeout(20, 20, 24, 0);
     AddAccessRequest(49, 1, 54, 0);
@@ -1293,7 +1319,7 @@
     //        |                                                             |
     //       30 access request.                                             ^ access request.
     //
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 40);
     AddAccessRequest(30, 2, 80, 0);
@@ -1317,7 +1343,7 @@
     //     |  rx  | sifs | aifsn |  tx  |
     //                |
     //               52 request access
-    StartTest(4, 6, 10, 20, MHz_u{40});
+    StartTest({.slotTime = 4, .sifs = 6, .chWidth = MHz_u{40}});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
@@ -1331,7 +1357,7 @@
     //     |  rx  | sifs | aifsn |  tx  |
     //                       |
     //                      58 request access
-    StartTest(4, 6, 10, 20, MHz_u{80});
+    StartTest({.slotTime = 4, .sifs = 6, .chWidth = MHz_u{80}});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
@@ -1345,7 +1371,7 @@
     //     |  rx  | sifs | aifsn | idle |  tx  |
     //                               |
     //                              62 request access
-    StartTest(4, 6, 10, 20, MHz_u{80});
+    StartTest({.slotTime = 4, .sifs = 6, .chWidth = MHz_u{80}});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddCcaBusyEvt(50, 14, WIFI_CHANLIST_SECONDARY40);
@@ -1360,7 +1386,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn |  tx  |
     //                   |
     //                  55 request access
-    StartTest(4, 6, 10, 20, MHz_u{160});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{160}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY);
@@ -1375,7 +1401,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn |  tx  |
     //                                        |
     //                                       70 request access
-    StartTest(4, 6, 10, 20, MHz_u{160});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{160}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY40);
@@ -1390,7 +1416,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn | idle |  tx  |
     //                                                     |
     //                                                    82 request access
-    StartTest(4, 6, 10, 20, MHz_u{160});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{160}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 34, WIFI_CHANLIST_SECONDARY80);
@@ -1405,7 +1431,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn |  tx  |
     //                   |
     //                  55 request access
-    StartTest(4, 6, 10, 20, MHz_u{320});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{320}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY);
@@ -1420,7 +1446,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn |  tx  |
     //                                        |
     //                                       70 request access
-    StartTest(4, 6, 10, 20, MHz_u{320});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{320}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY40);
@@ -1435,7 +1461,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn | idle |  tx  |
     //                                                     |
     //                                                    82 request access
-    StartTest(4, 6, 10, 20, MHz_u{320});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{320}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 34, WIFI_CHANLIST_SECONDARY80);
@@ -1450,7 +1476,7 @@
     //   |    rx    | sifs | acktxttime | sifs + aifsn | idle |  tx  |
     //                                                     |
     //                                                    82 request access
-    StartTest(4, 6, 10, 20, MHz_u{320});
+    StartTest({.slotTime = 4, .sifs = 6, .eifsNoDifsNoSifs = 10, .chWidth = MHz_u{320}});
     AddTxop(1);
     AddRxErrorEvt(20, 30);
     AddCcaBusyEvt(50, 34, WIFI_CHANLIST_SECONDARY160);
@@ -1463,7 +1489,7 @@
     //      |                        |          |          |          |
     //     30 request access.    decrement  decrement  decrement  decrement
     //        backoff slots: 4    slots: 3   slots: 2   slots: 1   slots: 0
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddAccessRequest(30, 20, 76, 0);
@@ -1476,7 +1502,7 @@
     //      |                  |                          |      |
     //   30 request access.  decrement                decrement  decrement
     //    backoff slots: 3    slots: 2                 slots: 1   slots: 0
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddRxOkEvt(61, 10);
@@ -1491,12 +1517,12 @@
     //      |                  |               |
     //   30 request access.  decrement       reset
     //    backoff slots: 3    slots: 2       backoff
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 5});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddAccessRequest(30, 20, 81, 0);
     ExpectBackoff(30, 3, 0);
-    AddPhyDisconnectEvt(61, 10, 0, 0);
+    AddPhyDisconnectEvt(61, 10, 0);
     EndTest();
 
     // Check backoff freeze while no PHY operates on a link for less than the threshold.
@@ -1505,12 +1531,12 @@
     //      |                  |               |              |      |
     //   30 request access.  decrement       resume      decrement  decrement
     //    backoff slots: 3    slots: 2       backoff      slots: 1   slots: 0
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 20});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddAccessRequest(30, 20, 89, 0);
     ExpectBackoff(30, 3, 0);
-    AddPhyDisconnectEvt(61, 10, 20, 0);
+    AddPhyDisconnectEvt(61, 10, 0);
     EndTest();
 
     // Check backoff left unmodified when previous PHY is reconnected to the link
@@ -1520,13 +1546,73 @@
     //      |                      |        |        |        |
     //   30 request access. decrement  decrement  decrement  decrement
     //    backoff slots: 4   slots: 3   slots: 2   slots: 1   slots: 0
-    StartTest(4, 6, 10);
+    StartTest({.slotTime = 4, .sifs = 6});
     AddTxop(1);
     AddRxOkEvt(20, 30);
     AddAccessRequest(30, 20, 76, 0);
     ExpectBackoff(30, 4, 0);
     AddPhyReconnectEvt(61, 10);
     EndTest();
+
+    // Check reset of backoff and generation of new backoff value after that PHY is put to sleep for
+    // more than the threshold.
+    //  20     50     56      60     63          73     79      83       87       91       95    115
+    //   |  rx  | sifs | aifsn | idle | phy sleep | sifs | aifsn |  idle  |  idle  |  idle  |  tx  |
+    //      |                  |                  |              |        |        |
+    //   30 request access.  decrement      reset backoff    decrement  decrement decrement
+    //    backoff slots: 3    slots: 2     backoff slots: 3  slots: 2   slots: 1  slots: 0
+    StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 5});
+    AddTxop(1);
+    AddRxOkEvt(20, 30);
+    AddAccessRequest(30, 20, 95, 0);
+    ExpectBackoff(30, 3, 0);
+    AddPhySleepEvt(63, 10);
+    ExpectBackoff(73, 3, 0);
+    EndTest();
+
+    // Check backoff freeze while PHY is put to sleep for less than the threshold.
+    //  20     50     56      60     61          71     77      81     85     89    109
+    //   |  rx  | sifs | aifsn | idle | phy sleep | sifs | aifsn | idle | idle |  tx  |
+    //      |                  |                  |              |      |
+    //   30 request access.  decrement          resume      decrement  decrement
+    //    backoff slots: 3    slots: 2          backoff      slots: 1   slots: 0
+    StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 20});
+    AddTxop(1);
+    AddRxOkEvt(20, 30);
+    AddAccessRequest(30, 20, 89, 0);
+    ExpectBackoff(30, 3, 0);
+    AddPhySleepEvt(61, 10);
+    EndTest();
+
+    // Check reset of backoff and generation of new backoff value after that PHY is put to off for
+    // more than the threshold.
+    //  20     50     56      60     61        71     77      81       85       89       93    113
+    //   |  rx  | sifs | aifsn | idle | phy off | sifs | aifsn |  idle  |  idle  |  idle  |  tx  |
+    //      |                  |                |              |        |        |
+    //   30 request access.  decrement    reset backoff    decrement  decrement decrement
+    //    backoff slots: 3    slots: 2   backoff slots: 3  slots: 2   slots: 1  slots: 0
+    StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 5});
+    AddTxop(1);
+    AddRxOkEvt(20, 30);
+    AddAccessRequest(30, 20, 93, 0);
+    ExpectBackoff(30, 3, 0);
+    AddPhyOffEvt(61, 10);
+    ExpectBackoff(71, 3, 0);
+    EndTest();
+
+    // Check backoff freeze while PHY is put to off for less than the threshold.
+    //  20     50     56      60     63        73     79      83     87     91    111
+    //   |  rx  | sifs | aifsn | idle | phy off | sifs | aifsn | idle | idle |  tx  |
+    //      |                  |                |              |      |
+    //   30 request access.  decrement        resume      decrement  decrement
+    //    backoff slots: 3    slots: 2        backoff      slots: 1   slots: 0
+    StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 20});
+    AddTxop(1);
+    AddRxOkEvt(20, 30);
+    AddAccessRequest(30, 20, 91, 0);
+    ExpectBackoff(30, 3, 0);
+    AddPhyOffEvt(63, 10);
+    EndTest();
 }
 
 /**
@@ -1748,15 +1834,15 @@
  * that the frame is not transmitted. A backoff value is kept being generated as long as the
  * frame is kept in the queue.
  *
- *                                                       Backoff                             Last
- * Backoff                 Backoff        Backoff        value #3,                          backoff
- * value #0                value #1       value #2       unblock queue                       value
- *  |              ┌─────┐    |              |              |              ┌─────┐   ┌────┐    |
- *  |       ┌───┐  │Assoc│    |    |Decrement|    |Decrement|    |Decrement│ADDBA│   │QoS │    |
- *  |       │ACK│  │Resp │    |AIFS| backoff |slot| backoff |slot| backoff │ Req │. .│data│    |
- * ──┬─────┬┴───┴──┴─────┴┬───┬────────────────────────────────────────────┴─────┴───┴────┴┬───┬──
- *   │Assoc│              │ACK│                                                            │ACK│
- *   │ Req │              └───┘                                                            └───┘
+ *                                                      Backoff                          Last
+ * Backoff                 Backoff          Backoff     value #3,                       backoff
+ * value #0                value #1         value #2    unblock queue                    value
+ *  |              ┌─────┐    |                |           |           ┌─────┐   ┌────┐    |
+ *  |       ┌───┐  │Assoc│    |    | Decrement | Decrement | Decrement │ADDBA│   │QoS │    |
+ *  |       │ACK│  │Resp │    |AIFS|  backoff  |  backoff  |  backoff  │ Req │. .│data│    |
+ * ──┬─────┬┴───┴──┴─────┴┬───┬────────────────────────────────────────┴─────┴───┴────┴┬───┬──
+ *   │Assoc│              │ACK│                                                        │ACK│
+ *   │ Req │              └───┘                                                        └───┘
  *   └─────┘
  *
  * The ProactiveBackoff test checks the generation of backoff values when the attribute is set
@@ -2166,10 +2252,6 @@
                                   offset,
                                   "Backoff value generated too early");
             m_nextBackoffGen.Cancel();
-
-            // we get here when the backoff expired but no transmission occurred, thus we have
-            // generated a new backoff value and we will start decrementing the counter in a slot
-            delay = m_apMac->GetWifiPhy(linkId)->GetSlot();
         }
 
         if (m_nGenBackoff < nValues)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/spectrum-wifi-phy-test.cc ns-3.46/src/wifi/test/spectrum-wifi-phy-test.cc
--- ns-3.45/src/wifi/test/spectrum-wifi-phy-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/spectrum-wifi-phy-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -2299,6 +2299,12 @@
                     txPpduPhy->GetPhyBand());
                 for (auto bw = txPpduPhy->GetChannelWidth(); bw >= MHz_u{20}; bw /= 2)
                 {
+                    if ((j == i) && (bw == m_rxPhys.at(j)->GetChannelWidth()))
+                    {
+                        // this test is not interested in RX PHY staying on the same channel as TX
+                        // PHY
+                        break;
+                    }
                     const auto& channelInfo =
                         (*WifiPhyOperatingChannel::FindFirst(0,
                                                              MHz_u{0},
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/tx-duration-test.cc ns-3.46/src/wifi/test/tx-duration-test.cc
--- ns-3.45/src/wifi/test/tx-duration-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/tx-duration-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -2235,8 +2235,7 @@
      * @param obtained the map of PHY header sections to check
      * @param expected the expected map of PHY header sections
      */
-    void CheckPhyHeaderSections(PhyEntity::PhyHeaderSections obtained,
-                                PhyEntity::PhyHeaderSections expected);
+    void CheckPhyHeaderSections(PhyHeaderSections obtained, PhyHeaderSections expected);
 };
 
 PhyHeaderSectionsTest::PhyHeaderSectionsTest()
@@ -2249,8 +2248,8 @@
 }
 
 void
-PhyHeaderSectionsTest::CheckPhyHeaderSections(PhyEntity::PhyHeaderSections obtained,
-                                              PhyEntity::PhyHeaderSections expected)
+PhyHeaderSectionsTest::CheckPhyHeaderSections(PhyHeaderSections obtained,
+                                              PhyHeaderSections expected)
 {
     NS_ASSERT_MSG(obtained.size() == expected.size(),
                   "The expected map size (" << expected.size() << ") was not obtained ("
@@ -2295,14 +2294,14 @@
 PhyHeaderSectionsTest::DoRun()
 {
     Time ppduStart = Seconds(1);
-    Ptr<PhyEntity> phyEntity;
-    PhyEntity::PhyHeaderSections sections;
+    std::shared_ptr<PhyEntity> phyEntity;
+    PhyHeaderSections sections;
     WifiTxVector txVector;
     WifiMode nonHtMode;
 
     // ==================================================================================
     // 11b (HR/DSSS)
-    phyEntity = Create<DsssPhy>();
+    phyEntity = std::make_shared<DsssPhy>();
     txVector.SetMode(DsssPhy::GetDsssRate1Mbps());
     txVector.SetChannelWidth(MHz_u{22});
 
@@ -2344,7 +2343,7 @@
     };
     for (auto variant : variants)
     {
-        phyEntity = Create<OfdmPhy>(variant.first);
+        phyEntity = std::make_shared<OfdmPhy>(variant.first);
         std::size_t ratio = variant.second;
         const auto bw = MHz_u{20} / ratio;
         txVector.SetChannelWidth(bw);
@@ -2362,7 +2361,7 @@
 
     // ==================================================================================
     // 11g (ERP-OFDM)
-    phyEntity = Create<ErpOfdmPhy>();
+    phyEntity = std::make_shared<ErpOfdmPhy>();
     txVector.SetChannelWidth(MHz_u{20});
     txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(54000000));
     nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps();
@@ -2375,7 +2374,7 @@
 
     // ==================================================================================
     // 11n (HT)
-    phyEntity = Create<HtPhy>(4);
+    phyEntity = std::make_shared<HtPhy>(4);
     txVector.SetChannelWidth(MHz_u{20});
     txVector.SetMode(HtPhy::GetHtMcs6());
     nonHtMode = OfdmPhy::GetOfdmRate6Mbps();
@@ -2410,7 +2409,7 @@
 
     // ==================================================================================
     // 11ac (VHT)
-    phyEntity = Create<VhtPhy>();
+    phyEntity = std::make_shared<VhtPhy>();
     txVector.SetChannelWidth(MHz_u{20});
     txVector.SetNess(0);
     txVector.SetMode(VhtPhy::GetVhtMcs7());
@@ -2453,7 +2452,7 @@
 
     // ==================================================================================
     // 11ax (HE)
-    phyEntity = Create<HePhy>();
+    phyEntity = std::make_shared<HePhy>();
     txVector.SetChannelWidth(MHz_u{20});
     txVector.SetNss(2); // HE-LTF duration assumed to be always 8 us for the time being (see note in
                         // HePhy::GetTrainingDuration)
@@ -2526,7 +2525,7 @@
     // 11be (EHT)
     sections.erase(WIFI_PPDU_FIELD_SIG_A); // FIXME: do we keep using separate type for 11be?
     sections.erase(WIFI_PPDU_FIELD_SIG_B); // FIXME: do we keep using separate type for 11be?
-    phyEntity = Create<EhtPhy>();
+    phyEntity = std::make_shared<EhtPhy>();
     txVector.SetChannelWidth(MHz_u{20});
     txVector.SetNss(2); // EHT-LTF duration assumed to be always 8 us for the time being (see note
                         // in HePhy::GetTrainingDuration)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-channel-switching-test.cc ns-3.46/src/wifi/test/wifi-channel-switching-test.cc
--- ns-3.45/src/wifi/test/wifi-channel-switching-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-channel-switching-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -209,8 +209,6 @@
 void
 WifiChannelSwitchingTest::DoRun()
 {
-    Time simulationTime(Seconds(6));
-
     RngSeedManager::SetSeed(1);
     RngSeedManager::SetRun(40);
     int64_t streamNumber = 100;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-dynamic-bw-op-test.cc ns-3.46/src/wifi/test/wifi-dynamic-bw-op-test.cc
--- ns-3.45/src/wifi/test/wifi-dynamic-bw-op-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-dynamic-bw-op-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -155,8 +155,8 @@
         client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
         client->SetRemote(m_sockets[0]);
         m_apDevices.Get(0)->GetNode()->AddApplication(client);
-        client->SetStartTime(Seconds(0)); // start now
-        client->SetStopTime(Seconds(1));  // stop in a second
+        client->SetStartTime(TimeStep(1)); // start shortly after the start of PPDU in BSS 1
+        client->SetStopTime(Seconds(1));   // stop in a second
         client->Initialize();
 
         // after 1us (to allow for propagation delay), the largest idle primary
@@ -470,20 +470,18 @@
     AddTestCase(
         new WifiUseAvailBwTest({"{50, 160, BAND_5GHZ, 5}", "{42, 80, BAND_5GHZ, 2}"}, MHz_u{80}),
         TestCase::Duration::QUICK);
-    // clang-format off
     /**
-     *                                                                                 ───────────────────────────── primary 160 ─────────────────────────────
-     *                                                                                                    primary20
-     *          ┌────────┬────────┬────────┬────────┬───────┬────────┬────────┬────────┌────────┬────────┬────────┬────────┬───────┬────────┬────────┬────────┐
-     *  BSS 0   │   1    │   5    │   9    │   13   │  17   │   21   │   25   │   29   │   33   │   37   │   41   │   45   │  49   │   53   │   57   │   61   │
-     *          └────────┴────────┴────────┴────────┴───────┴────────┴────────┴────────└────────┴────────┴────────┴────────┴───────┴────────┴────────┴────────┘
+     *                                                  ────────────── primary 160 ──────────────
+     *                                                           primary20
+     *          ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
+     *  BSS 0   │  1 │  5 │  9 │ 13 │ 17 │ 21 │ 25 │ 29 │ 33 │ 37 │ 41 │ 45 │ 49 │ 53 │ 57 │ 61 │
+     *          └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
      *
-     *          ┌────────┬────────┬────────┬────────┬───────┬────────┬────────┬────────┐
-     *  BSS 1   │   1    │   5    │   9    │   13   │  17   │   21   │   25   │   29   │
-     *          └────────┴────────┴────────┴────────┴───────┴────────┴────────┴────────┘
-     *                                                                         primary20
+     *          ┌────┬────┬────┬────┬────┬────┬────┬────┐
+     *  BSS 1   │  1 │  5 │  9 │ 13 │ 17 │ 21 │ 25 │ 29 │
+     *          └────┴────┴────┴────┴────┴────┴────┴────┘
+     *                                            primary20
      */
-    // clang-format on
     AddTestCase(
         new WifiUseAvailBwTest({"{31, 320, BAND_6GHZ, 10}", "{15, 160, BAND_6GHZ, 7}"}, 160),
         TestCase::Duration::QUICK);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-eht-info-elems-test.cc ns-3.46/src/wifi/test/wifi-eht-info-elems-test.cc
--- ns-3.45/src/wifi/test/wifi-eht-info-elems-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-eht-info-elems-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -635,7 +635,7 @@
 
     std::stringstream info;
 
-    if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+    if (channel2_4It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
     {
         WifiPhyOperatingChannel channel(channel2_4It);
 
@@ -652,7 +652,7 @@
         rnr.SetMldParameters(nbrId, 0, {0, 2, 3, 1, 1});
     }
 
-    if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+    if (channel5It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
     {
         WifiPhyOperatingChannel channel(channel5It);
 
@@ -676,7 +676,7 @@
         rnr.SetMldParameters(nbrId, 1, {0, 4, 5, 1, 0});
     }
 
-    if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+    if (channel6It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
     {
         WifiPhyOperatingChannel channel(channel6It);
 
@@ -703,14 +703,15 @@
     PhyOpChannelIt channel2_4It;
     PhyOpChannelIt channel5It;
     PhyOpChannelIt channel6It;
-    channel2_4It = channel5It = channel6It = WifiPhyOperatingChannel::m_frequencyChannels.cbegin();
+    channel2_4It = channel5It = channel6It =
+        WifiPhyOperatingChannel::GetFrequencyChannels().cbegin();
 
     // Test all available frequency channels
-    while (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend() ||
-           channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend() ||
-           channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+    while (channel2_4It != WifiPhyOperatingChannel::GetFrequencyChannels().cend() ||
+           channel5It != WifiPhyOperatingChannel::GetFrequencyChannels().cend() ||
+           channel6It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
     {
-        if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+        if (channel2_4It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
         {
             channel2_4It = WifiPhyOperatingChannel::FindFirst(0,
                                                               MHz_u{0},
@@ -719,7 +720,7 @@
                                                               WIFI_PHY_BAND_2_4GHZ,
                                                               channel2_4It);
         }
-        if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+        if (channel5It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
         {
             channel5It = WifiPhyOperatingChannel::FindFirst(0,
                                                             MHz_u{0},
@@ -728,7 +729,7 @@
                                                             WIFI_PHY_BAND_5GHZ,
                                                             channel5It);
         }
-        if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+        if (channel6It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
         {
             channel6It = WifiPhyOperatingChannel::FindFirst(0,
                                                             MHz_u{0},
@@ -741,15 +742,15 @@
         TestHeaderSerialization(GetReducedNeighborReport(channel2_4It, channel5It, channel6It));
 
         // advance all channel iterators
-        if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+        if (channel2_4It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
         {
             channel2_4It++;
         }
-        if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+        if (channel5It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
         {
             channel5It++;
         }
-        if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
+        if (channel6It != WifiPhyOperatingChannel::GetFrequencyChannels().cend())
         {
             channel6It++;
         }
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-emlsr-basic-exchanges-test.cc ns-3.46/src/wifi/test/wifi-emlsr-basic-exchanges-test.cc
--- ns-3.45/src/wifi/test/wifi-emlsr-basic-exchanges-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-emlsr-basic-exchanges-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -151,8 +151,6 @@
 {
     // Channel switch delay should be less than the ICF padding duration, otherwise
     // DL TXOPs cannot be initiated on auxiliary links
-    auto delay = std::min(MicroSeconds(100),
-                          *std::min_element(m_paddingDelay.cbegin(), m_paddingDelay.cend()));
     Config::SetDefault("ns3::WifiPhy::ChannelSwitchDelay", TimeValue(MicroSeconds(75)));
 
     EmlsrOperationsTestBase::DoSetup();
@@ -778,7 +776,6 @@
         bAckRespTxEnd = bAckRespIt->startTx + WifiPhy::CalculateTxDuration(bAckRespIt->psduMap,
                                                                            bAckRespIt->txVector,
                                                                            phy->GetPhyBand());
-        auto timeout = phy->GetSifs() + phy->GetSlot() + MicroSeconds(20);
 
         // the fourth frame exchange starts a PIFS after the previous one because the AP
         // performs PIFS recovery (the initial frame in the TXOP was successfully received by
@@ -2593,6 +2590,16 @@
                           "RTS before second data frame transmitted on an unexpected width");
     psduIt++;
     // CTS
+    if (m_nonEmlsrLink && psduIt != m_txPsdus.cend() &&
+        psduIt->psduMap.cbegin()->second->GetHeader(0).IsBlockAck())
+    {
+        // in case a non-EMLSR link is present, the QoS data frame (seq. numbers 6 and 7) may be
+        // sent late on that link due to the ongoing backoff, thus the corresponding BlockAck is
+        // transmitted on that link after the RTS but before the CTS transmitted on the other EMLSR
+        // aux link
+        ++psduIt;
+    }
+
     NS_TEST_ASSERT_MSG_EQ((psduIt != m_txPsdus.cend()),
                           true,
                           "CTS before second QoS data frame has not been transmitted");
@@ -2714,9 +2721,12 @@
                           "Fourth data frame not transmitted on the same width as RTS");
 }
 
-EmlsrUlOfdmaTest::EmlsrUlOfdmaTest(bool enableBsrp)
-    : EmlsrOperationsTestBase("Check UL OFDMA operations with an EMLSR client"),
+EmlsrUlOfdmaTest::EmlsrUlOfdmaTest(bool enableBsrp, bool protectSingleExchange)
+    : EmlsrOperationsTestBase("Check UL OFDMA operations with an EMLSR client (enableBsrp=" +
+                              std::to_string(enableBsrp) + ", protectSingleExchange=" +
+                              std::to_string(protectSingleExchange) + ")"),
       m_enableBsrp(enableBsrp),
+      m_protectSingleExchange(protectSingleExchange),
       m_txPsdusPos(0),
       m_startAccessReq(0)
 {
@@ -2733,6 +2743,11 @@
 EmlsrUlOfdmaTest::DoSetup()
 {
     Config::SetDefault("ns3::WifiPhy::ChannelSwitchDelay", TimeValue(m_transitionDelay.at(0)));
+    Config::SetDefault("ns3::QosFrameExchangeManager::ProtectSingleExchange",
+                       BooleanValue(m_protectSingleExchange));
+    Config::SetDefault("ns3::DefaultEmlsrManager::SwitchAuxPhy", BooleanValue(false));
+    Config::SetDefault("ns3::EhtFrameExchangeManager::EarlyTxopEndDetect",
+                       BooleanValue(!(m_enableBsrp && m_protectSingleExchange)));
 
     EmlsrOperationsTestBase::DoSetup();
 
@@ -2765,6 +2780,7 @@
         {
             // this is the first Trigger Frame sent after the AP requested channel access
             // through the Multi-user scheduler and it is an ICF for the EMLSR client
+            m_1stTfLinkId = linkId;
             m_txPsdusPos = m_txPsdus.size() - 1;
             auto txDuration = WifiPhy::CalculateTxDuration(psduMap,
                                                            txVector,
@@ -2795,6 +2811,37 @@
         }
         break;
 
+    case WIFI_MAC_QOSDATA_NULL:
+        if (linkId == m_1stTfLinkId &&
+            psdu->GetAddr2() == m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress())
+        {
+            NS_TEST_EXPECT_MSG_EQ(m_enableBsrp,
+                                  true,
+                                  "EMLSR client is not expected to send a QoS null on the same "
+                                  "link as the first TF when BSRP is disabled");
+
+            // the Duration/ID of the QoS null frame sent by the EMLSR client after the first
+            // Trigger Frame on the same link is zero if and only if ProtectSingleExchange is true
+            NS_TEST_EXPECT_MSG_EQ(psdu->GetDuration().IsZero(),
+                                  m_protectSingleExchange,
+                                  "Unexpected Duration/ID (" << psdu->GetDuration()
+                                                             << ") when ProtectSingleExchange="
+                                                             << m_protectSingleExchange);
+
+            const auto txDuration =
+                WifiPhy::CalculateTxDuration(psduMap,
+                                             txVector,
+                                             mac->GetWifiPhy(linkId)->GetPhyBand());
+            Simulator::Schedule(txDuration + MAX_PROPAGATION_DELAY, [=, this]() {
+                auto ehtFem = StaticCast<EhtFrameExchangeManager>(
+                    m_staMacs[0]->GetFrameExchangeManager(linkId));
+                NS_TEST_EXPECT_MSG_EQ(ehtFem->GetOngoingTxopEndEvent().IsPending(),
+                                      true,
+                                      "After QoS Null frame, the TXOP is not expected to be ended");
+            });
+        }
+        break;
+
     case WIFI_MAC_CTL_BACKRESP:
         if (!m_startAccessReq.IsZero() && Simulator::Now() >= m_startAccessReq)
         {
@@ -3083,8 +3130,14 @@
                     TestCase::Duration::QUICK);
     }
 
-    AddTestCase(new EmlsrUlOfdmaTest(false), TestCase::Duration::QUICK);
-    AddTestCase(new EmlsrUlOfdmaTest(true), TestCase::Duration::QUICK);
+    for (const auto enableBsrp : {true, false})
+    {
+        for (const auto protectSingleExchange : {true, false})
+        {
+            AddTestCase(new EmlsrUlOfdmaTest(enableBsrp, protectSingleExchange),
+                        TestCase::Duration::QUICK);
+        }
+    }
 }
 
 static WifiEmlsrBasicExchangesTestSuite g_wifiEmlsrBasicExchangesTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-emlsr-basic-exchanges-test.h ns-3.46/src/wifi/test/wifi-emlsr-basic-exchanges-test.h
--- ns-3.45/src/wifi/test/wifi-emlsr-basic-exchanges-test.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-emlsr-basic-exchanges-test.h	2025-10-01 18:46:32.000000000 -0700
@@ -392,6 +392,12 @@
  *   (AP MLD has blocked transmissions to the EMLSR client upon preparing the first Trigger Frame)
  * - the buffer status reported in QoS Null frames is as expected
  * - the EMLSR client sends a QoS Data frame in a TB PPDU
+ *
+ * It is also checked that, when sending BSRP TF is enabled and the single protection mechanism is
+ * used, the QoS Null frames sent in response to the BSRP TF acting as ICF have a Duration/ID of
+ * zero but the EMLSR client does not consider the TXOP ended when the transmission of the QoS Null
+ * frame ends (because in this case the ns3::EhtFrameExchangeManager::EarlyTxopEndDetect attribute
+ * is set to false) and therefore correctly receives the Basic Trigger Frame sent after a SIFS.
  */
 class EmlsrUlOfdmaTest : public EmlsrOperationsTestBase
 {
@@ -400,8 +406,9 @@
      * Constructor
      *
      * @param enableBsrp whether MU scheduler sends BSRP TFs
+     * @param protectSingleExchange whether single protection mechanism is used
      */
-    EmlsrUlOfdmaTest(bool enableBsrp);
+    EmlsrUlOfdmaTest(bool enableBsrp, bool protectSingleExchange);
 
   protected:
     void DoSetup() override;
@@ -420,9 +427,11 @@
   private:
     void StartTraffic() override;
 
-    bool m_enableBsrp;        //!< whether MU scheduler sends BSRP TFs
-    std::size_t m_txPsdusPos; //!< position in the vector of TX PSDUs of the first ICF
-    Time m_startAccessReq;    //!< start time of the first AP MLD access request via MU scheduler
+    bool m_enableBsrp;            //!< whether MU scheduler sends BSRP TFs
+    bool m_protectSingleExchange; //!< whether single protection mechanism is used
+    std::size_t m_txPsdusPos;     //!< position in the vector of TX PSDUs of the first ICF
+    Time m_startAccessReq; //!< start time of the first AP MLD access request via MU scheduler
+    std::optional<uint8_t> m_1stTfLinkId; //!< ID of the link on which the first TF is sent
 };
 
 /**
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-emlsr-link-switch-test.cc ns-3.46/src/wifi/test/wifi-emlsr-link-switch-test.cc
--- ns-3.45/src/wifi/test/wifi-emlsr-link-switch-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-emlsr-link-switch-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1677,18 +1677,20 @@
             m_staMacs[0]->GetDevice()->GetNode()->AddApplication(
                 GetApplication(UPLINK, 0, 1, 500, 4));
             // channel access can be obtained within a slot due to slot alignment
-            Simulator::Schedule(m_apMac->GetWifiPhy(m_linkIdForTid4)->GetSlot(), [=, this]() {
-                auto advEmlsrMgr =
-                    DynamicCast<AdvancedEmlsrManager>(m_staMacs[0]->GetEmlsrManager());
+            Simulator::Schedule(
+                m_apMac->GetWifiPhy(m_linkIdForTid4)->GetSlot() + TimeStep(1),
+                [=, this]() {
+                    auto advEmlsrMgr =
+                        DynamicCast<AdvancedEmlsrManager>(m_staMacs[0]->GetEmlsrManager());
 
-                NS_TEST_EXPECT_MSG_EQ(advEmlsrMgr->m_mainPhySwitchInfo.disconnected,
-                                      true,
-                                      "Expected the main PHY to be switching");
-                NS_TEST_EXPECT_MSG_EQ(
-                    +advEmlsrMgr->m_mainPhySwitchInfo.to,
-                    +(advEmlsrMgr->m_interruptSwitching ? m_linkIdForTid4 : m_mainPhyId),
-                    "Main PHY is switching to wrong link");
-            });
+                    NS_TEST_EXPECT_MSG_EQ(advEmlsrMgr->m_mainPhySwitchInfo.disconnected,
+                                          true,
+                                          "Expected the main PHY to be switching");
+                    NS_TEST_EXPECT_MSG_EQ(
+                        +advEmlsrMgr->m_mainPhySwitchInfo.to,
+                        +(advEmlsrMgr->m_interruptSwitching ? m_linkIdForTid4 : m_mainPhyId),
+                        "Test index " << +m_testIndex << ": Main PHY is switching to wrong link");
+                });
         });
         InsertEventsForQosTid4();
     };
@@ -2193,7 +2195,6 @@
     m_events.emplace_back(
         WIFI_MAC_CTL_ACK,
         [=, this](Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector, uint8_t linkId) {
-            const auto phyHdrDuration = WifiPhy::CalculatePhyPreambleAndHeaderDuration(txVector);
             const auto txDuration =
                 WifiPhy::CalculateTxDuration(psdu,
                                              txVector,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-emlsr-test-base.cc ns-3.46/src/wifi/test/wifi-emlsr-test-base.cc
--- ns-3.45/src/wifi/test/wifi-emlsr-test-base.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-emlsr-test-base.cc	2025-10-01 18:46:32.000000000 -0700
@@ -626,7 +626,7 @@
                                           std::string description,
                                           bool testUnblockedForOtherReasons)
 {
-    WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, dest, 0);
+    WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, dest, 0);
     auto mask = mac->GetMacQueueScheduler()->GetQueueLinkMask(AC_BE, queueId, linkId);
     NS_TEST_EXPECT_MSG_EQ(mask.has_value(),
                           true,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-fils-frame-test.cc ns-3.46/src/wifi/test/wifi-fils-frame-test.cc
--- ns-3.45/src/wifi/test/wifi-fils-frame-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-fils-frame-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -177,10 +177,7 @@
     MobilityHelper mobility;
     node.Create(1);
     phy.SetChannel(channel);
-    AttributeContainerValue<
-        TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
-        ';'>
-        channelValue;
+    WifiPhy::ChannelSettingsValue channelValue;
     channelValue.Set(WifiPhy::ChannelSegments{
         {INVALID_CHAN_NUM, m_params.bw, DEFAULT_BAND, DEFAULT_PRIMARY_INDEX}});
     phy.Set("ChannelSettings", channelValue);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-gcr-test.cc ns-3.46/src/wifi/test/wifi-gcr-test.cc
--- ns-3.45/src/wifi/test/wifi-gcr-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-gcr-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1806,7 +1806,7 @@
          std::vector<std::pair<bool, std::string>>{{false, "A-MPDU disabled"},
                                                    {true, "A-MPDU enabled"}})
     {
-        for (auto& [rtsThreshold, gcrPotection, protectionName] :
+        for (auto& [rtsThreshold, gcrProtection, protectionName] :
              std::vector<std::tuple<uint32_t, GroupcastProtectionMode, std::string>>{
                  {maxRtsCtsThreshold, GroupcastProtectionMode::RTS_CTS, "no protection"},
                  {500, GroupcastProtectionMode::RTS_CTS, "RTS-CTS"},
@@ -1850,7 +1850,7 @@
                                    .numGroupcastPackets = useAmpdu ? uint16_t(4) : uint16_t(2),
                                    .maxNumMpdusInPsdu = useAmpdu ? uint16_t(2) : uint16_t(1),
                                    .rtsThreshold = rtsThreshold,
-                                   .gcrProtectionMode = gcrPotection},
+                                   .gcrProtectionMode = gcrProtection},
                                   {}),
                     useSpectrum ? TestCase::Duration::EXTENSIVE : TestCase::Duration::QUICK);
                 AddTestCase(
@@ -1859,7 +1859,7 @@
                                    .numGroupcastPackets = useAmpdu ? uint16_t(4) : uint16_t(2),
                                    .maxNumMpdusInPsdu = useAmpdu ? uint16_t(2) : uint16_t(1),
                                    .rtsThreshold = rtsThreshold,
-                                   .gcrProtectionMode = gcrPotection,
+                                   .gcrProtectionMode = gcrProtection,
                                    // if no MPDU aggregation, MPDUs list is ignored
                                    .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}}}},
                                   {}),
@@ -1870,7 +1870,7 @@
                                    .numGroupcastPackets = useAmpdu ? uint16_t(4) : uint16_t(2),
                                    .maxNumMpdusInPsdu = useAmpdu ? uint16_t(2) : uint16_t(1),
                                    .rtsThreshold = rtsThreshold,
-                                   .gcrProtectionMode = gcrPotection,
+                                   .gcrProtectionMode = gcrProtection,
                                    // if no MPDU aggregation, MPDUs list is ignored
                                    .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}},
                                                              {2, {{0, {1, 2}}}},
@@ -1887,7 +1887,7 @@
                                    .numGroupcastPackets = useAmpdu ? uint16_t(4) : uint16_t(2),
                                    .maxNumMpdusInPsdu = useAmpdu ? uint16_t(2) : uint16_t(1),
                                    .rtsThreshold = rtsThreshold,
-                                   .gcrProtectionMode = gcrPotection,
+                                   .gcrProtectionMode = gcrProtection,
                                    // if no MPDU aggregation, MPDUs list is ignored
                                    .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}},
                                                              {2, {{0, {1, 2}}}},
@@ -1909,7 +1909,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{1, {{0, {2}}}},
                                                                  {2, {{0, {1}}}},
                                                                  {3, {{0, {2}}}},
@@ -1928,7 +1928,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{1, {{0, {1}}}},
                                                                  {2, {{0, {2}}}},
                                                                  {3, {{0, {1}}}},
@@ -1947,7 +1947,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}},
                                                                  {2, {{0, {1, 2}}}},
                                                                  {3, {{0, {1, 2}}}},
@@ -1966,7 +1966,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}},
                                                                  {2, {{0, {1, 2}}}},
                                                                  {3, {{0, {1, 2}}}},
@@ -1984,7 +1984,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}},
                                                                  {2, {{0, {1, 2}}}},
                                                                  {3, {{0, {1, 2}}}},
@@ -2003,7 +2003,7 @@
                                      .numGroupcastPackets = 4,
                                      .maxNumMpdusInPsdu = 2,
                                      .rtsThreshold = rtsThreshold,
-                                     .gcrProtectionMode = gcrPotection,
+                                     .gcrProtectionMode = gcrProtection,
                                      .mpdusToCorruptPerPsdu = {{9, {{0, {2}}}},
                                                                {10, {{0, {1}}}},
                                                                {11, {{0, {2}}}},
@@ -2023,7 +2023,7 @@
                                      .numGroupcastPackets = 4,
                                      .maxNumMpdusInPsdu = 2,
                                      .rtsThreshold = rtsThreshold,
-                                     .gcrProtectionMode = gcrPotection,
+                                     .gcrProtectionMode = gcrProtection,
                                      .mpdusToCorruptPerPsdu = {{9, {{0, {1}}}},
                                                                {10, {{0, {2}}}},
                                                                {11, {{0, {1}}}},
@@ -2043,7 +2043,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{9, {{0, {1, 2}}}},
                                                                  {10, {{0, {1, 2}}}},
                                                                  {11, {{0, {1, 2}}}},
@@ -2062,7 +2062,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{9, {{0, {1, 2}}}},
                                                                  {10, {{0, {1, 2}}}},
                                                                  {11, {{0, {1, 2}}}},
@@ -2080,7 +2080,7 @@
                                        .numGroupcastPackets = 4,
                                        .maxNumMpdusInPsdu = 2,
                                        .rtsThreshold = rtsThreshold,
-                                       .gcrProtectionMode = gcrPotection,
+                                       .gcrProtectionMode = gcrProtection,
                                        .mpdusToCorruptPerPsdu = {{9, {{0, {1, 2}}}},
                                                                  {10, {{0, {1, 2}}}},
                                                                  {11, {{0, {1, 2}}}},
@@ -2200,7 +2200,7 @@
                                                                           {{}, {1}},
                                                                           {{1}, {1}}})
         {
-            for (auto& [rtsThreshold, gcrPotection, protectionName] :
+            for (auto& [rtsThreshold, gcrProtection, protectionName] :
                  std::vector<std::tuple<uint32_t, GroupcastProtectionMode, std::string>>{
                      {maxRtsCtsThreshold, GroupcastProtectionMode::RTS_CTS, "no protection"},
                      {500, GroupcastProtectionMode::RTS_CTS, "RTS-CTS"},
@@ -2267,7 +2267,7 @@
                                                .startGroupcast = groupcastStartTime,
                                                .startUnicast = unicastStartTime,
                                                .rtsThreshold = rtsThreshold,
-                                               .gcrProtectionMode = gcrPotection},
+                                               .gcrProtectionMode = gcrProtection},
                                               {corruptedBars, corruptedBlockAcks}),
                                 useSpectrum ? TestCase::Duration::EXTENSIVE
                                             : TestCase::Duration::QUICK);
@@ -2281,7 +2281,7 @@
                                                    .startGroupcast = groupcastStartTime,
                                                    .startUnicast = unicastStartTime,
                                                    .rtsThreshold = rtsThreshold,
-                                                   .gcrProtectionMode = gcrPotection,
+                                                   .gcrProtectionMode = gcrProtection,
                                                    .mpdusToCorruptPerPsdu = {{1, {{0, {2}}}}}},
                                                   {corruptedBars, corruptedBlockAcks}),
                                     useSpectrum ? TestCase::Duration::EXTENSIVE
@@ -2294,7 +2294,7 @@
                                                    .startGroupcast = groupcastStartTime,
                                                    .startUnicast = unicastStartTime,
                                                    .rtsThreshold = rtsThreshold,
-                                                   .gcrProtectionMode = gcrPotection,
+                                                   .gcrProtectionMode = gcrProtection,
                                                    .mpdusToCorruptPerPsdu = {{1, {{0, {1}}}}}},
                                                   {corruptedBars, corruptedBlockAcks}),
                                     useSpectrum ? TestCase::Duration::EXTENSIVE
@@ -2307,7 +2307,7 @@
                                                    .startGroupcast = groupcastStartTime,
                                                    .startUnicast = unicastStartTime,
                                                    .rtsThreshold = rtsThreshold,
-                                                   .gcrProtectionMode = gcrPotection,
+                                                   .gcrProtectionMode = gcrProtection,
                                                    .mpdusToCorruptPerPsdu = {{1, {{0, {1, 2}}}}}},
                                                   {corruptedBars, corruptedBlockAcks}),
                                     useSpectrum ? TestCase::Duration::EXTENSIVE
@@ -2324,7 +2324,7 @@
                                                .startGroupcast = groupcastStartTime,
                                                .startUnicast = unicastStartTime,
                                                .rtsThreshold = rtsThreshold,
-                                               .gcrProtectionMode = gcrPotection,
+                                               .gcrProtectionMode = gcrProtection,
                                                .mpdusToCorruptPerPsdu = {{1, {{1, {2}}}}}},
                                               {corruptedBars, corruptedBlockAcks}),
                                 useSpectrum ? TestCase::Duration::EXTENSIVE
@@ -2339,7 +2339,7 @@
                                                .startGroupcast = groupcastStartTime,
                                                .startUnicast = unicastStartTime,
                                                .rtsThreshold = rtsThreshold,
-                                               .gcrProtectionMode = gcrPotection,
+                                               .gcrProtectionMode = gcrProtection,
                                                .mpdusToCorruptPerPsdu = {{1, {{1, {1}}}}}},
                                               {corruptedBars, corruptedBlockAcks}),
                                 useSpectrum ? TestCase::Duration::EXTENSIVE
@@ -2355,7 +2355,7 @@
                                      .startGroupcast = groupcastStartTime,
                                      .startUnicast = unicastStartTime,
                                      .rtsThreshold = rtsThreshold,
-                                     .gcrProtectionMode = gcrPotection,
+                                     .gcrProtectionMode = gcrProtection,
                                      .mpdusToCorruptPerPsdu = {{1, {{1, {1}}, {2, {2}}}}}},
                                     {corruptedBars, corruptedBlockAcks}),
                                 useSpectrum ? TestCase::Duration::EXTENSIVE
@@ -2371,7 +2371,7 @@
                                              .startGroupcast = groupcastStartTime,
                                              .startUnicast = unicastStartTime,
                                              .rtsThreshold = rtsThreshold,
-                                             .gcrProtectionMode = gcrPotection,
+                                             .gcrProtectionMode = gcrProtection,
                                              .mpdusToCorruptPerPsdu = {{1, {{1, {2}}, {2, {1}}}}}},
                                             {corruptedBars, corruptedBlockAcks}),
                                         useSpectrum ? TestCase::Duration::EXTENSIVE
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-mac-ofdma-test.cc ns-3.46/src/wifi/test/wifi-mac-ofdma-test.cc
--- ns-3.45/src/wifi/test/wifi-mac-ofdma-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-mac-ofdma-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -2231,7 +2231,7 @@
     {
         // create a listening VHT station
         wifi.SetStandard(WIFI_STANDARD_80211ac);
-        wifi.Install(phy, mac, Create<Node>());
+        wifi.Install(phy, mac, CreateObject<Node>());
     }
 
     wifi.SetStandard(m_scenario == WifiOfdmaScenario::HE ? WIFI_STANDARD_80211ax
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-mac-queue-test.cc ns-3.46/src/wifi/test/wifi-mac-queue-test.cc
--- ns-3.45/src/wifi/test/wifi-mac-queue-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-mac-queue-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -214,8 +214,8 @@
     Enqueue(rxAddr2, false, MilliSeconds(70));
     Enqueue(rxAddr2, false, MilliSeconds(75));
 
-    WifiContainerQueueId queueId1{WIFI_QOSDATA_QUEUE, WIFI_UNICAST, rxAddr1, 0};
-    WifiContainerQueueId queueId2{WIFI_QOSDATA_QUEUE, WIFI_UNICAST, rxAddr2, 0};
+    WifiContainerQueueId queueId1{WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, rxAddr1, 0};
+    WifiContainerQueueId queueId2{WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, rxAddr2, 0};
 
     Simulator::Schedule(MilliSeconds(25), [&]() {
         /**
@@ -421,6 +421,97 @@
  * @ingroup wifi-test
  * @ingroup tests
  *
+ * @brief Test that a wifi MAC queue is correctly flushed even if (at least) a container queue
+ * is blocked.
+ */
+class WifiMacQueueFlushTest : public TestCase
+{
+  public:
+    WifiMacQueueFlushTest();
+
+  private:
+    void DoRun() override;
+};
+
+WifiMacQueueFlushTest::WifiMacQueueFlushTest()
+    : TestCase("Test WifiMacQueue Flush operation")
+{
+}
+
+void
+WifiMacQueueFlushTest::DoRun()
+{
+    auto wifiMacQueue = CreateObject<WifiMacQueue>(AC_BE);
+    auto wifiMacScheduler = CreateObject<FcfsWifiQueueScheduler>();
+    wifiMacScheduler->m_perAcInfo[AC_BE].wifiMacQueue = wifiMacQueue;
+    wifiMacQueue->SetScheduler(wifiMacScheduler);
+
+    const auto addr1 = Mac48Address::Allocate();
+    const auto addr2 = Mac48Address::Allocate();
+
+    // Initialize the queue with some packets.
+    const auto tid = wifiAcList.at(AC_BE).GetLowTid();
+    const std::size_t nPackets = 5;
+    for (std::size_t i = 0; i < nPackets; i++)
+    {
+        WifiMacHeader header(WIFI_MAC_QOSDATA);
+        header.SetAddr1(addr1);
+        header.SetAddr2(addr2);
+        header.SetQosTid(tid);
+        auto item = Create<WifiMpdu>(Create<Packet>(), header);
+        wifiMacQueue->Enqueue(item);
+    }
+
+    WifiContainerQueueId queueId(WifiContainerQueueType::WIFI_QOSDATA_QUEUE,
+                                 WifiRcvAddr::UNICAST,
+                                 addr1,
+                                 tid);
+
+    // Check that all elements are inserted successfully.
+    NS_TEST_EXPECT_MSG_EQ(wifiMacQueue->GetNPackets(),
+                          nPackets,
+                          "Queue has unexpected number of elements");
+
+    NS_TEST_EXPECT_MSG_EQ(wifiMacQueue->GetNPackets(queueId),
+                          nPackets,
+                          "Unexpected number of packets in container queue");
+
+    NS_TEST_EXPECT_MSG_EQ(wifiMacScheduler->GetNext(AC_BE, SINGLE_LINK_OP_ID).has_value(),
+                          true,
+                          "Expected the scheduler to return a container queue");
+
+    // block the queue containing the packets
+    wifiMacScheduler->BlockQueues(WifiQueueBlockedReason::TID_NOT_MAPPED,
+                                  AC_BE,
+                                  {WifiContainerQueueType::WIFI_QOSDATA_QUEUE},
+                                  addr1,
+                                  addr2,
+                                  {tid},
+                                  {SINGLE_LINK_OP_ID});
+
+    NS_TEST_EXPECT_MSG_EQ(wifiMacScheduler->GetNext(AC_BE, SINGLE_LINK_OP_ID).has_value(),
+                          false,
+                          "Expected the container queue to  be blocked");
+
+    wifiMacQueue->Flush();
+
+    // Check that all elements are removed successfully.
+    NS_TEST_EXPECT_MSG_EQ(wifiMacQueue->GetNPackets(),
+                          0,
+                          "Queue has unexpected number of elements");
+
+    NS_TEST_EXPECT_MSG_EQ(wifiMacQueue->GetNPackets(queueId),
+                          0,
+                          "Unexpected number of packets in container queue");
+
+    wifiMacQueue->Dispose();
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup wifi-test
+ * @ingroup tests
+ *
  * @brief Wifi MAC Queue Test Suite
  */
 class WifiMacQueueTestSuite : public TestSuite
@@ -434,6 +525,7 @@
 {
     AddTestCase(new WifiMacQueueDropOldestTest, TestCase::Duration::QUICK);
     AddTestCase(new WifiExtractExpiredMpdusTest, TestCase::Duration::QUICK);
+    AddTestCase(new WifiMacQueueFlushTest, TestCase::Duration::QUICK);
 }
 
 static WifiMacQueueTestSuite g_wifiMacQueueTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-mlo-test.cc ns-3.46/src/wifi/test/wifi-mlo-test.cc
--- ns-3.45/src/wifi/test/wifi-mlo-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-mlo-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1581,7 +1581,7 @@
             (legacyAssoc
                  ? m_staMacs[0]->GetFrameExchangeManager(m_staSetupLinks.front())->GetAddress()
                  : m_staMacs[0]->GetAddress());
-        WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, addr, 0);
+        WifiContainerQueueId queueId(WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, addr, 0);
 
         // the queue on the AP should have a mask if and only if the link has been setup
         auto mask = m_apMac->GetMacQueueScheduler()->GetQueueLinkMask(AC_BE, queueId, linkId);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-non-ht-dup-test.cc ns-3.46/src/wifi/test/wifi-non-ht-dup-test.cc
--- ns-3.45/src/wifi/test/wifi-non-ht-dup-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-non-ht-dup-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -127,7 +127,8 @@
     void SetMuRtsTxVector(const WifiTxVector& muRtsTxVector);
 
   private:
-    Ptr<MuRtsCtsHePhy> m_muRtsCtsHePhy; ///< Pointer to HE PHY instance used for MU-RTS/CTS PHY test
+    std::shared_ptr<MuRtsCtsHePhy>
+        m_muRtsCtsHePhy; ///< Pointer to HE PHY instance used for MU-RTS/CTS PHY test
 
     // end of class MuRtsCtsSpectrumWifiPhy
 };
@@ -144,7 +145,7 @@
     : SpectrumWifiPhy()
 {
     NS_LOG_FUNCTION(this);
-    m_muRtsCtsHePhy = Create<MuRtsCtsHePhy>();
+    m_muRtsCtsHePhy = std::make_shared<MuRtsCtsHePhy>();
     m_muRtsCtsHePhy->SetOwner(this);
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-phy-cca-test.cc ns-3.46/src/wifi/test/wifi-phy-cca-test.cc
--- ns-3.45/src/wifi/test/wifi-phy-cca-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-phy-cca-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -140,7 +140,7 @@
      * signal occupies
      * @param expectedCcaThreshold the CCA threshold that is expected to be reported
      */
-    void VerifyCcaThreshold(const Ptr<PhyEntity> phy,
+    void VerifyCcaThreshold(const std::shared_ptr<PhyEntity> phy,
                             const Ptr<const WifiPpdu> ppdu,
                             WifiChannelListType channelType,
                             dBm_u expectedCcaThreshold);
@@ -273,7 +273,7 @@
 }
 
 void
-WifiPhyCcaThresholdsTest::VerifyCcaThreshold(const Ptr<PhyEntity> phy,
+WifiPhyCcaThresholdsTest::VerifyCcaThreshold(const std::shared_ptr<PhyEntity> phy,
                                              const Ptr<const WifiPpdu> ppdu,
                                              WifiChannelListType channelType,
                                              dBm_u expectedCcaThreshold)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-phy-mu-mimo-test.cc ns-3.46/src/wifi/test/wifi-phy-mu-mimo-test.cc
--- ns-3.45/src/wifi/test/wifi-phy-mu-mimo-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-phy-mu-mimo-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -273,7 +273,8 @@
     void DoInitialize() override;
     void DoDispose() override;
 
-    Ptr<MuMimoTestHePhy> m_ofdmTestHePhy; ///< Pointer to HE PHY instance used for MU-MIMO test
+    std::shared_ptr<MuMimoTestHePhy>
+        m_ofdmTestHePhy; ///< Pointer to HE PHY instance used for MU-MIMO test
 
     // end of class MuMimoSpectrumWifiPhy
 };
@@ -289,7 +290,7 @@
 MuMimoSpectrumWifiPhy::MuMimoSpectrumWifiPhy(uint16_t staId)
     : SpectrumWifiPhy()
 {
-    m_ofdmTestHePhy = Create<MuMimoTestHePhy>(staId);
+    m_ofdmTestHePhy = std::make_shared<MuMimoTestHePhy>(staId);
     m_ofdmTestHePhy->SetOwner(this);
 }
 
@@ -1373,7 +1374,7 @@
                                                    txVector,
                                                    m_phyAp->GetPhyBand());
     txVector.SetLength(length);
-    auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
+    auto hePhyAp = std::dynamic_pointer_cast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
     hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-phy-ofdma-test.cc ns-3.46/src/wifi/test/wifi-phy-ofdma-test.cc
--- ns-3.45/src/wifi/test/wifi-phy-ofdma-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-phy-ofdma-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -243,11 +243,11 @@
     /**
      * @return a const pointer to the latest PHY entity instance
      */
-    Ptr<LatestPhyEntityType> GetPhyEntity() const;
+    std::shared_ptr<LatestPhyEntityType> GetPhyEntity() const;
 
   private:
     /// Pointer to latest PHY entity instance used for OFDMA test
-    Ptr<OfdmaTestPhy<LatestPhyEntityType>> m_ofdmaTestPhy;
+    std::shared_ptr<OfdmaTestPhy<LatestPhyEntityType>> m_ofdmaTestPhy;
 
     /// Callback providing UID of the PPDU that is about to be transmitted
     TracedCallback<uint64_t> m_phyTxPpduUidTrace;
@@ -276,7 +276,7 @@
 OfdmaSpectrumWifiPhy<LatestPhyEntityType>::OfdmaSpectrumWifiPhy(uint16_t staId)
     : SpectrumWifiPhy()
 {
-    m_ofdmaTestPhy = Create<OfdmaTestPhy<LatestPhyEntityType>>(staId);
+    m_ofdmaTestPhy = std::make_shared<OfdmaTestPhy<LatestPhyEntityType>>(staId);
     m_ofdmaTestPhy->SetOwner(this);
 }
 
@@ -344,10 +344,10 @@
 }
 
 template <typename LatestPhyEntityType>
-Ptr<LatestPhyEntityType>
+std::shared_ptr<LatestPhyEntityType>
 OfdmaSpectrumWifiPhy<LatestPhyEntityType>::GetPhyEntity() const
 {
-    return DynamicCast<LatestPhyEntityType>(m_ofdmaTestPhy /*GetLatestPhyEntity()*/);
+    return std::dynamic_pointer_cast<LatestPhyEntityType>(m_ofdmaTestPhy /*GetLatestPhyEntity()*/);
 }
 
 /**
@@ -2706,7 +2706,7 @@
         HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, txVector, m_phy->GetPhyBand());
     txVector.SetLength(length);
     m_trigVector.SetLength(length);
-    auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
+    auto hePhy = std::dynamic_pointer_cast<HePhy>(m_phy->GetLatestPhyEntity());
     hePhy->SetTrigVector(m_trigVector, ppduDuration);
     ppdu->ResetTxVector();
     m_phy->StartRx(rxParams, nullptr);
@@ -4348,7 +4348,8 @@
     const auto detectionDuration = WifiPhy::GetPreambleDetectionDuration();
     const auto txVectorSta1 = GetTxVectorForTbPpdu(1, 1, 0);
     const auto txVectorSta2 = GetTxVectorForTbPpdu(2, 2, 0);
-    const auto phyEntity = DynamicCast<OfdmaTestPhy<LatestPhyEntityType>>(m_phyAp->GetPhyEntity());
+    const auto phyEntity =
+        std::dynamic_pointer_cast<OfdmaTestPhy<LatestPhyEntityType>>(m_phyAp->GetPhyEntity());
     const auto nonOfdmaDuration = phyEntity->CalculateNonHeDurationForHeTb(txVectorSta2);
     NS_ASSERT(nonOfdmaDuration == phyEntity->CalculateNonHeDurationForHeTb(txVectorSta1));
 
@@ -5589,7 +5590,7 @@
     std::tie(length, ppduDuration) =
         HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, trigVector, m_phyAp->GetPhyBand());
     trigVector.SetLength(length);
-    auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
+    auto hePhyAp = std::dynamic_pointer_cast<HePhy>(m_phyAp->GetLatestPhyEntity());
     hePhyAp->SetTrigVector(trigVector, ppduDuration);
 }
 
@@ -5866,7 +5867,7 @@
         {
             NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
         }
-        ui.SetUlTargetRssi(ulTargetRssi);
+        ui.SetUlTargetRxPower(ulTargetRssi);
 
         CtrlBAckRequestHeader bar;
         bar.SetType(BlockAckReqType::COMPRESSED);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-phy-reception-test.cc ns-3.46/src/wifi/test/wifi-phy-reception-test.cc
--- ns-3.45/src/wifi/test/wifi-phy-reception-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-phy-reception-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -849,7 +849,7 @@
     /**
      * Check the number of received packets
      * @param expectedSuccessCount the number of successfully received packets
-     * @param expectedFailureCount the number of unsuccessfuly received packets
+     * @param expectedFailureCount the number of unsuccessfully received packets
      */
     void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
 };
@@ -4207,7 +4207,7 @@
                    const std::vector<bool>& statusPerMpdu);
 
     /**
-     * Function called upon a PSDU received unsuccessfuly
+     * Function called upon a PSDU received unsuccessfully
      * @param psdu the PSDU
      */
     void RxFailure(Ptr<const WifiPsdu> psdu);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-phy-thresholds-test.cc ns-3.46/src/wifi/test/wifi-phy-thresholds-test.cc
--- ns-3.45/src/wifi/test/wifi-phy-thresholds-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-phy-thresholds-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -101,7 +101,7 @@
 
     Ptr<SpectrumWifiPhy> m_phy;   ///< PHY object
     uint32_t m_rxSuccess;         ///< count number of successfully received packets
-    uint32_t m_rxFailure;         ///< count number of unsuccessfuly received packets
+    uint32_t m_rxFailure;         ///< count number of unsuccessfully received packets
     uint32_t m_rxDropped;         ///< count number of dropped packets
     uint32_t m_stateChanged;      ///< count number of PHY state change
     uint32_t m_rxStateCount;      ///< count number of PHY state change to RX state
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-primary-channels-test.cc ns-3.46/src/wifi/test/wifi-primary-channels-test.cc
--- ns-3.45/src/wifi/test/wifi-primary-channels-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-primary-channels-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -197,14 +197,15 @@
     uint8_t m_nStationsPerBss;                    ///< number of stations per AP
     std::vector<NetDeviceContainer> m_staDevices; ///< containers for stations' NetDevices
     NetDeviceContainer m_apDevices;               ///< container for AP's NetDevice
-    std::vector<std::bitset<74>> m_received;  /**< whether the last packet transmitted to/from each
-                                                 of  the (up to 74 per BSS) stations was received */
-    std::vector<std::bitset<74>> m_processed; /**< whether the last packet transmitted to/from each
-                                                 of the (up to 74 per BSS) stations was processed */
-    Time m_time;                              ///< the time when the current action is executed
-    Ptr<WifiPsdu> m_trigger;                  ///< Basic Trigger Frame
-    WifiTxVector m_triggerTxVector;           ///< TX vector for Basic Trigger Frame
-    Time m_triggerTxDuration;                 ///< TX duration for Basic Trigger Frame
+    std::vector<std::bitset<144>> m_received; /**< whether the last packet transmitted to/from each
+                                                of  the (up to 144 per BSS) stations was received */
+    std::vector<std::bitset<144>>
+        m_processed;                /**< whether the last packet transmitted to/from each
+                                      of the (up to 144 per BSS) stations was processed */
+    Time m_time;                    ///< the time when the current action is executed
+    Ptr<WifiPsdu> m_trigger;        ///< Basic Trigger Frame
+    WifiTxVector m_triggerTxVector; ///< TX vector for Basic Trigger Frame
+    Time m_triggerTxDuration;       ///< TX duration for Basic Trigger Frame
 };
 
 WifiPrimaryChannelsTest::WifiPrimaryChannelsTest(WifiStandard standard,
@@ -381,10 +382,7 @@
                 "WaitBeaconTimeout",
                 TimeValue(MicroSeconds(102400))); // same as BeaconInterval
 
-    AttributeContainerValue<
-        TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
-        ';'>
-        channelValue;
+    WifiPhy::ChannelSettingsValue channelValue;
 
     // Each BSS uses a distinct primary20 channel
     for (uint8_t bss = 0; bss < m_nBss; bss++)
@@ -651,6 +649,7 @@
      */
     nRounds = 2;
     nApsPerRound = Count20MHzSubchannels(m_channelWidth) / 2;
+    const auto mc = GetModulationClassForStandard(m_standard);
     for (MHz_u txChannelWidth{20}; txChannelWidth <= m_channelWidth;
          txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
     {
@@ -659,12 +658,10 @@
 
         for (uint16_t round = 0; round < nRounds; round++)
         {
-            for (uint32_t type = 0; type < static_cast<uint32_t>(WifiRu::GetMaxRuType(
-                                               GetModulationClassForStandard(m_standard)));
-                 ++type)
+            for (uint32_t type = 0; type < static_cast<uint32_t>(WifiRu::GetMaxRuType(mc)); ++type)
             {
                 auto ruType = static_cast<RuType>(type);
-                std::size_t nRus = HeRu::GetNRus(txChannelWidth, ruType);
+                std::size_t nRus = WifiRu::GetNRus(txChannelWidth, ruType, mc);
                 std::set<uint8_t> txBss;
                 if (nRus > 0)
                 {
@@ -710,12 +707,10 @@
 
         for (uint16_t round = 0; round < nRounds; round++)
         {
-            for (uint32_t type = 0; type < static_cast<uint32_t>(WifiRu::GetMaxRuType(
-                                               GetModulationClassForStandard(m_standard)));
-                 ++type)
+            for (uint32_t type = 0; type < static_cast<uint32_t>(WifiRu::GetMaxRuType(mc)); ++type)
             {
                 auto ruType = static_cast<RuType>(type);
-                std::size_t nRus = HeRu::GetNRus(txChannelWidth, ruType);
+                std::size_t nRus = WifiRu::GetNRus(txChannelWidth, ruType, mc);
                 std::set<uint8_t> txBss;
                 if (nRus > 0)
                 {
@@ -834,7 +829,14 @@
 
     WifiConstPsduMap psduMap;
 
-    for (std::size_t i = 1; i <= nRus; i++)
+    auto numRus{nRus};
+    if ((m_standard != WIFI_STANDARD_80211ax) && (ruType == RuType::RU_26_TONE))
+    {
+        // for the loop, take undefined RUs for EHT into account
+        numRus += (txChannelWidth / MHz_u{80});
+    }
+    std::size_t staIdx{0};
+    for (std::size_t i = 1; i <= numRus; ++i)
     {
         auto primary80OrLow80{true};
         auto primary160{true};
@@ -861,13 +863,24 @@
                 primary80OrLow80 = p80OrLow80;
             }
         }
+        if ((m_standard != WIFI_STANDARD_80211ax) && (txChannelWidth >= MHz_u{80}) &&
+            (ruType == RuType::RU_26_TONE) && (index == 19))
+        {
+            // skip undefined RU for EHT
+            continue;
+        }
         const auto ru =
             (m_standard == WIFI_STANDARD_80211ax)
                 ? WifiRu::RuSpec(HeRu::RuSpec{ruType, index, primary80OrLow80})
                 : WifiRu::RuSpec(EhtRu::RuSpec{ruType, index, primary160, primary80OrLow80});
 
-        auto staDev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(i - 1));
-        uint16_t staId = DynamicCast<StaWifiMac>(staDev->GetMac())->GetAssociationId();
+        NS_ABORT_IF((bss >= m_staDevices.size()) || (staIdx >= m_staDevices[bss].GetN()));
+        auto staDev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(staIdx));
+        ++staIdx;
+
+        NS_ABORT_IF(!staDev);
+        const auto staId = DynamicCast<StaWifiMac>(staDev->GetMac())->GetAssociationId();
+
         txVector.SetHeMuUserInfo(staId, {ru, 8, 1});
         hdr.SetAddr1(staDev->GetMac()->GetAddress());
         psduMap[staId] = Create<const WifiPsdu>(Create<Packet>(1000), hdr);
@@ -933,7 +946,14 @@
         false,
         bssColor);
 
-    for (std::size_t i = 1; i <= nRus; i++)
+    auto numRus{nRus};
+    if ((m_standard != WIFI_STANDARD_80211ax) && (ruType == RuType::RU_26_TONE))
+    {
+        // for the loop, take undefined RUs for EHT into account
+        numRus += (txChannelWidth / MHz_u{80});
+    }
+    std::size_t staIdx{0};
+    for (std::size_t i = 1; i <= numRus; ++i)
     {
         NS_LOG_INFO("*** BSS " << +bss << " STA " << i - 1 << " transmits on primary "
                                << txChannelWidth
@@ -964,14 +984,22 @@
                 primary80OrLow80 = p80OrLow80;
             }
         }
+        if ((m_standard != WIFI_STANDARD_80211ax) && (txChannelWidth >= MHz_u{80}) &&
+            (ruType == RuType::RU_26_TONE) && (index == 19))
+        {
+            // skip undefined RU for EHT
+            continue;
+        }
         const auto ru =
             (m_standard == WIFI_STANDARD_80211ax)
                 ? WifiRu::RuSpec(HeRu::RuSpec{ruType, index, primary80OrLow80})
                 : WifiRu::RuSpec(EhtRu::RuSpec{ruType, index, primary160, primary80OrLow80});
 
-        auto staDev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(i - 1));
-        uint16_t staId = DynamicCast<StaWifiMac>(staDev->GetMac())->GetAssociationId();
+        NS_ABORT_IF((bss >= m_staDevices.size()) || (staIdx >= m_staDevices[bss].GetN()));
+        auto staDev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(staIdx));
+        ++staIdx;
 
+        const auto staId = DynamicCast<StaWifiMac>(staDev->GetMac())->GetAssociationId();
         WifiTxVector txVector(
             (m_standard == WIFI_STANDARD_80211ax) ? HePhy::GetHeMcs8() : EhtPhy::GetEhtMcs8(),
             0,
@@ -1010,7 +1038,7 @@
 
     // AP's PHY expects to receive a TRIGVECTOR (just once)
     trigVector.SetLength(length);
-    auto apHePhy = StaticCast<HePhy>(apDev->GetPhy()->GetLatestPhyEntity());
+    auto apHePhy = std::static_pointer_cast<HePhy>(apDev->GetPhy()->GetLatestPhyEntity());
     apHePhy->SetTrigVector(trigVector, duration);
 }
 
@@ -1594,10 +1622,12 @@
         AddTestCase(new WifiPrimaryChannelsTest(standard, MHz_u{160}, false),
                     TestCase::Duration::TAKES_FOREVER);
     }
-    AddTestCase(new WifiPrimaryChannelsTest(WIFI_STANDARD_80211be, MHz_u{320}, true),
+    // TODO: activate WifiPrimaryChannelsTest for 320 MHz channels once PHY operations are optimized
+    // to run faster, otherwise run-time is too long
+    /*AddTestCase(new WifiPrimaryChannelsTest(WIFI_STANDARD_80211be, MHz_u{320}, true),
                 TestCase::Duration::TAKES_FOREVER);
     AddTestCase(new WifiPrimaryChannelsTest(WIFI_STANDARD_80211be, MHz_u{320}, false),
-                TestCase::Duration::TAKES_FOREVER);
+                TestCase::Duration::TAKES_FOREVER);*/
     AddTestCase(new Wifi20MHzChannelIndicesTest(), TestCase::Duration::QUICK);
 }
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-retransmit-test.cc ns-3.46/src/wifi/test/wifi-retransmit-test.cc
--- ns-3.45/src/wifi/test/wifi-retransmit-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-retransmit-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -309,7 +309,7 @@
 {
     const auto psduNumber = std::distance(m_events.cbegin(), m_eventIt);
     const auto apAddr = Mac48Address::ConvertFrom(m_apDevice.Get(0)->GetAddress());
-    WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WIFI_UNICAST, apAddr, 0};
+    WifiContainerQueueId queueId{WIFI_QOSDATA_QUEUE, WifiRcvAddr::UNICAST, apAddr, 0};
     const auto staQueue = m_staMac->GetTxopQueue(AC_BE);
     NS_TEST_EXPECT_MSG_EQ(seqNoRetryCountMap.size(),
                           staQueue->GetNPackets(queueId),
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-static-emlsr-test.cc ns-3.46/src/wifi/test/wifi-static-emlsr-test.cc
--- ns-3.45/src/wifi/test/wifi-static-emlsr-test.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/test/wifi-static-emlsr-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2025
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sharan Naribole <sharan.naribole@gmail.com>
+ */
+
+#include "ns3/ap-wifi-mac.h"
+#include "ns3/assert.h"
+#include "ns3/attribute-container.h"
+#include "ns3/boolean.h"
+#include "ns3/emlsr-manager.h"
+#include "ns3/frame-exchange-manager.h"
+#include "ns3/log.h"
+#include "ns3/mac48-address.h"
+#include "ns3/multi-model-spectrum-channel.h"
+#include "ns3/node-container.h"
+#include "ns3/rng-seed-manager.h"
+#include "ns3/simulator.h"
+#include "ns3/spectrum-wifi-helper.h"
+#include "ns3/sta-wifi-mac.h"
+#include "ns3/string.h"
+#include "ns3/test.h"
+#include "ns3/wifi-mac-header.h"
+#include "ns3/wifi-mac-helper.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/wifi-static-setup-helper.h"
+#include "ns3/wifi-utils.h"
+
+#include <algorithm>
+#include <iterator>
+#include <set>
+#include <unordered_map>
+
+/// @ingroup wifi-test
+/// @ingroup tests
+/// @brief WifiStaticSetupHelper EMLSR setup test suite
+/// Test suite intended to test static EMLSR setup between AP MLD and client MLD.
+/// The test prepares AP WifiNetDevice and client WifiNetDevice based on test vector input and
+/// performs static EMLSR setup using WifiStaticSetupHelper. The test verifies if EMLSR state
+/// machine at ApWifiMac and StaWifiMac has been updated correctly.
+
+using namespace ns3;
+NS_LOG_COMPONENT_DEFINE("WifiStaticEmlsrTestSuite");
+
+namespace WifiStaticEmlsrTestConstants
+{
+const auto DEFAULT_RNG_SEED = 3;
+const auto DEFAULT_RNG_RUN = 7;
+const auto DEFAULT_STREAM_INDEX = 100;
+const auto DEFAULT_SIM_STOP_TIME = NanoSeconds(1);
+const auto DEFAULT_BEACON_GEN = false;
+const auto DEFAULT_DATA_MODE = "HeMcs3";
+const auto DEFAULT_CONTROL_MODE = "OfdmRate24Mbps";
+const auto DEFAULT_SWITCH_DELAY = MicroSeconds(64);
+const auto DEFAULT_AUX_PHY_CH_WIDTH = MHz_u{20};
+const auto DEFAULT_SWITCH_AUX_PHY = false;
+const auto DEFAULT_WIFI_STANDARD = WifiStandard::WIFI_STANDARD_80211be;
+const auto DEFAULT_SSID = Ssid("static-assoc-test");
+const std::string CHANNEL_0 = "{42, 80, BAND_5GHZ, 0}";
+const std::string CHANNEL_1 = "{23, 80, BAND_6GHZ, 0}";
+const std::string CHANNEL_2 = "{2, 0, BAND_2_4GHZ, 0}";
+const std::vector<std::string> DEFAULT_AP_CHS = {CHANNEL_0, CHANNEL_1, CHANNEL_2};
+using ChannelMap = std::unordered_map<WifiPhyBand, Ptr<MultiModelSpectrumChannel>>;
+} // namespace WifiStaticEmlsrTestConstants
+
+/// @brief test case information
+struct WifiStaticEmlsrTestVector
+{
+    std::string name;                     ///< Test case name
+    std::vector<std::string> clientChs{}; ///< Channel settings for client device
+    std::set<uint8_t> emlsrLinks{};       ///< EMLSR mode links
+    Time switchDelay{WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY}; ///< Radio Switch Delay
+    MHz_u auxPhyWidth{
+        WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH}; ///< Aux PHY channel width
+    bool switchAuxPhy{WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY}; ///< Switch Aux PHY
+};
+
+/**
+ * Test static setup of the EMLSR mode.
+ *
+ * It is checked that:
+ * - EMLSR mode is enabled on the expected set of links, both at client side and AP MLD side
+ * - the channel switch delay is configured on the client links as expected
+ */
+class WifiStaticEmlsrTest : public TestCase
+{
+  public:
+    /**
+     * Constructor.
+     *
+     * @param testVec the test vector
+     */
+    WifiStaticEmlsrTest(const WifiStaticEmlsrTestVector& testVec);
+
+  private:
+    /// Construct WifiNetDevice
+    /// @param isAp true if AP, false otherwise
+    /// @param channelMap created spectrum channels
+    /// @return constructed WifiNetDevice
+    Ptr<WifiNetDevice> GetWifiNetDevice(bool isAp,
+                                        const WifiStaticEmlsrTestConstants::ChannelMap& channelMap);
+
+    /// Construct PHY helper based on input operating channels
+    /// @param settings vector of strings specifying the operating channels to configure
+    /// @param channelMap created spectrum channels
+    /// @return PHY helper
+    SpectrumWifiPhyHelper GetPhyHelper(
+        const std::vector<std::string>& settings,
+        const WifiStaticEmlsrTestConstants::ChannelMap& channelMap) const;
+
+    /// @return the WifiHelper
+    WifiHelper GetWifiHelper() const;
+    /// @return the AP MAC helper
+    WifiMacHelper GetApMacHelper() const;
+    /// @return the Client MAC helper
+    WifiMacHelper GetClientMacHelper() const;
+    void ValidateEmlsr(); ///< Validate EMLSR setup
+    void DoRun() override;
+    void DoSetup() override;
+
+    WifiStaticEmlsrTestVector m_testVec;     ///< Test vector
+    Ptr<WifiNetDevice> m_apDev{nullptr};     ///< AP WiFi device
+    Ptr<WifiNetDevice> m_clientDev{nullptr}; ///< client WiFi device
+};
+
+WifiStaticEmlsrTest::WifiStaticEmlsrTest(const WifiStaticEmlsrTestVector& testVec)
+    : TestCase(testVec.name),
+      m_testVec(testVec)
+{
+}
+
+WifiHelper
+WifiStaticEmlsrTest::GetWifiHelper() const
+{
+    WifiHelper wifiHelper;
+    wifiHelper.SetStandard(WifiStaticEmlsrTestConstants::DEFAULT_WIFI_STANDARD);
+    wifiHelper.SetRemoteStationManager(
+        "ns3::ConstantRateWifiManager",
+        "DataMode",
+        StringValue(WifiStaticEmlsrTestConstants::DEFAULT_DATA_MODE),
+        "ControlMode",
+        StringValue(WifiStaticEmlsrTestConstants::DEFAULT_CONTROL_MODE));
+    wifiHelper.ConfigEhtOptions("EmlsrActivated", BooleanValue(true));
+    return wifiHelper;
+}
+
+SpectrumWifiPhyHelper
+WifiStaticEmlsrTest::GetPhyHelper(const std::vector<std::string>& settings,
+                                  const WifiStaticEmlsrTestConstants::ChannelMap& channelMap) const
+{
+    NS_ASSERT(not settings.empty());
+    SpectrumWifiPhyHelper helper(settings.size());
+
+    uint8_t linkId = 0;
+    for (const auto& str : settings)
+    {
+        helper.Set(linkId, "ChannelSettings", StringValue(str));
+        helper.Set(linkId, "ChannelSwitchDelay", TimeValue(m_testVec.switchDelay));
+        auto channelConfig = WifiChannelConfig::FromString(str);
+        auto phyBand = channelConfig.front().band;
+        auto freqRange = GetFrequencyRange(phyBand);
+        helper.AddPhyToFreqRangeMapping(linkId, freqRange);
+        helper.AddChannel(channelMap.at(phyBand), freqRange);
+
+        ++linkId;
+    }
+    return helper;
+}
+
+WifiMacHelper
+WifiStaticEmlsrTest::GetApMacHelper() const
+{
+    WifiMacHelper macHelper;
+    auto ssid = Ssid(WifiStaticEmlsrTestConstants::DEFAULT_SSID);
+
+    macHelper.SetType("ns3::ApWifiMac",
+                      "Ssid",
+                      SsidValue(ssid),
+                      "BeaconGeneration",
+                      BooleanValue(WifiStaticEmlsrTestConstants::DEFAULT_BEACON_GEN));
+    return macHelper;
+}
+
+WifiMacHelper
+WifiStaticEmlsrTest::GetClientMacHelper() const
+{
+    WifiMacHelper macHelper;
+    Ssid ssid = Ssid(WifiStaticEmlsrTestConstants::DEFAULT_SSID);
+    macHelper.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
+    macHelper.SetEmlsrManager("ns3::DefaultEmlsrManager",
+                              "EmlsrLinkSet",
+                              AttributeContainerValue<UintegerValue>(m_testVec.emlsrLinks),
+                              "AuxPhyChannelWidth",
+                              UintegerValue(m_testVec.auxPhyWidth),
+                              "SwitchAuxPhy",
+                              BooleanValue(m_testVec.switchAuxPhy));
+    return macHelper;
+}
+
+Ptr<WifiNetDevice>
+WifiStaticEmlsrTest::GetWifiNetDevice(bool isAp,
+                                      const WifiStaticEmlsrTestConstants::ChannelMap& channelMap)
+{
+    NodeContainer node(1);
+    auto wifiHelper = GetWifiHelper();
+    auto settings = isAp ? WifiStaticEmlsrTestConstants::DEFAULT_AP_CHS : m_testVec.clientChs;
+    auto phyHelper = GetPhyHelper(settings, channelMap);
+    auto macHelper = isAp ? GetApMacHelper() : GetClientMacHelper();
+    auto netDev = wifiHelper.Install(phyHelper, macHelper, node);
+    WifiHelper::AssignStreams(netDev, WifiStaticEmlsrTestConstants::DEFAULT_STREAM_INDEX);
+    return DynamicCast<WifiNetDevice>(netDev.Get(0));
+}
+
+void
+WifiStaticEmlsrTest::DoSetup()
+{
+    RngSeedManager::SetSeed(WifiStaticEmlsrTestConstants::DEFAULT_RNG_SEED);
+    RngSeedManager::SetRun(WifiStaticEmlsrTestConstants::DEFAULT_RNG_RUN);
+
+    WifiStaticEmlsrTestConstants::ChannelMap channelMap = {
+        {WIFI_PHY_BAND_2_4GHZ, CreateObject<MultiModelSpectrumChannel>()},
+        {WIFI_PHY_BAND_5GHZ, CreateObject<MultiModelSpectrumChannel>()},
+        {WIFI_PHY_BAND_6GHZ, CreateObject<MultiModelSpectrumChannel>()}};
+
+    m_apDev = GetWifiNetDevice(true, channelMap);
+    NS_ASSERT(m_apDev);
+    m_clientDev = GetWifiNetDevice(false, channelMap);
+    NS_ASSERT(m_clientDev);
+
+    WifiStaticSetupHelper::SetStaticAssociation(m_apDev, m_clientDev);
+    WifiStaticSetupHelper::SetStaticEmlsr(m_apDev, m_clientDev);
+}
+
+void
+WifiStaticEmlsrTest::ValidateEmlsr()
+{
+    auto clientMac = DynamicCast<StaWifiMac>(m_clientDev->GetMac());
+    NS_ASSERT_MSG(clientMac, "Expected StaWifiMac");
+    NS_TEST_ASSERT_MSG_EQ(clientMac->IsAssociated(), true, "Expected non-AP MLD to be associated");
+    auto setupLinks = clientMac->GetSetupLinkIds();
+    auto isMldAssoc = (setupLinks.size() > 1);
+    NS_TEST_ASSERT_MSG_EQ(isMldAssoc, true, "EMLSR mode requires association on multiple links");
+    auto emlsrManager = clientMac->GetEmlsrManager();
+    NS_ASSERT_MSG(emlsrManager, "EMLSR Manager not set");
+    auto clientEmlsrLinks = emlsrManager->GetEmlsrLinks();
+    auto match = (clientEmlsrLinks == m_testVec.emlsrLinks);
+    NS_TEST_ASSERT_MSG_EQ(match, true, "Unexpected set of EMLSR links enabled");
+    for (auto linkId : setupLinks)
+    {
+        auto expectedState = clientEmlsrLinks.contains(linkId);
+        auto clientLinkAddr = clientMac->GetFrameExchangeManager(linkId)->GetAddress();
+        auto apManager = m_apDev->GetRemoteStationManager(linkId);
+        auto actualState = apManager->GetEmlsrEnabled(clientLinkAddr);
+        NS_TEST_ASSERT_MSG_EQ(actualState,
+                              expectedState,
+                              "EMLSR state mismatch on client link ID " << +linkId);
+
+        // Validate Channel switch delay
+        auto actualDelay = clientMac->GetWifiPhy(linkId)->GetChannelSwitchDelay();
+        NS_TEST_ASSERT_MSG_EQ(actualDelay,
+                              m_testVec.switchDelay,
+                              "Channel switch delay mismatch on client link ID " << +linkId);
+    }
+}
+
+void
+WifiStaticEmlsrTest::DoRun()
+{
+    Simulator::Stop(WifiStaticEmlsrTestConstants::DEFAULT_SIM_STOP_TIME);
+    Simulator::Run();
+    ValidateEmlsr();
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup wifi-test
+ * @ingroup tests
+ *
+ * @brief EMLSR static setup test suite
+ */
+class WifiStaticEmlsrTestSuite : public TestSuite
+{
+  public:
+    WifiStaticEmlsrTestSuite();
+};
+
+WifiStaticEmlsrTestSuite::WifiStaticEmlsrTestSuite()
+    : TestSuite("wifi-static-emlsr-test", Type::UNIT)
+{
+    auto CHANNELS_2_LINKS = {WifiStaticEmlsrTestConstants::CHANNEL_0,
+                             WifiStaticEmlsrTestConstants::CHANNEL_1};
+    auto CHANNELS_3_LINKS = {WifiStaticEmlsrTestConstants::CHANNEL_0,
+                             WifiStaticEmlsrTestConstants::CHANNEL_1,
+                             WifiStaticEmlsrTestConstants::CHANNEL_2};
+    auto CHANNELS_2_LINKS_ALT = {WifiStaticEmlsrTestConstants::CHANNEL_0,
+                                 WifiStaticEmlsrTestConstants::CHANNEL_2};
+
+    for (const std::vector<WifiStaticEmlsrTestVector> inputs{
+             {"Setup-2-link-EMLSR-2-link",
+              CHANNELS_2_LINKS,
+              {0, 1},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"Setup-3-link-EMLSR-2-link",
+              CHANNELS_3_LINKS,
+              {0, 1},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"Setup-3-link-EMLSR-2-link-Diff",
+              CHANNELS_3_LINKS,
+              {1, 2},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"Setup-3-link-EMLSR-2-link-Diff-2",
+              CHANNELS_3_LINKS,
+              {0, 2},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"Setup-3-link-EMLSR-3-link",
+              CHANNELS_3_LINKS,
+              {0, 1, 2},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"Setup-2-link-EMLSR-2-link-Diff-Set",
+              CHANNELS_2_LINKS_ALT,
+              {0, 2},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"EMLSR-2-link-16us-delay",
+              CHANNELS_2_LINKS,
+              {0, 1},
+              MicroSeconds(16),
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"EMLSR-2-link-32us-delay",
+              CHANNELS_2_LINKS,
+              {0, 1},
+              MicroSeconds(32),
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"EMLSR-2-link-80MHz-AuxPhy",
+              CHANNELS_2_LINKS,
+              {0, 1},
+              MicroSeconds(32),
+              MHz_u{80},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_AUX_PHY},
+             {"EMLSR-2-link-Switch-Aux-PHY",
+              CHANNELS_2_LINKS,
+              {0, 1},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              WifiStaticEmlsrTestConstants::DEFAULT_AUX_PHY_CH_WIDTH,
+              true},
+             {"EMLSR-2-link-80MHz-AuxPhy-Switch",
+              CHANNELS_2_LINKS,
+              {0, 1},
+              WifiStaticEmlsrTestConstants::DEFAULT_SWITCH_DELAY,
+              MHz_u{80},
+              true}};
+         const auto& input : inputs)
+    {
+        AddTestCase(new WifiStaticEmlsrTest(input), TestCase::Duration::QUICK);
+    }
+}
+
+static WifiStaticEmlsrTestSuite g_wifiStaticEmlsrTestSuite;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-static-infra-bss-test.cc ns-3.46/src/wifi/test/wifi-static-infra-bss-test.cc
--- ns-3.45/src/wifi/test/wifi-static-infra-bss-test.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/wifi/test/wifi-static-infra-bss-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2025
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author: Sharan Naribole <sharan.naribole@gmail.com>
+ */
+
+#include "ns3/ap-wifi-mac.h"
+#include "ns3/assert.h"
+#include "ns3/boolean.h"
+#include "ns3/frame-exchange-manager.h"
+#include "ns3/log.h"
+#include "ns3/mac48-address.h"
+#include "ns3/multi-model-spectrum-channel.h"
+#include "ns3/node-container.h"
+#include "ns3/rng-seed-manager.h"
+#include "ns3/rr-multi-user-scheduler.h"
+#include "ns3/simulator.h"
+#include "ns3/spectrum-wifi-helper.h"
+#include "ns3/sta-wifi-mac.h"
+#include "ns3/string.h"
+#include "ns3/test.h"
+#include "ns3/wifi-mac-header.h"
+#include "ns3/wifi-mac-helper.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/wifi-ns3-constants.h"
+#include "ns3/wifi-static-setup-helper.h"
+#include "ns3/wifi-utils.h"
+
+#include <algorithm>
+#include <optional>
+#include <unordered_map>
+
+/// @ingroup wifi-test
+/// @ingroup tests
+/// @brief WifiStaticSetupHelper test suite
+/// Test suite intended to test static management exchanges between
+/// AP device and client device for single link and multi
+/// link operations.
+/// The test prepares AP WifiNetDevice and client WifiNetDevice
+/// based on test vector input and performs static exchanges for
+/// association, Block ACK agreement, UL MU disable etc.
+/// using WifiStaticSetupHelper. The test verifies if state machines
+/// at ApWifiMac and StaWifiMac has been updated correctly.
+
+using namespace ns3;
+NS_LOG_COMPONENT_DEFINE("WifiStaticInfraBssTestSuite");
+
+/// @brief Constants used in test suite
+namespace WifiStaticInfraBssTestConstants
+{
+const auto DEFAULT_RNG_SEED = 3;                    ///< default RNG seed
+const auto DEFAULT_RNG_RUN = 7;                     ///< default RNG run
+const auto DEFAULT_STREAM_INDEX = 100;              ///< default stream index
+const auto DEFAULT_SIM_STOP_TIME = NanoSeconds(1);  ///< default simulation stop time
+const auto DEFAULT_BEACON_GEN = false;              ///< default beacon generation value
+const auto DEFAULT_DATA_MODE = "HeMcs3";            ///< default data mode
+const auto DEFAULT_CONTROL_MODE = "OfdmRate24Mbps"; ///< default control mode
+const auto DEFAULT_WIFI_STANDARD = WifiStandard::WIFI_STANDARD_80211be; ///< default Wi-Fi standard
+const auto DEFAULT_SSID = Ssid("wifi-static-setup");                    ///< default SSID
+const tid_t DEFAULT_TEST_TID = 0;                                       ///< default TID
+const uint16_t DEFAULT_BA_BUFFER_SIZE = 64;  ///< default MPDU buffer size
+const uint8_t DEFAULT_WIFI_UL_MU_NUM_RU = 4; ///< default number of RUs in UL MU PPDUs
+} // namespace WifiStaticInfraBssTestConstants
+
+namespace consts = WifiStaticInfraBssTestConstants;
+
+/// @brief channel map typedef
+using ChannelMap = std::unordered_map<WifiPhyBand, Ptr<MultiModelSpectrumChannel>>;
+
+/// @brief test case information
+struct WifiStaticInfraBssTestVector
+{
+    std::string name;                                      ///< Test case name
+    StringVector apChs{};                                  ///< Channel setting for AP device
+    StringVector clientChs{};                              ///< Channel settings for client device
+    uint16_t apBufferSize{consts::DEFAULT_BA_BUFFER_SIZE}; ///< Originator Buffer Size
+    uint16_t clientBufferSize{consts::DEFAULT_BA_BUFFER_SIZE}; ///< Recipient Buffer Size
+    std::optional<Ipv4Address> apMulticastIp{std::nullopt};    ///< AP multicast IP
+    bool ulMuDataDisable{DEFAULT_WIFI_UL_MU_DATA_DISABLE};     ///< UL MU Data Disable
+};
+
+/**
+ * Test static setup of an infrastructure BSS.
+ */
+class WifiStaticInfraBssTest : public TestCase
+{
+  public:
+    /**
+     * Constructor.
+     *
+     * @param testVec the test vector
+     */
+    WifiStaticInfraBssTest(const WifiStaticInfraBssTestVector& testVec);
+
+  private:
+    /// Construct WifiNetDevice
+    /// @param isAp true if AP, false otherwise
+    /// @param channelMap created spectrum channels
+    /// @return constructed WifiNetDevice
+    Ptr<WifiNetDevice> GetWifiNetDevice(bool isAp, const ChannelMap& channelMap);
+
+    /// Construct PHY helper based on input operating channels
+    /// @param settings vector of strings specifying the operating channels to configure
+    /// @param channelMap created spectrum channels
+    /// @return PHY helper
+    SpectrumWifiPhyHelper GetPhyHelper(const StringVector& settings,
+                                       const ChannelMap& channelMap) const;
+
+    /// @return the WifiHelper
+    WifiHelper GetWifiHelper() const;
+    /// @return the AP MAC helper
+    WifiMacHelper GetApMacHelper() const;
+    /// @return the Client MAC helper
+    WifiMacHelper GetClientMacHelper() const;
+    void ValidateAssoc(); ///< Validate Association
+
+    /// Validate Multi-user scheduler setup
+    /// @param apMac AP MAC
+    /// @param clientMac Non-AP MAC
+    void ValidateMuScheduler(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac);
+
+    /// Validate association state machine at AP and client
+    /// for input link
+    /// @param clientLinkId client local Link ID
+    /// @param apMac AP MAC
+    /// @param clientMac Client MAC
+    void ValidateAssocForLink(linkId_t clientLinkId,
+                              Ptr<ApWifiMac> apMac,
+                              Ptr<StaWifiMac> clientMac);
+
+    /// Validate Block ACK Agreement at AP and client
+    /// @param apMac AP MAC
+    /// @param clientMac Client MAC
+    void ValidateBaAgr(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac);
+
+    void DoRun() override;
+    void DoSetup() override;
+
+    WifiStaticInfraBssTestVector m_testVec;       ///< Test vector
+    Ptr<WifiNetDevice> m_apDev{nullptr};          ///< AP WiFi device
+    Ptr<WifiNetDevice> m_clientDev{nullptr};      ///< client WiFi device
+    std::optional<Mac48Address> m_apGcrGroupAddr; ///< GCR group address
+};
+
+WifiStaticInfraBssTest::WifiStaticInfraBssTest(const WifiStaticInfraBssTestVector& testVec)
+    : TestCase(testVec.name),
+      m_testVec(testVec)
+{
+}
+
+WifiHelper
+WifiStaticInfraBssTest::GetWifiHelper() const
+{
+    WifiHelper wifiHelper;
+    wifiHelper.SetStandard(consts::DEFAULT_WIFI_STANDARD);
+    wifiHelper.SetRemoteStationManager("ns3::ConstantRateWifiManager",
+                                       "DataMode",
+                                       StringValue(consts::DEFAULT_DATA_MODE),
+                                       "ControlMode",
+                                       StringValue(consts::DEFAULT_CONTROL_MODE));
+    return wifiHelper;
+}
+
+SpectrumWifiPhyHelper
+WifiStaticInfraBssTest::GetPhyHelper(const StringVector& settings,
+                                     const ChannelMap& channelMap) const
+{
+    NS_ASSERT(!settings.empty());
+    SpectrumWifiPhyHelper helper(settings.size());
+
+    linkId_t linkId = 0;
+    for (const auto& str : settings)
+    {
+        helper.Set(linkId, "ChannelSettings", StringValue(str));
+
+        auto channelConfig = WifiChannelConfig::FromString(str);
+        auto phyBand = channelConfig.front().band;
+        auto freqRange = GetFrequencyRange(phyBand);
+        helper.AddPhyToFreqRangeMapping(linkId, freqRange);
+        helper.AddChannel(channelMap.at(phyBand), freqRange);
+
+        ++linkId;
+    }
+    return helper;
+}
+
+WifiMacHelper
+WifiStaticInfraBssTest::GetApMacHelper() const
+{
+    WifiMacHelper macHelper;
+    auto ssid = Ssid(consts::DEFAULT_SSID);
+
+    macHelper.SetType("ns3::ApWifiMac",
+                      "Ssid",
+                      SsidValue(ssid),
+                      "BeaconGeneration",
+                      BooleanValue(consts::DEFAULT_BEACON_GEN),
+                      "MpduBufferSize",
+                      UintegerValue(m_testVec.apBufferSize));
+    macHelper.SetMultiUserScheduler("ns3::RrMultiUserScheduler",
+                                    "NStations",
+                                    UintegerValue(consts::DEFAULT_WIFI_UL_MU_NUM_RU));
+    return macHelper;
+}
+
+WifiMacHelper
+WifiStaticInfraBssTest::GetClientMacHelper() const
+{
+    WifiMacHelper macHelper;
+    Ssid ssid = Ssid(consts::DEFAULT_SSID);
+    macHelper.SetType("ns3::StaWifiMac",
+                      "Ssid",
+                      SsidValue(ssid),
+                      "MpduBufferSize",
+                      UintegerValue(m_testVec.clientBufferSize));
+    return macHelper;
+}
+
+Ptr<WifiNetDevice>
+WifiStaticInfraBssTest::GetWifiNetDevice(bool isAp, const ChannelMap& channelMap)
+{
+    NodeContainer node(1);
+    auto wifiHelper = GetWifiHelper();
+    auto settings = isAp ? m_testVec.apChs : m_testVec.clientChs;
+    auto phyHelper = GetPhyHelper(settings, channelMap);
+    auto macHelper = isAp ? GetApMacHelper() : GetClientMacHelper();
+    auto netDev = wifiHelper.Install(phyHelper, macHelper, node);
+    WifiHelper::AssignStreams(netDev, consts::DEFAULT_STREAM_INDEX);
+    return DynamicCast<WifiNetDevice>(netDev.Get(0));
+}
+
+void
+WifiStaticInfraBssTest::DoSetup()
+{
+    RngSeedManager::SetSeed(consts::DEFAULT_RNG_SEED);
+    RngSeedManager::SetRun(consts::DEFAULT_RNG_RUN);
+
+    ChannelMap channelMap = {{WIFI_PHY_BAND_2_4GHZ, CreateObject<MultiModelSpectrumChannel>()},
+                             {WIFI_PHY_BAND_5GHZ, CreateObject<MultiModelSpectrumChannel>()},
+                             {WIFI_PHY_BAND_6GHZ, CreateObject<MultiModelSpectrumChannel>()}};
+
+    m_apDev = GetWifiNetDevice(true, channelMap); // AP
+    NS_ASSERT(m_apDev);
+    m_clientDev = GetWifiNetDevice(false, channelMap); // Client
+    NS_ASSERT(m_clientDev);
+
+    WifiStaticSetupHelper::SetStaticAssociation(m_apDev, m_clientDev);
+    if (auto multicastIp = m_testVec.apMulticastIp)
+    {
+        NS_ASSERT_MSG(multicastIp->IsMulticast(),
+                      "Assigned IP " << multicastIp.value() << " is not multicast");
+        m_apGcrGroupAddr = Mac48Address::ConvertFrom(m_apDev->GetMulticast(multicastIp.value()));
+    }
+    WifiStaticSetupHelper::SetStaticBlockAck(m_apDev,
+                                             m_clientDev,
+                                             consts::DEFAULT_TEST_TID,
+                                             m_apGcrGroupAddr);
+    WifiStaticSetupHelper::SetStaticBlockAck(m_clientDev, m_apDev, consts::DEFAULT_TEST_TID);
+}
+
+void
+WifiStaticInfraBssTest::ValidateAssocForLink(linkId_t clientLinkId,
+                                             Ptr<ApWifiMac> apMac,
+                                             Ptr<StaWifiMac> clientMac)
+{
+    const auto isMldAssoc = (apMac->GetNLinks() > 1) && (clientMac->GetNLinks() > 1);
+    const auto apLinkId = clientLinkId;
+    const auto clientFem = clientMac->GetFrameExchangeManager(clientLinkId);
+    const auto apFem = apMac->GetFrameExchangeManager(apLinkId);
+    const auto staAddr = clientFem->GetAddress();
+    const auto apAddr = apFem->GetAddress();
+    const auto staRemoteMgr = clientMac->GetWifiRemoteStationManager(clientLinkId);
+    const auto apRemoteMgr = apMac->GetWifiRemoteStationManager(apLinkId);
+
+    NS_TEST_ASSERT_MSG_EQ(clientFem->GetBssid(),
+                          apAddr,
+                          "Unexpected BSSID for STA link ID " << +clientLinkId);
+    NS_TEST_ASSERT_MSG_EQ(apRemoteMgr->IsAssociated(staAddr),
+                          true,
+                          "Expecting STA " << staAddr << " to be associated on AP link "
+                                           << +apLinkId);
+
+    const auto aid = apMac->GetAssociationId(staAddr, apLinkId);
+    NS_TEST_ASSERT_MSG_EQ(apMac->GetStaList(apLinkId).contains(aid),
+                          true,
+                          "STA " << staAddr << " not found in list of associated STAs");
+
+    if (!isMldAssoc)
+    {
+        return;
+    }
+
+    NS_TEST_ASSERT_MSG_EQ((staRemoteMgr->GetMldAddress(apAddr) == apMac->GetAddress()),
+                          true,
+                          "Incorrect MLD address stored by STA on link ID " << +clientLinkId);
+    NS_TEST_ASSERT_MSG_EQ((staRemoteMgr->GetAffiliatedStaAddress(apMac->GetAddress()) == apAddr),
+                          true,
+                          "Incorrect affiliated address stored by STA on link ID "
+                              << +clientLinkId);
+
+    NS_TEST_ASSERT_MSG_EQ((apRemoteMgr->GetMldAddress(staAddr) == clientMac->GetAddress()),
+                          true,
+                          "Incorrect MLD address stored by AP on link ID " << +apLinkId);
+    NS_TEST_ASSERT_MSG_EQ(
+        (apRemoteMgr->GetAffiliatedStaAddress(clientMac->GetAddress()) == staAddr),
+        true,
+        "Incorrect affiliated address stored by AP on link ID " << +apLinkId);
+}
+
+void
+WifiStaticInfraBssTest::ValidateMuScheduler(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac)
+{
+    auto muScheduler = apMac->GetObject<RrMultiUserScheduler>();
+    NS_ASSERT(muScheduler);
+    auto clientList = muScheduler->GetUlMuStas();
+    std::size_t expectedSize = m_testVec.ulMuDataDisable ? 0 : 1;
+    if (expectedSize == 0)
+    {
+        return;
+    }
+    auto clientAddr = clientList.front().address;
+    auto expectedAddr = clientMac->GetAddress();
+    NS_TEST_ASSERT_MSG_EQ(clientAddr, expectedAddr, "Client MAC address mismatch");
+}
+
+void
+WifiStaticInfraBssTest::ValidateBaAgr(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac)
+{
+    auto isMldAssoc = (apMac->GetNLinks() > 1) && (clientMac->GetNLinks() > 1);
+    auto setupLinks = clientMac->GetSetupLinkIds();
+    auto linkId = *(setupLinks.begin());
+    auto apAddr =
+        isMldAssoc ? apMac->GetAddress() : clientMac->GetFrameExchangeManager(linkId)->GetBssid();
+    auto clientAddr = isMldAssoc ? clientMac->GetAddress()
+                                 : clientMac->GetFrameExchangeManager(linkId)->GetAddress();
+
+    auto expectedBufferSize = std::min(m_testVec.apBufferSize, m_testVec.clientBufferSize);
+
+    // AP Block ACK Manager
+    auto baApOrig = apMac->GetBaAgreementEstablishedAsOriginator(clientAddr,
+                                                                 consts::DEFAULT_TEST_TID,
+                                                                 m_apGcrGroupAddr);
+    NS_TEST_ASSERT_MSG_EQ(baApOrig.has_value(),
+                          true,
+                          "BA Agreement not established at AP as originator");
+    NS_TEST_ASSERT_MSG_EQ(baApOrig->get().GetBufferSize(),
+                          expectedBufferSize,
+                          "BA Agreement buffer size mismatch");
+    auto baApRecip =
+        apMac->GetBaAgreementEstablishedAsRecipient(clientAddr, consts::DEFAULT_TEST_TID);
+    NS_TEST_ASSERT_MSG_EQ(baApRecip.has_value(),
+                          true,
+                          "BA Agreement not established at AP as recipient");
+    NS_TEST_ASSERT_MSG_EQ(baApRecip->get().GetBufferSize(),
+                          expectedBufferSize,
+                          "BA Agreement buffer size mismatch");
+
+    // Non-AP Block ACK Manager
+    auto baClientOrig =
+        clientMac->GetBaAgreementEstablishedAsOriginator(apAddr, consts::DEFAULT_TEST_TID);
+    NS_TEST_ASSERT_MSG_EQ(baClientOrig.has_value(),
+                          true,
+                          "BA Agreement not established at client as originator");
+    NS_TEST_ASSERT_MSG_EQ(baClientOrig->get().GetBufferSize(),
+                          expectedBufferSize,
+                          "BA Agreement buffer size mismatch");
+    auto baClientRecip = clientMac->GetBaAgreementEstablishedAsRecipient(apAddr,
+                                                                         consts::DEFAULT_TEST_TID,
+                                                                         m_apGcrGroupAddr);
+    NS_TEST_ASSERT_MSG_EQ(baClientRecip.has_value(),
+                          true,
+                          "BA Agreement not established at client as recipient");
+    NS_TEST_ASSERT_MSG_EQ(baClientOrig->get().GetBufferSize(),
+                          expectedBufferSize,
+                          "BA Agreement buffer size mismatch");
+}
+
+void
+WifiStaticInfraBssTest::ValidateAssoc()
+{
+    auto apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
+    NS_ASSERT(apMac);
+    auto clientMac = DynamicCast<StaWifiMac>(m_clientDev->GetMac());
+    NS_ASSERT(clientMac);
+
+    NS_TEST_ASSERT_MSG_EQ(clientMac->IsAssociated(), true, "Expected the STA to be associated");
+    const auto nClientLinks = m_testVec.clientChs.size();
+    auto clientLinkIds = clientMac->GetLinkIds();
+    NS_TEST_EXPECT_MSG_EQ(clientLinkIds.size(), nClientLinks, "Client number of links mismatch");
+    for (auto linkId : clientLinkIds)
+    {
+        ValidateAssocForLink(linkId, apMac, clientMac);
+    }
+
+    ValidateBaAgr(apMac, clientMac);
+    ValidateMuScheduler(apMac, clientMac);
+}
+
+void
+WifiStaticInfraBssTest::DoRun()
+{
+    Simulator::Stop(consts::DEFAULT_SIM_STOP_TIME);
+    Simulator::Run();
+    ValidateAssoc();
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup wifi-test
+ * @ingroup tests
+ *
+ * @brief WifiStaticSetupHelper test suite
+ */
+class WifiStaticInfraBssTestSuite : public TestSuite
+{
+  public:
+    WifiStaticInfraBssTestSuite();
+};
+
+WifiStaticInfraBssTestSuite::WifiStaticInfraBssTestSuite()
+    : TestSuite("wifi-static-infra-bss-test", Type::UNIT)
+{
+    for (const std::vector<WifiStaticInfraBssTestVector> inputs{
+             {"AP-1-link-Client-1-link",
+              {"{36, 0, BAND_5GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-1-link-Client-1-link-multicast",
+              {"{36, 0, BAND_5GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              "239.192.1.1",
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-2-link-Client-1-link",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-2-link-Client-1-link-Diff-Order",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}"},
+              {"{2, 0, BAND_2_4GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-3-link-Client-2-link",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-3-link-Client-2-link-Diff-Order",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              {"{2, 0, BAND_2_4GHZ, 0}", "{36, 0, BAND_5GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-3-link-Client-3-link",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"AP-80MHz-Client-20MHz",
+              {"{42, 80, BAND_5GHZ, 0}"},
+              {"{36, 20, BAND_5GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"Single-linkBuffer-Size-Test",
+              {"{36, 0, BAND_5GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}"},
+              64,
+              256,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"Single-linkBuffer-Size-Test-Alt",
+              {"{36, 0, BAND_5GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}"},
+              1024,
+              256,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"Multi-link-Buffer-Size-Test",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              256,
+              64,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"Multi-link-Buffer-Size-Test-Alt",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              1024,
+              1024,
+              std::nullopt,
+              DEFAULT_WIFI_UL_MU_DATA_DISABLE},
+             {"Single-link-UL-MU-Disable",
+              {"{36, 0, BAND_5GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              true},
+             {"2-link-UL-MU-Disable",
+              {"{36, 0, BAND_5GHZ, 0}", "{2, 0, BAND_2_4GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              {"{36, 0, BAND_5GHZ, 0}", "{1, 0, BAND_6GHZ, 0}"},
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              consts::DEFAULT_BA_BUFFER_SIZE,
+              std::nullopt,
+              true}};
+
+         const auto& input : inputs)
+    {
+        AddTestCase(new WifiStaticInfraBssTest(input), TestCase::Duration::QUICK);
+    }
+}
+
+static WifiStaticInfraBssTestSuite g_wifiStaticInfraBssTestSuite;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-test.cc ns-3.46/src/wifi/test/wifi-test.cc
--- ns-3.45/src/wifi/test/wifi-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -2618,7 +2618,7 @@
     uint16_t m_rxCount; ///< Count number of successfully received data packets
     uint16_t m_txCount; ///< Count number of transmitted data packets
     uint16_t
-        m_txMacFinalDataFailedCount; ///< Count number of unsuccessfuly transmitted data packets
+        m_txMacFinalDataFailedCount; ///< Count number of unsuccessfully transmitted data packets
 };
 
 Issue40TestCase::Issue40TestCase()
@@ -2736,7 +2736,7 @@
                         staDevice.Get(0)->GetAddress());
 
     // Transmit a second data packet once the station is away from the access point: it should be
-    // sent with the same high modulation and be unsuccessfuly received
+    // sent with the same high modulation and be unsuccessfully received
     Simulator::Schedule(Seconds(2),
                         &Issue40TestCase::SendPackets,
                         this,
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wifi/test/wifi-tx-stats-helper-test.cc ns-3.46/src/wifi/test/wifi-tx-stats-helper-test.cc
--- ns-3.45/src/wifi/test/wifi-tx-stats-helper-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wifi/test/wifi-tx-stats-helper-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -168,6 +168,8 @@
 void
 WifiTxStatsHelperTest::DoRun()
 {
+    Config::SetDefault("ns3::WifiRemoteStationManager::IncrementRetryCountUnderBa",
+                       BooleanValue(true));
     std::string dataMode;
     std::string ackMode;
     if (m_option == SINGLE_LINK_NON_QOS)
@@ -233,7 +235,8 @@
             if (freq == 6)
             {
                 mldChannelStr[1] = "{0, 20, BAND_6GHZ, 0}";
-                wifi.SetRemoteStationManager(static_cast<uint8_t>(1),
+                uint8_t linkId = 1;
+                wifi.SetRemoteStationManager(linkId,
                                              "ns3::ConstantRateWifiManager",
                                              "DataMode",
                                              StringValue(dataMode),
@@ -243,7 +246,13 @@
             else
             {
                 mldChannelStr[0] = "{0, 20, BAND_5GHZ, 0}";
-                wifi.SetRemoteStationManager(static_cast<uint8_t>(0),
+                // linkId is passed as a variable here because MSVC
+                // interprets uint8_t as a char, and the 0 value as a
+                // c-string null terminator \0. This results into a
+                // compilation error due to SetRemoteStationManager(uint8_t,...)
+                // and SetRemoteStationManager(std::string, ...) signatures.
+                uint8_t linkId = 0;
+                wifi.SetRemoteStationManager(linkId,
                                              "ns3::ConstantRateWifiManager",
                                              "DataMode",
                                              StringValue(dataMode),
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/AUTHORS ns-3.46/src/wimax/AUTHORS
--- ns-3.45/src/wimax/AUTHORS	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/AUTHORS	1969-12-31 16:00:00.000000000 -0800
@@ -1,54 +0,0 @@
-Jahanzeb Farooq
-===============
-Module manager and main developer
-2007,2008
-INRIA
-Jahanzeb.Farooq@sophia.inria.fr
-Fahanzeb.Farooq@gmail.com
-
-Mohamed Amine Ismail
-====================
-Module manager and main developer
-2008,2010
-INRIA, UDcast
-Amine.Ismail@sophia.inria.fr
-Amine.Ismail@udcast.com
-Amine.Ismail@gmail.com
-
-Giuseppe Piro
-=============
-Development and Integration of the rtps uplink scheduler
-2009-2010
-TELEMATICS LAB, Politecnico di Bari
-G.Piro@poliba.it
-
-Flavio Kubota, Juliana Freitag Borin, Nelson L. S. da Fonseca 
-==============================================================
-Development and Integration of the mbqos uplink scheduler
-2009
-LRC - Computer Networks Laboratory
-FlavioKubota@gmail.com
-juliana.freitag@gmail.com
-wimaxgroup@lrc.ic.unicamp.br
-
-Thierry Turletti
-================
-Project supervisor
-2007,2008,2009
-INRIA
-Thierry.Turletti@sophia.inria.fr
-
-Walid Dabbous
-=============
-Planete Project Manager
-2007,2008,2009
-INRIA
-Walid.Dabbous@sophia.inria.fr
-
-Mathieu Lacage
-==============
-Project supervisor
-2007,2008,2009
-INRIA
-Mathieu.Lacage@sophia.inria.fr
-
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/CMakeLists.txt ns-3.46/src/wimax/CMakeLists.txt
--- ns-3.45/src/wimax/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/CMakeLists.txt	1969-12-31 16:00:00.000000000 -0800
@@ -1,113 +0,0 @@
-set(source_files
-    helper/wimax-helper.cc
-    model/cid.cc
-    model/cid-factory.cc
-    model/wimax-net-device.cc
-    model/bs-net-device.cc
-    model/ss-net-device.cc
-    model/wimax-mac-header.cc
-    model/wimax-phy.cc
-    model/wimax-channel.cc
-    model/ofdm-downlink-frame-prefix.cc
-    model/wimax-connection.cc
-    model/ss-record.cc
-    model/mac-messages.cc
-    model/dl-mac-messages.cc
-    model/ul-mac-messages.cc
-    model/simple-ofdm-wimax-phy.cc
-    model/simple-ofdm-wimax-channel.cc
-    model/send-params.cc
-    model/ss-manager.cc
-    model/connection-manager.cc
-    model/bs-uplink-scheduler.cc
-    model/bs-uplink-scheduler-simple.cc
-    model/bs-uplink-scheduler-mbqos.cc
-    model/bs-uplink-scheduler-rtps.cc
-    model/bs-scheduler.cc
-    model/bs-scheduler-simple.cc
-    model/bs-scheduler-rtps.cc
-    model/wimax-mac-queue.cc
-    model/burst-profile-manager.cc
-    model/ss-scheduler.cc
-    model/service-flow.cc
-    model/service-flow-manager.cc
-    model/service-flow-record.cc
-    model/ss-link-manager.cc
-    model/bs-link-manager.cc
-    model/bandwidth-manager.cc
-    model/crc8.cc
-    model/ul-job.cc
-    model/snr-to-block-error-rate-record.cc
-    model/snr-to-block-error-rate-manager.cc
-    model/simple-ofdm-send-param.cc
-    model/ss-service-flow-manager.cc
-    model/bs-service-flow-manager.cc
-    model/ipcs-classifier.cc
-    model/ipcs-classifier-record.cc
-    model/wimax-tlv.cc
-    model/cs-parameters.cc
-    model/wimax-mac-to-mac-header.cc
-)
-
-set(header_files
-    helper/wimax-helper.h
-    model/wimax-channel.h
-    model/wimax-net-device.h
-    model/bs-net-device.h
-    model/ss-net-device.h
-    model/cid.h
-    model/cid-factory.h
-    model/ofdm-downlink-frame-prefix.h
-    model/wimax-connection.h
-    model/ss-record.h
-    model/mac-messages.h
-    model/dl-mac-messages.h
-    model/ul-mac-messages.h
-    model/wimax-phy.h
-    model/simple-ofdm-wimax-phy.h
-    model/simple-ofdm-wimax-channel.h
-    model/send-params.h
-    model/service-flow.h
-    model/ss-manager.h
-    model/connection-manager.h
-    model/wimax-mac-header.h
-    model/wimax-mac-queue.h
-    model/crc8.h
-    model/service-flow-manager.h
-    model/bs-uplink-scheduler.h
-    model/bs-uplink-scheduler-simple.h
-    model/bs-uplink-scheduler-mbqos.h
-    model/bs-uplink-scheduler-rtps.h
-    model/ul-job.h
-    model/bs-scheduler.h
-    model/bs-scheduler-simple.h
-    model/bs-scheduler-rtps.h
-    model/service-flow-record.h
-    model/snr-to-block-error-rate-record.h
-    model/snr-to-block-error-rate-manager.h
-    model/simple-ofdm-send-param.h
-    model/ss-service-flow-manager.h
-    model/bs-service-flow-manager.h
-    model/cs-parameters.h
-    model/ipcs-classifier-record.h
-    model/wimax-tlv.h
-    model/ipcs-classifier.h
-    model/bvec.h
-    model/wimax-mac-to-mac-header.h
-)
-
-build_lib(
-  LIBNAME wimax
-  SOURCE_FILES ${source_files}
-  HEADER_FILES ${header_files}
-  LIBRARIES_TO_LINK ${libinternet}
-                    ${libpropagation}
-  TEST_SOURCES
-    test/mac-messages-test.cc
-    test/phy-test.cc
-    test/qos-test.cc
-    test/ss-mac-test.cc
-    test/wimax-fragmentation-test.cc
-    test/wimax-service-flow-test.cc
-    test/wimax-tlv-test.cc
-)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/doc/wimax.rst ns-3.46/src/wimax/doc/wimax.rst
--- ns-3.45/src/wimax/doc/wimax.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/doc/wimax.rst	1969-12-31 16:00:00.000000000 -0800
@@ -1,516 +0,0 @@
-.. include:: replace.txt
-.. highlight:: cpp
-
-Wimax NetDevice
----------------
-
-This chapter describes the |ns3| WimaxNetDevice and related models. By
-adding WimaxNetDevice objects to |ns3| nodes, one can create models of
-802.16-based networks. Below, we list some more details about what
-the |ns3| WiMAX models cover but, in summary, the most important features
-of the |ns3| model are:
-
-* a scalable and realistic physical layer and channel model
-* a packet classifier for the IP convergence sublayer
-* efficient uplink and downlink schedulers
-* support for Multicast and Broadcast Service (MBS), and
-* packet tracing functionality
-
-The source code for the WiMAX models lives in the directory
-``src/wimax``.
-
-There have been two academic papers published on this model:
-
-* M.A. Ismail, G. Piro, L.A. Grieco, and T. Turletti, "An Improved IEEE 802.16
-  WiMAX Module for the NS-3 Simulator", SIMUTools 2010 Conference, March 2010.
-* J. Farooq and T. Turletti, "An IEEE 802.16 WiMAX module for the NS-3
-  Simulator," SIMUTools 2009 Conference, March 2009.
-
-
-Scope of the model
-******************
-
-From a MAC perspective, there are two basic modes of operation, that of a
-Subscriber Station (SS) or a Base Station (BS). These are implemented as two
-subclasses of the base class :cpp:class:`ns3::NetDevice`, class
-:cpp:class:`SubscriberStationNetDevice` and class
-:cpp:class:`BaseStationNetDevice`. As is typical in |ns3|, there is also a
-physical layer class :cpp:class:`WimaxPhy` and a channel class
-:cpp:class:`WimaxChannel` which serves to hold the references to all of the
-attached Phy devices. The main physical layer class is the
-:cpp:class:`SimpleOfdmWimaxChannel` class.
-
-Another important aspect of WiMAX is the uplink and downlink scheduler, and
-there are three primary scheduler types implemented:
-
-* SIMPLE:  a simple priority based FCFS scheduler
-* RTPS:  a real-time polling service (rtPS) scheduler
-* MBQOS:  a migration-based uplink scheduler
-
-The following additional aspects of the 802.16 specifications, as well as
-physical layer and channel models, are modelled:
-
-* leverages existing |ns3| wireless propagation loss and delay models, as well
-  as |ns3| mobility models
-* Point-to-Multipoint (PMP) mode and the WirelessMAN-OFDM PHY layer
-* Initial Ranging
-* Service Flow Initialization
-* Management Connection
-* Transport Initialization
-* UGS, rtPS, nrtPS, and BE connections
-
-The following aspects are not presently modelled but would be good topics for
-future extensions:
-
-* OFDMA PHY layer
-* Link adaptation
-* Mesh topologies
-* ARQ
-* ertPS connection
-* packet header suppression
-
-Using the Wimax models
-**********************
-
-The main way that users who write simulation scripts will typically interact
-with the Wimax models is through the helper API and through the publicly visible
-attributes of the model.
-
-The helper API is defined in ``src/wimax/helper/wimax-helper.{cc,h}``.
-
-The example ``src/wimax/examples/wimax-simple.cc`` contains some basic code that
-shows how to set up the model::
-
-  switch (schedType)
-    {
-    case 0:
-      scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-      break;
-    case 1:
-      scheduler = WimaxHelper::SCHED_TYPE_MBQOS;
-      break;
-    case 2:
-      scheduler = WimaxHelper::SCHED_TYPE_RTPS;
-      break;
-    default:
-      scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    }
-
-  NodeContainer ssNodes;
-  NodeContainer bsNodes;
-
-  ssNodes.Create(2);
-  bsNodes.Create(1);
-
-  WimaxHelper wimax;
-
-  NetDeviceContainer ssDevs, bsDevs;
-
-  ssDevs = wimax.Install(ssNodes,
-                         WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                         WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                         scheduler);
-  bsDevs = wimax.Install(bsNodes, WimaxHelper::DEVICE_TYPE_BASE_STATION, WimaxHelper::SIMPLE_PHY_TYPE_OFDM, scheduler);
-
-This example shows that there are two subscriber stations and one base station
-created. The helper method ``Install`` allows the user to specify the scheduler
-type, the physical layer type, and the device type.
-
-Different variants of ``Install`` are available; for instance, the example
-``src/wimax/examples/wimax-multicast.cc`` shows how to specify a non-default channel
-or propagation model::
-
-  channel = CreateObject<SimpleOfdmWimaxChannel>();
-  channel->SetPropagationModel(SimpleOfdmWimaxChannel::COST231_PROPAGATION);
-  ssDevs = wimax.Install(ssNodes,
-                         WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                         WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                         channel,
-                         scheduler);
-  Ptr<WimaxNetDevice> dev = wimax.Install(bsNodes.Get(0),
-                                          WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                                          WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                                          channel,
-                                          scheduler);
-
-Mobility is also supported in the same way as in Wifi models; see the
-``src/wimax/examples/wimax-multicast.cc``.
-
-Another important concept in WiMAX is that of a service flow. This is a
-unidirectional flow of packets with a set of QoS parameters such as traffic
-priority, rate, scheduling type, etc. The base station is responsible for
-issuing service flow identifiers and mapping them to WiMAX connections. The
-following code from ``src/wimax/examples/wimax-multicast.cc`` shows how this is
-configured from a helper level::
-
- ServiceFlow MulticastServiceFlow = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_DOWN,
-                                                            ServiceFlow::SF_TYPE_UGS,
-                                                            MulticastClassifier);
-
-  bs->GetServiceFlowManager()->AddMulticastServiceFlow(MulticastServiceFlow, WimaxPhy::MODULATION_TYPE_QPSK_12);
-
-
-Wimax Attributes
-****************
-
-The WimaxNetDevice makes heavy use of the |ns3| attributes subsystem for
-configuration and default value management.  Presently, approximately 60 values
-are stored in this system.
-
-For instance, class ``ns-3::SimpleOfdmWimaxPhy`` exports these
-attributes:
-
-* NoiseFigure:  Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.
-* TxPower:  Transmission power (dB)
-* G:  The ratio of CP time to useful time
-* txGain:  Transmission gain (dB)
-* RxGain:  Reception gain (dB)
-* Nfft:  FFT size
-* TraceFilePath:  Path to the directory containing SNR to block error rate files
-
-
-For a full list of attributes in these models, consult the Doxygen page that
-lists all attributes for |ns3|.
-
-Wimax Tracing
-*************
-
-|ns3| has a sophisticated tracing infrastructure that allows users to hook into
-existing trace sources, or to define and export new ones.
-
-Many |ns3| users use the built-in Pcap or Ascii tracing, and the
-WimaxHelper has similar APIs::
-
-    AsciiTraceHelper ascii;
-    WimaxHelper wimax;
-    wimax.EnablePcap("wimax-program", false);
-    wimax.EnableAsciiAll(ascii.CreateFileStream("wimax-program.tr");
-
-Unlike other helpers, there is also a special ``EnableAsciiForConnection()``
-method that limits the ascii tracing to a specific device and connection.
-
-These helpers access the low level trace sources that exist in the WiMAX
-physical layer, net device, and queue models. Like other |ns3| trace sources,
-users may hook their own functions to these trace sources if they want to do
-customized things based on the packet events. See the Doxygen List of trace
-sources for a complete list of these sources.
-
-Wimax MAC model
-***************
-
-The 802.16 model provided in |ns3| attempts to provide an accurate MAC and PHY
-level implementation of the 802.16 specification with the Point-to-Multipoint
-(PMP) mode and the WirelessMAN-OFDM PHY layer. The model is mainly composed of
-three layers:
-
-* The convergence sublayer (CS)
-* The MAC CP Common Part Sublayer (MAC-CPS)
-* Physical (PHY) layer
-
-
-The following figure :ref:`wimax-architecture` shows the relationships of these
-models.
-
-.. _wimax-architecture:
-
-.. figure:: figures/WimaxArchitecture.*
-
-  WiMAX architecture
-
-Convergence Sublayer
-++++++++++++++++++++
-
-The Convergence sublayer (CS) provided with this module implements the Packet
-CS, designed to work with the packet-based protocols at higher layers. The CS is
-responsible of receiving packet from the higher layer and from peer stations,
-classifying packets to appropriate connections (or service flows) and processing
-packets. It keeps a mapping of transport connections to service flows. This
-enables the MAC CPS identifying the Quality of Service (QoS) parameters
-associated to a transport connection and ensuring the QoS requirements. The CS
-currently employs an IP classifier.
-
-IP Packet Classifier
-++++++++++++++++++++
-
-An IP packet classifier is used to map incoming packets to appropriate
-connections based on a set of criteria. The classifier maintains a list of
-mapping rules which associate an IP flow (src IP address and mask, dst IP
-address and mask, src port range, dst port range and protocol) to one of the
-service flows.  By analyzing the IP and the TCP/UDP headers the classifier will
-append the incoming packet (from the upper layer) to the queue of the
-appropriate WiMAX connection. Class :cpp:class:`IpcsClassifier` and class
-:cpp:class:`IpcsClassifierRecord` implement the classifier module for both SS
-and BS
-
-MAC Common Part Sublayer
-++++++++++++++++++++++++
-
-The MAC Common Part Sublayer (CPS) is the main sublayer of the IEEE 802.16 MAC
-and performs the fundamental functions of the MAC. The module implements the
-Point-Multi-Point (PMP) mode. In PMP mode BS is responsible of managing
-communication among multiple SSs. The key functionalities of the MAC CPS include
-framing and addressing, generation of MAC management messages, SS initialization
-and registration, service flow management, bandwidth management and scheduling
-services.  Class :cpp:class:`WimaxNetDevice` represents the MAC layer of a WiMAX
-network device. This class extends the class :cpp:class:`NetDevice` of the |ns3|
-API that provides abstraction of a network device. Class
-:cpp:class:`WimaxNetDevice` is further extended by class
-:cpp:class:`BaseStationNetDevice` and class
-:cpp:class:`SubscriberStationNetDevice`, defining MAC layers of BS and SS,
-respectively.  Besides these main classes, the key functions of MAC are
-distributed to several other classes.
-
-Framing and Management Messages
-+++++++++++++++++++++++++++++++
-
-The module implements a frame as a fixed duration of time, i.e., frame
-boundaries are defined with respect to time. Each frame is further subdivided
-into downlink (DL) and uplink (UL) subframes. The module implements the Time
-Division Duplex (TDD) mode where DL and UL operate on same frequency but are
-separated in time. A number of DL and UL bursts are then allocated in DL and UL
-subframes, respectively. Since the standard allows sending and receiving bursts
-of packets in a given DL or UL burst, the unit of transmission at the MAC layer
-is a packet burst. The module implements a special PacketBurst data structure
-for this purpose. A packet burst is essentially a list of packets. The BS
-downlink and uplink schedulers, implemented by class :cpp:class:`BSScheduler`
-and class :cpp:class:`UplinkScheduler`, are responsible of generating DL and UL
-subframes, respectively. In the case of DL, the subframe is simulated by
-transmitting consecutive bursts (instances PacketBurst). In case of UL, the
-subframe is divided, with respect to time, into a number of slots. The bursts
-transmitted by the SSs in these slots are then aligned to slot boundaries. The
-frame is divided into integer number of symbols and Physical Slots (PS) which
-helps in managing bandwidth more effectively. The number of symbols per frame
-depends on the  underlying implementation of the PHY layer. The size of a DL or
-UL burst is specified in units of symbols.
-
-Network Entry and Initialization
-++++++++++++++++++++++++++++++++
-
-The network entry and initialization phase is basically divided into two
-sub-phases, (1) scanning and synchronization and (2) initial ranging. The entire
-phase is performed by the LinkManager component of SS and BS. Once an SS wants
-to join the network, it first scans the downlink frequencies to search for a
-suitable channel. The search is complete as soon as it detects a PHY frame. The
-next step is to establish synchronization with the BS. Once SS receives a
-Downlink-MAP (DL-MAP) message the synchronization phase is complete and it
-remains synchronized as long as it keeps receiving DL-MAP and  Downlink Channel
-Descriptor (DCD) messages. After the synchronization is established, SS waits
-for a Uplink Channel Descriptor (UCD) message to acquire uplink channel
-parameters. Once acquired, the first sub-phase of the network entry and
-initialization is complete. Once synchronization is achieved, the SS waits for a
-UL-MAP message to locate a special grant, called initial ranging interval, in
-the UL subframe. This grant is allocated by the BS Uplink Scheduler at regular
-intervals. Currently this interval is set to 0.5 ms, however the user is enabled
-to modify its value from the simulation script.
-
-Connections and Addressing
-++++++++++++++++++++++++++
-
-All communication at the MAC layer is carried in terms of connections. The
-standard defines a connection as a unidirectional mapping between the SS and
-BS's MAC entities for the transmission of traffic. The standard defines two
-types of connections: management connections for transmitting control messages
-and transport connections for data transmission. A connection is identified by a
-16-bit Connection Identifier (CID).  Class :cpp:class:`WimaxConnection` and
-class :cpp:class:`Cid` implement the connection and CID, respectively. Note that
-each connection maintains its own transmission queue where packets to transmit
-on that connection are queued. The ConnectionManager component of BS is
-responsible of creating and managing connections for all SSs.
-
-The two key management connections defined by the standard, namely the Basic and
-Primary management connections, are created and allocated to the SS during the
-ranging process. Basic connection plays an important role throughout the
-operation of SS also because all (unicast) DL and UL grants are directed towards
-SS's Basic CID. In addition to management connections, an SS may have one or
-more transport connections to send data packets. The Connection Manager
-component of SS manages the connections associated to SS. As defined by the
-standard, a management connection is bidirectional, i.e., a pair of downlink and
-uplink connections is represented by the same CID. This feature is implemented
-in a way that one connection (in DL direction) is created by the BS and upon
-receiving the CID the SS then creates an identical connection (in UL direction)
-with the same CID.
-
-Scheduling Services
-+++++++++++++++++++
-
-The module supports the four scheduling services defined by the 802.16-2004
-standard:
-
-* Unsolicited Grant Service (UGS)
-* Real-Time Polling Services (rtPS)
-* Non Real-Time Polling Services (nrtPS)
-* Best Effort (BE)
-
-These scheduling services behave differently with respect to how they request
-bandwidth as well as how the it is granted. Each service flow is associated to
-exactly one scheduling service, and the QoS parameter set associated to a
-service flow actually defines the scheduling service it belongs to. When a
-service flow is created the UplinkScheduler calculates necessary parameters such
-as grant size and grant interval based on QoS parameters associated to it.
-
-WiMAX Uplink Scheduler Model
-++++++++++++++++++++++++++++
-
-Uplink Scheduler at the BS decides which of the SSs will be assigned uplink
-allocations based on the QoS parameters associated to a service flow (or
-scheduling service) and bandwidth requests from the SSs. Uplink scheduler
-together with Bandwidth Manager implements the complete scheduling service
-functionality. The standard defines up to four scheduling services (BE, UGS,
-rtPS, nrtPS) for applications with different types of QoS requirements. The
-service flows of these scheduling services behave differently with respect to
-how they request for bandwidth as well as how the bandwidth is granted. The
-module supports all four scheduling services. Each service flow is associated to
-exactly one transport connection and one scheduling service. The QoS parameters
-associated to a service flow actually define the scheduling service it belongs
-to. Standard QoS parameters for UGS, rtPS, nrtPS and BE services, as specified
-in Tables 111a to 111d of the 802.16e amendment, are supported. When a service
-flow is created the uplink scheduler calculates necessary parameters such as
-grant size and allocation interval based on QoS parameters associated to it.
-The current WiMAX module provides three different versions of schedulers.
-
-* The first one is a simple priority-based First Come First Serve (FCFS).  For
-  the real-time services (UGS and rtPS) the BS then allocates grants/polls on
-  regular basis based on the calculated interval. For the non real-time services
-  (nrtPS and BE) only minimum reserved bandwidth is guaranteed if available
-  after servicing real-time flows. Note that not all of these parameters are
-  utilized by the uplink scheduler. Also note that currently only service flow
-  with fixed-size packet size are supported, as currently set up in simulation
-  scenario with OnOff application of fixed packet size. This scheduler is
-  implemented by class :cpp:class:`BSSchedulerSimple` and class
-  :cpp:class:`UplinkSchedulerSimple`.
-
-* The second one is similar to first scheduler except by rtPS service flow. All
-  rtPS Connections are able to transmit all packet in the queue according to the
-  available bandwidth. The bandwidth saturation control has been implemented to
-  redistribute the effective available bandwidth to all rtPS that have at least
-  one packet to transmit. The remaining bandwidth is allocated to nrtPS and BE
-  Connections. This scheduler is implemented by class
-  :cpp:class:`BSSchedulerRtps` and class
-  :cpp:class:`UplinkSchedulerRtps`.
-
-* The third one is a Migration-based Quality of Service uplink scheduler This
-  uplink scheduler uses three queues, the low priority queue, the intermediate
-  queue and the high priority queue. The scheduler serves the requests in
-  strict priority order from the high priority queue to the low priority queue.
-  The low priority queue stores the bandwidth requests of the BE service flow.
-  The intermediate queue holds bandwidth requests sent by rtPS and by nrtPS
-  connections. rtPS and nrtPS requests can migrate to the high priority queue to
-  guarantee that their QoS requirements are met. Besides the requests migrated
-  from the intermediate queue, the high priority queue stores periodic grants
-  and unicast request opportunities that must be scheduled in the following
-  frame. To guarantee the maximum delay requirement, the BS assigns a deadline
-  to each rtPS bandwidth request in the intermediate queue. The minimum
-  bandwidth requirement of both rtPS and nrtPS connections is guaranteed over a
-  window of duration T. This scheduler is implemented by class
-  :cpp:class:`UplinkSchedulerMBQoS`.
-
-WiMAX Outbound Schedulers Model
-+++++++++++++++++++++++++++++++
-
-Besides the uplink scheduler these are the outbound schedulers at BS and SS side
-(BSScheduler and SSScheduler). The outbound schedulers decide which of the
-packets from the outbound queues will be transmitted in a given allocation. The
-outbound scheduler at the BS schedules the downlink traffic, i.e., packets to be
-transmitted to the SSs in the downlink subframe. Similarly the outbound
-scheduler at a SS schedules the packet to be transmitted in the uplink
-allocation assigned to that SS in the uplink subframe. All three schedulers have
-been implemented to work as FCFS scheduler, as they allocate grants starting
-from highest priority scheduling service to the lower priority one (UGS> rtPS>
-nrtPS> BE). The standard does not suggest any scheduling algorithm and instead
-leaves this decision up to the manufacturers. Of course more sophisticated
-algorithms can be added later if required.
-
-WimaxChannel and WimaxPhy models
-********************************
-
-The module implements the Wireless MAN OFDM PHY specifications as the more
-relevant for implementation as it is the schema chosen by the WiMAX Forum. This
-specification is designed for non-light-of-sight (NLOS) including fixed and
-mobile broadband wireless access. The proposed model uses a 256 FFT processor,
-with 192 data subcarriers. It supports all the seven modulation and coding
-schemes specified by Wireless MAN-OFDM. It is composed of two parts: the channel
-model and the physical model.
-
-Channel model
-*************
-
-The channel model we propose is implemented by the class
-:cpp:class:`SimpleOFDMWimaxChannel` which extends the class
-:cpp:class:`wimaxchannel`. The channel entity has a private structure named
-m_phyList which handles all the physical devices connected to it. When a
-physical device sends a packet (FEC Block) to the channel, the channel handles
-the packet, and then for each physical device connected to it, it calculates the
-propagation delay, the path loss according to a given propagation model and
-eventually forwards the packet to the receiver device.  The channel class uses
-the method `GetDistanceFrom()` to calculate the distance between two physical
-entities according to their 3D coordinates. The delay is
-computed as `delay = distance/C`, where `C` is the speed of the light.
-
-Physical model
-**************
-
-The physical layer performs two main operations: (i) It receives a burst from a
-channel and forwards it to the MAC layer, (ii) it receives a burst from the MAC
-layer and transmits it on the channel. In order to reduce the simulation
-complexity of the WiMAX physical layer, we have chosen to model offline part of
-the physical layer. More specifically we have developed an OFDM simulator to
-generate trace files used by the reception process to evaluate if a FEC block
-can be correctly decoded or not.
-
-Transmission Process: A burst is a set of WiMAX MAC PDUs. At the sending
-process, a burst is converted into bit-streams and then split into smaller
-FEC blocks which are then sent to the channel with a power equal P_tx.
-
-Reception Process: The reception process includes the following operations:
-
-#. Receive a FEC block from the channel.
-#. Calculate the noise level.
-#. Estimate the signal to noise ratio (SNR) with the following formula.
-#. Determine if a FEC block can be correctly decoded.
-#. Concatenate received FEC blocks to reconstruct the original burst.
-#. Forward the burst to the upper layer.
-
-The developed process to evaluate if a FEC block can be correctly received or
-not uses pre-generated traces.  The trace files are generated by an external
-OFDM simulator (described later). A class named SNRToBlockErrorRateManager
-handles a repository containing seven trace files (one for each modulation and
-coding scheme). A repository is specific for a particular channel model.
-
-A trace file is made of 6 columns. The first column provides the SNR value (1),
-whereas the other columns give respectively the bit error rate BER (2), the
-block error rate BlcER(3), the standard deviation on BlcER, and the confidence
-interval (4 and 5).  These trace files are loaded into memory by the
-SNRToBlockErrorRateManager entity at the beginning of the simulation.
-
-Currently, The first process uses the first and third columns to determine if a
-FEC block is correctly received. When the physical layer receives a packet with
-an SNR equal to SNR_rx, it asks the SNRToBlockErrorRateManager to return the
-corresponding block error rate BlcER. A random number RAND between 0 and 1 is
-then generated. If RAND is greater than BlcER, then the block is correctly
-received, otherwise the block is considered erroneous and is ignored.
-
-The module provides defaults SNR to block error rate traces in default-traces.h.
-The traces have been generated by an External WiMAX OFDM simulator. The
-simulator is based on an external mathematics and signal processing library IT++
-and includes : a random block generator, a Reed Solomon (RS) coder, a
-convolutional coder, an interleaver, a 256 FFT-based OFDM modulator, a
-multi-path channel simulator and an equalizer. The multipath channel is
-simulated using the TDL_channel class of the IT++ library.
-
-Users can configure the module to use their own traces generated by another OFDM
-simulator or ideally by performing experiments in real environment. For this
-purpose, a path to a repository containing trace files should be provided.  If
-no repository is provided the traces form default-traces.h will be loaded. A
-valid repository should contain 7 files, one for each modulation and coding
-scheme.
-
-The names of the files should respect the following format: modulation0.txt for
-modulation 0, modulation1.txt for modulation 1 and so on...  The file format
-should be as follows:
-
-.. sourcecode:: text
-
-    SNR_value1   BER  Blc_ER  STANDARD_DEVIATION  CONFIDENCE_INTERVAL1  CONFIDENCE_INTERVAL2
-    SNR_value2   BER  Blc_ER  STANDARD_DEVIATION  CONFIDENCE_INTERVAL1  CONFIDENCE_INTERVAL2
-     ...          ...  ...     ...                 ...                   ...
-     ...          ...  ...     ...                 ...                   ...
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/examples/CMakeLists.txt ns-3.46/src/wimax/examples/CMakeLists.txt
--- ns-3.45/src/wimax/examples/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/examples/CMakeLists.txt	1969-12-31 16:00:00.000000000 -0800
@@ -1,30 +0,0 @@
-build_lib_example(
-  NAME wimax-ipv4
-  SOURCE_FILES wimax-ipv4.cc
-  LIBRARIES_TO_LINK
-    ${libwimax}
-    ${libinternet}
-    ${libmobility}
-    ${libcsma}
-    ${libapplications}
-)
-
-build_lib_example(
-  NAME wimax-multicast
-  SOURCE_FILES wimax-multicast.cc
-  LIBRARIES_TO_LINK
-    ${libwimax}
-    ${libinternet}
-    ${libcsma}
-    ${libapplications}
-)
-
-build_lib_example(
-  NAME wimax-simple
-  SOURCE_FILES wimax-simple.cc
-  LIBRARIES_TO_LINK
-    ${libwimax}
-    ${libinternet}
-    ${libmobility}
-    ${libapplications}
-)
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/examples/wimax-ipv4.cc ns-3.46/src/wimax/examples/wimax-ipv4.cc
--- ns-3.45/src/wimax/examples/wimax-ipv4.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/examples/wimax-ipv4.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,216 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-//
-// Default network topology includes a base station (BS) and some number of
-// subscriber station (SS) specified by the variable nbSS (defaults to six).
-// The SSs are grouped into two groups: senders and receivers. SSs from 0 to
-// nbSS/2 are designed as senders and SSs from (nbSS/2 + 1) to nbSS-1 will
-// designed as receivers.
-// Each SS creates 3 transport connection with the BS. the fist one has as QoS
-// scheduling type UGS, the second one rtPS and the third one BE.
-// Senders SSs send some stamped IP packets with variable bitrate to receiver SSs
-// through the BS station. receiver SSs receive the IP packets analyze them and
-// based on a sequence number decide if all the packets are coorectly received
-
-//      +-----+    +-----+    +-----+
-//      | SS0 |    | SS1 |    | SS2 |
-//      +-----+    +-----+    +-----+
-//     10.1.1.1   10.1.1.2   10.1.1.3
-//      --------  --------    -------
-//        ((*))    ((*))       ((*))
-//
-//                  10.1.1.7
-//               +------------+
-//               |Base Station| ==((*))
-//               +------------+
-//
-//        ((*))    ((*))       ((*))
-//       -------   --------   --------
-//      10.1.1.4   10.1.1.5   10.1.1.6
-//       +-----+    +-----+    +-----+
-//       | SS3 |    | SS4 |    | SS5 |
-//       +-----+    +-----+    +-----+
-
-#include "ns3/applications-module.h"
-#include "ns3/core-module.h"
-#include "ns3/global-route-manager.h"
-#include "ns3/internet-module.h"
-#include "ns3/mobility-module.h"
-#include "ns3/network-module.h"
-#include "ns3/wimax-module.h"
-
-#include <iostream>
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE("wimaxIpV4Simulation");
-
-int
-main(int argc, char* argv[])
-{
-    // default values
-    int nbSS = 4;
-    int duration = 7;
-    int schedType = 0;
-    bool verbose = false;
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
-    LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
-
-    CommandLine cmd(__FILE__);
-    cmd.AddValue("nbSS", "number of subscriber station to create", nbSS);
-    cmd.AddValue("scheduler", "type of scheduler to use with the network devices", schedType);
-    cmd.AddValue("duration", "duration of the simulation in seconds", duration);
-    cmd.AddValue("verbose", "turn on all WimaxNetDevice log components", verbose);
-    cmd.Parse(argc, argv);
-
-    switch (schedType)
-    {
-    case 0:
-        scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-        break;
-    case 1:
-        scheduler = WimaxHelper::SCHED_TYPE_MBQOS;
-        break;
-    case 2:
-        scheduler = WimaxHelper::SCHED_TYPE_RTPS;
-        break;
-    default:
-        scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    }
-
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-
-    ssNodes.Create(nbSS);
-    bsNodes.Create(1);
-
-    WimaxHelper wimax;
-
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-
-    auto ss = new Ptr<SubscriberStationNetDevice>[nbSS];
-
-    for (int i = 0; i < nbSS; i++)
-    {
-        ss[i] = ssDevs.Get(i)->GetObject<SubscriberStationNetDevice>();
-        ss[i]->SetModulationType(WimaxPhy::MODULATION_TYPE_QAM16_12);
-    }
-
-    Ptr<BaseStationNetDevice> bs;
-    bs = bsDevs.Get(0)->GetObject<BaseStationNetDevice>();
-
-    MobilityHelper mobility;
-    mobility.Install(bsNodes);
-    mobility.Install(ssNodes);
-
-    InternetStackHelper stack;
-    stack.Install(bsNodes);
-    stack.Install(ssNodes);
-
-    Ipv4AddressHelper address;
-    address.SetBase("10.1.1.0", "255.255.255.0");
-
-    Ipv4InterfaceContainer SSinterfaces = address.Assign(ssDevs);
-    Ipv4InterfaceContainer BSinterface = address.Assign(bsDevs);
-    if (verbose)
-    {
-        WimaxHelper::EnableLogComponents(); // Turn on all wimax logging
-    }
-    /*------------------------------*/
-    auto udpServer = new UdpServerHelper[nbSS / 2];
-    auto serverApps = new ApplicationContainer[nbSS / 2];
-    auto udpClient = new UdpClientHelper[nbSS / 2];
-    auto clientApps = new ApplicationContainer[nbSS / 2];
-
-    for (int i = 0; i < nbSS / 2; i++)
-    {
-        // set server port to 100+(i*10)
-        udpServer[i] = UdpServerHelper(100 + (i * 10));
-        serverApps[i] = udpServer[i].Install(ssNodes.Get(i));
-        serverApps[i].Start(Seconds(6));
-        serverApps[i].Stop(Seconds(duration));
-
-        udpClient[i] = UdpClientHelper(SSinterfaces.GetAddress(i), 100 + (i * 10));
-        udpClient[i].SetAttribute("MaxPackets", UintegerValue(1200));
-        udpClient[i].SetAttribute("Interval", TimeValue(Seconds(0.12)));
-        udpClient[i].SetAttribute("PacketSize", UintegerValue(800));
-
-        clientApps[i] = udpClient[i].Install(ssNodes.Get(i + (nbSS / 2)));
-        clientApps[i].Start(Seconds(6));
-        clientApps[i].Stop(Seconds(duration));
-    }
-
-    Simulator::Stop(Seconds(duration + 0.1));
-    /*
-     * Setup 1 transport connections between each SS and the BS
-     */
-    for (int i = 0; i < nbSS / 2; i++)
-    {
-        IpcsClassifierRecord DlClassifierBe(Ipv4Address("0.0.0.0"),
-                                            Ipv4Mask("0.0.0.0"),
-                                            SSinterfaces.GetAddress(i),
-                                            Ipv4Mask("255.255.255.255"),
-                                            0,
-                                            65000,
-                                            100 + (i * 10),
-                                            100 + (i * 10),
-                                            17,
-                                            1);
-        ServiceFlow DlServiceFlowBe = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_DOWN,
-                                                              ServiceFlow::SF_TYPE_BE,
-                                                              DlClassifierBe);
-        ss[i]->AddServiceFlow(DlServiceFlowBe);
-        IpcsClassifierRecord ulClassifierBe(SSinterfaces.GetAddress(i + (nbSS / 2)),
-                                            Ipv4Mask("255.255.255.255"),
-                                            Ipv4Address("0.0.0.0"),
-                                            Ipv4Mask("0.0.0.0"),
-                                            0,
-                                            65000,
-                                            100 + (i * 10),
-                                            100 + (i * 10),
-                                            17,
-                                            1);
-        ServiceFlow ulServiceFlowBe = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_UP,
-                                                              ServiceFlow::SF_TYPE_BE,
-                                                              ulClassifierBe);
-        ss[i + (nbSS / 2)]->AddServiceFlow(ulServiceFlowBe);
-    }
-
-    NS_LOG_INFO("Starting simulation.....");
-    Simulator::Run();
-
-    delete[] clientApps;
-    delete[] udpClient;
-    delete[] serverApps;
-    delete[] udpServer;
-    for (int i = 0; i < nbSS; i++)
-    {
-        ss[i] = nullptr;
-    }
-    delete[] ss;
-
-    bs = nullptr;
-
-    Simulator::Destroy();
-    NS_LOG_INFO("Done.");
-
-    return 0;
-}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/examples/wimax-multicast.cc ns-3.46/src/wimax/examples/wimax-multicast.cc
--- ns-3.45/src/wimax/examples/wimax-multicast.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/examples/wimax-multicast.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,317 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-// Default network topology includes:
-// - A base station (BS)
-// - Some number of SSs specified by the variable nbSS (defaults to 10)
-// - A multicast router (ASNGW)
-// - A multicast streamer
-
-// Two Lans are setup: The first one between the multicast streamer and the
-// ASNGW, the second one between the ASNGW (router) and the base station
-
-//      +-----+    +-----+    +-----+   +-----+    +-----+
-//      | SS0 |    | SS1 |    | SS2 |   | SS3 |    | SS4 |
-//      +-----+    +-----+    +-----+   +-----+    +-----+
-//     10.1.0.1   10.1.0.2   10.1.0.3  10.1.0.4   10.1.0.5
-//      --------  --------    -------   -------   --------
-//        ((*))    ((*))       ((*))     ((*))       ((*))
-//
-//                              LAN2 (11.1.1.0)
-//                          ===============
-//        10.1.0.11          |          |
-//              +------------+        ASNGW           multicast Streamer
-//       ((*))==|Base Station|          |  (12.1.1.0)   |
-//              +------------+         ==================
-//                                            LAN1
-//
-//        ((*))    ((*))       ((*))        ((*))    ((*))
-//       -------   --------   --------    -------   --------
-//      10.1.0.6   10.1.0.7   10.1.0.8    10.1.0.9   10.1.0.10
-//       +-----+    +-----+    +-----+    +-----+    +-----+
-//       | SS5 |    | SS6 |    | SS7 |    | SS8 |    | SS9 |
-//       +-----+    +-----+    +-----+    +-----+    +-----+
-
-#include "ns3/applications-module.h"
-#include "ns3/core-module.h"
-#include "ns3/csma-module.h"
-#include "ns3/global-route-manager.h"
-#include "ns3/internet-module.h"
-#include "ns3/mobility-module.h"
-#include "ns3/network-module.h"
-#include "ns3/vector.h"
-#include "ns3/wimax-module.h"
-
-#include <iostream>
-#include <vector>
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE("WimaxMulticastSimulation");
-
-int
-main(int argc, char* argv[])
-{
-    bool verbose = false;
-
-    NodeContainer ssNodes;
-    std::vector<Ptr<SubscriberStationNetDevice>> ss;
-    NetDeviceContainer ssDevs;
-    Ipv4InterfaceContainer SSinterfaces;
-
-    NodeContainer bsNodes;
-    Ptr<BaseStationNetDevice> bs;
-    NetDeviceContainer bsDevs;
-    NetDeviceContainer bsDevsOne;
-    Ipv4InterfaceContainer BSinterfaces;
-
-    UdpTraceClientHelper udpClient;
-    ApplicationContainer clientApps;
-
-    Ptr<SimpleOfdmWimaxChannel> channel;
-    NodeContainer Streamer_Node;
-    NodeContainer ASNGW_Node;
-
-    Ptr<ConstantPositionMobilityModel> BSPosition;
-    std::vector<Ptr<RandomWaypointMobilityModel>> SSPosition;
-    std::vector<Ptr<RandomRectanglePositionAllocator>> SSPosAllocator;
-
-    // default values
-    int nbSS = 10;
-    int duration = 7;
-    int schedType = 0;
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-
-    CommandLine cmd(__FILE__);
-    cmd.AddValue("nbSS", "number of subscriber station to create", nbSS);
-    cmd.AddValue("scheduler", "type of scheduler to use with the netdevices", schedType);
-    cmd.AddValue("duration", "duration of the simulation in seconds", duration);
-    cmd.AddValue("verbose", "turn on all WimaxNetDevice log components", verbose);
-    cmd.Parse(argc, argv);
-
-    LogComponentEnable("UdpTraceClient", LOG_LEVEL_INFO);
-    LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
-
-    switch (schedType)
-    {
-    case 0:
-        scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-        break;
-    case 1:
-        scheduler = WimaxHelper::SCHED_TYPE_MBQOS;
-        break;
-    case 2:
-        scheduler = WimaxHelper::SCHED_TYPE_RTPS;
-        break;
-    default:
-        scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    }
-
-    ss.resize(nbSS);
-    SSPosition.resize(nbSS);
-    SSPosAllocator.resize(nbSS);
-
-    ssNodes.Create(nbSS);
-    bsNodes.Create(1);
-
-    Streamer_Node.Create(1);
-    ASNGW_Node.Create(1);
-
-    WimaxHelper wimax;
-
-    channel = CreateObject<SimpleOfdmWimaxChannel>();
-    channel->SetPropagationModel(SimpleOfdmWimaxChannel::COST231_PROPAGATION);
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           channel,
-                           scheduler);
-    Ptr<WimaxNetDevice> dev = wimax.Install(bsNodes.Get(0),
-                                            WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                                            WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                                            channel,
-                                            scheduler);
-
-    BSPosition = CreateObject<ConstantPositionMobilityModel>();
-
-    BSPosition->SetPosition(Vector(1000, 0, 0));
-    bsNodes.Get(0)->AggregateObject(BSPosition);
-    bsDevs.Add(dev);
-    if (verbose)
-    {
-        WimaxHelper::EnableLogComponents(); // Turn on all wimax logging
-    }
-
-    for (int i = 0; i < nbSS; i++)
-    {
-        SSPosition[i] = CreateObject<RandomWaypointMobilityModel>();
-        SSPosAllocator[i] = CreateObject<RandomRectanglePositionAllocator>();
-        Ptr<UniformRandomVariable> xVar = CreateObject<UniformRandomVariable>();
-        xVar->SetAttribute("Min", DoubleValue((i / 40.0) * 2000));
-        xVar->SetAttribute("Max", DoubleValue((i / 40.0 + 1) * 2000));
-        SSPosAllocator[i]->SetX(xVar);
-        Ptr<UniformRandomVariable> yVar = CreateObject<UniformRandomVariable>();
-        yVar->SetAttribute("Min", DoubleValue((i / 40.0) * 2000));
-        yVar->SetAttribute("Max", DoubleValue((i / 40.0 + 1) * 2000));
-        SSPosAllocator[i]->SetY(yVar);
-        SSPosition[i]->SetAttribute("PositionAllocator", PointerValue(SSPosAllocator[i]));
-        SSPosition[i]->SetAttribute("Speed",
-                                    StringValue("ns3::UniformRandomVariable[Min=10.3|Max=40.7]"));
-        SSPosition[i]->SetAttribute("Pause",
-                                    StringValue("ns3::ConstantRandomVariable[Constant=0.01]"));
-
-        ss[i] = ssDevs.Get(i)->GetObject<SubscriberStationNetDevice>();
-        ss[i]->SetModulationType(WimaxPhy::MODULATION_TYPE_QAM16_12);
-        ssNodes.Get(i)->AggregateObject(SSPosition[i]);
-    }
-
-    bs = bsDevs.Get(0)->GetObject<BaseStationNetDevice>();
-
-    CsmaHelper csmaASN_BS;
-    CsmaHelper csmaStreamer_ASN;
-
-    // First LAN BS and ASN
-    NodeContainer LAN_ASN_BS;
-
-    LAN_ASN_BS.Add(bsNodes.Get(0));
-
-    LAN_ASN_BS.Add(ASNGW_Node.Get(0));
-
-    csmaASN_BS.SetChannelAttribute("DataRate", DataRateValue(DataRate(10000000)));
-    csmaASN_BS.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
-    csmaASN_BS.SetDeviceAttribute("Mtu", UintegerValue(1500));
-    NetDeviceContainer LAN_ASN_BS_Devs = csmaASN_BS.Install(LAN_ASN_BS);
-
-    NetDeviceContainer BS_CSMADevs;
-
-    BS_CSMADevs.Add(LAN_ASN_BS_Devs.Get(0));
-
-    NetDeviceContainer ASN_Devs1;
-    ASN_Devs1.Add(LAN_ASN_BS_Devs.Get(1));
-
-    // Second LAN ASN-GW and Streamer
-
-    NodeContainer LAN_ASN_STREAMER;
-    LAN_ASN_STREAMER.Add(ASNGW_Node.Get(0));
-    LAN_ASN_STREAMER.Add(Streamer_Node.Get(0));
-
-    csmaStreamer_ASN.SetChannelAttribute("DataRate", DataRateValue(DataRate(10000000)));
-    csmaStreamer_ASN.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
-    csmaStreamer_ASN.SetDeviceAttribute("Mtu", UintegerValue(1500));
-
-    NetDeviceContainer LAN_ASN_STREAMER_Devs = csmaStreamer_ASN.Install(LAN_ASN_STREAMER);
-
-    NetDeviceContainer STREAMER_Devs;
-    NetDeviceContainer ASN_Devs2;
-    ASN_Devs2.Add(LAN_ASN_STREAMER_Devs.Get(0));
-    STREAMER_Devs.Add(LAN_ASN_STREAMER_Devs.Get(1));
-
-    MobilityHelper mobility;
-    InternetStackHelper stack;
-    mobility.Install(bsNodes);
-    stack.Install(bsNodes);
-    mobility.Install(ssNodes);
-    stack.Install(ssNodes);
-    stack.Install(Streamer_Node);
-    stack.Install(ASNGW_Node);
-
-    Ipv4AddressHelper address;
-
-    address.SetBase("10.1.0.0", "255.255.255.0");
-    bsDevsOne.Add(bs);
-    BSinterfaces = address.Assign(bsDevsOne);
-    SSinterfaces = address.Assign(ssDevs);
-
-    address.SetBase("11.1.1.0", "255.255.255.0");
-    Ipv4InterfaceContainer BSCSMAInterfaces = address.Assign(BS_CSMADevs);
-    Ipv4InterfaceContainer ASNCSMAInterfaces1 = address.Assign(ASN_Devs1);
-
-    address.SetBase("12.1.1.0", "255.255.255.0");
-    Ipv4InterfaceContainer ASNCSMAInterfaces2 = address.Assign(ASN_Devs2);
-    Ipv4InterfaceContainer StreamerCSMAInterfaces = address.Assign(STREAMER_Devs);
-
-    Ipv4Address multicastSource("12.1.1.2");
-    Ipv4Address multicastGroup("224.30.10.81");
-
-    Ipv4StaticRoutingHelper multicast;
-    // 1) Configure a (static) multicast route on ASNGW (multicastRouter)
-    Ptr<Node> multicastRouter = ASNGW_Node.Get(0); // The node in question
-    Ptr<NetDevice> inputIf = ASN_Devs2.Get(0);     // The input NetDevice
-
-    multicast.AddMulticastRoute(multicastRouter,
-                                multicastSource,
-                                multicastGroup,
-                                inputIf,
-                                ASN_Devs1);
-
-    // 2) Set up a default multicast route on the sender n0
-    Ptr<Node> sender = Streamer_Node.Get(0);
-    Ptr<NetDevice> senderIf = STREAMER_Devs.Get(0);
-    multicast.SetDefaultMulticastRoute(sender, senderIf);
-
-    // 1) Configure a (static) multicast route on ASNGW (multicastRouter)
-    multicastRouter = bsNodes.Get(0); // The node in question
-    inputIf = BS_CSMADevs.Get(0);     // The input NetDevice
-
-    multicast.AddMulticastRoute(multicastRouter,
-                                multicastSource,
-                                multicastGroup,
-                                inputIf,
-                                bsDevsOne);
-
-    uint16_t multicast_port = 100;
-
-    UdpServerHelper udpServerHelper = UdpServerHelper(multicast_port);
-    ApplicationContainer serverApps;
-    serverApps = udpServerHelper.Install(ssNodes);
-    serverApps.Start(Seconds(6));
-    serverApps.Stop(Seconds(duration));
-
-    udpClient = UdpTraceClientHelper(multicastGroup, multicast_port, "");
-
-    clientApps = udpClient.Install(Streamer_Node.Get(0));
-    clientApps.Start(Seconds(6));
-    clientApps.Stop(Seconds(duration));
-
-    IpcsClassifierRecord MulticastClassifier(Ipv4Address("0.0.0.0"),
-                                             Ipv4Mask("0.0.0.0"),
-                                             multicastGroup,
-                                             Ipv4Mask("255.255.255.255"),
-                                             0,
-                                             65000,
-                                             multicast_port,
-                                             multicast_port,
-                                             17,
-                                             1);
-
-    ServiceFlow MulticastServiceFlow = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_DOWN,
-                                                               ServiceFlow::SF_TYPE_UGS,
-                                                               MulticastClassifier);
-
-    bs->GetServiceFlowManager()->AddMulticastServiceFlow(MulticastServiceFlow,
-                                                         WimaxPhy::MODULATION_TYPE_QPSK_12);
-
-    Simulator::Stop(Seconds(duration + 0.1));
-    NS_LOG_INFO("Starting simulation.....");
-    Simulator::Run();
-
-    for (int i = 0; i < nbSS; i++)
-    {
-        ss[i] = nullptr;
-        SSPosition[i] = nullptr;
-        SSPosAllocator[i] = nullptr;
-    }
-
-    bs = nullptr;
-
-    Simulator::Destroy();
-    NS_LOG_INFO("Done.");
-
-    return 0;
-}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/examples/wimax-simple.cc ns-3.46/src/wimax/examples/wimax-simple.cc
--- ns-3.45/src/wimax/examples/wimax-simple.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/examples/wimax-simple.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,197 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-//
-// Default network topology includes a base station (BS) and 2
-// subscriber station (SS).
-
-//      +-----+
-//      | SS0 |
-//      +-----+
-//     10.1.1.1
-//      -------
-//        ((*))
-//
-//                  10.1.1.7
-//               +------------+
-//               |Base Station| ==((*))
-//               +------------+
-//
-//        ((*))
-//       -------
-//      10.1.1.2
-//       +-----+
-//       | SS1 |
-//       +-----+
-
-#include "ns3/applications-module.h"
-#include "ns3/core-module.h"
-#include "ns3/global-route-manager.h"
-#include "ns3/internet-module.h"
-#include "ns3/ipcs-classifier-record.h"
-#include "ns3/mobility-module.h"
-#include "ns3/network-module.h"
-#include "ns3/service-flow.h"
-#include "ns3/wimax-module.h"
-
-#include <iostream>
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE("WimaxSimpleExample");
-
-int
-main(int argc, char* argv[])
-{
-    bool verbose = false;
-
-    int duration = 7;
-    int schedType = 0;
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-
-    CommandLine cmd(__FILE__);
-    cmd.AddValue("scheduler", "type of scheduler to use with the network devices", schedType);
-    cmd.AddValue("duration", "duration of the simulation in seconds", duration);
-    cmd.AddValue("verbose", "turn on all WimaxNetDevice log components", verbose);
-    cmd.Parse(argc, argv);
-    LogComponentEnable("UdpClient", LOG_LEVEL_INFO);
-    LogComponentEnable("UdpServer", LOG_LEVEL_INFO);
-    switch (schedType)
-    {
-    case 0:
-        scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-        break;
-    case 1:
-        scheduler = WimaxHelper::SCHED_TYPE_MBQOS;
-        break;
-    case 2:
-        scheduler = WimaxHelper::SCHED_TYPE_RTPS;
-        break;
-    default:
-        scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    }
-
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-
-    ssNodes.Create(2);
-    bsNodes.Create(1);
-
-    WimaxHelper wimax;
-
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-
-    wimax.EnableAscii("bs-devices", bsDevs);
-    wimax.EnableAscii("ss-devices", ssDevs);
-
-    Ptr<SubscriberStationNetDevice> ss[2];
-
-    for (int i = 0; i < 2; i++)
-    {
-        ss[i] = ssDevs.Get(i)->GetObject<SubscriberStationNetDevice>();
-        ss[i]->SetModulationType(WimaxPhy::MODULATION_TYPE_QAM16_12);
-    }
-
-    Ptr<BaseStationNetDevice> bs;
-
-    bs = bsDevs.Get(0)->GetObject<BaseStationNetDevice>();
-
-    InternetStackHelper stack;
-    stack.Install(bsNodes);
-    stack.Install(ssNodes);
-
-    Ipv4AddressHelper address;
-    address.SetBase("10.1.1.0", "255.255.255.0");
-
-    Ipv4InterfaceContainer SSinterfaces = address.Assign(ssDevs);
-    Ipv4InterfaceContainer BSinterface = address.Assign(bsDevs);
-
-    if (verbose)
-    {
-        WimaxHelper::EnableLogComponents(); // Turn on all wimax logging
-    }
-    /*------------------------------*/
-    UdpServerHelper udpServer;
-    ApplicationContainer serverApps;
-    UdpClientHelper udpClient;
-    ApplicationContainer clientApps;
-
-    udpServer = UdpServerHelper(100);
-
-    serverApps = udpServer.Install(ssNodes.Get(0));
-    serverApps.Start(Seconds(6));
-    serverApps.Stop(Seconds(duration));
-
-    udpClient = UdpClientHelper(SSinterfaces.GetAddress(0), 100);
-    udpClient.SetAttribute("MaxPackets", UintegerValue(1200));
-    udpClient.SetAttribute("Interval", TimeValue(Seconds(0.5)));
-    udpClient.SetAttribute("PacketSize", UintegerValue(1024));
-
-    clientApps = udpClient.Install(ssNodes.Get(1));
-    clientApps.Start(Seconds(6));
-    clientApps.Stop(Seconds(duration));
-
-    Simulator::Stop(Seconds(duration + 0.1));
-
-    wimax.EnablePcap("wimax-simple-ss0", ssNodes.Get(0)->GetId(), ss[0]->GetIfIndex());
-    wimax.EnablePcap("wimax-simple-ss1", ssNodes.Get(1)->GetId(), ss[1]->GetIfIndex());
-    wimax.EnablePcap("wimax-simple-bs0", bsNodes.Get(0)->GetId(), bs->GetIfIndex());
-
-    IpcsClassifierRecord DlClassifierUgs(Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         SSinterfaces.GetAddress(0),
-                                         Ipv4Mask("255.255.255.255"),
-                                         0,
-                                         65000,
-                                         100,
-                                         100,
-                                         17,
-                                         1);
-    ServiceFlow DlServiceFlowUgs = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_DOWN,
-                                                           ServiceFlow::SF_TYPE_RTPS,
-                                                           DlClassifierUgs);
-
-    IpcsClassifierRecord UlClassifierUgs(SSinterfaces.GetAddress(1),
-                                         Ipv4Mask("255.255.255.255"),
-                                         Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         0,
-                                         65000,
-                                         100,
-                                         100,
-                                         17,
-                                         1);
-    ServiceFlow UlServiceFlowUgs = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_UP,
-                                                           ServiceFlow::SF_TYPE_RTPS,
-                                                           UlClassifierUgs);
-    ss[0]->AddServiceFlow(DlServiceFlowUgs);
-    ss[1]->AddServiceFlow(UlServiceFlowUgs);
-
-    NS_LOG_INFO("Starting simulation.....");
-    Simulator::Run();
-
-    ss[0] = nullptr;
-    ss[1] = nullptr;
-    bs = nullptr;
-
-    Simulator::Destroy();
-    NS_LOG_INFO("Done.");
-
-    return 0;
-}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/helper/wimax-helper.cc ns-3.46/src/wimax/helper/wimax-helper.cc
--- ns-3.45/src/wimax/helper/wimax-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/helper/wimax-helper.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,705 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#include "wimax-helper.h"
-
-#include "ns3/bs-net-device.h"
-#include "ns3/config.h"
-#include "ns3/log.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simple-ofdm-wimax-channel.h"
-#include "ns3/simple-ofdm-wimax-phy.h"
-#include "ns3/simulator.h"
-#include "ns3/ss-net-device.h"
-#include "ns3/wimax-channel.h"
-#include "ns3/wimax-mac-to-mac-header.h"
-#include "ns3/wimax-net-device.h"
-#include "ns3/wimax-phy.h"
-
-#include <string>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("WimaxHelper");
-
-WimaxHelper::WimaxHelper()
-    : m_channel(nullptr)
-{
-}
-
-WimaxHelper::~WimaxHelper()
-{
-}
-
-void
-WimaxHelper::EnableAsciiForConnection(Ptr<OutputStreamWrapper> os,
-                                      uint32_t nodeid,
-                                      uint32_t deviceid,
-                                      char* netdevice,
-                                      char* connection)
-{
-    std::ostringstream oss;
-    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::" << netdevice << "/"
-        << connection << "/TxQueue/Enqueue";
-    Config::Connect(oss.str(),
-                    MakeBoundCallback(&AsciiTraceHelper::DefaultEnqueueSinkWithContext, os));
-
-    oss.str("");
-    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::" << netdevice << "/"
-        << connection << "/TxQueue/Dequeue";
-    Config::Connect(oss.str(),
-                    MakeBoundCallback(&AsciiTraceHelper::DefaultDequeueSinkWithContext, os));
-
-    oss.str("");
-    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::" << netdevice << "/"
-        << connection << "/TxQueue/Drop";
-    Config::Connect(oss.str(),
-                    MakeBoundCallback(&AsciiTraceHelper::DefaultDropSinkWithContext, os));
-}
-
-Ptr<WimaxPhy>
-WimaxHelper::CreatePhy(PhyType phyType)
-{
-    Ptr<WimaxPhy> phy;
-    switch (phyType)
-    {
-    case SIMPLE_PHY_TYPE_OFDM:
-        phy = CreateObject<SimpleOfdmWimaxPhy>();
-        if (!m_channel)
-        {
-            m_channel =
-                CreateObject<SimpleOfdmWimaxChannel>(SimpleOfdmWimaxChannel::COST231_PROPAGATION);
-        }
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid physical type");
-        break;
-    }
-
-    return phy;
-}
-
-void
-WimaxHelper::SetPropagationLossModel(SimpleOfdmWimaxChannel::PropModel propagationModel)
-{
-    if (!m_channel)
-    {
-        m_channel = CreateObject<SimpleOfdmWimaxChannel>();
-    }
-    m_channel->GetObject<SimpleOfdmWimaxChannel>()->SetPropagationModel(propagationModel);
-}
-
-Ptr<WimaxPhy>
-WimaxHelper::CreatePhy(PhyType phyType, char* SNRTraceFilePath, bool activateLoss)
-{
-    Ptr<WimaxPhy> phy;
-    Ptr<SimpleOfdmWimaxPhy> sphy;
-    switch (phyType)
-    {
-    case SIMPLE_PHY_TYPE_OFDM:
-        sphy = CreateObject<SimpleOfdmWimaxPhy>();
-        phy = sphy;
-        sphy->SetSNRToBlockErrorRateTracesPath(SNRTraceFilePath);
-        sphy->ActivateLoss(activateLoss);
-        if (!m_channel)
-        {
-            m_channel =
-                CreateObject<SimpleOfdmWimaxChannel>(SimpleOfdmWimaxChannel::COST231_PROPAGATION);
-        }
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid physical type");
-        break;
-    }
-
-    return phy;
-}
-
-Ptr<WimaxPhy>
-WimaxHelper::CreatePhyWithoutChannel(PhyType phyType)
-{
-    Ptr<WimaxPhy> phy;
-    switch (phyType)
-    {
-    case SIMPLE_PHY_TYPE_OFDM:
-        phy = CreateObject<SimpleOfdmWimaxPhy>();
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid physical type");
-        break;
-    }
-
-    return phy;
-}
-
-Ptr<WimaxPhy>
-WimaxHelper::CreatePhyWithoutChannel(PhyType phyType, char* SNRTraceFilePath, bool activateLoss)
-{
-    Ptr<WimaxPhy> phy;
-    Ptr<SimpleOfdmWimaxPhy> sphy;
-    switch (phyType)
-    {
-    case SIMPLE_PHY_TYPE_OFDM:
-        sphy = CreateObject<SimpleOfdmWimaxPhy>();
-        phy = sphy;
-        sphy->SetSNRToBlockErrorRateTracesPath(SNRTraceFilePath);
-        sphy->ActivateLoss(activateLoss);
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid physical type");
-        break;
-    }
-
-    return phy;
-}
-
-Ptr<UplinkScheduler>
-WimaxHelper::CreateUplinkScheduler(SchedulerType schedulerType)
-{
-    Ptr<UplinkScheduler> uplinkScheduler;
-    switch (schedulerType)
-    {
-    case SCHED_TYPE_SIMPLE:
-        uplinkScheduler = CreateObject<UplinkSchedulerSimple>();
-        break;
-    case SCHED_TYPE_RTPS:
-        uplinkScheduler = CreateObject<UplinkSchedulerRtps>();
-        break;
-    case SCHED_TYPE_MBQOS:
-        uplinkScheduler = CreateObject<UplinkSchedulerMBQoS>(Seconds(0.25));
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-        break;
-    }
-    return uplinkScheduler;
-}
-
-Ptr<BSScheduler>
-WimaxHelper::CreateBSScheduler(SchedulerType schedulerType)
-{
-    Ptr<BSScheduler> bsScheduler;
-    switch (schedulerType)
-    {
-    case SCHED_TYPE_SIMPLE:
-        bsScheduler = CreateObject<BSSchedulerSimple>();
-        break;
-    case SCHED_TYPE_RTPS:
-        bsScheduler = CreateObject<BSSchedulerRtps>();
-        break;
-    case SCHED_TYPE_MBQOS:
-        bsScheduler = CreateObject<BSSchedulerSimple>();
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-        break;
-    }
-    return bsScheduler;
-}
-
-NetDeviceContainer
-WimaxHelper::Install(NodeContainer c,
-                     NetDeviceType deviceType,
-                     PhyType phyType,
-                     SchedulerType schedulerType,
-                     double frameDuration)
-{
-    NetDeviceContainer devices;
-    for (auto i = c.Begin(); i != c.End(); i++)
-    {
-        Ptr<Node> node = *i;
-        Ptr<WimaxPhy> phy = CreatePhy(phyType);
-
-        // Set SuperFrame Duration
-        phy->SetFrameDuration(Seconds(frameDuration));
-
-        Ptr<WimaxNetDevice> device;
-        Ptr<UplinkScheduler> uplinkScheduler = CreateUplinkScheduler(schedulerType);
-        Ptr<BSScheduler> bsScheduler = CreateBSScheduler(schedulerType);
-
-        if (deviceType == DEVICE_TYPE_BASE_STATION)
-        {
-            // attach phy
-            Ptr<BaseStationNetDevice> deviceBS;
-            deviceBS = CreateObject<BaseStationNetDevice>(node, phy, uplinkScheduler, bsScheduler);
-            device = deviceBS;
-            uplinkScheduler->SetBs(deviceBS);
-            bsScheduler->SetBs(deviceBS);
-        }
-        else
-        {
-            device = CreateObject<SubscriberStationNetDevice>(node, phy);
-        }
-        device->SetAddress(Mac48Address::Allocate());
-        phy->SetDevice(device);
-        device->Start();
-        device->Attach(m_channel); // attach channel
-
-        node->AddDevice(device);
-
-        devices.Add(device);
-    }
-    return devices;
-}
-
-NetDeviceContainer
-WimaxHelper::Install(NodeContainer c,
-                     NetDeviceType deviceType,
-                     PhyType phyType,
-                     SchedulerType schedulerType)
-{
-    NetDeviceContainer devices;
-    for (auto i = c.Begin(); i != c.End(); i++)
-    {
-        Ptr<Node> node = *i;
-        Ptr<WimaxPhy> phy = CreatePhy(phyType);
-        Ptr<WimaxNetDevice> device;
-        Ptr<UplinkScheduler> uplinkScheduler = CreateUplinkScheduler(schedulerType);
-        Ptr<BSScheduler> bsScheduler = CreateBSScheduler(schedulerType);
-
-        if (deviceType == DEVICE_TYPE_BASE_STATION)
-        {
-            // attach phy
-            Ptr<BaseStationNetDevice> deviceBS;
-            deviceBS = CreateObject<BaseStationNetDevice>(node, phy, uplinkScheduler, bsScheduler);
-            device = deviceBS;
-            uplinkScheduler->SetBs(deviceBS);
-            bsScheduler->SetBs(deviceBS);
-        }
-        else
-        {
-            device = CreateObject<SubscriberStationNetDevice>(node, phy);
-        }
-        device->SetAddress(Mac48Address::Allocate());
-        phy->SetDevice(device);
-        device->Start();
-        device->Attach(m_channel); // attach channel
-
-        node->AddDevice(device);
-
-        devices.Add(device);
-    }
-    return devices;
-}
-
-NetDeviceContainer
-WimaxHelper::Install(NodeContainer c,
-                     NetDeviceType deviceType,
-                     PhyType phyType,
-                     Ptr<WimaxChannel> channel,
-                     SchedulerType schedulerType)
-{
-    NetDeviceContainer devices;
-    for (auto i = c.Begin(); i != c.End(); i++)
-    {
-        Ptr<Node> node = *i;
-
-        Ptr<WimaxPhy> phy = CreatePhyWithoutChannel(phyType, (char*)"dummy", false);
-        Ptr<WimaxNetDevice> device;
-        Ptr<UplinkScheduler> uplinkScheduler = CreateUplinkScheduler(schedulerType);
-        Ptr<BSScheduler> bsScheduler = CreateBSScheduler(schedulerType);
-
-        if (deviceType == DEVICE_TYPE_BASE_STATION)
-        {
-            Ptr<BaseStationNetDevice> deviceBS;
-            deviceBS = CreateObject<BaseStationNetDevice>(node, phy, uplinkScheduler, bsScheduler);
-            device = deviceBS;
-            uplinkScheduler->SetBs(deviceBS);
-            bsScheduler->SetBs(deviceBS);
-        }
-        else
-        {
-            device = CreateObject<SubscriberStationNetDevice>(node, phy);
-        }
-        device->SetAddress(Mac48Address::Allocate());
-        phy->SetDevice(device);
-        device->Start();
-        device->Attach(channel);
-
-        node->AddDevice(device);
-        devices.Add(device);
-    }
-    return devices;
-}
-
-Ptr<WimaxNetDevice>
-WimaxHelper::Install(Ptr<Node> node,
-                     NetDeviceType deviceType,
-                     PhyType phyType,
-                     Ptr<WimaxChannel> channel,
-                     SchedulerType schedulerType)
-{
-    // Ptr<WimaxPhy> phy = CreatePhyWithoutChannel (phyType);
-    Ptr<WimaxPhy> phy = CreatePhyWithoutChannel(phyType, (char*)"dummy", false);
-    Ptr<WimaxNetDevice> device;
-    Ptr<UplinkScheduler> uplinkScheduler = CreateUplinkScheduler(schedulerType);
-    Ptr<BSScheduler> bsScheduler = CreateBSScheduler(schedulerType);
-
-    if (deviceType == DEVICE_TYPE_BASE_STATION)
-    {
-        Ptr<BaseStationNetDevice> deviceBS;
-        deviceBS = CreateObject<BaseStationNetDevice>(node, phy, uplinkScheduler, bsScheduler);
-        device = deviceBS;
-        uplinkScheduler->SetBs(deviceBS);
-        bsScheduler->SetBs(deviceBS);
-    }
-    else
-    {
-        device = CreateObject<SubscriberStationNetDevice>(node, phy);
-    }
-    device->SetAddress(Mac48Address::Allocate());
-    phy->SetDevice(device);
-    device->Start();
-    device->Attach(channel);
-
-    node->AddDevice(device);
-
-    return device;
-}
-
-void
-WimaxHelper::EnableLogComponents()
-{
-    LogComponentEnable("BandwidthManager", LOG_LEVEL_ALL);
-    LogComponentEnable("BSLinkManager", LOG_LEVEL_ALL);
-    LogComponentEnable("BaseStationNetDevice", LOG_LEVEL_ALL);
-    LogComponentEnable("BSSchedulerRtps", LOG_LEVEL_ALL);
-    LogComponentEnable("BSSchedulerSimple", LOG_LEVEL_ALL);
-    LogComponentEnable("BSScheduler", LOG_LEVEL_ALL);
-    LogComponentEnable("BsServiceFlowManager", LOG_LEVEL_ALL);
-    LogComponentEnable("UplinkSchedulerMBQoS", LOG_LEVEL_ALL);
-    LogComponentEnable("UplinkSchedulerRtps", LOG_LEVEL_ALL);
-    LogComponentEnable("UplinkSchedulerSimple", LOG_LEVEL_ALL);
-    LogComponentEnable("UplinkScheduler", LOG_LEVEL_ALL);
-    LogComponentEnable("BurstProfileManager", LOG_LEVEL_ALL);
-    LogComponentEnable("ConnectionManager", LOG_LEVEL_ALL);
-    LogComponentEnable("IpcsClassifierRecord", LOG_LEVEL_ALL);
-    LogComponentEnable("IpcsClassifier", LOG_LEVEL_ALL);
-    LogComponentEnable("MACMESSAGES", LOG_LEVEL_ALL);
-    LogComponentEnable("PacketBurst", LOG_LEVEL_ALL);
-    LogComponentEnable("ServiceFlowManager", LOG_LEVEL_ALL);
-    LogComponentEnable("simpleOfdmWimaxChannel", LOG_LEVEL_ALL);
-    LogComponentEnable("SimpleOfdmWimaxPhy", LOG_LEVEL_ALL);
-    LogComponentEnable("SNRToBlockErrorRateManager", LOG_LEVEL_ALL);
-    LogComponentEnable("SSLinkManager", LOG_LEVEL_ALL);
-    LogComponentEnable("SSManager", LOG_LEVEL_ALL);
-    LogComponentEnable("SubscriberStationNetDevice", LOG_LEVEL_ALL);
-    LogComponentEnable("SSScheduler", LOG_LEVEL_ALL);
-    LogComponentEnable("SsServiceFlowManager", LOG_LEVEL_ALL);
-    LogComponentEnable("WimaxChannel", LOG_LEVEL_ALL);
-    LogComponentEnable("WimaxMacQueue", LOG_LEVEL_ALL);
-    LogComponentEnable("WimaxNetDevice", LOG_LEVEL_ALL);
-    LogComponentEnable("WimaxPhy", LOG_LEVEL_ALL);
-    LogComponentEnable("Tlv", LOG_LEVEL_ALL);
-    LogComponentEnable("BandwidthManager", LOG_LEVEL_ALL);
-    LogComponentEnable("BaseStationNetDevice", LOG_LEVEL_ALL);
-    LogComponentEnable("BSSchedulerRtps", LOG_LEVEL_ALL);
-    LogComponentEnable("BSSchedulerSimple", LOG_LEVEL_ALL);
-    LogComponentEnable("BSScheduler", LOG_LEVEL_ALL);
-    LogComponentEnable("SubscriberStationNetDevice", LOG_LEVEL_ALL);
-    LogComponentEnable("SSScheduler", LOG_LEVEL_ALL);
-    LogComponentEnable("WimaxMacQueue", LOG_LEVEL_ALL);
-}
-
-void
-WimaxHelper::AsciiRxEvent(Ptr<OutputStreamWrapper> stream,
-                          std::string path,
-                          Ptr<const Packet> packet,
-                          const Mac48Address& source)
-{
-    *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " from: " << source << " ";
-    *stream->GetStream() << path << std::endl;
-}
-
-void
-WimaxHelper::AsciiTxEvent(Ptr<OutputStreamWrapper> stream,
-                          std::string path,
-                          Ptr<const Packet> packet,
-                          const Mac48Address& dest)
-{
-    *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " to: " << dest << " ";
-    *stream->GetStream() << path << std::endl;
-}
-
-ServiceFlow
-WimaxHelper::CreateServiceFlow(ServiceFlow::Direction direction,
-                               ServiceFlow::SchedulingType schedulingType,
-                               IpcsClassifierRecord classifier)
-{
-    CsParameters csParam(CsParameters::ADD, classifier);
-    ServiceFlow serviceFlow = ServiceFlow(direction);
-    serviceFlow.SetConvergenceSublayerParam(csParam);
-    serviceFlow.SetCsSpecification(ServiceFlow::IPV4);
-    serviceFlow.SetServiceSchedulingType(schedulingType);
-    serviceFlow.SetMaxSustainedTrafficRate(100);
-    serviceFlow.SetMinReservedTrafficRate(1000000);
-    serviceFlow.SetMinTolerableTrafficRate(1000000);
-    serviceFlow.SetMaximumLatency(100);
-    serviceFlow.SetMaxTrafficBurst(2000);
-    serviceFlow.SetTrafficPriority(1);
-    serviceFlow.SetUnsolicitedGrantInterval(1);
-    serviceFlow.SetMaxSustainedTrafficRate(70);
-    serviceFlow.SetToleratedJitter(10);
-    serviceFlow.SetSduSize(49);
-    serviceFlow.SetRequestTransmissionPolicy(0);
-    return serviceFlow;
-}
-
-void
-WimaxHelper::EnableAsciiInternal(Ptr<OutputStreamWrapper> stream,
-                                 std::string prefix,
-                                 Ptr<NetDevice> nd,
-                                 bool explicitFilename)
-{
-    //
-    // All of the ascii enable functions vector through here including the ones
-    // that are wandering through all of devices on perhaps all of the nodes in
-    // the system.  We can only deal with devices of type CsmaNetDevice.
-    //
-    Ptr<WimaxNetDevice> device = nd->GetObject<WimaxNetDevice>();
-    if (!device)
-    {
-        NS_LOG_INFO("WimaxHelper::EnableAsciiInternal(): Device "
-                    << device << " not of type ns3::WimaxNetDevice");
-        return;
-    }
-
-    //
-    // Our default trace sinks are going to use packet printing, so we have to
-    // make sure that is turned on.
-    //
-    Packet::EnablePrinting();
-
-    //
-    // If we are not provided an OutputStreamWrapper, we are expected to create
-    // one using the usual trace filename conventions and do a Hook*WithoutContext
-    // since there will be one file per context and therefore the context would
-    // be redundant.
-    //
-    if (!stream)
-    {
-        //
-        // Set up an output stream object to deal with private ofstream copy
-        // constructor and lifetime issues.  Let the helper decide the actual
-        // name of the file given the prefix.
-        //
-        AsciiTraceHelper asciiTraceHelper;
-        std::string filename;
-        if (explicitFilename)
-        {
-            filename = prefix;
-        }
-        else
-        {
-            filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device);
-        }
-        Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream(filename);
-
-        uint32_t nodeid = nd->GetNode()->GetId();
-        uint32_t deviceid = nd->GetIfIndex();
-        std::ostringstream oss;
-        //
-        // The MacRx trace source provides our "r" event.
-        //
-
-        oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WimaxNetDevice/Rx";
-        Config::Connect(oss.str(), MakeBoundCallback(&WimaxHelper::AsciiRxEvent, theStream));
-        oss.str("");
-        oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WimaxNetDevice/Tx";
-        Config::Connect(oss.str(), MakeBoundCallback(&WimaxHelper::AsciiTxEvent, theStream));
-        //
-        // The "+", '-', and 'd' events are driven by trace sources actually in the
-        // transmit queue.
-        //
-
-        EnableAsciiForConnection(theStream,
-                                 nodeid,
-                                 deviceid,
-                                 (char*)"WimaxNetDevice",
-                                 (char*)"InitialRangingConnection");
-        EnableAsciiForConnection(theStream,
-                                 nodeid,
-                                 deviceid,
-                                 (char*)"WimaxNetDevice",
-                                 (char*)"BroadcastConnection");
-
-        // The following connections can not be made right away because the BasicConnection and the
-        // PrimaryConnection are created later. We defer the creation to the
-        // SubscriberStationNetDevice
-
-        // EnableAsciiForConnection (theStream, nodeid, deviceid, (char*)
-        // "SubscriberStationNetDevice", (char*) "BasicConnection"); EnableAsciiForConnection
-        // (theStream, nodeid, deviceid, (char*) "SubscriberStationNetDevice", (char*)
-        // "PrimaryConnection");
-
-        Ptr<SubscriberStationNetDevice> ssNetDev = DynamicCast<SubscriberStationNetDevice>(nd);
-        if (ssNetDev)
-        {
-            SubscriberStationNetDevice::AsciiTraceCallback EnqueueCb =
-                MakeBoundCallback(&AsciiTraceHelper::DefaultEnqueueSinkWithContext, theStream);
-            ssNetDev->SetAsciiTxQueueEnqueueCallback(EnqueueCb);
-
-            SubscriberStationNetDevice::AsciiTraceCallback DequeueCb =
-                MakeBoundCallback(&AsciiTraceHelper::DefaultDequeueSinkWithContext, theStream);
-            ssNetDev->SetAsciiTxQueueDequeueCallback(DequeueCb);
-
-            SubscriberStationNetDevice::AsciiTraceCallback DropCb =
-                MakeBoundCallback(&AsciiTraceHelper::DefaultDropSinkWithContext, theStream);
-            ssNetDev->SetAsciiTxQueueDropCallback(DropCb);
-        }
-
-        return;
-    }
-
-    //
-    // If we are provided an OutputStreamWrapper, we are expected to use it, and
-    // to provide a context.  We are free to come up with our own context if we
-    // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
-    // compatibility and simplicity, we just use Config::Connect and let it deal
-    // with the context.
-    //
-    // Note that we are going to use the default trace sinks provided by the
-    // ascii trace helper.  There is actually no AsciiTraceHelper in sight here,
-    // but the default trace sinks are actually publicly available static
-    // functions that are always there waiting for just such a case.
-    //
-    uint32_t nodeid = nd->GetNode()->GetId();
-    uint32_t deviceid = nd->GetIfIndex();
-    std::ostringstream oss;
-
-    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WimaxNetDevice/Rx";
-    Config::Connect(oss.str(), MakeBoundCallback(&WimaxHelper::AsciiRxEvent, stream));
-
-    oss.str("");
-    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WimaxNetDevice/Tx";
-    Config::Connect(oss.str(), MakeBoundCallback(&WimaxHelper::AsciiTxEvent, stream));
-
-    EnableAsciiForConnection(stream,
-                             nodeid,
-                             deviceid,
-                             (char*)"WimaxNetDevice",
-                             (char*)"InitialRangingConnection");
-    EnableAsciiForConnection(stream,
-                             nodeid,
-                             deviceid,
-                             (char*)"WimaxNetDevice",
-                             (char*)"BroadcastConnection");
-
-    // The following connections can not be made right away because the BasicConnection and the
-    // PrimaryConnection are created later. We defer the creation to the SubscriberStationNetDevice
-
-    // EnableAsciiForConnection (stream, nodeid, deviceid, (char*) "SubscriberStationNetDevice",
-    // (char*) "BasicConnection"); EnableAsciiForConnection (stream, nodeid, deviceid, (char*)
-    // "SubscriberStationNetDevice", (char*) "PrimaryConnection");
-
-    Ptr<SubscriberStationNetDevice> ssNetDev = DynamicCast<SubscriberStationNetDevice>(nd);
-    if (ssNetDev)
-    {
-        SubscriberStationNetDevice::AsciiTraceCallback EnqueueCb =
-            MakeBoundCallback(&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream);
-        ssNetDev->SetAsciiTxQueueEnqueueCallback(EnqueueCb);
-
-        SubscriberStationNetDevice::AsciiTraceCallback DequeueCb =
-            MakeBoundCallback(&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream);
-        ssNetDev->SetAsciiTxQueueDequeueCallback(DequeueCb);
-
-        SubscriberStationNetDevice::AsciiTraceCallback DropCb =
-            MakeBoundCallback(&AsciiTraceHelper::DefaultDropSinkWithContext, stream);
-        ssNetDev->SetAsciiTxQueueDropCallback(DropCb);
-    }
-}
-
-/**
- * @brief print pcap record
- * @param file pcap file
- * @param burst packet burst to print
- */
-static void
-PcapSniffTxRxEvent(Ptr<PcapFileWrapper> file, Ptr<const PacketBurst> burst)
-{
-    std::list<Ptr<Packet>> packets = burst->GetPackets();
-    for (auto iter = packets.begin(); iter != packets.end(); ++iter)
-    {
-        Ptr<Packet> p = (*iter)->Copy();
-        WimaxMacToMacHeader m2m(p->GetSize());
-        p->AddHeader(m2m);
-        file->Write(Simulator::Now(), p);
-    }
-}
-
-void
-WimaxHelper::EnablePcapInternal(std::string prefix,
-                                Ptr<NetDevice> nd,
-                                bool explicitFilename,
-                                bool promiscuous)
-{
-    //
-    // All of the Pcap enable functions vector through here including the ones
-    // that are wandering through all of devices on perhaps all of the nodes in
-    // the system.  We can only deal with devices of type WimaxNetDevice.
-    //
-    Ptr<WimaxNetDevice> device = nd->GetObject<WimaxNetDevice>();
-    if (!device)
-    {
-        NS_LOG_INFO("WimaxHelper::EnablePcapInternal(): Device "
-                    << &device << " not of type ns3::WimaxNetDevice");
-        return;
-    }
-
-    Ptr<WimaxPhy> phy = device->GetPhy();
-    PcapHelper pcapHelper;
-    std::string filename;
-    if (explicitFilename)
-    {
-        filename = prefix;
-    }
-    else
-    {
-        filename = pcapHelper.GetFilenameFromDevice(prefix, device);
-    }
-
-    Ptr<PcapFileWrapper> file =
-        pcapHelper.CreateFile(filename, std::ios::out, PcapHelper::DLT_EN10MB);
-
-    phy->TraceConnectWithoutContext("Tx", MakeBoundCallback(&PcapSniffTxRxEvent, file));
-    phy->TraceConnectWithoutContext("Rx", MakeBoundCallback(&PcapSniffTxRxEvent, file));
-}
-
-int64_t
-WimaxHelper::AssignStreams(int64_t stream)
-{
-    NS_LOG_FUNCTION(this << stream);
-    return m_channel->AssignStreams(stream);
-}
-
-int64_t
-WimaxHelper::AssignStreams(NetDeviceContainer c, int64_t stream)
-{
-    int64_t currentStream = stream;
-    Ptr<NetDevice> netDevice;
-    for (auto i = c.Begin(); i != c.End(); ++i)
-    {
-        netDevice = (*i);
-        Ptr<WimaxNetDevice> wimax = DynamicCast<WimaxNetDevice>(netDevice);
-        if (wimax)
-        {
-            // Handle any random numbers in the PHY objects.
-            currentStream += wimax->GetPhy()->AssignStreams(currentStream);
-        }
-    }
-
-    // Handle any random numbers in the channel.
-    currentStream += m_channel->AssignStreams(currentStream);
-
-    return (currentStream - stream);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/helper/wimax-helper.h ns-3.46/src/wimax/helper/wimax-helper.h
--- ns-3.45/src/wimax/helper/wimax-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/helper/wimax-helper.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDCAST
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef WIMAX_HELPER_H
-#define WIMAX_HELPER_H
-
-#include "ns3/bs-net-device.h"
-#include "ns3/bs-scheduler-rtps.h"
-#include "ns3/bs-scheduler-simple.h"
-#include "ns3/bs-scheduler.h"
-#include "ns3/bs-uplink-scheduler-mbqos.h"
-#include "ns3/bs-uplink-scheduler-rtps.h"
-#include "ns3/bs-uplink-scheduler-simple.h"
-#include "ns3/bs-uplink-scheduler.h"
-#include "ns3/net-device-container.h"
-#include "ns3/node-container.h"
-#include "ns3/object-factory.h"
-#include "ns3/propagation-loss-model.h"
-#include "ns3/service-flow.h"
-#include "ns3/simple-ofdm-wimax-channel.h"
-#include "ns3/ss-net-device.h"
-#include "ns3/trace-helper.h"
-
-#include <string>
-
-namespace ns3
-{
-
-class WimaxChannel;
-class WimaxPhy;
-class UplinkScheduler;
-
-/**
- * @brief helps to manage and create WimaxNetDevice objects
- *
- * This class can help to create a large set of similar
- * WimaxNetDevice objects and to configure their attributes
- * during creation.
- */
-
-class WimaxHelper : public PcapHelperForDevice, public AsciiTraceHelperForDevice
-{
-  public:
-    /**
-     * Net Device Type
-     * Distinguish a subscriber station(SS) device from base station(BS) device
-     */
-    enum NetDeviceType
-    {
-        DEVICE_TYPE_SUBSCRIBER_STATION, /**< Subscriber station(SS) device */
-        DEVICE_TYPE_BASE_STATION
-        /**< Base station(BS) device */
-    };
-
-    /**
-     * WiMAX Physical layer
-     * WiMAX Physical layers with different levels of detail
-     */
-    enum PhyType
-    {
-        SIMPLE_PHY_TYPE_OFDM
-    };
-
-    /**
-     * Scheduler Type
-     * Different implementations of uplink/downlink scheduler
-     */
-    enum SchedulerType
-    {
-        SCHED_TYPE_SIMPLE, /**< A simple priority-based FCFS scheduler */
-        SCHED_TYPE_RTPS,   /**< A simple scheduler - rtPS based scheduler */
-        SCHED_TYPE_MBQOS
-        /**< An migration-based uplink scheduler */
-    };
-
-    /**
-     * @brief Create a Wimax helper in an empty state.
-     */
-    WimaxHelper();
-    ~WimaxHelper() override;
-    /**
-     * @brief Enable ascii trace output on the indicated net device for a given connection
-     * @param oss The output stream object to use when logging ascii traces.
-     * @param nodeid the id of the node for which you want to enable tracing.
-     * @param deviceid the id of the net device for which you want to enable tracing.
-     * @param netdevice the type of net device for which you want to enable tracing
-     * (SubscriberStationNetDevice, BaseStationNetDevice or WimaxNetDevice)
-     * @param connection the connection for which you want to enable tracing
-     * (InitialRangingConnection, BroadcastConnection, BasicConnection, PrimaryConnection).
-     */
-    static void EnableAsciiForConnection(Ptr<OutputStreamWrapper> oss,
-                                         uint32_t nodeid,
-                                         uint32_t deviceid,
-                                         char* netdevice,
-                                         char* connection);
-
-    /**
-     * @param phyType WiMAX Physical layer type
-     * @return WiMAX Phy object
-     *
-     * Creates a physical layer object to be used in simulation.
-     */
-    Ptr<WimaxPhy> CreatePhy(PhyType phyType);
-
-    /**
-     * @param schedulerType Scheduling mechanism
-     * @return Uplink scheduler
-     *
-     * Creates a uplink scheduler to be used by base station
-     * according to selected scheduling mechanism.
-     */
-    Ptr<UplinkScheduler> CreateUplinkScheduler(SchedulerType schedulerType);
-
-    /**
-     * @param schedulerType Scheduling mechanism
-     * @return Downlink scheduler
-     *
-     * Creates a downlink scheduler to be used by base station
-     * according to selected scheduling mechanism.
-     */
-    Ptr<BSScheduler> CreateBSScheduler(SchedulerType schedulerType);
-
-    /**
-     * @param c a set of nodes
-     * @param type device type to create
-     * @param phyType a phy to use
-     * @param schedulerType the type of the scheduling algorithm to install
-     * @return NetDeviceContainer
-     *
-     * For each of the input nodes, a new WiMAX net device (either
-     * ns3::SubscriberStationNetDevice or ns3::BaseStationNetDevice
-     * depending on the type parameter) is attached to the shared input channel.
-     */
-    NetDeviceContainer Install(NodeContainer c,
-                               NetDeviceType type,
-                               PhyType phyType,
-                               SchedulerType schedulerType);
-
-    /**
-     * @param c A set of nodes.
-     * @param deviceType Device type to create.
-     * @param phyType PHY type to create.
-     * @param channel A channel to use.
-     * @param schedulerType The scheduling mechanism.
-     * @return NetDeviceContainer
-     *
-     * For each of the input nodes, a new WiMAX net device (either
-     * ns3::SubscriberStationNetDevice or ns3::BaseStationNetDevice
-     * depending on the type parameter) is attached to the shared input channel.
-     */
-    NetDeviceContainer Install(NodeContainer c,
-                               NetDeviceType deviceType,
-                               PhyType phyType,
-                               Ptr<WimaxChannel> channel,
-                               SchedulerType schedulerType);
-    /**
-     * @param c A set of nodes.
-     * @param deviceType Device type to create.
-     * @param phyType PHY type to create.
-     * @param schedulerType The scheduling mechanism.
-     * @param frameDuration the farme duration in seconds
-     * @return NetDeviceContainer
-     *
-     * For each of the input nodes, a new WiMAX net device (either
-     * ns3::SubscriberStationNetDevice or ns3::BaseStationNetDevice
-     * depending on the type parameter) is attached to the shared input channel.
-     */
-    NetDeviceContainer Install(NodeContainer c,
-                               NetDeviceType deviceType,
-                               PhyType phyType,
-                               SchedulerType schedulerType,
-                               double frameDuration);
-
-    /**
-     * @brief Set the propagation and loss model of the channel. By default the channel
-     *  uses a COST231 propagation and loss model.
-     * @param propagationModel The propagation and loss model to set
-     */
-    void SetPropagationLossModel(SimpleOfdmWimaxChannel::PropModel propagationModel);
-
-    /**
-     * @param phyType WiMAX Physical layer type
-     * @return WiMAX Phy object
-     *
-     * Creates a physical layer without a channel
-     */
-    Ptr<WimaxPhy> CreatePhyWithoutChannel(PhyType phyType);
-
-    /**
-     * @param phyType WiMAX Physical layer type
-     * @param SNRTraceFilePath of the repository containing the SNR traces files
-     * @param activateLoss set to 1 to activate losses 0 otherwise
-     * @return WiMAX Phy object
-     *
-     * Creates a physical layer without creating a channel
-     */
-    Ptr<WimaxPhy> CreatePhyWithoutChannel(PhyType phyType,
-                                          char* SNRTraceFilePath,
-                                          bool activateLoss);
-
-    /**
-     * @param phyType WiMAX Physical layer type
-     * @param SNRTraceFilePath the path to the repository containing the SNR traces files
-     * @param activateLoss set to 1 if you want ton activate losses 0 otherwise
-     * @return WiMAX Phy object
-     *
-     * Creates a physical layer
-     */
-    Ptr<WimaxPhy> CreatePhy(PhyType phyType, char* SNRTraceFilePath, bool activateLoss);
-    /**
-     * @param node Node to be installed.
-     * @param deviceType Device type to create.
-     * @param phyType PHY type to create.
-     * @param channel A channel to use.
-     * @param schedulerType The scheduling mechanism to install on the device.
-     * @return Ptr<WimaxNetDevice>
-     *
-     * For each of the input nodes, a new WiMAX net device (either
-     * ns3::SubscriberStationNetDevice or ns3::BaseStationNetDevice
-     * depending on the type parameter) is attached to the shared input channel.
-     */
-    Ptr<WimaxNetDevice> Install(Ptr<Node> node,
-                                NetDeviceType deviceType,
-                                PhyType phyType,
-                                Ptr<WimaxChannel> channel,
-                                SchedulerType schedulerType);
-
-    /**
-     * @brief Creates a transport service flow.
-     * @param direction the direction of the service flow: UP or DOWN.
-     * @param schedulingType The service scheduling type to be used: UGS, RTPS, NRTPS, BE
-     * @param classifier The classifier to be used for this service flow
-     * @return ServiceFlow
-     *
-     */
-    ServiceFlow CreateServiceFlow(ServiceFlow::Direction direction,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  IpcsClassifierRecord classifier);
-
-    /**
-     * Helper to enable all WimaxNetDevice log components with one statement
-     */
-    static void EnableLogComponents();
-
-    /**
-     * Assign a fixed random variable stream number to the random variables
-     * used by this model.  Return the number of streams (possibly zero) that
-     * have been assigned.
-     *
-     * @param stream first stream index to use
-     * @return the number of stream indices assigned by this model
-     */
-    int64_t AssignStreams(int64_t stream);
-
-    /**
-     * Assign a fixed random variable stream number to the random variables
-     * used by this model. Return the number of streams (possibly zero) that
-     * have been assigned. The Install() method should have previously been
-     * called by the user.
-     *
-     * @param c NetDeviceContainer of the set of net devices for which the
-     *          WimaxNetDevice should be modified to use a fixed stream
-     * @param stream first stream index to use
-     * @return the number of stream indices assigned by this helper
-     */
-    int64_t AssignStreams(NetDeviceContainer c, int64_t stream);
-
-  private:
-    /**
-     * ASCII trace receive event
-     * @param stream the output stream
-     * @param path the path name
-     * @param packet the packet
-     * @param source the source MAC address
-     */
-    static void AsciiRxEvent(Ptr<OutputStreamWrapper> stream,
-                             std::string path,
-                             Ptr<const Packet> packet,
-                             const Mac48Address& source);
-    /**
-     * ASCII trace transmit event
-     * @param stream the output stream
-     * @param path the path
-     * @param packet the packet
-     * @param dest the destination MAC address
-     */
-    static void AsciiTxEvent(Ptr<OutputStreamWrapper> stream,
-                             std::string path,
-                             Ptr<const Packet> packet,
-                             const Mac48Address& dest);
-    /**
-     * @brief Enable pcap output on the indicated net device.
-     *
-     * NetDevice-specific implementation mechanism for hooking the trace and
-     * writing to the trace file.
-     *
-     * @param prefix Filename prefix to use for pcap files.
-     * @param nd Net device for which you want to enable tracing.
-     * @param explicitFilename Treat the prefix as an explicit filename if true
-     * @param promiscuous If true capture all possible packets available at the device.
-     */
-    void EnablePcapInternal(std::string prefix,
-                            Ptr<NetDevice> nd,
-                            bool explicitFilename,
-                            bool promiscuous) override;
-
-    /**
-     * @brief Enable ascii trace output on the indicated net device.
-     *
-     * NetDevice-specific implementation mechanism for hooking the trace and
-     * writing to the trace file.
-     *
-     * @param stream The output stream object to use when logging ascii traces.
-     * @param prefix Filename prefix to use for ascii trace files.
-     * @param nd Net device for which you want to enable tracing.
-     * @param explicitFilename Treat the prefix as an explicit filename if true
-     */
-    void EnableAsciiInternal(Ptr<OutputStreamWrapper> stream,
-                             std::string prefix,
-                             Ptr<NetDevice> nd,
-                             bool explicitFilename) override;
-
-    Ptr<WimaxChannel> m_channel; ///< wifi channel
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_HELPER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bandwidth-manager.cc ns-3.46/src/wimax/model/bandwidth-manager.cc
--- ns-3.45/src/wimax/model/bandwidth-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bandwidth-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "bandwidth-manager.h"
-
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-net-device.h"
-#include "ss-record.h"
-
-#include "ns3/node.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BandwidthManager");
-
-NS_OBJECT_ENSURE_REGISTERED(BandwidthManager);
-
-TypeId
-BandwidthManager::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::BandwidthManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-BandwidthManager::BandwidthManager(Ptr<WimaxNetDevice> device)
-    : m_device(device),
-      m_nrBwReqsSent(0)
-{
-}
-
-BandwidthManager::~BandwidthManager()
-{
-}
-
-void
-BandwidthManager::DoDispose()
-{
-    m_device = nullptr;
-}
-
-uint32_t
-BandwidthManager::CalculateAllocationSize(const SSRecord* ssRecord, const ServiceFlow* serviceFlow)
-{
-    Time currentTime = Simulator::Now();
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-    uint32_t allocationSize = 0;
-
-    // if SS has a UGS flow then it must set poll-me bit in order to be polled for non-UGS flows
-    if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS &&
-        ssRecord->GetHasServiceFlowUgs() && !ssRecord->GetPollMeBit())
-    {
-        return 0;
-    }
-
-    switch (serviceFlow->GetSchedulingType())
-    {
-    case ServiceFlow::SF_TYPE_UGS: {
-        if ((currentTime - serviceFlow->GetRecord()->GetGrantTimeStamp()).GetMilliSeconds() >=
-            serviceFlow->GetUnsolicitedGrantInterval())
-        {
-            allocationSize = serviceFlow->GetRecord()->GetGrantSize();
-            serviceFlow->GetRecord()->SetGrantTimeStamp(currentTime);
-        }
-    }
-    break;
-    case ServiceFlow::SF_TYPE_RTPS: {
-        if ((currentTime - serviceFlow->GetRecord()->GetGrantTimeStamp()).GetMilliSeconds() >=
-            serviceFlow->GetUnsolicitedPollingInterval())
-        {
-            allocationSize = bs->GetBwReqOppSize();
-            serviceFlow->GetRecord()->SetGrantTimeStamp(currentTime);
-        }
-    }
-    break;
-    case ServiceFlow::SF_TYPE_NRTPS:
-        /* nrtPS shall be serviced only if sufficient bandwidth is available after servicing
-         UGS and rtPS scheduling types, hence no specific service interval is used */
-    case ServiceFlow::SF_TYPE_BE: {
-        /* BE shall be serviced only if sufficient bandwidth is available after servicing
-         the rest of three scheduling types, hence no specific service interval is used */
-
-        allocationSize = bs->GetBwReqOppSize();
-    }
-    break;
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-    }
-
-    return allocationSize;
-}
-
-ServiceFlow*
-BandwidthManager::SelectFlowForRequest(uint32_t& bytesToRequest)
-{
-    Ptr<Packet> packet;
-    ServiceFlow* serviceFlow = nullptr;
-
-    Ptr<SubscriberStationNetDevice> ss = m_device->GetObject<SubscriberStationNetDevice>();
-    std::vector<ServiceFlow*> serviceFlows =
-        ss->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_ALL);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        serviceFlow = *iter;
-        if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS ||
-            serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS ||
-            serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_BE)
-        {
-            if (serviceFlow->HasPackets(MacHeaderType::HEADER_TYPE_GENERIC))
-            {
-                // bandwidth is requested for all packets
-                bytesToRequest = serviceFlow->GetQueue()->GetQueueLengthWithMACOverhead();
-                break;
-            }
-        }
-    }
-
-    return serviceFlow;
-}
-
-void
-BandwidthManager::SendBandwidthRequest(uint8_t uiuc, uint16_t allocationSize)
-{
-    Ptr<SubscriberStationNetDevice> ss = m_device->GetObject<SubscriberStationNetDevice>();
-
-    uint32_t bytesToRequest = 0;
-    ServiceFlow* serviceFlow = SelectFlowForRequest(bytesToRequest);
-
-    if (!serviceFlow || !bytesToRequest)
-    {
-        return;
-    }
-    BandwidthRequestHeader bwRequestHdr;
-
-    // bytesToRequest is the queue length of Service Flow and so,
-    // the header type must be HEADER_TYPE_AGGREGATE!
-
-    bwRequestHdr.SetType((uint8_t)BandwidthRequestHeader::HEADER_TYPE_AGGREGATE);
-    bwRequestHdr.SetCid(serviceFlow->GetConnection()->GetCid());
-    bwRequestHdr.SetBr(bytesToRequest);
-
-    Ptr<Packet> packet = Create<Packet>();
-    packet->AddHeader(bwRequestHdr);
-    ss->Enqueue(packet,
-                MacHeaderType(MacHeaderType::HEADER_TYPE_BANDWIDTH),
-                serviceFlow->GetConnection());
-    m_nrBwReqsSent++;
-    NS_ASSERT_MSG(uiuc == OfdmUlBurstProfile::UIUC_REQ_REGION_FULL,
-                  "Send Bandwidth Request: !UIUC_REQ_REGION_FULL");
-    ss->SendBurst(uiuc,
-                  allocationSize,
-                  serviceFlow->GetConnection(),
-                  MacHeaderType::HEADER_TYPE_BANDWIDTH);
-}
-
-void
-BandwidthManager::ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr)
-{
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-
-    ServiceFlow* serviceFlow =
-        bs->GetConnectionManager()->GetConnection(bwRequestHdr.GetCid())->GetServiceFlow();
-    if (bwRequestHdr.GetType() == (uint8_t)BandwidthRequestHeader::HEADER_TYPE_INCREMENTAL)
-    {
-        serviceFlow->GetRecord()->UpdateRequestedBandwidth(bwRequestHdr.GetBr());
-    }
-    else
-    {
-        serviceFlow->GetRecord()->SetRequestedBandwidth(bwRequestHdr.GetBr());
-        bs->GetUplinkScheduler()->OnSetRequestedBandwidth(serviceFlow->GetRecord());
-    }
-    bs->GetUplinkScheduler()->ProcessBandwidthRequest(bwRequestHdr);
-    // update backlogged
-    serviceFlow->GetRecord()->IncreaseBacklogged(bwRequestHdr.GetBr());
-}
-
-void
-BandwidthManager::SetSubframeRatio()
-{
-    // sets ratio of the DL and UL subframes
-
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-
-    uint32_t symbolsPerFrame = bs->GetPhy()->GetSymbolsPerFrame();
-
-    /* temporarily divided in half (360 symbols each), shall actually be determined based on UL and
-     * DL traffic*/
-    bs->SetNrDlSymbols(symbolsPerFrame / 2);
-    bs->SetNrUlSymbols(symbolsPerFrame / 2);
-}
-
-uint32_t
-BandwidthManager::GetSymbolsPerFrameAllocated()
-{
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-
-    uint32_t allocationPerFrame = 0;
-
-    std::vector<SSRecord*>* ssRecords = bs->GetSSManager()->GetSSRecords();
-    for (auto iter1 = ssRecords->begin(); iter1 != ssRecords->end(); ++iter1)
-    {
-        std::vector<ServiceFlow*> ssServiceFlows =
-            (*iter1)->GetServiceFlows(ServiceFlow::SF_TYPE_ALL);
-        for (auto iter2 = ssServiceFlows.begin(); iter2 != ssServiceFlows.end(); ++iter2)
-        {
-            allocationPerFrame += (*iter2)->GetRecord()->GetGrantSize();
-        }
-    }
-    return allocationPerFrame;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bandwidth-manager.h ns-3.46/src/wimax/model/bandwidth-manager.h
--- ns-3.45/src/wimax/model/bandwidth-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bandwidth-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef BANDWIDTH_MANAGER_H
-#define BANDWIDTH_MANAGER_H
-
-#include "bs-uplink-scheduler.h"
-#include "cid.h"
-#include "ul-job.h"
-#include "wimax-net-device.h"
-
-#include <stdint.h>
-
-/*
- The same bandwidth manager class serves both for BS and SS though some functions are exclusive to
- only one of them.
- */
-
-namespace ns3
-{
-
-class SSRecord;
-class ServiceFlow;
-class UlJob;
-class UplinkScheduler;
-
-/**
- * @ingroup wimax
- * @brief This class manage the bandwidth request and grant mechanism.
- * The bandwidth request and grant mechanism is supported by the Bandwidth
- * Manager. Both BS and SS maintain a bandwidth manager. Furthermore BS's
- * bandwidth manager works together with the uplink scheduler to determine
- * total bandwidth available and allocation size for each service flow.
- * Bandwidth request mechanism is a key feature of the WiMAX scheduler
- * since all three non-UGS services explicitly request for bandwidth by
- * sending a bandwidth request to BS.
- */
-class BandwidthManager : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    /**
-     * Constructor
-     *
-     * @param device WIMAX device
-     */
-    BandwidthManager(Ptr<WimaxNetDevice> device);
-    ~BandwidthManager() override;
-
-    // Delete copy constructor and assignment operator to avoid misuse
-    BandwidthManager(const BandwidthManager&) = delete;
-    BandwidthManager& operator=(const BandwidthManager&) = delete;
-
-    void DoDispose() override;
-
-    /**
-     * Calculate allocation size function
-     * @param ssRecord the SS record
-     * @param serviceFlow the service flow
-     * @returns the allocation size
-     */
-    uint32_t CalculateAllocationSize(const SSRecord* ssRecord, const ServiceFlow* serviceFlow);
-    /**
-     * Select flow for request function
-     * @param bytesToRequest bytes to request
-     * @returns a service flow
-     */
-    ServiceFlow* SelectFlowForRequest(uint32_t& bytesToRequest);
-    /**
-     * Send bandwidth request
-     * @param uiuc the UIUC
-     * @param allocationSize the allocation size
-     */
-    void SendBandwidthRequest(uint8_t uiuc, uint16_t allocationSize);
-    /**
-     * Process bandwidth request
-     * @param bwRequestHdr the bandwidth request
-     */
-    void ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr);
-    /// Set subframe ratio
-    void SetSubframeRatio();
-    /**
-     * Get symbols per frame allocated
-     * @returns the symbols per the frame allocated
-     */
-    uint32_t GetSymbolsPerFrameAllocated();
-
-  private:
-    Ptr<WimaxNetDevice> m_device; ///< the device
-    uint16_t m_nrBwReqsSent;      ///< bandwidth requests sent
-};
-
-} // namespace ns3
-
-#endif /* BANDWIDTH_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-link-manager.cc ns-3.46/src/wimax/model/bs-link-manager.cc
--- ns-3.45/src/wimax/model/bs-link-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-link-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "bs-link-manager.h"
-
-#include "bs-uplink-scheduler.h"
-#include "burst-profile-manager.h"
-#include "connection-manager.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/simulator.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BSLinkManager");
-
-NS_OBJECT_ENSURE_REGISTERED(BSLinkManager);
-
-TypeId
-BSLinkManager::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::BSLinkManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-BSLinkManager::BSLinkManager(Ptr<BaseStationNetDevice> bs)
-    : m_bs(bs),
-      m_signalQuality(10),
-      m_signalQualityThreshold(10) // arbitrary value
-{
-    tries = 0;
-}
-
-BSLinkManager::~BSLinkManager()
-{
-    m_bs = nullptr;
-}
-
-uint8_t
-BSLinkManager::CalculateRangingOppsToAllocate()
-{
-    // randomly selecting TOs up to 10, shall actually be decided by scheduler
-    return rand() % 8 + 2;
-}
-
-/*
- * Function mainly to avoid duplicate code in DoReceive ()
- */
-void
-BSLinkManager::ProcessRangingRequest(Cid cid, RngReq rngreq)
-{
-    NS_ASSERT_MSG(m_bs->GetState() == BaseStationNetDevice::BS_STATE_UL_SUB_FRAME,
-                  "Base station: Error while processing ranging request: !BS_STATE_UL_SUB_FRAME");
-
-    Time irIntervalBoundary;
-
-    if (m_bs->GetUplinkScheduler()->GetIsInvIrIntrvlAllocated())
-    {
-        if (m_bs->GetUplinkScheduler()->GetIsIrIntrvlAllocated())
-        {
-            irIntervalBoundary =
-                m_bs->GetUlSubframeStartTime() +
-                Seconds((m_bs->GetUplinkScheduler()->GetNrIrOppsAllocated() + 1) *
-                        m_bs->GetRangReqOppSize() * m_bs->GetSymbolDuration().GetSeconds());
-        }
-        else
-        {
-            irIntervalBoundary =
-                m_bs->GetUlSubframeStartTime() +
-                Seconds(m_bs->GetRangReqOppSize() * m_bs->GetSymbolDuration().GetSeconds());
-        }
-    }
-    else
-    {
-        NS_ASSERT_MSG(
-            m_bs->GetUplinkScheduler()->GetIsIrIntrvlAllocated(),
-            "Base station: Error while processing ranging request: IR interval not allocated");
-
-        irIntervalBoundary =
-            m_bs->GetUlSubframeStartTime() +
-            Seconds(m_bs->GetUplinkScheduler()->GetNrIrOppsAllocated() * m_bs->GetRangReqOppSize() *
-                    m_bs->GetSymbolDuration().GetSeconds());
-    }
-
-    tries++;
-
-    if (Simulator::Now() >= m_bs->GetUlSubframeStartTime() && Simulator::Now() < irIntervalBoundary)
-    {
-        PerformRanging(cid, rngreq);
-    }
-}
-
-void
-BSLinkManager::PerformRanging(Cid cid, RngReq rngreq)
-{
-    RngRsp rngrsp;
-    bool decodable = false;
-
-    // assuming low power, packet lost or undecodable first 2 times
-    if (tries < 2)
-    {
-        return;
-    }
-    if (tries >= 3)
-    {
-        decodable = true;
-    }
-
-    NS_LOG_DEBUG("RNG-REQ:");
-    rngreq.PrintDebug();
-
-    if (!decodable)
-    {
-        rngrsp.SetFrameNumber(m_bs->GetNrFrames());
-        rngrsp.SetInitRangOppNumber(m_bs->GetRangingOppNumber());
-
-        SetParametersToAdjust(&rngrsp);
-        rngrsp.SetRangStatus(WimaxNetDevice::RANGING_STATUS_CONTINUE); // see Figure 64
-        ScheduleRngRspMessage(cid, &rngrsp);
-    }
-    else
-    {
-        if (cid.IsInitialRanging())
-        {
-            PerformInitialRanging(cid, &rngreq, &rngrsp);
-        }
-        else
-        {
-            // invited initial ranging or periodic ranging
-            PerformInvitedRanging(cid, &rngrsp);
-        }
-    }
-}
-
-void
-BSLinkManager::PerformInitialRanging(Cid cid, RngReq* rngreq, RngRsp* rngrsp)
-{
-    SSRecord* ssRecord = nullptr;
-    bool isOldSS = m_bs->GetSSManager()->IsInRecord(rngreq->GetMacAddress());
-    if (isOldSS)
-    {
-        ssRecord = m_bs->GetSSManager()->GetSSRecord(rngreq->GetMacAddress());
-        // if this fails it would mean the RNG-RSP with success status was not received by the SS
-    }
-    else
-    {
-        ssRecord = m_bs->GetSSManager()->CreateSSRecord(rngreq->GetMacAddress());
-    }
-
-    if (ChangeDlChannel())
-    {
-        rngrsp->SetDlFreqOverride(GetNewDlChannel());
-        AbortRanging(cid, rngrsp, ssRecord, isOldSS);
-        return;
-    }
-
-    if (isOldSS)
-    {
-        // CIDs already assigned, e.g., RNG-REQ was lost and resent after timeout. reusing old CIDs
-        ssRecord->ResetRangingCorrectionRetries();
-        ssRecord->ResetInvitedRangingRetries();
-    }
-    else
-    {
-        m_bs->GetConnectionManager()->AllocateManagementConnections(ssRecord, rngrsp);
-
-        WimaxPhy::ModulationType modulationType;
-        uint8_t diuc =
-            m_bs->GetBurstProfileManager()->GetBurstProfileForSS(ssRecord, rngreq, modulationType);
-        ssRecord->SetModulationType(modulationType);
-
-        // specify in RNG-RSP only if different than what SS requested
-        if (rngreq->GetReqDlBurstProfile() != diuc)
-        {
-            rngrsp->SetDlOperBurstProfile(diuc);
-        }
-
-        // add SS (Basic CID) to poll list for invited ranging intervals, see Table 115
-        ssRecord->EnablePollForRanging();
-    }
-
-    rngrsp->SetMacAddress(rngreq->GetMacAddress());
-
-    if (isOldSS) // CIDs had already been allocated
-    {
-        cid = ssRecord->GetBasicCid();
-    }
-
-    if (IsRangingAcceptable())
-    {
-        AcceptRanging(cid, rngrsp, ssRecord);
-    }
-    else
-    {
-        ContinueRanging(cid, rngrsp, ssRecord);
-    }
-}
-
-void
-BSLinkManager::PerformInvitedRanging(Cid cid, RngRsp* rngrsp)
-{
-    SSRecord* ssRecord = m_bs->GetSSManager()->GetSSRecord(cid);
-    ssRecord->IncrementRangingCorrectionRetries();
-    ssRecord->ResetInvitedRangingRetries();
-
-    if (IsRangingAcceptable())
-    {
-        AcceptRanging(cid, rngrsp, ssRecord);
-    }
-    else
-    {
-        if (ssRecord->GetRangingCorrectionRetries() == m_bs->GetMaxRangingCorrectionRetries())
-        {
-            AbortRanging(cid, rngrsp, ssRecord, true);
-        }
-        else
-        {
-            ContinueRanging(cid, rngrsp, ssRecord);
-        }
-    }
-}
-
-void
-BSLinkManager::VerifyInvitedRanging(Cid cid, uint8_t uiuc)
-{
-    if (uiuc == OfdmUlBurstProfile::UIUC_INITIAL_RANGING)
-    {
-        SSRecord* ssRecord = m_bs->GetSSManager()->GetSSRecord(cid);
-        if (ssRecord->GetInvitedRangRetries() > 0)
-        {
-            ssRecord->IncrementInvitedRangingRetries();
-
-            if (ssRecord->GetInvitedRangRetries() == m_bs->GetMaxInvitedRangRetries())
-            {
-                auto rngrsp = new RngRsp();
-                AbortRanging(ssRecord->GetBasicCid(), rngrsp, ssRecord, true);
-            }
-            // else keep polling
-        }
-    }
-}
-
-void
-BSLinkManager::SetParametersToAdjust(RngRsp* rngrsp)
-{
-    // code to calculate parameter adjustment values goes here
-    rngrsp->SetTimingAdjust(40);
-    rngrsp->SetPowerLevelAdjust(8);
-    rngrsp->SetOffsetFreqAdjust(30);
-}
-
-void
-BSLinkManager::AbortRanging(Cid cid, RngRsp* rngrsp, SSRecord* ssRecord, bool isOldSS)
-{
-    rngrsp->SetRangStatus(WimaxNetDevice::RANGING_STATUS_ABORT);
-    ScheduleRngRspMessage(cid, rngrsp);
-
-    if (isOldSS)
-    {
-        ssRecord->SetRangingStatus(WimaxNetDevice::RANGING_STATUS_ABORT);
-    }
-
-    ssRecord->DisablePollForRanging();
-    DeallocateCids(cid);
-}
-
-void
-BSLinkManager::AcceptRanging(Cid cid, RngRsp* rngrsp, SSRecord* ssRecord)
-{
-    rngrsp->SetRangStatus(WimaxNetDevice::RANGING_STATUS_SUCCESS);
-    ScheduleRngRspMessage(cid, rngrsp);
-
-    /*Shall not be set until the SS receives the RNG-RSP, as it may be lost etc. may be state field
-     is also added to SSRecord which then set to SS_STATE_REGISTERED once confirmed that SS has
-     received this RNG-RSP, but how to determine that, may be as a data packet is received by the
-     SS*/
-    ssRecord->SetRangingStatus(WimaxNetDevice::RANGING_STATUS_SUCCESS);
-
-    ssRecord->DisablePollForRanging();
-}
-
-void
-BSLinkManager::ContinueRanging(Cid cid, RngRsp* rngrsp, SSRecord* ssRecord)
-{
-    rngrsp->SetRangStatus(WimaxNetDevice::RANGING_STATUS_CONTINUE);
-    ScheduleRngRspMessage(cid, rngrsp);
-    ssRecord->SetRangingStatus(WimaxNetDevice::RANGING_STATUS_CONTINUE);
-}
-
-void
-BSLinkManager::ScheduleRngRspMessage(Cid cid, RngRsp* rngrsp)
-{
-    if (rngrsp->GetRangStatus() == WimaxNetDevice::RANGING_STATUS_SUCCESS ||
-        rngrsp->GetRangStatus() == WimaxNetDevice::RANGING_STATUS_CONTINUE)
-    {
-        SetParametersToAdjust(rngrsp);
-    }
-
-    Ptr<Packet> p = Create<Packet>();
-    p->AddHeader(*rngrsp);
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_RNG_RSP));
-
-    m_bs->Enqueue(p, MacHeaderType(), m_bs->GetConnection(cid));
-}
-
-void
-BSLinkManager::DeallocateCids(Cid cid)
-{
-    // if necessary, delete entire connections or simply set CIDs to 0
-}
-
-uint64_t
-BSLinkManager::SelectDlChannel()
-{
-    // Values according to WirelessMAN-OFDM RF profile for 10 MHz channelization
-    // Section 12.3.3.1 from IEEE 802.16-2004 standard
-    // profR10_3 :
-    // channels: 5000 + n â‹… 5 MHz, âˆ€n âˆˆ { 147, 149, 151, 153, 155, 157, 159, 161, 163, 165,
-    // 167 } temporarily set to 1 for quick scanning. To be standard compliant, use a value in the
-    // list above
-    return m_bs->GetChannel(1);
-}
-
-bool
-BSLinkManager::ChangeDlChannel()
-{
-    // code to decide if SS shall move to a new channel/frequency goes here
-    return false;
-}
-
-uint32_t
-BSLinkManager::GetNewDlChannel()
-{
-    // code to determine suggested new frequency goes here
-    return 100;
-}
-
-uint8_t
-BSLinkManager::GetSignalQuality()
-{
-    // code to measure signal quality goes here
-    uint8_t signalQuality = m_signalQuality;
-    m_signalQuality++;
-    return signalQuality;
-}
-
-bool
-BSLinkManager::IsRangingAcceptable()
-{
-    return GetSignalQuality() > m_signalQualityThreshold;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-link-manager.h ns-3.46/src/wimax/model/bs-link-manager.h
--- ns-3.45/src/wimax/model/bs-link-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-link-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef LINK_MANAGER_H
-#define LINK_MANAGER_H
-
-#include "bs-net-device.h"
-#include "cid.h"
-#include "mac-messages.h"
-#include "wimax-net-device.h"
-
-#include "ns3/event-id.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- *
- * BaseStation Link Manager
- */
-class BSLinkManager : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    BSLinkManager(Ptr<BaseStationNetDevice> bs);
-    ~BSLinkManager() override;
-
-    // Delete copy constructor and assignment operator to avoid misuse
-    BSLinkManager(const BSLinkManager&) = delete;
-    BSLinkManager& operator=(const BSLinkManager&) = delete;
-
-    /**
-     * @return the ranging opportunities to allocate
-     */
-    uint8_t CalculateRangingOppsToAllocate();
-    /**
-     * @return an available downlink channel
-     */
-    uint64_t SelectDlChannel();
-    /**
-     * @brief process a ranging request message
-     * @param cid the connection identifier in which the ranging message was received
-     * @param rngreq the ranging request message
-     */
-
-    void ProcessRangingRequest(Cid cid, RngReq rngreq);
-    /**
-     * @brief Verifies at the end of an invited ranging interval if SS sent ranging message in it or
-     * not
-     * @param cid the connection identifier in which the ranging message was received
-     * @param uiuc the ranging
-     */
-    void VerifyInvitedRanging(Cid cid, uint8_t uiuc);
-
-  private:
-    /**
-     * Perform ranging function
-     * @param cid the CID
-     * @param rngreq the ranging request
-     */
-    void PerformRanging(Cid cid, RngReq rngreq);
-    /**
-     * Perform initial ranging function
-     * @param cid the CID
-     * @param rngreq the ranging request
-     * @param rngrsp the ranging response
-     */
-    void PerformInitialRanging(Cid cid, RngReq* rngreq, RngRsp* rngrsp);
-    /**
-     * Perform inivted ranging function
-     * @param cid the CID
-     * @param rngrsp the ranging response
-     */
-    void PerformInvitedRanging(Cid cid, RngRsp* rngrsp);
-
-    /**
-     * Set parameters to adjust function
-     * @param rngrsp the ranging response
-     */
-    void SetParametersToAdjust(RngRsp* rngrsp);
-    /**
-     * Abort ranging function
-     * @param cid the CID
-     * @param rngrsp the ranging response
-     * @param ssRecord the SS record
-     * @param isNewSS true if a new SS
-     */
-    void AbortRanging(Cid cid, RngRsp* rngrsp, SSRecord* ssRecord, bool isNewSS);
-    /**
-     * Accept ranging function
-     * @param cid the CID
-     * @param rngrsp the ranging response
-     * @param ssRecord the SS record
-     */
-    void AcceptRanging(Cid cid, RngRsp* rngrsp, SSRecord* ssRecord);
-    /**
-     * Continue ranging function
-     * @param cid the CID
-     * @param rngrsp the ranging response
-     * @param ssRecord the SS record
-     */
-    void ContinueRanging(Cid cid, RngRsp* rngrsp, SSRecord* ssRecord);
-    /**
-     * Schedule range response message function
-     * @param cid the CID
-     * @param rngrsp the ranging response
-     */
-    void ScheduleRngRspMessage(Cid cid, RngRsp* rngrsp);
-    /**
-     * Deallocate CIDs function
-     * @param cid the CID
-     */
-    void DeallocateCids(Cid cid);
-
-    /**
-     * Change DL channel function
-     * @returns true if the DL channel changed
-     */
-    bool ChangeDlChannel();
-    /**
-     * Get new DL channel function
-     * @returns the new DL channel
-     */
-    uint32_t GetNewDlChannel();
-    /**
-     * Get signal quality function
-     * @returns the signal quality
-     */
-    uint8_t GetSignalQuality();
-    /**
-     * Is ranging acceptable function
-     * @returns true if ranging is acceptable
-     */
-    bool IsRangingAcceptable();
-
-    Ptr<BaseStationNetDevice> m_bs; ///< base station
-
-    // ranging parameters
-    uint32_t m_signalQuality;         ///< signal quality
-    uint8_t m_signalQualityThreshold; ///< signal quality threshold
-    int tries; ///< variable to test multiple RNG-REQ by the SS for example undecodable at BS or
-               ///< lost RNG-RSP
-};
-
-} // namespace ns3
-
-#endif /* LINK_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-net-device.cc ns-3.46/src/wimax/model/bs-net-device.cc
--- ns-3.45/src/wimax/model/bs-net-device.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-net-device.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,1249 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "bs-net-device.h"
-
-#include "bandwidth-manager.h"
-#include "bs-link-manager.h"
-#include "bs-scheduler.h"
-#include "bs-uplink-scheduler.h"
-#include "burst-profile-manager.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-#include "wimax-mac-queue.h"
-#include "wimax-phy.h"
-
-#include "ns3/enum.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/llc-snap-header.h"
-#include "ns3/node.h"
-#include "ns3/packet-burst.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-
-#include <cmath>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BaseStationNetDevice");
-
-NS_OBJECT_ENSURE_REGISTERED(BaseStationNetDevice);
-
-TypeId
-BaseStationNetDevice::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::BaseStationNetDevice")
-
-            .SetParent<WimaxNetDevice>()
-
-            .SetGroupName("Wimax")
-
-            .AddConstructor<BaseStationNetDevice>()
-
-            .AddAttribute("BSScheduler",
-                          "Downlink Scheduler for BS",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::m_scheduler),
-                          MakePointerChecker<BSScheduler>())
-
-            .AddAttribute("InitialRangInterval",
-                          "Time between Initial Ranging regions assigned by the BS. Maximum is 2s",
-                          TimeValue(Seconds(0.05)),
-                          MakeTimeAccessor(&BaseStationNetDevice::GetInitialRangingInterval,
-                                           &BaseStationNetDevice::SetInitialRangingInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("DcdInterval",
-                          "Time between transmission of DCD messages. Maximum value is 10s.",
-                          TimeValue(Seconds(3)),
-                          MakeTimeAccessor(&BaseStationNetDevice::GetDcdInterval,
-                                           &BaseStationNetDevice::SetDcdInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("UcdInterval",
-                          "Time between transmission of UCD messages. Maximum value is 10s.",
-                          TimeValue(Seconds(3)),
-                          MakeTimeAccessor(&BaseStationNetDevice::GetUcdInterval,
-                                           &BaseStationNetDevice::SetUcdInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("IntervalT8",
-                          "Wait for DSA/DSC Acknowledge timeout. Maximum 300ms.",
-                          TimeValue(Seconds(0.05)),
-                          MakeTimeAccessor(&BaseStationNetDevice::GetIntervalT8,
-                                           &BaseStationNetDevice::SetIntervalT8),
-                          MakeTimeChecker())
-
-            .AddAttribute("RangReqOppSize",
-                          "The ranging opportunity size in symbols",
-                          UintegerValue(8),
-                          MakeUintegerAccessor(&BaseStationNetDevice::GetRangReqOppSize,
-                                               &BaseStationNetDevice::SetRangReqOppSize),
-                          MakeUintegerChecker<uint8_t>(1, 256))
-
-            .AddAttribute("BwReqOppSize",
-                          "The bandwidth request opportunity size in symbols",
-                          UintegerValue(2),
-                          MakeUintegerAccessor(&BaseStationNetDevice::GetBwReqOppSize,
-                                               &BaseStationNetDevice::SetBwReqOppSize),
-                          MakeUintegerChecker<uint8_t>(1, 256))
-
-            .AddAttribute(
-                "MaxRangCorrectionRetries",
-                "Number of retries on contention Ranging Requests",
-                UintegerValue(16),
-                MakeUintegerAccessor(&BaseStationNetDevice::GetMaxRangingCorrectionRetries,
-                                     &BaseStationNetDevice::SetMaxRangingCorrectionRetries),
-                MakeUintegerChecker<uint8_t>(1, 16))
-
-            .AddAttribute("SSManager",
-                          "The ss manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::GetSSManager,
-                                              &BaseStationNetDevice::SetSSManager),
-                          MakePointerChecker<SSManager>())
-
-            .AddAttribute("Scheduler",
-                          "The BS scheduler attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::GetBSScheduler,
-                                              &BaseStationNetDevice::SetBSScheduler),
-                          MakePointerChecker<BSScheduler>())
-
-            .AddAttribute("LinkManager",
-                          "The link manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::GetLinkManager,
-                                              &BaseStationNetDevice::SetLinkManager),
-                          MakePointerChecker<BSLinkManager>())
-
-            .AddAttribute("UplinkScheduler",
-                          "The uplink scheduler attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::GetUplinkScheduler,
-                                              &BaseStationNetDevice::SetUplinkScheduler),
-                          MakePointerChecker<UplinkScheduler>())
-
-            .AddAttribute("BsIpcsPacketClassifier",
-                          "The uplink IP packet classifier attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::GetBsClassifier,
-                                              &BaseStationNetDevice::SetBsClassifier),
-                          MakePointerChecker<IpcsClassifier>())
-
-            .AddAttribute("ServiceFlowManager",
-                          "The service flow manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&BaseStationNetDevice::GetServiceFlowManager,
-                                              &BaseStationNetDevice::SetServiceFlowManager),
-                          MakePointerChecker<ServiceFlowManager>())
-
-            .AddTraceSource("BSTx",
-                            "A packet has been received from higher layers "
-                            "and is being processed in preparation "
-                            "for queueing for transmission.",
-                            MakeTraceSourceAccessor(&BaseStationNetDevice::m_bsTxTrace),
-                            "ns3::Packet::TracedCallback")
-
-            .AddTraceSource("BSTxDrop",
-                            "A packet has been dropped in the MAC layer "
-                            "before being queued for transmission.",
-                            MakeTraceSourceAccessor(&BaseStationNetDevice::m_bsTxDropTrace),
-                            "ns3::Packet::TracedCallback")
-
-            .AddTraceSource("BSPromiscRx",
-                            "A packet has been received by this device, "
-                            "has been passed up from the physical layer "
-                            "and is being forwarded up the local protocol stack.  "
-                            "This is a promiscuous trace,",
-                            MakeTraceSourceAccessor(&BaseStationNetDevice::m_bsPromiscRxTrace),
-                            "ns3::Packet::TracedCallback")
-
-            .AddTraceSource("BSRx",
-                            "A packet has been received by this device, "
-                            "has been passed up from the physical layer "
-                            "and is being forwarded up the local protocol stack.  "
-                            "This is a non-promiscuous trace,",
-                            MakeTraceSourceAccessor(&BaseStationNetDevice::m_bsRxTrace),
-                            "ns3::Packet::TracedCallback")
-
-            .AddTraceSource("BSRxDrop",
-                            "A packet has been dropped in the MAC layer "
-                            "after it has been passed up from the physical layer.",
-                            MakeTraceSourceAccessor(&BaseStationNetDevice::m_bsRxDropTrace),
-                            "ns3::Packet::TracedCallback");
-    return tid;
-}
-
-BaseStationNetDevice::BaseStationNetDevice()
-{
-    InitBaseStationNetDevice();
-}
-
-void
-BaseStationNetDevice::InitBaseStationNetDevice()
-{
-    m_initialRangInterval = Seconds(0.05); // maximum is 2
-    m_dcdInterval = Seconds(3);            // maximum is 10
-    m_ucdInterval = Seconds(3);            // maximum is 10
-    m_intervalT8 = MilliSeconds(50);       // maximum is 300 milliseconds
-    m_maxRangCorrectionRetries = 16;
-    m_maxInvitedRangRetries = 16;
-    m_rangReqOppSize =
-        8;              // 8 symbols = 2 (preamble) + 2 (RNG-REQ) + 4 (round-trip propagation time)
-    m_bwReqOppSize = 2; // 2 symbols = 1 (preamble) + 1 (bandwidth request header)
-    m_nrDlSymbols = 0;
-    m_nrUlSymbols = 0;
-    m_nrDlMapSent = 0;
-    m_nrUlMapSent = 0;
-    m_nrDcdSent = 0;
-    m_nrUcdSent = 0;
-    m_dcdConfigChangeCount = 0;
-    m_ucdConfigChangeCount = 0;
-    m_framesSinceLastDcd = 0;
-    m_framesSinceLastUcd = 0;
-    m_nrDlFrames = 0;
-    m_nrUlFrames = 0;
-    m_nrSsRegistered = 0;
-    m_nrDlAllocations = 0;
-    m_nrUlAllocations = 0;
-    m_dlSubframeStartTime = Seconds(0);
-    m_ulSubframeStartTime = Seconds(0);
-    m_ulAllocationNumber = 0;
-    m_rangingOppNumber = 0;
-    m_allocationStartTime = 0;
-    m_psDuration = Seconds(0);
-    m_symbolDuration = Seconds(0);
-    m_linkManager = CreateObject<BSLinkManager>(this);
-    m_cidFactory = new CidFactory();
-    m_ssManager = CreateObject<SSManager>();
-    m_bsClassifier = CreateObject<IpcsClassifier>();
-    m_serviceFlowManager = CreateObject<BsServiceFlowManager>(this);
-}
-
-BaseStationNetDevice::BaseStationNetDevice(Ptr<Node> node, Ptr<WimaxPhy> phy)
-{
-    InitBaseStationNetDevice();
-    this->SetNode(node);
-    this->SetPhy(phy);
-}
-
-BaseStationNetDevice::BaseStationNetDevice(Ptr<Node> node,
-                                           Ptr<WimaxPhy> phy,
-                                           Ptr<UplinkScheduler> uplinkScheduler,
-                                           Ptr<BSScheduler> bsScheduler)
-{
-    InitBaseStationNetDevice();
-    this->SetNode(node);
-    this->SetPhy(phy);
-    m_uplinkScheduler = uplinkScheduler;
-    m_scheduler = bsScheduler;
-}
-
-BaseStationNetDevice::~BaseStationNetDevice()
-{
-}
-
-void
-BaseStationNetDevice::DoDispose()
-{
-    delete m_cidFactory;
-
-    m_linkManager = nullptr;
-    m_ssManager = nullptr;
-    m_bsClassifier = nullptr;
-    m_serviceFlowManager = nullptr;
-    m_uplinkScheduler = nullptr;
-    m_cidFactory = nullptr;
-    m_ssManager = nullptr;
-    m_uplinkScheduler = nullptr;
-    m_scheduler = nullptr;
-
-    WimaxNetDevice::DoDispose();
-}
-
-void
-BaseStationNetDevice::SetBsClassifier(Ptr<IpcsClassifier> bsc)
-{
-    m_bsClassifier = bsc;
-}
-
-Ptr<IpcsClassifier>
-BaseStationNetDevice::GetBsClassifier() const
-{
-    return m_bsClassifier;
-}
-
-void
-BaseStationNetDevice::SetInitialRangingInterval(Time initialRangInterval)
-{
-    m_initialRangInterval = initialRangInterval;
-}
-
-Time
-BaseStationNetDevice::GetInitialRangingInterval() const
-{
-    return m_initialRangInterval;
-}
-
-void
-BaseStationNetDevice::SetDcdInterval(Time dcdInterval)
-{
-    m_dcdInterval = dcdInterval;
-}
-
-Time
-BaseStationNetDevice::GetDcdInterval() const
-{
-    return m_dcdInterval;
-}
-
-void
-BaseStationNetDevice::SetUcdInterval(Time ucdInterval)
-{
-    m_ucdInterval = ucdInterval;
-}
-
-Time
-BaseStationNetDevice::GetUcdInterval() const
-{
-    return m_ucdInterval;
-}
-
-void
-BaseStationNetDevice::SetIntervalT8(Time interval)
-{
-    m_intervalT8 = interval;
-}
-
-Time
-BaseStationNetDevice::GetIntervalT8() const
-{
-    return m_intervalT8;
-}
-
-void
-BaseStationNetDevice::SetMaxRangingCorrectionRetries(uint8_t maxRangCorrectionRetries)
-{
-    m_maxRangCorrectionRetries = maxRangCorrectionRetries;
-}
-
-uint8_t
-BaseStationNetDevice::GetMaxRangingCorrectionRetries() const
-{
-    return m_maxRangCorrectionRetries;
-}
-
-void
-BaseStationNetDevice::SetMaxInvitedRangRetries(uint8_t maxInvitedRangRetries)
-{
-    m_maxInvitedRangRetries = maxInvitedRangRetries;
-}
-
-uint8_t
-BaseStationNetDevice::GetMaxInvitedRangRetries() const
-{
-    return m_maxInvitedRangRetries;
-}
-
-void
-BaseStationNetDevice::SetRangReqOppSize(uint8_t rangReqOppSize)
-{
-    m_rangReqOppSize = rangReqOppSize;
-}
-
-uint8_t
-BaseStationNetDevice::GetRangReqOppSize() const
-{
-    return m_rangReqOppSize;
-}
-
-void
-BaseStationNetDevice::SetBwReqOppSize(uint8_t bwReqOppSize)
-{
-    m_bwReqOppSize = bwReqOppSize;
-}
-
-uint8_t
-BaseStationNetDevice::GetBwReqOppSize() const
-{
-    return m_bwReqOppSize;
-}
-
-void
-BaseStationNetDevice::SetNrDlSymbols(uint32_t nrDlSymbols)
-{
-    m_nrDlSymbols = nrDlSymbols;
-}
-
-uint32_t
-BaseStationNetDevice::GetNrDlSymbols() const
-{
-    return m_nrDlSymbols;
-}
-
-void
-BaseStationNetDevice::SetNrUlSymbols(uint32_t nrUlSymbols)
-{
-    m_nrUlSymbols = nrUlSymbols;
-}
-
-uint32_t
-BaseStationNetDevice::GetNrUlSymbols() const
-{
-    return m_nrUlSymbols;
-}
-
-uint32_t
-BaseStationNetDevice::GetNrDcdSent() const
-{
-    return m_nrDcdSent;
-}
-
-uint32_t
-BaseStationNetDevice::GetNrUcdSent() const
-{
-    return m_nrUcdSent;
-}
-
-Time
-BaseStationNetDevice::GetDlSubframeStartTime() const
-{
-    return m_dlSubframeStartTime;
-}
-
-Time
-BaseStationNetDevice::GetUlSubframeStartTime() const
-{
-    return m_ulSubframeStartTime;
-}
-
-uint8_t
-BaseStationNetDevice::GetRangingOppNumber() const
-{
-    return m_rangingOppNumber;
-}
-
-Ptr<SSManager>
-BaseStationNetDevice::GetSSManager() const
-{
-    return m_ssManager;
-}
-
-void
-BaseStationNetDevice::SetSSManager(Ptr<SSManager> ssm)
-{
-    m_ssManager = ssm;
-}
-
-Ptr<BsServiceFlowManager>
-BaseStationNetDevice::GetServiceFlowManager() const
-{
-    return m_serviceFlowManager;
-}
-
-void
-BaseStationNetDevice::SetServiceFlowManager(Ptr<BsServiceFlowManager> sfm)
-{
-    m_serviceFlowManager = sfm;
-}
-
-Ptr<UplinkScheduler>
-BaseStationNetDevice::GetUplinkScheduler() const
-{
-    return m_uplinkScheduler;
-}
-
-void
-BaseStationNetDevice::SetUplinkScheduler(Ptr<UplinkScheduler> uls)
-{
-    m_uplinkScheduler = uls;
-}
-
-Ptr<BSLinkManager>
-BaseStationNetDevice::GetLinkManager() const
-{
-    return m_linkManager;
-}
-
-void
-BaseStationNetDevice::SetLinkManager(Ptr<BSLinkManager> lm)
-{
-    m_linkManager = lm;
-}
-
-void
-BaseStationNetDevice::SetBSScheduler(Ptr<BSScheduler> bss)
-{
-    m_scheduler = bss;
-}
-
-Ptr<BSScheduler>
-BaseStationNetDevice::GetBSScheduler() const
-{
-    return m_scheduler;
-}
-
-Time
-BaseStationNetDevice::GetPsDuration() const
-{
-    return m_psDuration;
-}
-
-Time
-BaseStationNetDevice::GetSymbolDuration() const
-{
-    return m_symbolDuration;
-}
-
-void
-BaseStationNetDevice::Start()
-{
-    SetReceiveCallback();
-    GetConnectionManager()->SetCidFactory(m_cidFactory);
-    GetPhy()->SetPhyParameters();
-    GetPhy()->SetDataRates();
-    SetTtg(GetPhy()->GetTtg());
-    SetRtg(GetPhy()->GetRtg());
-    m_psDuration = GetPhy()->GetPsDuration();
-    m_symbolDuration = GetPhy()->GetSymbolDuration();
-    GetBandwidthManager()->SetSubframeRatio();
-
-    CreateDefaultConnections();
-    GetPhy()->SetSimplex(m_linkManager->SelectDlChannel());
-    Simulator::ScheduleNow(&BaseStationNetDevice::StartFrame, this);
-
-    /* shall actually be 2 symbols = 1 (preamble) + 1 (bandwidth request header)*/
-    m_bwReqOppSize = 6;
-    m_uplinkScheduler->InitOnce();
-}
-
-void
-BaseStationNetDevice::Stop()
-{
-}
-
-void
-BaseStationNetDevice::StartFrame()
-{
-    // setting DL/UL subframe allocation for this frame
-    uint32_t symbolsPerFrame = GetPhy()->GetSymbolsPerFrame();
-    SetNrDlSymbols((symbolsPerFrame / 2) -
-                   static_cast<uint32_t>(std::ceil(GetTtg() * m_psDuration.GetSeconds() /
-                                                   m_symbolDuration.GetSeconds())));
-    SetNrUlSymbols((symbolsPerFrame / 2) -
-                   static_cast<uint32_t>(std::ceil(GetRtg() * m_psDuration.GetSeconds() /
-                                                   m_symbolDuration.GetSeconds())));
-
-    m_frameStartTime = Simulator::Now();
-
-    NS_LOG_INFO("----------------------frame" << GetNrFrames() + 1 << "----------------------");
-
-    StartDlSubFrame();
-}
-
-void
-BaseStationNetDevice::StartDlSubFrame()
-{
-    m_dlSubframeStartTime = Simulator::Now(); // same as m_frameStartTime
-
-    NS_LOG_DEBUG("DL frame started : " << m_frameStartTime.As(Time::S));
-
-    SetNrFrames(GetNrFrames() + 1);
-    SetState(BS_STATE_DL_SUB_FRAME);
-    m_direction = DIRECTION_DOWNLINK;
-    m_uplinkScheduler->Schedule();
-    CreateMapMessages();
-    m_scheduler->Schedule();
-    SendBursts();
-    Simulator::Schedule(Seconds(m_nrDlSymbols * m_symbolDuration.GetSeconds()),
-                        &BaseStationNetDevice::EndDlSubFrame,
-                        this);
-}
-
-void
-BaseStationNetDevice::EndDlSubFrame()
-{
-    m_nrDlFrames++;
-    SetState(BS_STATE_TTG);
-    Simulator::Schedule(Seconds(GetTtg() * m_psDuration.GetSeconds()),
-                        &BaseStationNetDevice::StartUlSubFrame,
-                        this);
-}
-
-void
-BaseStationNetDevice::StartUlSubFrame()
-{
-    m_ulSubframeStartTime = Simulator::Now();
-
-    NS_LOG_INFO("UL frame started : " << m_ulSubframeStartTime.As(Time::S));
-
-    SetState(BS_STATE_UL_SUB_FRAME);
-    m_direction = DIRECTION_UPLINK;
-    MarkUplinkAllocations();
-    Simulator::Schedule(Seconds(m_nrUlSymbols * m_symbolDuration.GetSeconds()),
-                        &BaseStationNetDevice::EndUlSubFrame,
-                        this);
-}
-
-void
-BaseStationNetDevice::EndUlSubFrame()
-{
-    m_nrUlFrames++;
-    SetState(BS_STATE_RTG);
-    Simulator::Schedule(Seconds(GetRtg() * m_psDuration.GetSeconds()),
-                        &BaseStationNetDevice::EndFrame,
-                        this);
-}
-
-void
-BaseStationNetDevice::EndFrame()
-{
-    StartFrame();
-}
-
-bool
-BaseStationNetDevice::DoSend(Ptr<Packet> packet,
-                             const Mac48Address& source,
-                             const Mac48Address& dest,
-                             uint16_t protocolNumber)
-{
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-    ServiceFlow* serviceFlow = nullptr;
-
-    NS_LOG_INFO("BS (" << source << "):");
-    NS_LOG_INFO("\tSending packet...");
-    NS_LOG_INFO("\t\tDestination: " << dest);
-    NS_LOG_INFO("\t\tPacket Size:  " << packet->GetSize());
-    NS_LOG_INFO("\t\tProtocol:    " << protocolNumber);
-
-    if (protocolNumber == 2048)
-    {
-        serviceFlow = m_bsClassifier->Classify(packet,
-                                               GetServiceFlowManager(),
-                                               ServiceFlow::SF_DIRECTION_DOWN);
-    }
-
-    if (protocolNumber != 2048 || serviceFlow == nullptr)
-    {
-        serviceFlow = *GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_ALL).begin();
-    }
-
-    if (serviceFlow == nullptr)
-    {
-        NS_LOG_INFO("No Service Flow!!");
-        m_bsTxDropTrace(packet);
-        return false;
-    }
-    if (serviceFlow->GetIsEnabled())
-    {
-        if (!Enqueue(packet, MacHeaderType(), serviceFlow->GetConnection()))
-        {
-            NS_LOG_INFO("Enqueue Error!!");
-            m_bsTxDropTrace(packet);
-            return false;
-        }
-    }
-    else
-    {
-        m_bsTxDropTrace(packet);
-        NS_LOG_INFO("Service Flow is not enabled");
-        return false;
-    }
-    m_bsTxTrace(packet);
-
-    return true;
-}
-
-bool
-BaseStationNetDevice::Enqueue(Ptr<Packet> packet,
-                              const MacHeaderType& hdrType,
-                              Ptr<WimaxConnection> connection)
-{
-    NS_ASSERT_MSG(
-        connection,
-        "BS: Can not enqueue packet on the selected connection: the connection is not initialized");
-
-    GenericMacHeader hdr;
-    hdr.SetLen(packet->GetSize() + hdr.GetSerializedSize());
-
-    hdr.SetCid(connection->GetCid());
-
-    return connection->Enqueue(packet, hdrType, hdr);
-}
-
-void
-BaseStationNetDevice::DoReceive(Ptr<Packet> packet)
-{
-    GenericMacHeader gnrcMacHdr;
-    BandwidthRequestHeader bwRequestHdr;
-    ManagementMessageType msgType;
-    RngReq rngReq;
-    Cid cid;
-    uint8_t type = 0;
-    GrantManagementSubheader grantMgmntSubhdr;
-    Mac48Address source;
-    LlcSnapHeader llc;
-    Ptr<WimaxConnection> connection = nullptr;
-    FragmentationSubheader fragSubhdr;
-    bool fragmentation = false; // it becomes true when there is a fragmentation subheader
-
-    packet->RemoveHeader(gnrcMacHdr);
-    if (gnrcMacHdr.GetHt() == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        if (!gnrcMacHdr.check_hcs())
-        {
-            // The header is noisy
-            m_bsRxDropTrace(packet);
-            NS_LOG_INFO("Header HCS ERROR");
-            return;
-        }
-
-        cid = gnrcMacHdr.GetCid();
-
-        // checking for subheaders (only grant management subheader is implemented)
-        type = gnrcMacHdr.GetType();
-        if (type)
-        {
-            // checking 1st bit, see Table 6
-            if (type & 1)
-            {
-                packet->RemoveHeader(grantMgmntSubhdr);
-            }
-            // Check if there is a fragmentation Subheader
-            uint8_t tmpType = type;
-            if (((tmpType >> 2) & 1) == 1)
-            {
-                // a TRANSPORT packet with fragmentation subheader has been received!
-                NS_LOG_INFO("FRAG_DEBUG: DoReceive -> the packet is a fragment" << std::endl);
-                fragmentation = true;
-            }
-        }
-
-        if (cid.IsInitialRanging()) // initial ranging connection
-        {
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_RNG_REQ: {
-                packet->RemoveHeader(rngReq);
-                m_linkManager->ProcessRangingRequest(cid, rngReq);
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_RNG_RSP:
-                // from other base station, ignore
-                break;
-            default:
-                NS_FATAL_ERROR("Invalid message type");
-            }
-        }
-        else if (m_cidFactory->IsBasic(cid)) // basic management connection
-        {
-            source = m_ssManager->GetMacAddress(cid);
-            m_traceBSRx(packet, source, cid);
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_RNG_REQ: {
-                packet->RemoveHeader(rngReq);
-                m_linkManager->ProcessRangingRequest(cid, rngReq);
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_RNG_RSP:
-                // from other base station, ignore
-                break;
-            default:
-                NS_FATAL_ERROR("Invalid message type");
-            }
-        }
-        else if (m_cidFactory->IsPrimary(cid)) // primary management connection
-        {
-            source = m_ssManager->GetMacAddress(cid);
-            m_traceBSRx(packet, source, cid);
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_REG_REQ:
-                // not yet implemented
-            case ManagementMessageType::MESSAGE_TYPE_REG_RSP:
-                // from other base station, ignore
-                break;
-            case ManagementMessageType::MESSAGE_TYPE_DSA_REQ: {
-                DsaReq dsaReq;
-                packet->RemoveHeader(dsaReq);
-                GetServiceFlowManager()->AllocateServiceFlows(dsaReq, cid);
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_DSA_RSP:
-
-                /*from other base station, as DSA initiated
-                 from BS is not supported, ignore*/
-                break;
-            case ManagementMessageType::MESSAGE_TYPE_DSA_ACK: {
-                Simulator::Cancel(GetServiceFlowManager()->GetDsaAckTimeoutEvent());
-                DsaAck dsaAck;
-                packet->RemoveHeader(dsaAck);
-                GetServiceFlowManager()->ProcessDsaAck(dsaAck, cid);
-                break;
-            }
-            default:
-                NS_FATAL_ERROR("Invalid message type");
-            }
-        }
-        else if (cid.IsBroadcast()) // broadcast connection
-        {
-            // from other base station, ignore
-            // or perhaps data packet (using other protocol) for BS, handle later
-            return;
-        }
-        else // transport connection
-        {
-            // If fragmentation is true, the packet is a fragment.
-            Ptr<Packet> C_Packet = packet->Copy();
-            if (!fragmentation)
-            {
-                C_Packet->RemoveHeader(llc);
-                source = m_ssManager->GetMacAddress(cid);
-                m_bsRxTrace(packet);
-                ForwardUp(packet->Copy(), source, Mac48Address::GetBroadcast());
-            }
-            else
-            {
-                NS_LOG_INFO("FRAG_DEBUG: BS DoReceive, the Packet is a fragment" << std::endl);
-                packet->RemoveHeader(fragSubhdr);
-                uint32_t fc = fragSubhdr.GetFc();
-                NS_LOG_INFO("\t fragment size = " << packet->GetSize() << std::endl);
-                if (fc == 2)
-                {
-                    // This is the latest fragment.
-                    // Take the fragment queue, defragment a packet and send it to the upper layer
-                    NS_LOG_INFO("\t Received the latest fragment" << std::endl);
-                    GetConnectionManager()->GetConnection(cid)->FragmentEnqueue(packet);
-                    WimaxConnection::FragmentsQueue fragmentsQueue =
-                        GetConnectionManager()->GetConnection(cid)->GetFragmentsQueue();
-                    Ptr<Packet> fullPacket = Create<Packet>();
-
-                    // DEFRAGMENTATION
-                    NS_LOG_INFO("\t BS PACKET DEFRAGMENTATION" << std::endl);
-                    for (auto iter = fragmentsQueue.begin(); iter != fragmentsQueue.end(); ++iter)
-                    {
-                        // Create the whole Packet
-                        fullPacket->AddAtEnd(*iter);
-                    }
-                    GetConnectionManager()->GetConnection(cid)->ClearFragmentsQueue();
-
-                    NS_LOG_INFO("\t fullPacket size = " << fullPacket->GetSize() << std::endl);
-                    source = m_ssManager->GetMacAddress(cid);
-                    m_bsRxTrace(fullPacket);
-                    ForwardUp(fullPacket->Copy(), source, Mac48Address::GetBroadcast());
-                }
-                else
-                {
-                    // This is the first or middle fragment.
-                    // Take the fragment queue, store the fragment into the queue
-                    NS_LOG_INFO("\t Received the first or the middle fragment" << std::endl);
-                    GetConnectionManager()->GetConnection(cid)->FragmentEnqueue(packet);
-                }
-            }
-        }
-    }
-    else
-    {
-        // bandwidth request header
-        packet->AddHeader(gnrcMacHdr);
-        packet->RemoveHeader(bwRequestHdr);
-        NS_ASSERT_MSG(bwRequestHdr.GetHt() == MacHeaderType::HEADER_TYPE_BANDWIDTH,
-                      "A bandwidth request should be carried by a bandwidth header type");
-        if (!bwRequestHdr.check_hcs())
-        {
-            // The header is noisy
-            NS_LOG_INFO("BS:Header HCS ERROR");
-            return;
-        }
-        cid = bwRequestHdr.GetCid();
-        source = m_ssManager->GetMacAddress(cid);
-        m_traceBSRx(packet, source, cid);
-        GetBandwidthManager()->ProcessBandwidthRequest(bwRequestHdr);
-    }
-}
-
-void
-BaseStationNetDevice::CreateMapMessages()
-{
-    Ptr<Packet> dlmap;
-    Ptr<Packet> ulmap;
-    bool sendDcd = false;
-    bool sendUcd = false;
-    bool updateDcd = false;
-    bool updateUcd = false;
-
-    uint16_t currentNrSsRegistered = m_ssManager->GetNRegisteredSSs();
-
-    if (m_nrSsRegistered == currentNrSsRegistered)
-    {
-        m_uplinkScheduler->GetChannelDescriptorsToUpdate(updateDcd, updateUcd, sendDcd, sendUcd);
-    }
-    else
-    {
-        sendDcd = sendUcd = true;
-    }
-
-    m_nrSsRegistered = currentNrSsRegistered;
-
-    /*either DCD and UCD must be created first because CCC is set during their
-     creation, or CCC must be calculated first so that it could be set during
-     creation of DL-MAP and UL-MAP and then set during creation of DCD and UCD*/
-
-    if (sendDcd)
-    {
-        m_dcdConfigChangeCount += 1 % 256;
-    }
-
-    if (sendUcd)
-    {
-        m_ucdConfigChangeCount += 1 % 256;
-    }
-
-    dlmap = CreateDlMap();
-    Enqueue(dlmap, MacHeaderType(), GetBroadcastConnection());
-    m_nrDlMapSent++;
-
-    ulmap = CreateUlMap();
-    Enqueue(ulmap, MacHeaderType(), GetBroadcastConnection());
-    m_nrUlMapSent++;
-
-    CreateDescriptorMessages(sendDcd, sendUcd);
-}
-
-void
-BaseStationNetDevice::CreateDescriptorMessages(bool sendDcd, bool sendUcd)
-{
-    Ptr<Packet> dcd;
-    Ptr<Packet> ucd;
-
-    if (sendDcd)
-    {
-        dcd = CreateDcd();
-        Enqueue(dcd, MacHeaderType(), GetBroadcastConnection());
-        m_nrDcdSent++;
-        m_framesSinceLastDcd = 0;
-    }
-    else
-    {
-        m_framesSinceLastDcd++;
-    }
-
-    if (sendUcd)
-    {
-        ucd = CreateUcd();
-        Enqueue(ucd, MacHeaderType(), GetBroadcastConnection());
-        m_nrUcdSent++;
-        m_framesSinceLastUcd = 0;
-    }
-    else
-    {
-        m_framesSinceLastUcd++;
-    }
-}
-
-/*
- Sends bursts in the downlink subframe. i.e., creates the downlink subframe. The first burst
- is broadcast burst with MAC management messages. The rest of the bursts contain data packets.
- */
-void
-BaseStationNetDevice::SendBursts()
-{
-    Time txTime;
-    std::pair<OfdmDlMapIe*, Ptr<PacketBurst>> pair;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts =
-        m_scheduler->GetDownlinkBursts();
-    Ptr<PacketBurst> burst;
-    OfdmDlMapIe* dlMapIe;
-    Cid cid;
-
-    while (!downlinkBursts->empty())
-    {
-        pair = downlinkBursts->front();
-        burst = pair.second;
-        dlMapIe = pair.first;
-        cid = dlMapIe->GetCid();
-        uint8_t diuc = dlMapIe->GetDiuc();
-
-        if (cid != GetInitialRangingConnection()->GetCid() &&
-            cid != GetBroadcastConnection()->GetCid())
-        {
-            modulationType =
-                GetBurstProfileManager()->GetModulationType(diuc,
-                                                            WimaxNetDevice::DIRECTION_DOWNLINK);
-        }
-        else
-        {
-            modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-        }
-
-        Simulator::Schedule(txTime, &WimaxNetDevice::ForwardDown, this, burst, modulationType);
-        txTime += GetPhy()->GetTransmissionTime(burst->GetSize(), modulationType);
-        downlinkBursts->pop_front();
-        delete dlMapIe;
-    }
-}
-
-Ptr<Packet>
-BaseStationNetDevice::CreateDlMap()
-{
-    m_nrDlAllocations = 0;
-
-    DlMap dlmap;
-    dlmap.SetDcdCount(m_dcdConfigChangeCount);
-    dlmap.SetBaseStationId(GetMacAddress());
-
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts =
-        m_scheduler->GetDownlinkBursts();
-
-    for (auto iter = downlinkBursts->begin(); iter != downlinkBursts->end(); ++iter)
-    {
-        iter->first->SetPreamblePresent(0);
-        iter->first->SetStartTime(0);
-        dlmap.AddDlMapElement(*(iter->first));
-    }
-
-    OfdmDlMapIe dlMapIeEnd;
-
-    dlMapIeEnd.SetCid(Cid::InitialRanging());
-    dlMapIeEnd.SetDiuc(OfdmDlBurstProfile::DIUC_END_OF_MAP);
-    dlMapIeEnd.SetPreamblePresent(0);
-    dlMapIeEnd.SetStartTime(0);
-
-    dlmap.AddDlMapElement(dlMapIeEnd);
-    m_nrDlAllocations = downlinkBursts->size();
-
-    Ptr<Packet> p = Create<Packet>();
-    p->AddHeader(dlmap);
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_DL_MAP));
-    return p;
-}
-
-Ptr<Packet>
-BaseStationNetDevice::CreateDcd()
-{
-    Dcd dcd;
-    OfdmDcdChannelEncodings chnlEncodings;
-
-    chnlEncodings.SetBsEirp(0);
-    chnlEncodings.SetEirxPIrMax(0);
-    chnlEncodings.SetFrequency(GetPhy()->GetFrequency());
-    chnlEncodings.SetChannelNr(0);
-    chnlEncodings.SetTtg(GetTtg());
-    chnlEncodings.SetRtg(GetRtg());
-    chnlEncodings.SetBaseStationId(GetMacAddress());
-    chnlEncodings.SetFrameDurationCode(GetPhy()->GetFrameDurationCode());
-    chnlEncodings.SetFrameNumber(GetNrFrames());
-
-    dcd.SetConfigurationChangeCount(m_dcdConfigChangeCount);
-    dcd.SetChannelEncodings(chnlEncodings);
-
-    SetDlBurstProfiles(&dcd);
-    SetCurrentDcd(dcd);
-
-    Ptr<Packet> p = Create<Packet>();
-    p->AddHeader(dcd);
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_DCD));
-    return p;
-}
-
-Ptr<Packet>
-BaseStationNetDevice::CreateUlMap()
-{
-    m_ulAllocationNumber = 0;
-    m_rangingOppNumber = 0;
-    m_nrUlAllocations = 0;
-
-    UlMap ulmap;
-    ulmap.SetUcdCount(m_ucdConfigChangeCount);
-    ulmap.SetAllocationStartTime(m_uplinkScheduler->CalculateAllocationStartTime());
-
-    std::list<OfdmUlMapIe> uplinkAllocations = m_uplinkScheduler->GetUplinkAllocations();
-
-    for (auto iter = uplinkAllocations.begin(); iter != uplinkAllocations.end(); ++iter)
-    {
-        ulmap.AddUlMapElement(*iter);
-    }
-
-    m_nrUlAllocations = uplinkAllocations.size();
-
-    Ptr<Packet> p = Create<Packet>();
-    p->AddHeader(ulmap);
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_UL_MAP));
-    return p;
-}
-
-Ptr<Packet>
-BaseStationNetDevice::CreateUcd()
-{
-    Ucd ucd;
-    ucd.SetConfigurationChangeCount(m_ucdConfigChangeCount);
-    ucd.SetRangingBackoffStart(3); // setting to 7. i.e., 2^3 = 8 -> 0-7
-    ucd.SetRangingBackoffEnd(6);   // setting to 63. i.e., 2^6 = 64 -> 0-63
-    ucd.SetRequestBackoffStart(3);
-    ucd.SetRequestBackoffEnd(6);
-
-    OfdmUcdChannelEncodings chnlEncodings;
-
-    chnlEncodings.SetBwReqOppSize(m_bwReqOppSize * GetPhy()->GetPsPerSymbol());
-    chnlEncodings.SetRangReqOppSize(m_rangReqOppSize * GetPhy()->GetPsPerSymbol());
-
-    chnlEncodings.SetFrequency(GetPhy()->GetFrequency());
-    chnlEncodings.SetSbchnlReqRegionFullParams(0);
-    chnlEncodings.SetSbchnlFocContCodes(0);
-
-    ucd.SetChannelEncodings(chnlEncodings);
-
-    SetUlBurstProfiles(&ucd);
-    SetCurrentUcd(ucd);
-
-    Ptr<Packet> p = Create<Packet>();
-    p->AddHeader(ucd);
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_UCD));
-    return p;
-}
-
-void
-BaseStationNetDevice::SetDlBurstProfiles(Dcd* dcd)
-{
-    for (int i = 0; i < GetBurstProfileManager()->GetNrBurstProfilesToDefine(); ++i)
-    {
-        OfdmDlBurstProfile brstProfile;
-        brstProfile.SetType(0);
-        brstProfile.SetLength(0);
-        brstProfile.SetDiuc(i + 1); // DIUC will be between 1-11, see Table 237
-        brstProfile.SetFecCodeType(i);
-        dcd->AddDlBurstProfile(brstProfile);
-    }
-}
-
-void
-BaseStationNetDevice::SetUlBurstProfiles(Ucd* ucd)
-{
-    for (int i = 0; i < GetBurstProfileManager()->GetNrBurstProfilesToDefine(); ++i)
-    {
-        OfdmUlBurstProfile brstProfile;
-        brstProfile.SetType(0);
-        brstProfile.SetLength(0);
-        // UIUC will be between 5-12, see Table 246. UIUC 1 (initial ranging) is not included
-        brstProfile.SetUiuc(i + 5);
-        brstProfile.SetFecCodeType(i);
-
-        ucd->AddUlBurstProfile(brstProfile);
-    }
-}
-
-Ptr<WimaxConnection>
-BaseStationNetDevice::GetConnection(Cid cid)
-{
-    Ptr<WimaxConnection> connection = nullptr;
-    if (cid.IsInitialRanging())
-    {
-        return GetInitialRangingConnection();
-    }
-    else if (cid.IsBroadcast())
-    {
-        connection = GetBroadcastConnection();
-    }
-    else
-    {
-        connection = GetConnectionManager()->GetConnection(cid);
-    }
-
-    NS_ASSERT_MSG(connection, "BS: Invalid connection=0");
-    return connection;
-}
-
-void
-BaseStationNetDevice::MarkUplinkAllocations()
-{
-    uint16_t symbolsToAllocation = 0;
-    const auto& uplinkAllocations = m_uplinkScheduler->GetUplinkAllocations();
-    for (const auto& uplinkAllocation : uplinkAllocations)
-    {
-        if (uplinkAllocation.GetUiuc() == OfdmUlBurstProfile::UIUC_END_OF_MAP)
-        {
-            break;
-        }
-
-        symbolsToAllocation = uplinkAllocation.GetStartTime();
-        MarkUplinkAllocationStart(symbolsToAllocation * m_symbolDuration);
-        MarkUplinkAllocationEnd((symbolsToAllocation + uplinkAllocation.GetDuration()) *
-                                    m_symbolDuration,
-                                uplinkAllocation.GetCid(),
-                                uplinkAllocation.GetUiuc());
-    }
-}
-
-void
-BaseStationNetDevice::MarkUplinkAllocationStart(Time allocationStartTime)
-{
-    Simulator::Schedule(allocationStartTime, &BaseStationNetDevice::UplinkAllocationStart, this);
-}
-
-void
-BaseStationNetDevice::MarkUplinkAllocationEnd(Time allocationEndTime, Cid cid, uint8_t uiuc)
-{
-    Simulator::Schedule(allocationEndTime,
-                        &BaseStationNetDevice::UplinkAllocationEnd,
-                        this,
-                        cid,
-                        uiuc);
-}
-
-void
-BaseStationNetDevice::UplinkAllocationStart()
-{
-    m_ulAllocationNumber++;
-
-    NS_LOG_DEBUG("--UL allocation " << (uint32_t)m_ulAllocationNumber
-                                    << " started : " << Simulator::Now().As(Time::S));
-}
-
-void
-BaseStationNetDevice::UplinkAllocationEnd(Cid cid, uint8_t uiuc)
-{
-    NS_LOG_DEBUG("--UL allocation " << (uint32_t)m_ulAllocationNumber
-                                    << " ended : " << Simulator::Now().As(Time::S));
-
-    if (m_cidFactory->IsBasic(cid))
-    {
-        m_linkManager->VerifyInvitedRanging(cid, uiuc);
-    }
-}
-
-void
-BaseStationNetDevice::MarkRangingOppStart(Time rangingOppStartTime)
-{
-    Simulator::Schedule(rangingOppStartTime, &BaseStationNetDevice::RangingOppStart, this);
-}
-
-void
-BaseStationNetDevice::RangingOppStart()
-{
-    m_rangingOppNumber++;
-
-    NS_LOG_DEBUG("Ranging TO " << (uint32_t)m_rangingOppNumber << ": "
-                               << Simulator::Now().As(Time::S));
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-net-device.h ns-3.46/src/wimax/model/bs-net-device.h
--- ns-3.45/src/wimax/model/bs-net-device.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-net-device.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,506 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef WIMAX_BS_NET_DEVICE_H
-#define WIMAX_BS_NET_DEVICE_H
-
-#include "bs-service-flow-manager.h"
-#include "dl-mac-messages.h"
-#include "ipcs-classifier.h"
-#include "wimax-connection.h"
-#include "wimax-net-device.h"
-
-#include "ns3/event-id.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/mac48-address.h"
-#include "ns3/nstime.h"
-
-namespace ns3
-{
-
-class Node;
-class Packet;
-class SSRecord;
-class SSManager;
-class BSScheduler;
-class BurstProfileManager;
-class BSLinkManager;
-class UplinkScheduler;
-class BsServiceFlowManager;
-
-/**
- * @ingroup wimax
- *
- * BaseStation NetDevice
- */
-class BaseStationNetDevice : public WimaxNetDevice
-{
-  public:
-    /// State enumeration
-    enum State
-    {
-        BS_STATE_DL_SUB_FRAME,
-        BS_STATE_UL_SUB_FRAME,
-        BS_STATE_TTG,
-        BS_STATE_RTG
-    };
-
-    /// MacPreamble enumeration
-    enum MacPreamble
-    {
-        SHORT_PREAMBLE = 1,
-        LONG_PREAMBLE
-    };
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    BaseStationNetDevice();
-    /**
-     * Constructor
-     *
-     * @param node the node
-     * @param phy the wimax phy
-     */
-    BaseStationNetDevice(Ptr<Node> node, Ptr<WimaxPhy> phy);
-    /**
-     * Constructor
-     *
-     * @param node the node
-     * @param phy the wimax phy
-     * @param uplinkScheduler uplink scheduler
-     * @param bsScheduler bs scheduler
-     */
-    BaseStationNetDevice(Ptr<Node> node,
-                         Ptr<WimaxPhy> phy,
-                         Ptr<UplinkScheduler> uplinkScheduler,
-                         Ptr<BSScheduler> bsScheduler);
-    ~BaseStationNetDevice() override;
-    /**
-     * @param initialRangInterval Time between initial ranging regions assigned by the BS
-     */
-    void SetInitialRangingInterval(Time initialRangInterval);
-    /**
-     * @brief initializes the BS net device and sets its parameters to the default values
-     */
-    void InitBaseStationNetDevice();
-    /**
-     * @returns Time between initial ranging regions assigned by the BS
-     */
-    Time GetInitialRangingInterval() const;
-    /**
-     * @param dcdInterval Time between transmission of DCD messages
-     */
-    void SetDcdInterval(Time dcdInterval);
-    /**
-     * @returns the Time between transmission of DCD messages
-     */
-    Time GetDcdInterval() const;
-    /**
-     * @param ucdInterval the Time between transmission of UCD messages
-     */
-    void SetUcdInterval(Time ucdInterval);
-    /**
-     * @returns Time between transmission of UCD messages
-     */
-    Time GetUcdInterval() const;
-    /**
-     * @param interval the Wait for DSA/DSC Acknowledge timeout
-     */
-    void SetIntervalT8(Time interval);
-    /**
-     * @returns the Wait for DSA/DSC Acknowledge timeout
-     */
-    Time GetIntervalT8() const;
-    /**
-     * @param maxRangCorrectionRetries the number of retries on contention Ranging Requests
-     */
-    void SetMaxRangingCorrectionRetries(uint8_t maxRangCorrectionRetries);
-    /**
-     * @returns the number of retries on contention Ranging Requests
-     */
-    uint8_t GetMaxRangingCorrectionRetries() const;
-    /**
-     * @param maxInvitedRangRetries the number of retries on contention Ranging
-     */
-    void SetMaxInvitedRangRetries(uint8_t maxInvitedRangRetries);
-    /**
-     * @returns the number of retries on contention Ranging
-     */
-    uint8_t GetMaxInvitedRangRetries() const;
-    /**
-     * @param rangReqOppSize The ranging opportunity size in symbols
-     */
-    void SetRangReqOppSize(uint8_t rangReqOppSize);
-    /**
-     * @returns The ranging opportunity size in symbols
-     */
-    uint8_t GetRangReqOppSize() const;
-    /**
-     * @param bwReqOppSize The bandwidth request opportunity size in symbols
-     */
-    void SetBwReqOppSize(uint8_t bwReqOppSize);
-    /**
-     * @returns The bandwidth request opportunity size in symbols
-     */
-    uint8_t GetBwReqOppSize() const;
-    /**
-     * @param dlSymbols the number of symbols in the downlink sub-frame
-     */
-    void SetNrDlSymbols(uint32_t dlSymbols);
-    /**
-     * @returns the number of symbols in the downlink sub-frame
-     */
-    uint32_t GetNrDlSymbols() const;
-    /**
-     * @param ulSymbols the number of symbols in the uplink sub-frame
-     */
-    void SetNrUlSymbols(uint32_t ulSymbols);
-    /**
-     * @returns the number of symbols in the uplink sub-frame
-     */
-    uint32_t GetNrUlSymbols() const;
-    /**
-     * @returns the number dcd messages already sent
-     */
-    uint32_t GetNrDcdSent() const;
-    /**
-     * @returns the number ucd messages already sent
-     */
-    uint32_t GetNrUcdSent() const;
-    /**
-     * @returns the DL subframe start time
-     */
-    Time GetDlSubframeStartTime() const;
-    /**
-     * @returns the UL subframe start time
-     */
-    Time GetUlSubframeStartTime() const;
-    /**
-     * @returns the ranging opp number
-     */
-    uint8_t GetRangingOppNumber() const;
-    /**
-     * @returns a pointer to the SS manager
-     */
-    Ptr<SSManager> GetSSManager() const;
-    /**
-     * @param ssManager the SS manager to be installed on the BS
-     */
-    void SetSSManager(Ptr<SSManager> ssManager);
-    /**
-     * @returns a pointer to the uplink scheduler installed on the device
-     */
-    Ptr<UplinkScheduler> GetUplinkScheduler() const;
-    /**
-     * @param ulScheduler the ulScheduler to be isnstalled on the BS
-     */
-    void SetUplinkScheduler(Ptr<UplinkScheduler> ulScheduler);
-    /**
-     * @returns a pointer to the link manager installed on the BS
-     */
-    Ptr<BSLinkManager> GetLinkManager() const;
-    /**
-     * @param bsSchedule the downlink scheduler to be installed on the BS
-     */
-    void SetBSScheduler(Ptr<BSScheduler> bsSchedule);
-    /**
-     * @returns The BS scheduler installed on the BS
-     */
-    Ptr<BSScheduler> GetBSScheduler() const;
-    /**
-     * @param linkManager The link manager installed on the BS
-     */
-    void SetLinkManager(Ptr<BSLinkManager> linkManager);
-    /**
-     * @returns a pointer to the classifier installed on the BS
-     */
-    Ptr<IpcsClassifier> GetBsClassifier() const;
-    /**
-     * @param classifier a classifier to be installed on the BS
-     */
-    void SetBsClassifier(Ptr<IpcsClassifier> classifier);
-
-    /**
-     * @returns PS duration
-     */
-    Time GetPsDuration() const;
-    /**
-     * @returns symbol duration
-     */
-    Time GetSymbolDuration() const;
-    /**
-     * @brief Start device
-     */
-    void Start() override;
-    /**
-     * @brief Stop device
-     */
-    void Stop() override;
-    /**
-     * @brief Enqueue a packet into a connection queue
-     * @param packet the packet to be enqueued
-     * @param hdrType the mac header type to be appended to the packet
-     * @param connection the connection to be used
-     * @return true if successful
-     */
-    bool Enqueue(Ptr<Packet> packet,
-                 const MacHeaderType& hdrType,
-                 Ptr<WimaxConnection> connection) override;
-    /**
-     * @param cid connection ID
-     * @returns a pointer to the connection
-     */
-    Ptr<WimaxConnection> GetConnection(Cid cid);
-
-    /**
-     * @brief Mark uplink allocations
-     */
-    void MarkUplinkAllocations();
-    /**
-     * @brief Mark ranging opp start
-     * @param rangingOppStartTime start time
-     */
-    void MarkRangingOppStart(Time rangingOppStartTime);
-    /**
-     * @returns service flow manager
-     */
-    Ptr<BsServiceFlowManager> GetServiceFlowManager() const;
-    /**
-     * @brief Set service flow manager
-     * @param sfm the service flow manager
-     */
-    void SetServiceFlowManager(Ptr<BsServiceFlowManager> sfm);
-
-  private:
-    void DoDispose() override;
-    /**
-     * @brief Start frame function
-     */
-    void StartFrame();
-    /**
-     * @brief Start DL subframe function
-     */
-    void StartDlSubFrame();
-    /**
-     * @brief End DL subframe function
-     */
-    void EndDlSubFrame();
-    /**
-     * @brief Start UL subframe function
-     */
-    void StartUlSubFrame();
-    /**
-     * @brief End UL subframe function
-     */
-    void EndUlSubFrame();
-    /**
-     * @brief End frame function
-     */
-    void EndFrame();
-    /**
-     * @brief Send packet
-     * @param packet to send
-     * @param source MAC address
-     * @param dest destination MAC address
-     * @param protocolNumber protocol number
-     * @returns true if successful
-     */
-    bool DoSend(Ptr<Packet> packet,
-                const Mac48Address& source,
-                const Mac48Address& dest,
-                uint16_t protocolNumber) override;
-    /**
-     * @brief Receive packet
-     * @param packet to send
-     */
-    void DoReceive(Ptr<Packet> packet) override;
-    /**
-     * @brief creates the MAC management messages DL-MAP and UL-MAP
-     */
-    void CreateMapMessages();
-    /**
-     * @brief creates the channel descriptor MAC management messages DCD and UCD
-     * @param sendDcd true if send DCD
-     * @param sendUcd true if send UCD
-     */
-    void CreateDescriptorMessages(bool sendDcd, bool sendUcd);
-    /**
-     * @brief Send burst function
-     */
-    void SendBursts();
-
-    /**
-     * @brief Create DL map
-     * @returns packet
-     */
-    Ptr<Packet> CreateDlMap();
-    /**
-     * @brief Create DCD
-     * @returns packet
-     */
-    Ptr<Packet> CreateDcd();
-    /**
-     * @brief Create UL map
-     * @returns packet
-     */
-    Ptr<Packet> CreateUlMap();
-    /**
-     * @brief Create UCD
-     * @returns packet
-     */
-    Ptr<Packet> CreateUcd();
-    /**
-     * @brief Send DL burst profiles
-     * @param dcd burst profile
-     */
-    void SetDlBurstProfiles(Dcd* dcd);
-    /**
-     * @brief Send UL burst profiles
-     * @param ucd burst profile
-     */
-    void SetUlBurstProfiles(Ucd* ucd);
-
-    /**
-     * @brief Mark uplink allocation start
-     * @param allocationStartTime allocation start time
-     */
-    void MarkUplinkAllocationStart(Time allocationStartTime);
-    /**
-     * @brief Mark uplink allocation end
-     * @param allocationEndTime allocation end time
-     * @param cid connection ID
-     * @param uiuc
-     */
-    void MarkUplinkAllocationEnd(Time allocationEndTime, Cid cid, uint8_t uiuc);
-    /**
-     * @brief Uplink allocation start
-     */
-    void UplinkAllocationStart();
-    /**
-     * @brief Uplink allocation end
-     * @param cid connection ID
-     * @param uiuc
-     */
-    void UplinkAllocationEnd(Cid cid, uint8_t uiuc);
-    /**
-     * @brief Ranging opp start
-     */
-    void RangingOppStart();
-
-    // parameters defined in Table 342
-    Time m_initialRangInterval; ///< in seconds
-    Time m_dcdInterval;         ///< in seconds
-    Time m_ucdInterval;         ///< in seconds
-    Time m_intervalT8;          ///< in milliseconds, wait for DSA/DSC Acknowledge timeout
-
-    uint8_t m_maxRangCorrectionRetries; ///< maximum range correction retries
-    uint8_t m_maxInvitedRangRetries;    ///< maximum invited range retries
-    uint8_t m_rangReqOppSize;           ///< in symbols
-    uint8_t m_bwReqOppSize;             ///< in symbols
-
-    uint32_t m_nrDlSymbols; ///< number of DL symbols
-    uint32_t m_nrUlSymbols; ///< number of UL symbols
-
-    // to keep track total number of a certain management messages sent by the BS
-    uint32_t m_nrDlMapSent; ///< number DL map sent
-    uint32_t m_nrUlMapSent; ///< number UL map sent
-    // number of DCDs and UCDs sent even if same
-    uint32_t m_nrDcdSent; ///< number DCD sent
-    uint32_t m_nrUcdSent; ///< number UCD sent
-
-    uint32_t m_dcdConfigChangeCount; ///< DCD config change count
-    uint32_t m_ucdConfigChangeCount; ///< UCD config change count
-
-    uint32_t m_framesSinceLastDcd; ///< frames since last DCD
-    uint32_t m_framesSinceLastUcd; ///< frames since last UCD
-
-    // uint32_t m_nrFrames; //temporarily defined in wimax-net-device, as static
-    uint32_t m_nrDlFrames; ///< number DL frames
-    uint32_t m_nrUlFrames; ///< number UL frames
-
-    // to keep track if number of SSs have changed since the last frame
-    uint16_t m_nrSsRegistered; ///< number SS registered
-
-    uint16_t m_nrDlAllocations; ///< number DL allocations
-    uint16_t m_nrUlAllocations; ///< number UL allocations
-
-    Time m_dlSubframeStartTime; ///< DL subframe start time
-    Time m_ulSubframeStartTime; ///< UL subframe start time
-
-    uint8_t m_ulAllocationNumber; ///< to see UL burst number
-    uint8_t m_rangingOppNumber;   ///< current ranging TO number
-
-    CidFactory* m_cidFactory; ///< the CID factory
-
-    uint32_t m_allocationStartTime; ///< allocation start time
-
-    Ptr<SSManager> m_ssManager;                     ///< the SS manager
-    Ptr<UplinkScheduler> m_uplinkScheduler;         ///< the uplink scheduler
-    Ptr<BSScheduler> m_scheduler;                   ///< the base station scheduler
-    Ptr<BSLinkManager> m_linkManager;               ///< the link manager
-    Ptr<IpcsClassifier> m_bsClassifier;             ///< the base station classifier
-    Ptr<BsServiceFlowManager> m_serviceFlowManager; ///< the service flow manager
-    // same fields as in PHY, for quick access
-    Time m_psDuration;     ///< ps duration
-    Time m_symbolDuration; ///< symbol duration
-
-    TracedCallback<Ptr<const Packet>, Mac48Address, Cid>
-        m_traceBSRx; ///< the base station receive trace callback
-
-    /**
-     * The trace source fired when packets come into the "top" of the device
-     * at the L3/L2 transition, before being queued for transmission.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_bsTxTrace; ///< the base station transmit trace callback
-
-    /**
-     * The trace source fired when packets coming into the "top" of the device
-     * are dropped at the MAC layer during transmission.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>>
-        m_bsTxDropTrace; ///< base station transmit drop trace callback
-
-    /**
-     * The trace source fired for packets successfully received by the device
-     * immediately before being forwarded up to higher layers (at the L2/L3
-     * transition).  This is a promiscuous trace.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>>
-        m_bsPromiscRxTrace; ///< base station promiscuous receive trace callback
-
-    /**
-     * The trace source fired for packets successfully received by the device
-     * immediately before being forwarded up to higher layers (at the L2/L3
-     * transition).  This is a non- promiscuous trace.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_bsRxTrace; ///< base station receive trace callback
-
-    /**
-     * The trace source fired when packets coming into the "top" of the device
-     * are dropped at the MAC layer during reception.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_bsRxDropTrace; ///< base station receive drop trace callback
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_BS_NET_DEVICE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-scheduler.cc ns-3.46/src/wimax/model/bs-scheduler.cc
--- ns-3.45/src/wimax/model/bs-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-scheduler.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "bs-scheduler.h"
-
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-#include "wimax-connection.h"
-#include "wimax-mac-header.h"
-#include "wimax-mac-queue.h"
-
-#include "ns3/log.h"
-#include "ns3/packet-burst.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BSScheduler");
-
-NS_OBJECT_ENSURE_REGISTERED(BSScheduler);
-
-TypeId
-BSScheduler::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::BSScheduler").SetParent<Object>().SetGroupName("Wimax")
-        // No AddConstructor because this is an abstract class.
-        ;
-    return tid;
-}
-
-BSScheduler::BSScheduler()
-    : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
-{
-    // m_downlinkBursts is filled by AddDownlinkBurst and emptied by
-    // wimax-bs-net-device::sendBurst and wimax-ss-net-device::sendBurst
-}
-
-BSScheduler::BSScheduler(Ptr<BaseStationNetDevice> bs)
-    : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
-{
-}
-
-BSScheduler::~BSScheduler()
-{
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts = m_downlinkBursts;
-    std::pair<OfdmDlMapIe*, Ptr<PacketBurst>> pair;
-    while (!downlinkBursts->empty())
-    {
-        pair = downlinkBursts->front();
-        pair.second = nullptr;
-        delete pair.first;
-    }
-    SetBs(nullptr);
-    delete m_downlinkBursts;
-    m_downlinkBursts = nullptr;
-}
-
-void
-BSScheduler::SetBs(Ptr<BaseStationNetDevice> bs)
-{
-    m_bs = bs;
-}
-
-Ptr<BaseStationNetDevice>
-BSScheduler::GetBs()
-{
-    return m_bs;
-}
-
-bool
-BSScheduler::CheckForFragmentation(Ptr<WimaxConnection> connection,
-                                   int availableSymbols,
-                                   WimaxPhy::ModulationType modulationType)
-{
-    NS_LOG_INFO("BS Scheduler, CheckForFragmentation");
-    if (connection->GetType() != Cid::TRANSPORT)
-    {
-        NS_LOG_INFO("\t No Transport connection, Fragmentation IS NOT possible");
-        return false;
-    }
-    uint32_t availableByte = GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-
-    uint32_t headerSize =
-        connection->GetQueue()->GetFirstPacketHdrSize(MacHeaderType::HEADER_TYPE_GENERIC);
-    NS_LOG_INFO("\t availableByte = " << availableByte << " headerSize = " << headerSize);
-
-    if (availableByte > headerSize)
-    {
-        NS_LOG_INFO("\t Fragmentation IS possible");
-        return true;
-    }
-    else
-    {
-        NS_LOG_INFO("\t Fragmentation IS NOT possible");
-        return false;
-    }
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-scheduler.h ns-3.46/src/wimax/model/bs-scheduler.h
--- ns-3.45/src/wimax/model/bs-scheduler.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-scheduler.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-/* BS outbound scheduler as per in Section 6.3.5.1 */
-
-#ifndef BS_SCHEDULER_H
-#define BS_SCHEDULER_H
-
-#include "dl-mac-messages.h"
-#include "service-flow.h"
-#include "wimax-phy.h"
-
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-
-#include <list>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class GenericMacHeader;
-class WimaxConnection;
-class Cid;
-
-/**
- * @ingroup wimax
- *
- * BaseStation Scheduler
- */
-class BSScheduler : public Object
-{
-  public:
-    BSScheduler();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    BSScheduler(Ptr<BaseStationNetDevice> bs);
-    ~BSScheduler() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief This function returns all the downlink bursts scheduled for the next
-     * downlink sub-frame
-     * @returns  all the downlink bursts scheduled for the next downlink sub-frame
-     */
-    virtual std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* GetDownlinkBursts() const = 0;
-    /**
-     * @brief This function adds a downlink burst to the list of downlink bursts
-     * scheduled for the next downlink sub-frame
-     * @param connection a pointer to connection in which the burst will be sent
-     * @param diuc downlink iuc
-     * @param modulationType the modulation type of the burst
-     * @param burst the downlink burst to add to the downlink sub frame
-     */
-    virtual void AddDownlinkBurst(Ptr<const WimaxConnection> connection,
-                                  uint8_t diuc,
-                                  WimaxPhy::ModulationType modulationType,
-                                  Ptr<PacketBurst> burst) = 0;
-
-    /**
-     * @brief the scheduling function for the downlink subframe.
-     */
-    virtual void Schedule() = 0;
-    /**
-     * @brief Selects a connection from the list of connections having packets to be sent .
-     * @param connection will point to a connection that have packets to be sent
-     * @returns false if no connection has packets to be sent, true otherwise
-     */
-    virtual bool SelectConnection(Ptr<WimaxConnection>& connection) = 0;
-
-    /**
-     * @brief Creates a downlink UGS burst
-     * @param serviceFlow the service flow of the burst
-     * @param modulationType the modulation type to be used for the burst
-     * @param availableSymbols maximum number of OFDM symbols to be used by the burst
-     * @returns a Burst (list of packets)
-     */
-    virtual Ptr<PacketBurst> CreateUgsBurst(ServiceFlow* serviceFlow,
-                                            WimaxPhy::ModulationType modulationType,
-                                            uint32_t availableSymbols) = 0;
-
-    /**
-     * @brief Get the base station.
-     * @returns the base station net device
-     */
-    virtual Ptr<BaseStationNetDevice> GetBs();
-    /**
-     * @brief Set the base station.
-     * @param bs the base station net device
-     */
-    virtual void SetBs(Ptr<BaseStationNetDevice> bs);
-
-    /**
-     * @brief Check if the packet fragmentation is possible for transport connection.
-     * @param connection the downlink connection
-     * @param availableSymbols maximum number of OFDM symbols to be used by the burst
-     * @param modulationType the modulation type to be used for the burst
-     * @returns false if packet fragmentation is not possible, true otherwise
-     */
-    bool CheckForFragmentation(Ptr<WimaxConnection> connection,
-                               int availableSymbols,
-                               WimaxPhy::ModulationType modulationType);
-
-  private:
-    Ptr<BaseStationNetDevice> m_bs;                                         ///< base station
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* m_downlinkBursts; ///< down link bursts
-};
-
-} // namespace ns3
-
-#endif /* BS_SCHEDULER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-scheduler-rtps.cc ns-3.46/src/wimax/model/bs-scheduler-rtps.cc
--- ns-3.45/src/wimax/model/bs-scheduler-rtps.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-scheduler-rtps.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,734 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *               2009 TELEMATICS LAB, Politecnico di Bari
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Giuseppe Piro <g.piro@poliba.it>
- */
-
-#include "bs-scheduler-rtps.h"
-
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-#include "wimax-connection.h"
-#include "wimax-mac-header.h"
-#include "wimax-mac-queue.h"
-
-#include "ns3/log.h"
-#include "ns3/packet-burst.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BSSchedulerRtps");
-
-NS_OBJECT_ENSURE_REGISTERED(BSSchedulerRtps);
-
-TypeId
-BSSchedulerRtps::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::BSSchedulerRtps")
-                            .SetParent<BSScheduler>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<BSSchedulerRtps>();
-    return tid;
-}
-
-BSSchedulerRtps::BSSchedulerRtps()
-    : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
-{
-    SetBs(nullptr);
-}
-
-BSSchedulerRtps::BSSchedulerRtps(Ptr<BaseStationNetDevice> bs)
-    : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
-{
-    // m_downlinkBursts is filled by AddDownlinkBurst and emptied by
-    // wimax-bs-net-device::sendBurst and wimax-ss-net-device::sendBurst
-    SetBs(bs);
-}
-
-BSSchedulerRtps::~BSSchedulerRtps()
-{
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts = m_downlinkBursts;
-    std::pair<OfdmDlMapIe*, Ptr<PacketBurst>> pair;
-    while (!downlinkBursts->empty())
-    {
-        pair = downlinkBursts->front();
-        pair.second = nullptr;
-        delete pair.first;
-    }
-
-    SetBs(nullptr);
-    delete m_downlinkBursts;
-    m_downlinkBursts = nullptr;
-}
-
-std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>*
-BSSchedulerRtps::GetDownlinkBursts() const
-{
-    return m_downlinkBursts;
-}
-
-void
-BSSchedulerRtps::AddDownlinkBurst(Ptr<const WimaxConnection> connection,
-                                  uint8_t diuc,
-                                  WimaxPhy::ModulationType modulationType,
-                                  Ptr<PacketBurst> burst)
-{
-    auto dlMapIe = new OfdmDlMapIe();
-    dlMapIe->SetCid(connection->GetCid());
-    dlMapIe->SetDiuc(diuc);
-
-    NS_LOG_INFO("BS scheduler, burst size: " << burst->GetSize() << " bytes"
-                                             << ", pkts: " << burst->GetNPackets()
-                                             << ", connection: " << connection->GetTypeStr()
-                                             << ", CID: " << connection->GetCid());
-    if (connection->GetType() == Cid::TRANSPORT)
-    {
-        NS_LOG_INFO(", SFID: " << connection->GetServiceFlow()->GetSfid() << ", service: "
-                               << connection->GetServiceFlow()->GetSchedulingTypeStr());
-    }
-    NS_LOG_INFO(", modulation: " << modulationType << ", DIUC: " << (uint32_t)diuc);
-
-    m_downlinkBursts->emplace_back(dlMapIe, burst);
-}
-
-/**
- * @brief A DownLink Scheduler for rtPS Flows
- *
- * The DL Scheduler assigns the available bandwidth in the following order:
- * - IR Connections
- * - Broadcast Connections
- * - Basic and Primary Connections
- * - UGS Connections
- * - rtPS Connections
- * - nrtPS Connections
- * - BE Connections
- * All rtPS flows that have packets in the queue can transmit at least one
- * packet, according to the available bandwidth.
- */
-void
-BSSchedulerRtps::Schedule()
-{
-    uint32_t availableSymbols = GetBs()->GetNrDlSymbols();
-
-    BSSchedulerBroadcastConnection(availableSymbols);
-
-    BSSchedulerInitialRangingConnection(availableSymbols);
-
-    BSSchedulerBasicConnection(availableSymbols);
-
-    BSSchedulerPrimaryConnection(availableSymbols);
-
-    BSSchedulerUGSConnection(availableSymbols);
-
-    BSSchedulerRTPSConnection(availableSymbols);
-
-    BSSchedulerNRTPSConnection(availableSymbols);
-
-    BSSchedulerBEConnection(availableSymbols);
-
-    if (!m_downlinkBursts->empty())
-    {
-        NS_LOG_DEBUG(
-            "BS scheduler, number of bursts: "
-            << m_downlinkBursts->size() << ", symbols left: " << availableSymbols << std::endl
-            << "BS scheduler, queues:"
-            << " IR " << GetBs()->GetInitialRangingConnection()->GetQueue()->GetSize()
-            << " broadcast " << GetBs()->GetBroadcastConnection()->GetQueue()->GetSize()
-            << " basic "
-            << GetBs()->GetConnectionManager()->GetNPackets(Cid::BASIC, ServiceFlow::SF_TYPE_NONE)
-            << " primary "
-            << GetBs()->GetConnectionManager()->GetNPackets(Cid::PRIMARY, ServiceFlow::SF_TYPE_NONE)
-            << " transport "
-            << GetBs()->GetConnectionManager()->GetNPackets(Cid::TRANSPORT,
-                                                            ServiceFlow::SF_TYPE_ALL));
-    }
-}
-
-Ptr<PacketBurst>
-BSSchedulerRtps::CreateUgsBurst(ServiceFlow* serviceFlow,
-                                WimaxPhy::ModulationType modulationType,
-                                uint32_t availableSymbols)
-{
-    Time timeStamp;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-    uint32_t nrSymbolsRequired = 0;
-
-    // serviceFlow->CleanUpQueue ();
-    Ptr<WimaxConnection> connection = serviceFlow->GetConnection();
-    while (serviceFlow->HasPackets())
-    {
-        uint32_t FirstPacketSize =
-            connection->GetQueue()->GetFirstPacketRequiredByte(MacHeaderType::HEADER_TYPE_GENERIC);
-        nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
-        if (availableSymbols < nrSymbolsRequired &&
-            CheckForFragmentation(connection, availableSymbols, modulationType))
-        {
-            uint32_t availableByte =
-                GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-            packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-            availableSymbols = 0;
-        }
-        else
-        {
-            packet = connection->Dequeue();
-            availableSymbols -= nrSymbolsRequired;
-        }
-        burst->AddPacket(packet);
-        if (availableSymbols <= 0)
-        {
-            break;
-        }
-    }
-    return burst;
-}
-
-bool
-BSSchedulerRtps::SelectConnection(Ptr<WimaxConnection>& connection)
-{
-    return false;
-}
-
-void
-BSSchedulerRtps::BSSchedulerBroadcastConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = OfdmDlBurstProfile::DIUC_BURST_PROFILE_1;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    while (GetBs()->GetBroadcastConnection()->HasPackets() && availableSymbols > 0)
-    {
-        connection = GetBs()->GetBroadcastConnection();
-
-        packet = connection->GetQueue()->Peek(hdr);
-        nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-
-        if (availableSymbols < nrSymbolsRequired &&
-            !CheckForFragmentation(connection, availableSymbols, modulationType))
-        {
-            break;
-        }
-        else if (availableSymbols < nrSymbolsRequired &&
-                 CheckForFragmentation(connection, availableSymbols, modulationType))
-        {
-            uint32_t availableByte =
-                GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-            packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-        }
-        else
-        {
-            packet = connection->Dequeue();
-        }
-
-        NS_ASSERT_MSG(hdr.GetCid().GetIdentifier() == connection->GetCid(),
-                      "Base station: Error while scheduling broadcast connection: header CID != "
-                      "connection CID");
-        burst->AddPacket(packet);
-        availableSymbols -= nrSymbolsRequired;
-    }
-    if (burst->GetNPackets() != 0)
-    {
-        AddDownlinkBurst(connection, diuc, modulationType, burst);
-    }
-}
-
-void
-BSSchedulerRtps::BSSchedulerInitialRangingConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = OfdmDlBurstProfile::DIUC_BURST_PROFILE_1;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    while (GetBs()->GetInitialRangingConnection()->HasPackets() && availableSymbols > 0)
-    {
-        connection = GetBs()->GetInitialRangingConnection();
-
-        packet = connection->GetQueue()->Peek(hdr);
-        nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-
-        // PIRO: check for fragmentation
-        if (availableSymbols < nrSymbolsRequired &&
-            !CheckForFragmentation(connection, availableSymbols, modulationType))
-        {
-            break;
-        }
-        else if (availableSymbols < nrSymbolsRequired &&
-                 CheckForFragmentation(connection, availableSymbols, modulationType))
-        {
-            uint32_t availableByte =
-                GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-            packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-        }
-        else
-        {
-            packet = connection->Dequeue();
-        }
-
-        NS_ASSERT_MSG(hdr.GetCid() == connection->GetCid(),
-                      "Base station: Error while scheduling initial ranging connection: header CID "
-                      "!= connection CID");
-        burst->AddPacket(packet);
-        availableSymbols -= nrSymbolsRequired;
-    }
-    if (burst->GetNPackets())
-    {
-        AddDownlinkBurst(connection, diuc, modulationType, burst);
-    }
-}
-
-void
-BSSchedulerRtps::BSSchedulerBasicConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = OfdmDlBurstProfile::DIUC_BURST_PROFILE_1;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    std::vector<Ptr<WimaxConnection>> connections;
-
-    connections = GetBs()->GetConnectionManager()->GetConnections(Cid::BASIC);
-    for (auto iter = connections.begin(); iter != connections.end(); ++iter)
-    {
-        while ((*iter)->HasPackets() && availableSymbols > 0)
-        {
-            connection = *iter;
-
-            modulationType =
-                GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
-            diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-
-            packet = connection->GetQueue()->Peek(hdr);
-            nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-
-            // PIRO: check for fragmentation
-            if (availableSymbols < nrSymbolsRequired &&
-                !CheckForFragmentation(connection, availableSymbols, modulationType))
-            {
-                break;
-            }
-            else if (availableSymbols < nrSymbolsRequired &&
-                     CheckForFragmentation(connection, availableSymbols, modulationType))
-            {
-                uint32_t availableByte =
-                    GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-                packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-            }
-            else
-            {
-                packet = connection->Dequeue();
-            }
-
-            NS_ASSERT_MSG(hdr.GetCid() == connection->GetCid(),
-                          "Base station: Error while scheduling basic connection: header CID != "
-                          "connection CID");
-            burst->AddPacket(packet);
-            availableSymbols -= nrSymbolsRequired;
-        }
-        if (burst->GetNPackets() != 0)
-        {
-            AddDownlinkBurst(connection, diuc, modulationType, burst);
-            burst = Create<PacketBurst>();
-        }
-    }
-}
-
-void
-BSSchedulerRtps::BSSchedulerPrimaryConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = 0;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    std::vector<Ptr<WimaxConnection>> connections;
-
-    connections = GetBs()->GetConnectionManager()->GetConnections(Cid::PRIMARY);
-    for (auto iter = connections.begin(); iter != connections.end(); ++iter)
-    {
-        while ((*iter)->HasPackets() && availableSymbols > 0)
-        {
-            connection = *iter;
-
-            modulationType =
-                GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
-            diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-
-            packet = connection->GetQueue()->Peek(hdr);
-            nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-
-            // PIRO: check for fragmentation
-            if (availableSymbols < nrSymbolsRequired &&
-                !CheckForFragmentation(connection, availableSymbols, modulationType))
-            {
-                break;
-            }
-            else if (availableSymbols < nrSymbolsRequired &&
-                     CheckForFragmentation(connection, availableSymbols, modulationType))
-            {
-                uint32_t availableByte =
-                    GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-                packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-            }
-            else
-            {
-                packet = connection->Dequeue();
-            }
-
-            NS_ASSERT_MSG(hdr.GetCid() == connection->GetCid(),
-                          "Base station: Error while scheduling primary connection: header CID != "
-                          "connection CID");
-            burst->AddPacket(packet);
-            availableSymbols -= nrSymbolsRequired;
-        }
-        if (burst->GetNPackets() != 0)
-        {
-            AddDownlinkBurst(connection, diuc, modulationType, burst);
-        }
-    }
-}
-
-void
-BSSchedulerRtps::BSSchedulerUGSConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    Time currentTime = Simulator::Now();
-
-    ServiceFlowRecord* serviceFlowRecord;
-    std::vector<ServiceFlow*> serviceFlows;
-
-    serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_UGS);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        serviceFlowRecord = (*iter)->GetRecord();
-        // if latency would exceed in case grant is allocated in next frame then allocate in current
-        // frame
-        if ((*iter)->HasPackets() &&
-            ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
-             GetBs()->GetPhy()->GetFrameDuration()) > MilliSeconds((*iter)->GetMaximumLatency()))
-        {
-            connection = (*iter)->GetConnection();
-            if (connection->GetType() == Cid::MULTICAST)
-            {
-                modulationType = connection->GetServiceFlow()->GetModulation();
-            }
-            else
-            {
-                modulationType =
-                    GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
-            }
-            diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-
-            nrSymbolsRequired = connection->GetServiceFlow()->GetRecord()->GetGrantSize();
-
-            // Packet fragmentation for UGS connections has not been implemented yet!
-            if (availableSymbols > nrSymbolsRequired)
-            {
-                availableSymbols -= nrSymbolsRequired;
-                burst =
-                    CreateUgsBurst(connection->GetServiceFlow(), modulationType, nrSymbolsRequired);
-                if (burst->GetNPackets() != 0)
-                {
-                    AddDownlinkBurst(connection, diuc, modulationType, burst);
-                    currentTime = Simulator::Now();
-                    serviceFlowRecord->SetDlTimeStamp(currentTime);
-                    burst = Create<PacketBurst>();
-                }
-            }
-        }
-    }
-}
-
-void
-BSSchedulerRtps::BSSchedulerRTPSConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    Time currentTime = Simulator::Now();
-
-    std::vector<Ptr<WimaxConnection>> connections;
-    ServiceFlowRecord* serviceFlowRecord;
-    std::vector<ServiceFlow*> serviceFlows;
-
-    uint32_t symbolsRequired[100];
-    WimaxPhy::ModulationType modulationType_[100];
-    uint8_t diuc_[100];
-    Ptr<WimaxConnection> rtPSConnection[100];
-    uint32_t dataToSend;
-    uint32_t totSymbolsRequired = 0;
-    int nbConnection = 0;
-
-    NS_LOG_INFO("\tDL Scheduler for rtPS flows \n"
-                << "\t\tavailableSymbols = " << availableSymbols);
-
-    serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_RTPS);
-    nbConnection = 0;
-    for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-    {
-        // DL RTPS Scheduler works for all rtPS connection that have packets to transmitt!!!
-        serviceFlowRecord = (*iter2)->GetRecord();
-
-        if ((*iter2)->HasPackets())
-        {
-            currentTime = Simulator::Now();
-            serviceFlowRecord->SetDlTimeStamp(currentTime);
-            rtPSConnection[nbConnection] = (*iter2)->GetConnection();
-            if (rtPSConnection[nbConnection]->GetType() == Cid::MULTICAST)
-            {
-                modulationType_[nbConnection] =
-                    rtPSConnection[nbConnection]->GetServiceFlow()->GetModulation();
-            }
-            else
-            {
-                modulationType_[nbConnection] =
-                    GetBs()
-                        ->GetSSManager()
-                        ->GetSSRecord(rtPSConnection[nbConnection]->GetCid())
-                        ->GetModulationType();
-            }
-            diuc_[nbConnection] = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType_[nbConnection],
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-
-            dataToSend = rtPSConnection[nbConnection]->GetQueue()->GetQueueLengthWithMACOverhead();
-            NS_LOG_INFO("\t\tRTPS DL Scheduler for CID = " << rtPSConnection[nbConnection]->GetCid()
-                                                           << "\n\t\t\t dataToSend = "
-                                                           << dataToSend);
-
-            symbolsRequired[nbConnection] =
-                GetBs()->GetPhy()->GetNrSymbols(dataToSend, modulationType_[nbConnection]);
-
-            totSymbolsRequired += symbolsRequired[nbConnection];
-            nbConnection++;
-        }
-    }
-
-    NS_LOG_INFO("\t\ttotSymbolsRequired = " << totSymbolsRequired);
-
-    // Channel Saturation
-    while (totSymbolsRequired > availableSymbols)
-    {
-        NS_LOG_INFO("\tDL Channel Saturation: totSymbolsRequired > availableSymbols_rtPS");
-        double delta = double(availableSymbols) / double(totSymbolsRequired);
-        NS_LOG_INFO("\t\tdelta = " << delta);
-        totSymbolsRequired = 0;
-        for (int i = 0; i < nbConnection; i++)
-        {
-            NS_LOG_INFO("\t\tprevious symbolsRequired[" << i << "] = " << symbolsRequired[i]);
-            symbolsRequired[i] = (uint32_t)std::floor(symbolsRequired[i] * delta);
-            totSymbolsRequired += symbolsRequired[i];
-            NS_LOG_INFO("\t\tnew symbolsRequired[" << i << "] = " << symbolsRequired[i]);
-        }
-        NS_LOG_INFO("\t\ttotSymbolsRequired = " << totSymbolsRequired);
-    }
-
-    // Downlink Bandwidth Allocation
-    for (int i = 0; i < nbConnection; i++)
-    {
-        packet = rtPSConnection[i]->GetQueue()->Peek(hdr);
-        uint32_t symbolsForPacketTransmission = 0;
-        burst = Create<PacketBurst>();
-        NS_LOG_INFO("\t\tCID = " << rtPSConnection[i]->GetCid()
-                                 << " assignedSymbols = " << symbolsRequired[i]);
-
-        while (symbolsRequired[i] > 0)
-        {
-            symbolsForPacketTransmission = GetBs()->GetPhy()->GetNrSymbols(
-                rtPSConnection[i]->GetQueue()->GetFirstPacketRequiredByte(
-                    MacHeaderType::HEADER_TYPE_GENERIC),
-                modulationType_[i]);
-
-            // PIRO: check for fragmentation
-            if (symbolsForPacketTransmission > symbolsRequired[i] &&
-                !CheckForFragmentation(rtPSConnection[i], symbolsRequired[i], modulationType_[i]))
-            {
-                break;
-            }
-            else if (symbolsForPacketTransmission > symbolsRequired[i] &&
-                     CheckForFragmentation(rtPSConnection[i],
-                                           symbolsRequired[i],
-                                           modulationType_[i]))
-            {
-                uint32_t availableByte =
-                    GetBs()->GetPhy()->GetNrBytes(symbolsRequired[i], modulationType_[i]);
-                packet =
-                    rtPSConnection[i]->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-                symbolsRequired[i] = 0;
-            }
-            else
-            {
-                packet = rtPSConnection[i]->Dequeue();
-                symbolsRequired[i] -= symbolsForPacketTransmission;
-            }
-
-            NS_ASSERT_MSG(hdr.GetCid() == rtPSConnection[i]->GetCid(),
-                          "Base station: Error while scheduling RTPs connection: header CID != "
-                          "connection CID");
-            burst->AddPacket(packet);
-        }
-
-        if (burst->GetNPackets() != 0)
-        {
-            AddDownlinkBurst(rtPSConnection[i], diuc_[i], modulationType_[i], burst);
-        }
-    }
-
-    availableSymbols -= totSymbolsRequired;
-}
-
-void
-BSSchedulerRtps::BSSchedulerNRTPSConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = 0;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    std::vector<ServiceFlow*> serviceFlows;
-
-    serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_NRTPS);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        connection = (*iter)->GetConnection();
-
-        while ((*iter)->HasPackets() && availableSymbols > 0)
-        {
-            if (connection->GetType() == Cid::MULTICAST)
-            {
-                modulationType = connection->GetServiceFlow()->GetModulation();
-            }
-            else
-            {
-                modulationType =
-                    GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
-            }
-
-            diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-
-            packet = connection->GetQueue()->Peek(hdr);
-            nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-
-            if (availableSymbols < nrSymbolsRequired)
-            {
-                break;
-            }
-
-            packet = connection->Dequeue();
-            NS_ASSERT_MSG(hdr.GetCid() == connection->GetCid(),
-                          "Base station: Error while scheduling NRTPs connection: header CID != "
-                          "connection CID");
-            burst->AddPacket(packet);
-            availableSymbols -= nrSymbolsRequired;
-        }
-        if (burst->GetNPackets() != 0)
-        {
-            AddDownlinkBurst(connection, diuc, modulationType, burst);
-            burst = Create<PacketBurst>();
-        }
-    }
-}
-
-void
-BSSchedulerRtps::BSSchedulerBEConnection(uint32_t& availableSymbols)
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = 0;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    std::vector<ServiceFlow*> serviceFlows;
-
-    serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_BE);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        connection = (*iter)->GetConnection();
-
-        while ((*iter)->HasPackets() && availableSymbols > 0)
-        {
-            if (connection->GetType() == Cid::MULTICAST)
-            {
-                modulationType = connection->GetServiceFlow()->GetModulation();
-            }
-            else
-            {
-                modulationType =
-                    GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
-            }
-            diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-
-            packet = connection->GetQueue()->Peek(hdr);
-            nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-
-            if (availableSymbols < nrSymbolsRequired)
-            {
-                break;
-            }
-
-            packet = connection->Dequeue();
-            NS_ASSERT_MSG(
-                hdr.GetCid() == connection->GetCid(),
-                "Base station: Error while scheduling BE connection: header CID != connection CID");
-            burst->AddPacket(packet);
-            availableSymbols -= nrSymbolsRequired;
-        }
-        if (burst->GetNPackets() != 0)
-        {
-            AddDownlinkBurst(connection, diuc, modulationType, burst);
-            burst = Create<PacketBurst>();
-        }
-    }
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-scheduler-rtps.h ns-3.46/src/wimax/model/bs-scheduler-rtps.h
--- ns-3.45/src/wimax/model/bs-scheduler-rtps.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-scheduler-rtps.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *               2009 TELEMATICS LAB, Politecnico di Bari
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Giuseppe Piro <g.piro@poliba.it>
- */
-
-/* BS outbound scheduler as per in Section 6.3.5.1 */
-
-#ifndef BS_SCHEDULER_RTPS_H
-#define BS_SCHEDULER_RTPS_H
-
-#include "bs-scheduler.h"
-#include "dl-mac-messages.h"
-#include "wimax-phy.h"
-
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-
-#include <list>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class GenericMacHeader;
-class WimaxConnection;
-class Cid;
-
-/**
- * @ingroup wimax
- * @brief This class implements a simple downlink scheduler for rtPS flows.
- *
- * The DL-rtPS-Scheduler assigns the available bandwidth the service flows
- * in the following order: IR Connections, Broadcast Connections, Basic and
- * Primary Connections, UGS Connections, rtPS Connections, nrtPS Connections,
- * BE Connections.
- * The IR, Broadcast and Basic/Primary Connections must transmit
- * all packet in the queue. The UGS flows can transmit the quota of date equal to
- * the "Grant Size" (that is one of service flows QoS parameters) according to their
- * requested MaxLatency (another QoS parameter).
- * All rtPS flows are able to transmit all packet in the queue according to the available
- * bandwidth. The bandwidth saturation control has been implemented to redistribute
- *the effective available bandwidth to all rtPS flows that have at least one packet
- * to transmit. The remaining bandwidth is allocated to rntPS and BE Connections.
- */
-class BSSchedulerRtps : public BSScheduler
-{
-  public:
-    BSSchedulerRtps();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    BSSchedulerRtps(Ptr<BaseStationNetDevice> bs);
-    ~BSSchedulerRtps() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief This function returns all the downlink bursts scheduled for the next
-     * downlink sub-frame
-     * @returns  all the downlink bursts scheduled for the next downlink sub-frame
-     */
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* GetDownlinkBursts() const override;
-
-    /**
-     * @brief This function adds a downlink burst to the list of downlink bursts
-     * scheduled for the next downlink sub-frame
-     * @param connection a pointer to connection in which the burst will be sent
-     * @param diuc downlink iuc
-     * @param modulationType the modulation type of the burst
-     * @param burst the downlink burst to add to the downlink sub frame
-     */
-    void AddDownlinkBurst(Ptr<const WimaxConnection> connection,
-                          uint8_t diuc,
-                          WimaxPhy::ModulationType modulationType,
-                          Ptr<PacketBurst> burst) override;
-    /**
-     * @brief Schedule function.
-     */
-    void Schedule() override;
-    /**
-     * @brief Check for IR and Broadcast connections that have packets to transmit.
-     * @param connection will point to a initial ranging or broadcast connection
-     * which have packets to transmit
-     * @returns false if no initial ranging or broadcast connection has packets
-     * to transmit, true otherwise
-     */
-    bool SelectIRandBCConnection(Ptr<WimaxConnection>& connection);
-    /**
-     * @brief Check for Basic and Primary connections that have packets to transmit.
-     * @param connection will point to a basic or primary connection
-     * which have packets to transmit
-     * @returns false if no basic or primary connection has packets
-     * to transmit, true otherwise
-     */
-    bool SelectMenagementConnection(Ptr<WimaxConnection>& connection);
-    /**
-     * @brief Check for UGS connections that have packets to transmit.
-     *
-     * The method return the UGS connection that have packets to transmits,
-     * according to the MaxLatency specifications.
-     * @param connection will point to a connection that has packets to be sent
-     * @return true if successful
-     */
-    bool SelectUGSConnection(Ptr<WimaxConnection>& connection);
-    /**
-     * @brief Check for rtPS connections that have packets to transmit.
-     * @param connection will point to a connection that has packets to be sent
-     * @returns false if no connection has packets to be sent, true otherwise
-     */
-    bool SelectRTPSConnection(Ptr<WimaxConnection>& connection);
-    /**
-     * @brief Check for nrtPS connections that have packets to transmit.
-     * @param connection will point to a connection that has packets to be sent
-     * @returns false if no connection has packets to be sent, true otherwise
-     */
-    bool SelectNRTPSConnection(Ptr<WimaxConnection>& connection);
-    /**
-     * @brief Check for BE connections that have packets to transmit.
-     * @param connection will point to a connection that has packets to be sent
-     * @returns false if no connection has packets to be sent, true otherwise
-     */
-    bool SelectBEConnection(Ptr<WimaxConnection>& connection);
-
-    /**
-     * @brief Selects a connection from the list of connections having packets to be sent .
-     * @param connection will point to a connection that has packets to be sent
-     * @returns false if no connection has packets to be sent, true otherwise
-     */
-    bool SelectConnection(Ptr<WimaxConnection>& connection) override;
-
-    /**
-     * @brief schedules the broadcast connections
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerBroadcastConnection(uint32_t& availableSymbols);
-
-    /**
-     * @brief schedules the IR connections
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerInitialRangingConnection(uint32_t& availableSymbols);
-
-    /**
-     * @brief schedules the basic connections
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerBasicConnection(uint32_t& availableSymbols);
-
-    /**
-     * @brief schedules the primary connection
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerPrimaryConnection(uint32_t& availableSymbols);
-    /**
-     * @brief schedules the UGS connection
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerUGSConnection(uint32_t& availableSymbols);
-    /**
-     * @brief Downlink Scheduler for rtPS connections.
-     *
-     * @param availableSymbols available symbols for rtPS flows
-     *
-     * This method represent the DL Scheduler for rtPS  connections.
-     * The scheduler is designed to serve all rtPS connections that
-     * have at least one packet to transmit, every DL Subframe.
-     * To each rtPS connections are allocated,  at the beginning,
-     * the bandwidth to transmit a quota of data equal to the
-     * queue length.
-     * If the sum of all pre-allocated bandwidth exceed the available
-     * symbols for rtPS connections, the Channel Saturation Control function
-     * is called to redistribute the available bandwidth.
-     */
-    void BSSchedulerRTPSConnection(uint32_t& availableSymbols);
-
-    /**
-     * @brief schedules the NRTPS connections
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerNRTPSConnection(uint32_t& availableSymbols);
-
-    /**
-     * @brief schedules the BE connection
-     * @param availableSymbols the remaining free OFDM symbols in the current subframe
-     */
-    void BSSchedulerBEConnection(uint32_t& availableSymbols);
-
-    /**
-     * @brief Creates a downlink UGS burst
-     * @param serviceFlow the service flow of the burst
-     * @param modulationType the modulation type to be used for the burst
-     * @param availableSymbols maximum number of OFDM symbols to be used by the burst
-     * @returns a Burst (list of packets)
-     */
-    Ptr<PacketBurst> CreateUgsBurst(ServiceFlow* serviceFlow,
-                                    WimaxPhy::ModulationType modulationType,
-                                    uint32_t availableSymbols) override;
-
-  private:
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* m_downlinkBursts; ///< down link bursts
-};
-
-} // namespace ns3
-
-#endif /* BS_SCHEDULER_RTPS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-scheduler-simple.cc ns-3.46/src/wimax/model/bs-scheduler-simple.cc
--- ns-3.45/src/wimax/model/bs-scheduler-simple.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-scheduler-simple.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,388 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "bs-scheduler-simple.h"
-
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-#include "wimax-connection.h"
-#include "wimax-mac-header.h"
-#include "wimax-mac-queue.h"
-
-#include "ns3/log.h"
-#include "ns3/packet-burst.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BSSchedulerSimple");
-
-NS_OBJECT_ENSURE_REGISTERED(BSSchedulerSimple);
-
-TypeId
-BSSchedulerSimple::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::BSSchedulerSimple")
-                            .SetParent<BSScheduler>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<BSSchedulerSimple>();
-    return tid;
-}
-
-BSSchedulerSimple::BSSchedulerSimple()
-    : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
-{
-    SetBs(nullptr);
-}
-
-BSSchedulerSimple::BSSchedulerSimple(Ptr<BaseStationNetDevice> bs)
-    : m_downlinkBursts(new std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>())
-{
-    // m_downlinkBursts is filled by AddDownlinkBurst and emptied by
-    // wimax-bs-net-device::sendBurst and wimax-ss-net-device::sendBurst
-    SetBs(bs);
-}
-
-BSSchedulerSimple::~BSSchedulerSimple()
-{
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* downlinkBursts = m_downlinkBursts;
-    std::pair<OfdmDlMapIe*, Ptr<PacketBurst>> pair;
-    while (!downlinkBursts->empty())
-    {
-        pair = downlinkBursts->front();
-        pair.second = nullptr;
-        delete pair.first;
-    }
-    SetBs(nullptr);
-    delete m_downlinkBursts;
-    m_downlinkBursts = nullptr;
-}
-
-std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>*
-BSSchedulerSimple::GetDownlinkBursts() const
-{
-    return m_downlinkBursts;
-}
-
-void
-BSSchedulerSimple::AddDownlinkBurst(Ptr<const WimaxConnection> connection,
-                                    uint8_t diuc,
-                                    WimaxPhy::ModulationType modulationType,
-                                    Ptr<PacketBurst> burst)
-{
-    auto dlMapIe = new OfdmDlMapIe();
-    dlMapIe->SetCid(connection->GetCid());
-    dlMapIe->SetDiuc(diuc);
-
-    NS_LOG_INFO("BS scheduler, burst size: " << burst->GetSize() << " bytes"
-                                             << ", pkts: " << burst->GetNPackets()
-                                             << ", connection: " << connection->GetTypeStr()
-                                             << ", CID: " << connection->GetCid());
-    if (connection->GetType() == Cid::TRANSPORT)
-    {
-        NS_LOG_INFO(", SFID: " << connection->GetServiceFlow()->GetSfid() << ", service: "
-                               << connection->GetServiceFlow()->GetSchedulingTypeStr());
-    }
-    NS_LOG_INFO(", modulation: " << modulationType << ", DIUC: " << (uint32_t)diuc);
-
-    m_downlinkBursts->emplace_back(dlMapIe, burst);
-}
-
-void
-BSSchedulerSimple::Schedule()
-{
-    Ptr<WimaxConnection> connection;
-    WimaxPhy::ModulationType modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    uint8_t diuc = OfdmDlBurstProfile::DIUC_BURST_PROFILE_1;
-    uint32_t nrSymbolsRequired = 0;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst;
-    ServiceFlow::SchedulingType schedulingType = ServiceFlow::SF_TYPE_NONE;
-    uint32_t availableSymbols = GetBs()->GetNrDlSymbols();
-
-    while (SelectConnection(connection))
-    {
-        if (connection != GetBs()->GetInitialRangingConnection() &&
-            connection != GetBs()->GetBroadcastConnection())
-        {
-            /* determines modulation/DIUC only once per burst as it is always same for a particular
-             * CID */
-            if (connection->GetType() == Cid::MULTICAST)
-            {
-                modulationType = connection->GetServiceFlow()->GetModulation();
-            }
-            else
-            {
-                modulationType =
-                    GetBs()->GetSSManager()->GetSSRecord(connection->GetCid())->GetModulationType();
-            }
-            diuc = GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_DOWNLINK);
-        }
-        else if (connection == GetBs()->GetInitialRangingConnection() ||
-                 connection == GetBs()->GetBroadcastConnection())
-        {
-            modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-            diuc = OfdmDlBurstProfile::DIUC_BURST_PROFILE_1;
-        }
-
-        if (connection->GetType() == Cid::TRANSPORT || connection->GetType() == Cid::MULTICAST)
-        {
-            schedulingType = (ServiceFlow::SchedulingType)connection->GetSchedulingType();
-        }
-
-        if (schedulingType == ServiceFlow::SF_TYPE_UGS)
-        {
-            nrSymbolsRequired = connection->GetServiceFlow()->GetRecord()->GetGrantSize();
-            if (nrSymbolsRequired < availableSymbols)
-            {
-                burst =
-                    CreateUgsBurst(connection->GetServiceFlow(), modulationType, nrSymbolsRequired);
-            }
-            else
-            {
-                burst =
-                    CreateUgsBurst(connection->GetServiceFlow(), modulationType, availableSymbols);
-            }
-            if (burst->GetNPackets() != 0)
-            {
-                uint32_t BurstSizeSymbols =
-                    GetBs()->GetPhy()->GetNrSymbols(burst->GetSize(), modulationType);
-                AddDownlinkBurst(connection, diuc, modulationType, burst);
-
-                if (availableSymbols <= BurstSizeSymbols)
-                {
-                    availableSymbols -=
-                        BurstSizeSymbols; /// \todo Overflows but don't know how to fix
-                    break;
-                }
-            }
-        }
-        else
-        {
-            burst = Create<PacketBurst>();
-            while (connection->HasPackets())
-            {
-                uint32_t FirstPacketSize = connection->GetQueue()->GetFirstPacketRequiredByte(
-                    MacHeaderType::HEADER_TYPE_GENERIC);
-                nrSymbolsRequired =
-                    GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
-                if (availableSymbols < nrSymbolsRequired &&
-                    CheckForFragmentation(connection, availableSymbols, modulationType))
-                {
-                    uint32_t availableByte =
-                        GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-                    packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-                    availableSymbols = 0;
-                }
-                else if (availableSymbols >= nrSymbolsRequired)
-                {
-                    packet = connection->Dequeue();
-                    availableSymbols -= nrSymbolsRequired;
-                }
-                else
-                {
-                    break;
-                }
-                burst->AddPacket(packet);
-            }
-            AddDownlinkBurst(connection, diuc, modulationType, burst);
-        }
-        if (availableSymbols == 0)
-        {
-            break;
-        }
-    }
-
-    if (!m_downlinkBursts->empty())
-    {
-        NS_LOG_DEBUG(
-            "BS scheduler, number of bursts: "
-            << m_downlinkBursts->size() << ", symbols left: " << availableSymbols << std::endl
-            << "BS scheduler, queues:"
-            << " IR " << GetBs()->GetInitialRangingConnection()->GetQueue()->GetSize()
-            << " broadcast " << GetBs()->GetBroadcastConnection()->GetQueue()->GetSize()
-            << " basic "
-            << GetBs()->GetConnectionManager()->GetNPackets(Cid::BASIC, ServiceFlow::SF_TYPE_NONE)
-            << " primary "
-            << GetBs()->GetConnectionManager()->GetNPackets(Cid::PRIMARY, ServiceFlow::SF_TYPE_NONE)
-            << " transport "
-            << GetBs()->GetConnectionManager()->GetNPackets(Cid::TRANSPORT,
-                                                            ServiceFlow::SF_TYPE_ALL));
-    }
-}
-
-bool
-BSSchedulerSimple::SelectConnection(Ptr<WimaxConnection>& connection)
-{
-    connection = nullptr;
-    Time currentTime = Simulator::Now();
-    ServiceFlowRecord* serviceFlowRecord;
-    NS_LOG_INFO("BS Scheduler: Selecting connection...");
-    if (GetBs()->GetBroadcastConnection()->HasPackets())
-    {
-        NS_LOG_INFO("Return GetBroadcastConnection");
-        connection = GetBs()->GetBroadcastConnection();
-        return true;
-    }
-    else if (GetBs()->GetInitialRangingConnection()->HasPackets())
-    {
-        NS_LOG_INFO("Return GetInitialRangingConnection");
-        connection = GetBs()->GetInitialRangingConnection();
-        return true;
-    }
-    else
-    {
-        std::vector<Ptr<WimaxConnection>> connections;
-        std::vector<ServiceFlow*> serviceFlows;
-
-        connections = GetBs()->GetConnectionManager()->GetConnections(Cid::BASIC);
-        for (auto iter1 = connections.begin(); iter1 != connections.end(); ++iter1)
-        {
-            if ((*iter1)->HasPackets())
-            {
-                NS_LOG_INFO("Return Basic");
-                connection = *iter1;
-                return true;
-            }
-        }
-
-        connections = GetBs()->GetConnectionManager()->GetConnections(Cid::PRIMARY);
-        for (auto iter1 = connections.begin(); iter1 != connections.end(); ++iter1)
-        {
-            if ((*iter1)->HasPackets())
-            {
-                NS_LOG_INFO("Return Primary");
-                connection = *iter1;
-                return true;
-            }
-        }
-
-        serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_UGS);
-        for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-        {
-            serviceFlowRecord = (*iter2)->GetRecord();
-            NS_LOG_INFO("processing UGS: HAS PACKET="
-                        << (*iter2)->HasPackets() << "max Latency = "
-                        << MilliSeconds((*iter2)->GetMaximumLatency()) << "Delay = "
-                        << ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
-                            GetBs()->GetPhy()->GetFrameDuration()));
-            // if latency would exceed in case grant is allocated in next frame then allocate in
-            // current frame
-            if ((*iter2)->HasPackets() && ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
-                                           GetBs()->GetPhy()->GetFrameDuration()) >
-                                              MilliSeconds((*iter2)->GetMaximumLatency()))
-            {
-                serviceFlowRecord->SetDlTimeStamp(currentTime);
-                connection = (*iter2)->GetConnection();
-                NS_LOG_INFO("Return UGS SF: CID = " << (*iter2)->GetCid()
-                                                    << "SFID = " << (*iter2)->GetSfid());
-                return true;
-            }
-        }
-
-        serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_RTPS);
-        for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-        {
-            serviceFlowRecord = (*iter2)->GetRecord();
-            // if latency would exceed in case poll is allocated in next frame then allocate in
-            // current frame
-            if ((*iter2)->HasPackets() && ((currentTime - serviceFlowRecord->GetDlTimeStamp()) +
-                                           GetBs()->GetPhy()->GetFrameDuration()) >
-                                              MilliSeconds((*iter2)->GetMaximumLatency()))
-            {
-                serviceFlowRecord->SetDlTimeStamp(currentTime);
-                connection = (*iter2)->GetConnection();
-                NS_LOG_INFO("Return RTPS SF: CID = " << (*iter2)->GetCid()
-                                                     << "SFID = " << (*iter2)->GetSfid());
-                return true;
-            }
-        }
-
-        serviceFlows =
-            GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_NRTPS);
-        for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-        {
-            // unused: serviceFlowRecord = (*iter2)->GetRecord ();
-            if ((*iter2)->HasPackets())
-            {
-                NS_LOG_INFO("Return NRTPS SF: CID = " << (*iter2)->GetCid()
-                                                      << "SFID = " << (*iter2)->GetSfid());
-                connection = (*iter2)->GetConnection();
-                return true;
-            }
-        }
-
-        serviceFlows = GetBs()->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_BE);
-        for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-        {
-            // unused: serviceFlowRecord = (*iter2)->GetRecord ();
-            if ((*iter2)->HasPackets())
-            {
-                NS_LOG_INFO("Return BE SF: CID = " << (*iter2)->GetCid()
-                                                   << "SFID = " << (*iter2)->GetSfid());
-                connection = (*iter2)->GetConnection();
-                return true;
-            }
-        }
-    }
-    NS_LOG_INFO("NO connection is selected!");
-    return false;
-}
-
-Ptr<PacketBurst>
-BSSchedulerSimple::CreateUgsBurst(ServiceFlow* serviceFlow,
-                                  WimaxPhy::ModulationType modulationType,
-                                  uint32_t availableSymbols)
-{
-    Time timeStamp;
-    GenericMacHeader hdr;
-    Ptr<Packet> packet;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-    uint32_t nrSymbolsRequired = 0;
-
-    // serviceFlow->CleanUpQueue ();
-    Ptr<WimaxConnection> connection = serviceFlow->GetConnection();
-    while (serviceFlow->HasPackets())
-    {
-        uint32_t FirstPacketSize =
-            connection->GetQueue()->GetFirstPacketRequiredByte(MacHeaderType::HEADER_TYPE_GENERIC);
-        nrSymbolsRequired = GetBs()->GetPhy()->GetNrSymbols(FirstPacketSize, modulationType);
-        if (availableSymbols < nrSymbolsRequired &&
-            CheckForFragmentation(connection, availableSymbols, modulationType))
-        {
-            uint32_t availableByte =
-                GetBs()->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-            packet = connection->Dequeue(MacHeaderType::HEADER_TYPE_GENERIC, availableByte);
-            availableSymbols = 0;
-        }
-        else
-        {
-            packet = connection->Dequeue();
-            availableSymbols -= nrSymbolsRequired;
-        }
-        burst->AddPacket(packet);
-        if (availableSymbols <= 0)
-        {
-            break;
-        }
-    }
-    return burst;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-scheduler-simple.h ns-3.46/src/wimax/model/bs-scheduler-simple.h
--- ns-3.45/src/wimax/model/bs-scheduler-simple.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-scheduler-simple.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-/* BS outbound scheduler as per in Section 6.3.5.1 */
-
-#ifndef BS_SCHEDULER_SIMPLE_H
-#define BS_SCHEDULER_SIMPLE_H
-
-#include "bs-scheduler.h"
-#include "dl-mac-messages.h"
-#include "wimax-phy.h"
-
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-
-#include <list>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class GenericMacHeader;
-class WimaxConnection;
-class Cid;
-
-/**
- * @ingroup wimax
- *
- * BaseStation Scheduler - simplified
- */
-class BSSchedulerSimple : public BSScheduler
-{
-  public:
-    BSSchedulerSimple();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    BSSchedulerSimple(Ptr<BaseStationNetDevice> bs);
-    ~BSSchedulerSimple() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief This function returns all the downlink bursts scheduled for the next
-     * downlink sub-frame
-     * @returns  all the downlink bursts scheduled for the next downlink sub-frame
-     */
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* GetDownlinkBursts() const override;
-    /**
-     * @brief This function adds a downlink burst to the list of downlink bursts
-     * scheduled for the next downlink sub-frame
-     * @param connection a pointer to connection in which the burst will be sent
-     * @param diuc downlink iuc
-     * @param modulationType the modulation type of the burst
-     * @param burst the downlink burst to add to the downlink sub frame
-     */
-    void AddDownlinkBurst(Ptr<const WimaxConnection> connection,
-                          uint8_t diuc,
-                          WimaxPhy::ModulationType modulationType,
-                          Ptr<PacketBurst> burst) override;
-
-    /**
-     * @brief the scheduling function for the downlink subframe.
-     */
-    void Schedule() override;
-    /**
-     * @brief Selects a connection from the list of connections having packets to be sent .
-     * @param connection will point to a connection that have packets to be sent
-     * @returns false if no connection has packets to be sent, true otherwise
-     */
-    bool SelectConnection(Ptr<WimaxConnection>& connection) override;
-    /**
-     * @brief Creates a downlink UGS burst
-     * @param serviceFlow the service flow of the burst
-     * @param modulationType the modulation type to be used for the burst
-     * @param availableSymbols maximum number of OFDM symbols to be used by the burst
-     * @returns a Burst (list of packets)
-     */
-    Ptr<PacketBurst> CreateUgsBurst(ServiceFlow* serviceFlow,
-                                    WimaxPhy::ModulationType modulationType,
-                                    uint32_t availableSymbols) override;
-
-  private:
-    std::list<std::pair<OfdmDlMapIe*, Ptr<PacketBurst>>>* m_downlinkBursts; ///< down link bursts
-};
-
-} // namespace ns3
-
-#endif /* BS_SCHEDULER_SIMPLE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-service-flow-manager.cc ns-3.46/src/wimax/model/bs-service-flow-manager.cc
--- ns-3.45/src/wimax/model/bs-service-flow-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-service-flow-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,263 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#include "bs-net-device.h"
-#include "bs-uplink-scheduler.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-#include "ss-scheduler.h"
-#include "wimax-connection.h"
-
-#include "ns3/buffer.h"
-#include "ns3/enum.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BsServiceFlowManager");
-
-BsServiceFlowManager::BsServiceFlowManager(Ptr<BaseStationNetDevice> device)
-    : m_device(device),
-      m_sfidIndex(100),
-      m_maxDsaRspRetries(100) // default value
-{
-    m_inuseScheduleDsaRspCid = Cid::InitialRanging();
-}
-
-BsServiceFlowManager::~BsServiceFlowManager()
-{
-}
-
-/* static */
-TypeId
-BsServiceFlowManager::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::BsServiceFlowManager").SetParent<ServiceFlowManager>().SetGroupName("Wifi")
-        // No AddConstructor because this class has no default constructor.
-        ;
-    return tid;
-}
-
-void
-BsServiceFlowManager::DoDispose()
-{
-    ServiceFlowManager::DoDispose();
-}
-
-void
-BsServiceFlowManager::SetMaxDsaRspRetries(uint8_t maxDsaRspRetries)
-{
-    m_maxDsaRspRetries = maxDsaRspRetries;
-}
-
-uint8_t
-BsServiceFlowManager::GetMaxDsaRspRetries() const
-{
-    return m_maxDsaRspRetries;
-}
-
-EventId
-BsServiceFlowManager::GetDsaAckTimeoutEvent() const
-{
-    return m_dsaAckTimeoutEvent;
-}
-
-void
-BsServiceFlowManager::AddServiceFlow(ServiceFlow* serviceFlow)
-{
-    ServiceFlowManager::AddServiceFlow(serviceFlow);
-}
-
-ServiceFlow*
-BsServiceFlowManager::GetServiceFlow(uint32_t sfid) const
-{
-    return ServiceFlowManager::GetServiceFlow(sfid);
-}
-
-ServiceFlow*
-BsServiceFlowManager::GetServiceFlow(Cid cid) const
-{
-    return ServiceFlowManager::GetServiceFlow(cid);
-}
-
-std::vector<ServiceFlow*>
-BsServiceFlowManager::GetServiceFlows(ServiceFlow::SchedulingType schedulingType) const
-{
-    return ServiceFlowManager::GetServiceFlows(schedulingType);
-}
-
-DsaRsp
-BsServiceFlowManager::CreateDsaRsp(const ServiceFlow* serviceFlow, uint16_t transactionId)
-{
-    DsaRsp dsaRsp;
-    dsaRsp.SetTransactionId(transactionId);
-    dsaRsp.SetServiceFlow(*serviceFlow);
-    // assuming SS can supports all of the service flow parameters
-    dsaRsp.SetConfirmationCode(CONFIRMATION_CODE_SUCCESS);
-
-    return dsaRsp;
-}
-
-void
-BsServiceFlowManager::ScheduleDsaRsp(ServiceFlow* serviceFlow, Cid cid)
-{
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-
-    SSRecord* ssRecord = bs->GetSSManager()->GetSSRecord(cid);
-    if (ssRecord == nullptr)
-    {
-        NS_LOG_INFO("SS not registered with the BS CID:" << cid);
-        return;
-    }
-
-    serviceFlow->SetIsEnabled(true);
-    serviceFlow->SetType(ServiceFlow::SF_TYPE_ACTIVE);
-    ssRecord->AddServiceFlow(serviceFlow);
-
-    bs->GetUplinkScheduler()->SetupServiceFlow(ssRecord, serviceFlow);
-
-    Ptr<Packet> p = Create<Packet>();
-    DsaRsp dsaRsp;
-
-    if (ssRecord->GetDsaRspRetries() == 0)
-    {
-        dsaRsp = CreateDsaRsp(serviceFlow, ssRecord->GetSfTransactionId());
-        p->AddHeader(dsaRsp);
-        ssRecord->SetDsaRsp(dsaRsp);
-    }
-    else
-    {
-        if (ssRecord->GetDsaRspRetries() < m_maxDsaRspRetries)
-        {
-            p->AddHeader(ssRecord->GetDsaRsp());
-        }
-        else
-        {
-            NS_LOG_DEBUG("Service flows could not be initialized!");
-        }
-    }
-
-    ssRecord->IncrementDsaRspRetries();
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_DSA_RSP));
-
-    if (m_dsaAckTimeoutEvent.IsPending())
-    {
-        Simulator::Cancel(m_dsaAckTimeoutEvent);
-    }
-
-    m_inuseScheduleDsaRspCid = cid;
-
-    m_dsaAckTimeoutEvent = Simulator::Schedule(bs->GetIntervalT8(),
-                                               &BsServiceFlowManager::ScheduleDsaRsp,
-                                               this,
-                                               serviceFlow,
-                                               cid);
-    m_device->Enqueue(p, MacHeaderType(), bs->GetConnection(ssRecord->GetPrimaryCid()));
-}
-
-ServiceFlow*
-BsServiceFlowManager::ProcessDsaReq(const DsaReq& dsaReq, Cid cid)
-{
-    ServiceFlow* serviceFlow;
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-    SSRecord* ssRecord = bs->GetSSManager()->GetSSRecord(cid);
-
-    NS_LOG_INFO("BsServiceFlowManager: Processing DSA-REQ...");
-    if (ssRecord->GetSfTransactionId() != 0)
-    {
-        // had already received DSA-REQ. DSA-RSP was lost
-        NS_ASSERT_MSG(
-            dsaReq.GetTransactionId() == ssRecord->GetSfTransactionId(),
-            "Error while processing DSA request:the received transaction ID is not expected");
-        serviceFlow = GetServiceFlow(ssRecord->GetDsaRsp().GetSfid());
-    }
-    else
-    {
-        ServiceFlow sf = dsaReq.GetServiceFlow();
-        Ptr<WimaxConnection> transportConnection;
-        Ptr<ConnectionManager> BsConManager = bs->GetConnectionManager();
-        transportConnection = BsConManager->CreateConnection(Cid::TRANSPORT);
-        serviceFlow = new ServiceFlow(m_sfidIndex++, sf.GetDirection(), transportConnection);
-        transportConnection->SetServiceFlow(serviceFlow);
-        serviceFlow->CopyParametersFrom(sf);
-        serviceFlow->SetUnsolicitedGrantInterval(1);
-        serviceFlow->SetUnsolicitedPollingInterval(1);
-        serviceFlow->SetConvergenceSublayerParam(sf.GetConvergenceSublayerParam());
-        AddServiceFlow(serviceFlow);
-        ssRecord->SetSfTransactionId(dsaReq.GetTransactionId());
-        NS_LOG_INFO("BsServiceFlowManager: Creating a new Service flow: SFID = "
-                    << serviceFlow->GetSfid() << " CID = " << serviceFlow->GetCid());
-    }
-    return serviceFlow;
-}
-
-void
-BsServiceFlowManager::AddMulticastServiceFlow(ServiceFlow sf, WimaxPhy::ModulationType modulation)
-{
-    auto serviceFlow = new ServiceFlow();
-    serviceFlow->CopyParametersFrom(sf);
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-    Ptr<WimaxConnection> multicastConnection =
-        bs->GetConnectionManager()->CreateConnection(Cid::MULTICAST);
-    serviceFlow->SetConnection(multicastConnection);
-    AddServiceFlow(serviceFlow);
-    serviceFlow->SetIsEnabled(true);
-    serviceFlow->SetType(ServiceFlow::SF_TYPE_ACTIVE);
-    serviceFlow->SetIsMulticast(true);
-    serviceFlow->SetModulation(modulation);
-    bs->GetUplinkScheduler()->SetupServiceFlow(nullptr, serviceFlow);
-}
-
-void
-BsServiceFlowManager::AllocateServiceFlows(const DsaReq& dsaReq, Cid cid)
-{
-    ServiceFlow* serviceFlow = ProcessDsaReq(dsaReq, cid);
-    if (serviceFlow)
-    {
-        ScheduleDsaRsp(serviceFlow, cid);
-    }
-    else
-    {
-        NS_LOG_INFO("No service Flow. Could not connect.");
-    }
-}
-
-void
-BsServiceFlowManager::ProcessDsaAck(const DsaAck& dsaAck, Cid cid)
-{
-    Ptr<BaseStationNetDevice> bs = m_device->GetObject<BaseStationNetDevice>();
-    SSRecord* ssRecord = bs->GetSSManager()->GetSSRecord(cid);
-
-    if (dsaAck.GetTransactionId() != ssRecord->GetSfTransactionId())
-    {
-        return;
-    }
-
-    ssRecord->SetDsaRspRetries(0);
-    ssRecord->SetSfTransactionId(0);
-
-    // check if all service flow have been initiated
-    if (AreServiceFlowsAllocated(ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_ALL)))
-    {
-        ssRecord->SetAreServiceFlowsAllocated(true);
-    }
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-service-flow-manager.h ns-3.46/src/wimax/model/bs-service-flow-manager.h
--- ns-3.45/src/wimax/model/bs-service-flow-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-service-flow-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef BS_SERVICE_FLOW_MANAGER_H
-#define BS_SERVICE_FLOW_MANAGER_H
-
-#include "bs-net-device.h"
-#include "mac-messages.h"
-#include "service-flow-manager.h"
-
-#include "ns3/buffer.h"
-#include "ns3/event-id.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class Packet;
-class ServiceFlow;
-class WimaxNetDevice;
-class SSRecord;
-class WimaxConnection;
-class BaseStationNetDevice;
-
-/**
- * @ingroup wimax
- * @brief BsServiceFlowManager
- */
-class BsServiceFlowManager : public ServiceFlowManager
-{
-  public:
-    /// Confirmation code enumeration
-    enum ConfirmationCode // as per Table 384 (not all codes implemented)
-    {
-        CONFIRMATION_CODE_SUCCESS,
-        CONFIRMATION_CODE_REJECT
-    };
-
-    /**
-     * Constructor
-     *
-     * @param device base station device
-     */
-    BsServiceFlowManager(Ptr<BaseStationNetDevice> device);
-    ~BsServiceFlowManager() override;
-    void DoDispose() override;
-    /**
-     * Register this type.
-     * @return The TypeId.
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief Add a new service flow
-     * @param serviceFlow the service flow to add
-     */
-    void AddServiceFlow(ServiceFlow* serviceFlow);
-    /**
-     * @param sfid the service flow identifier
-     * @return the service flow which has as identifier sfid
-     */
-    ServiceFlow* GetServiceFlow(uint32_t sfid) const;
-    /**
-     * @param cid the connection identifier
-     * @return the service flow which has as connection identifier cid
-     */
-    ServiceFlow* GetServiceFlow(Cid cid) const;
-    /**
-     * @param schedulingType the scheduling type
-     * @return the list of service flows configured with schedulingType as a QoS class
-     */
-    std::vector<ServiceFlow*> GetServiceFlows(ServiceFlow::SchedulingType schedulingType) const;
-    /**
-     * @brief set the maximum Dynamic ServiceFlow Add (DSA) retries
-     * @param maxDsaRspRetries the maximum DSA response retries
-     */
-    void SetMaxDsaRspRetries(uint8_t maxDsaRspRetries);
-
-    /**
-     * @return the DSA ack timeout event
-     */
-    EventId GetDsaAckTimeoutEvent() const;
-    /**
-     * @brief allocate service flows
-     * @param dsaReq the DSA request
-     * @param cid the connection identifier
-     */
-    void AllocateServiceFlows(const DsaReq& dsaReq, Cid cid);
-    /**
-     * @brief add a multicast service flow
-     * @param sf the service flow
-     * @param modulation the wimax phy modulation type
-     */
-    void AddMulticastServiceFlow(ServiceFlow sf, WimaxPhy::ModulationType modulation);
-    /**
-     * @brief process a DSA-ACK message
-     * @param dsaAck the message to process
-     * @param cid the identifier of the connection on which the message was received
-     */
-    void ProcessDsaAck(const DsaAck& dsaAck, Cid cid);
-
-    /**
-     * @brief process a DSA-Req message
-     * @param dsaReq the message to process
-     * @param cid the identifier of the connection on which the message was received
-     * @return a pointer to the service flow
-     */
-    ServiceFlow* ProcessDsaReq(const DsaReq& dsaReq, Cid cid);
-
-  private:
-    /**
-     * Create DSA response function
-     * @param serviceFlow service flow
-     * @param transactionId transaction ID
-     * @return the DSA response
-     */
-    DsaRsp CreateDsaRsp(const ServiceFlow* serviceFlow, uint16_t transactionId);
-    /**
-     * @return the maximum DSA response retries
-     */
-    uint8_t GetMaxDsaRspRetries() const;
-    /**
-     * Create DSA response function
-     * @param serviceFlow service flow
-     * @param cid the identifier of the connection on which the message was received
-     */
-    void ScheduleDsaRsp(ServiceFlow* serviceFlow, Cid cid);
-    Ptr<WimaxNetDevice> m_device; ///< the device
-    uint32_t m_sfidIndex;         ///< SFID index
-    uint8_t m_maxDsaRspRetries;   ///< maximum number of DSA response retries
-    EventId m_dsaAckTimeoutEvent; ///< DSA ack timeout event
-    Cid m_inuseScheduleDsaRspCid; ///< in use schedule DSA response CID
-};
-
-} // namespace ns3
-
-#endif /* BS_SERVICE_FLOW_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler.cc ns-3.46/src/wimax/model/bs-uplink-scheduler.cc
--- ns-3.45/src/wimax/model/bs-uplink-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "bs-uplink-scheduler.h"
-
-#include "bandwidth-manager.h"
-#include "bs-link-manager.h"
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("UplinkScheduler");
-
-NS_OBJECT_ENSURE_REGISTERED(UplinkScheduler);
-
-UplinkScheduler::UplinkScheduler()
-    : m_bs(nullptr),
-      m_timeStampIrInterval(),
-      m_nrIrOppsAllocated(0),
-      m_isIrIntrvlAllocated(false),
-      m_isInvIrIntrvlAllocated(false),
-      m_dcdTimeStamp(Simulator::Now()),
-      m_ucdTimeStamp(Simulator::Now())
-{
-}
-
-UplinkScheduler::UplinkScheduler(Ptr<BaseStationNetDevice> bs)
-    : m_bs(bs),
-      m_timeStampIrInterval(),
-      m_nrIrOppsAllocated(0),
-      m_isIrIntrvlAllocated(false),
-      m_isInvIrIntrvlAllocated(false),
-      m_dcdTimeStamp(Simulator::Now()),
-      m_ucdTimeStamp(Simulator::Now())
-{
-}
-
-UplinkScheduler::~UplinkScheduler()
-{
-    m_bs = nullptr;
-    m_uplinkAllocations.clear();
-}
-
-void
-UplinkScheduler::InitOnce()
-{
-}
-
-TypeId
-UplinkScheduler::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::UplinkScheduler").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-uint8_t
-UplinkScheduler::GetNrIrOppsAllocated() const
-{
-    return m_nrIrOppsAllocated;
-}
-
-void
-UplinkScheduler::SetNrIrOppsAllocated(uint8_t nrIrOppsAllocated)
-{
-    m_nrIrOppsAllocated = nrIrOppsAllocated;
-}
-
-bool
-UplinkScheduler::GetIsIrIntrvlAllocated() const
-{
-    return m_isIrIntrvlAllocated;
-}
-
-void
-UplinkScheduler::SetIsIrIntrvlAllocated(bool isIrIntrvlAllocated)
-{
-    m_isIrIntrvlAllocated = isIrIntrvlAllocated;
-}
-
-bool
-UplinkScheduler::GetIsInvIrIntrvlAllocated() const
-{
-    return m_isInvIrIntrvlAllocated;
-}
-
-void
-UplinkScheduler::SetIsInvIrIntrvlAllocated(bool isInvIrIntrvlAllocated)
-{
-    m_isInvIrIntrvlAllocated = isInvIrIntrvlAllocated;
-}
-
-Time
-UplinkScheduler::GetDcdTimeStamp() const
-{
-    return m_dcdTimeStamp;
-}
-
-void
-UplinkScheduler::SetDcdTimeStamp(Time dcdTimeStamp)
-{
-    m_dcdTimeStamp = dcdTimeStamp;
-}
-
-Time
-UplinkScheduler::GetUcdTimeStamp() const
-{
-    return m_ucdTimeStamp;
-}
-
-void
-UplinkScheduler::SetUcdTimeStamp(Time ucdTimeStamp)
-{
-    m_ucdTimeStamp = ucdTimeStamp;
-}
-
-std::list<OfdmUlMapIe>
-UplinkScheduler::GetUplinkAllocations() const
-{
-    return m_uplinkAllocations;
-}
-
-Time
-UplinkScheduler::GetTimeStampIrInterval()
-{
-    return m_timeStampIrInterval;
-}
-
-void
-UplinkScheduler::SetTimeStampIrInterval(Time timeStampIrInterval)
-{
-    m_timeStampIrInterval = timeStampIrInterval;
-}
-
-Ptr<BaseStationNetDevice>
-UplinkScheduler::GetBs()
-{
-    return m_bs;
-}
-
-void
-UplinkScheduler::SetBs(Ptr<BaseStationNetDevice> bs)
-{
-    m_bs = bs;
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler.h ns-3.46/src/wimax/model/bs-uplink-scheduler.h
--- ns-3.45/src/wimax/model/bs-uplink-scheduler.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef UPLINK_SCHEDULER_H
-#define UPLINK_SCHEDULER_H
-
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ul-mac-messages.h"
-#include "wimax-phy.h"
-
-#include "ns3/nstime.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class SSRecord;
-class ServiceFlow;
-class ServiceFlowRecord;
-
-/**
- * @ingroup wimax
- * @brief Virtual class for uplink scheduler.
- */
-class UplinkScheduler : public Object
-{
-  public:
-    UplinkScheduler();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    UplinkScheduler(Ptr<BaseStationNetDevice> bs);
-    ~UplinkScheduler() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @return the number of IR opps allocated
-     */
-    virtual uint8_t GetNrIrOppsAllocated() const;
-    /**
-     * @brief Set the number of IR opps allocated
-     * @param nrIrOppsAllocated number of IR opps allocated
-     */
-    virtual void SetNrIrOppsAllocated(uint8_t nrIrOppsAllocated);
-
-    /**
-     * @return true if the IR interval is allocated
-     */
-    virtual bool GetIsIrIntrvlAllocated() const;
-    /**
-     * @brief Set if the IR interval is allocated
-     * @param isIrIntrvlAllocated
-     */
-    virtual void SetIsIrIntrvlAllocated(bool isIrIntrvlAllocated);
-
-    /**
-     * @return true if the Inv IR interval is allocated
-     */
-    virtual bool GetIsInvIrIntrvlAllocated() const;
-    /**
-     * @brief Set if the Inv IR interval is allocated
-     * @param isInvIrIntrvlAllocated
-     */
-    virtual void SetIsInvIrIntrvlAllocated(bool isInvIrIntrvlAllocated);
-
-    /**
-     * @return uplink allocations
-     */
-    virtual std::list<OfdmUlMapIe> GetUplinkAllocations() const;
-
-    /**
-     * @return the timestamp of the IR interval
-     */
-    virtual Time GetTimeStampIrInterval();
-    /**
-     * @brief Set timestamp IR interval
-     * @param timeStampIrInterval
-     */
-    virtual void SetTimeStampIrInterval(Time timeStampIrInterval);
-
-    /**
-     * @return the DCD timestamp
-     */
-    virtual Time GetDcdTimeStamp() const;
-    /**
-     * @brief Set DCD timestamp
-     * @param dcdTimeStamp
-     */
-    virtual void SetDcdTimeStamp(Time dcdTimeStamp);
-
-    /**
-     * @return the UCD timestamp
-     */
-    virtual Time GetUcdTimeStamp() const;
-    /**
-     * @brief Set UCD timestamp
-     * @param ucdTimeStamp
-     */
-    virtual void SetUcdTimeStamp(Time ucdTimeStamp);
-
-    /**
-     * @return the base station device
-     */
-    virtual Ptr<BaseStationNetDevice> GetBs();
-    /**
-     * @brief Set base station device
-     * @param bs
-     */
-    virtual void SetBs(Ptr<BaseStationNetDevice> bs);
-    /**
-     * Determines if channel descriptors sent in the current frame are
-     * required to be updated
-     */
-    virtual void GetChannelDescriptorsToUpdate(bool&, bool&, bool&, bool&) = 0;
-    /**
-     * @return the calculated allocation start time
-     */
-    virtual uint32_t CalculateAllocationStartTime() = 0;
-    /**
-     * Add uplink allocation
-     * @param ulMapIe the UL map IE
-     * @param allocationSize the allocation size
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    virtual void AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                                     const uint32_t& allocationSize,
-                                     uint32_t& symbolsToAllocation,
-                                     uint32_t& availableSymbols) = 0;
-    /**
-     * Schedule function
-     */
-    virtual void Schedule() = 0;
-    /**
-     * Service unsolicited grants function
-     * @param ssRecord the SS record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    virtual void ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                          ServiceFlow::SchedulingType schedulingType,
-                                          OfdmUlMapIe& ulMapIe,
-                                          const WimaxPhy::ModulationType modulationType,
-                                          uint32_t& symbolsToAllocation,
-                                          uint32_t& availableSymbols) = 0;
-    /**
-     * Service bandwidth request function
-     * @param ssRecord the SS record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    virtual void ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                          ServiceFlow::SchedulingType schedulingType,
-                                          OfdmUlMapIe& ulMapIe,
-                                          const WimaxPhy::ModulationType modulationType,
-                                          uint32_t& symbolsToAllocation,
-                                          uint32_t& availableSymbols) = 0;
-    /**
-     * Service bandwidth request function
-     * @param serviceFlow the service flow
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     * @returns true if successful
-     */
-    virtual bool ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                          ServiceFlow::SchedulingType schedulingType,
-                                          OfdmUlMapIe& ulMapIe,
-                                          const WimaxPhy::ModulationType modulationType,
-                                          uint32_t& symbolsToAllocation,
-                                          uint32_t& availableSymbols) = 0;
-    /**
-     * Allocate initial ranging interval function
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    virtual void AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                                uint32_t& availableSymbols) = 0;
-    /**
-     * Setp service flow function
-     * @param ssRecord the SS record
-     * @param serviceFlow the service flow
-     */
-    virtual void SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow) = 0;
-    /**
-     * Process bandwidth request function
-     * @param bwRequestHdr
-     */
-    virtual void ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr) = 0;
-
-    /**
-     * one time initialization function
-     */
-    virtual void InitOnce() = 0;
-
-    /**
-     * @brief Set requested bandwidth
-     * @param sfr service flow record
-     */
-    virtual void OnSetRequestedBandwidth(ServiceFlowRecord* sfr) = 0;
-
-  private:
-    Ptr<BaseStationNetDevice> m_bs;             ///< the base station
-    std::list<OfdmUlMapIe> m_uplinkAllocations; ///< uplink allocations
-    Time m_timeStampIrInterval;                 ///< timestamp IR interval
-    uint8_t m_nrIrOppsAllocated;                ///< number IR opps allocated
-    bool m_isIrIntrvlAllocated;                 ///< is IR interval allocated
-    bool m_isInvIrIntrvlAllocated;              ///< is Inv IR interval allocated
-    Time m_dcdTimeStamp;                        ///< DCD timestamp
-    Time m_ucdTimeStamp;                        ///< UCD timestamp
-};
-
-} // namespace ns3
-
-#endif /* UPLINK_SCHEDULER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler-mbqos.cc ns-3.46/src/wimax/model/bs-uplink-scheduler-mbqos.cc
--- ns-3.45/src/wimax/model/bs-uplink-scheduler-mbqos.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler-mbqos.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,1197 +0,0 @@
-/*
- * SPDX-License-Identifier: GPL-2.0-only
- *
- */
-
-#include "bs-uplink-scheduler-mbqos.h"
-
-#include "bandwidth-manager.h"
-#include "bs-link-manager.h"
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "connection-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("UplinkSchedulerMBQoS");
-
-NS_OBJECT_ENSURE_REGISTERED(UplinkSchedulerMBQoS);
-
-UplinkSchedulerMBQoS::UplinkSchedulerMBQoS()
-{
-}
-
-UplinkSchedulerMBQoS::UplinkSchedulerMBQoS(Time time)
-    : m_windowInterval(time)
-{
-}
-
-UplinkSchedulerMBQoS::~UplinkSchedulerMBQoS()
-{
-    SetBs(nullptr);
-    m_uplinkAllocations.clear();
-}
-
-TypeId
-UplinkSchedulerMBQoS::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::UplinkSchedulerMBQoS")
-
-                            .SetParent<UplinkScheduler>()
-
-                            .SetGroupName("Wimax")
-
-                            .AddAttribute("WindowInterval",
-                                          "The time to wait to reset window",
-                                          TimeValue(Seconds(1)),
-                                          MakeTimeAccessor(&UplinkSchedulerMBQoS::m_windowInterval),
-                                          MakeTimeChecker());
-    return tid;
-}
-
-void
-UplinkSchedulerMBQoS::InitOnce()
-{
-    UplinkSchedWindowTimer();
-}
-
-std::list<OfdmUlMapIe>
-UplinkSchedulerMBQoS::GetUplinkAllocations() const
-{
-    return m_uplinkAllocations;
-}
-
-void
-UplinkSchedulerMBQoS::GetChannelDescriptorsToUpdate(bool& updateDcd,
-                                                    bool& updateUcd,
-                                                    bool& sendDcd,
-                                                    bool& sendUcd)
-{
-    /* DCD and UCD shall actually be updated when channel or burst profile definitions
-     change. burst profiles are updated based on number of SSs, network conditions and etc.
-     for now temporarily assuming DCD/UCD shall be updated every time */
-
-    uint32_t randNr = rand();
-    if (randNr % 5 == 0 || GetBs()->GetNrDcdSent() == 0)
-    {
-        sendDcd = true;
-    }
-
-    randNr = rand();
-    if (randNr % 5 == 0 || GetBs()->GetNrUcdSent() == 0)
-    {
-        sendUcd = true;
-    }
-
-    // -------------------------------------
-    // additional, just to send more frequently
-    if (!sendDcd)
-    {
-        randNr = rand();
-        if (randNr % 4 == 0)
-        {
-            sendDcd = true;
-        }
-    }
-
-    if (!sendUcd)
-    {
-        randNr = rand();
-        if (randNr % 4 == 0)
-        {
-            sendUcd = true;
-        }
-    }
-    // -------------------------------------
-
-    Time timeSinceLastDcd = Simulator::Now() - GetDcdTimeStamp();
-    Time timeSinceLastUcd = Simulator::Now() - GetUcdTimeStamp();
-
-    if (timeSinceLastDcd > GetBs()->GetDcdInterval())
-    {
-        sendDcd = true;
-        SetDcdTimeStamp(Simulator::Now());
-    }
-
-    if (timeSinceLastUcd > GetBs()->GetUcdInterval())
-    {
-        sendUcd = true;
-        SetUcdTimeStamp(Simulator::Now());
-    }
-}
-
-uint32_t
-UplinkSchedulerMBQoS::CalculateAllocationStartTime()
-{
-    return GetBs()->GetNrDlSymbols() * GetBs()->GetPhy()->GetPsPerSymbol() + GetBs()->GetTtg();
-}
-
-void
-UplinkSchedulerMBQoS::AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                                          const uint32_t& allocationSize,
-                                          uint32_t& symbolsToAllocation,
-                                          uint32_t& availableSymbols)
-{
-    ulMapIe.SetDuration(allocationSize);
-    ulMapIe.SetStartTime(symbolsToAllocation);
-    m_uplinkAllocations.push_back(ulMapIe);
-    symbolsToAllocation += allocationSize;
-    availableSymbols -= allocationSize;
-}
-
-void
-UplinkSchedulerMBQoS::UplinkSchedWindowTimer()
-{
-    NS_LOG(LOG_DEBUG, "Window Reset at " << (Simulator::Now()).As(Time::S));
-
-    uint32_t min_bw = 0;
-
-    if (!GetBs()->GetSSManager())
-    {
-        Simulator::Schedule(m_windowInterval, &UplinkSchedulerMBQoS::UplinkSchedWindowTimer, this);
-        return;
-    }
-
-    std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
-
-    // For each SS
-    for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-    {
-        SSRecord* ssRecord = *iter;
-        std::vector<ServiceFlow*> serviceFlows =
-            ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_ALL);
-
-        // For each flow
-        for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-        {
-            ServiceFlow* serviceFlow = *iter2;
-            if ((serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS) ||
-                (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS))
-            {
-                min_bw = (int)ceil(serviceFlow->GetMinReservedTrafficRate());
-
-                // This way we can compensate flows which did not get min_bw in the previous window
-                if ((serviceFlow->GetRecord()->GetBacklogged() > 0) &&
-                    (serviceFlow->GetRecord()->GetBwSinceLastExpiry() < min_bw))
-                {
-                    serviceFlow->GetRecord()->UpdateBwSinceLastExpiry(-min_bw);
-
-                    // if backlogged < granted_bw then we don't need to provide granted_bw + min_bw
-                    // in next window, but backlogged + min_bw
-                    if (serviceFlow->GetRecord()->GetBacklogged() <
-                        (serviceFlow->GetRecord()->GetBwSinceLastExpiry()))
-                    {
-                        serviceFlow->GetRecord()->SetBwSinceLastExpiry(
-                            -serviceFlow->GetRecord()->GetBacklogged());
-                    }
-                }
-                else
-                {
-                    serviceFlow->GetRecord()->SetBwSinceLastExpiry(0);
-                }
-            }
-        }
-    }
-
-    // Periodically reset window
-    Simulator::Schedule(m_windowInterval, &UplinkSchedulerMBQoS::UplinkSchedWindowTimer, this);
-}
-
-void
-UplinkSchedulerMBQoS::Schedule()
-{
-    m_uplinkAllocations.clear();
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    bool allocationForDsa = false;
-
-    uint32_t symbolsToAllocation = 0;
-    uint32_t allocationSize = 0; // size in symbols
-    uint32_t availableSymbols = GetBs()->GetNrUlSymbols();
-
-    AllocateInitialRangingInterval(symbolsToAllocation, availableSymbols);
-
-    std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
-    for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-    {
-        SSRecord* ssRecord = *iter;
-
-        if (ssRecord->GetIsBroadcastSS())
-        {
-            continue;
-        }
-        Cid cid = ssRecord->GetBasicCid();
-        OfdmUlMapIe ulMapIe;
-        ulMapIe.SetCid(cid);
-
-        if (ssRecord->GetPollForRanging() &&
-            ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_CONTINUE)
-        {
-            // SS's ranging is not yet complete
-            // allocating invited initial ranging interval
-            ulMapIe.SetUiuc(OfdmUlBurstProfile::UIUC_INITIAL_RANGING);
-            allocationSize = GetBs()->GetRangReqOppSize();
-            SetIsInvIrIntrvlAllocated(true);
-
-            if (availableSymbols >= allocationSize)
-            {
-                AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
-            }
-            else
-            {
-                break;
-            }
-        }
-        else
-        {
-            WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
-
-            // need to update because modulation/FEC to UIUC mapping may vary over time
-            ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_UPLINK));
-
-            // establish service flows for SS
-            if (ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_SUCCESS &&
-                !ssRecord->GetAreServiceFlowsAllocated())
-            {
-                // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ
-                // and DSA-ACK only one DSA allocation per frame
-                if (!allocationForDsa)
-                {
-                    allocationSize =
-                        GetBs()->GetPhy()->GetNrSymbols(sizeof(DsaReq), modulationType);
-
-                    if (availableSymbols >= allocationSize)
-                    {
-                        AddUplinkAllocation(ulMapIe,
-                                            allocationSize,
-                                            symbolsToAllocation,
-                                            availableSymbols);
-                        allocationForDsa = true;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-            }
-            else
-            {
-                // all service flows associated to SS are established now
-
-                /* Implementation of uplink scheduler
-                 * [1] Freitag, J.; da Fonseca, N.L.S., "Uplink Scheduling with Quality of Service
-                 * in IEEE 802.16 Networks," Global Telecommunications Conference, 2007. GLOBECOM
-                 * '07. IEEE , vol., no., pp.2503-2508, 26-30 Nov. 2007 URL:
-                 * http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=4411386&isnumber=4410910 */
-
-                // Step 1
-                if (availableSymbols)
-                {
-                    /*allocating grants for data transmission for UGS flows (Data Grant Burst Type
-                     IEs, 6.3.7.4.3.3) (grant has been referred by different names e.g. transmission
-                     opportunity, slot,         uplink allocation, etc)*/
-                    if (ssRecord->GetHasServiceFlowUgs())
-                    {
-                        NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
-                                           << " offering be unicast polling");
-                        // Recover period interval information for UGS flow
-                        Time frame_duration = GetBs()->GetPhy()->GetFrameDuration();
-                        Time timestamp =
-                            (*(ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_UGS).begin()))
-                                ->GetRecord()
-                                ->GetLastGrantTime() +
-                            MilliSeconds(
-                                (*(ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_UGS).begin()))
-                                    ->GetUnsolicitedGrantInterval());
-
-                        int64_t frame = ((timestamp - Simulator::Now()) / frame_duration).GetHigh();
-
-                        if (frame <= 1)
-                        {
-                            // UGS Grants
-                            // It is not necessary to enqueue UGS grants once it is periodically
-                            // served
-                            ServiceUnsolicitedGrants(ssRecord,
-                                                     ServiceFlow::SF_TYPE_UGS,
-                                                     ulMapIe,
-                                                     modulationType,
-                                                     symbolsToAllocation,
-                                                     availableSymbols);
-                        }
-                    }
-
-                    // enqueue allocate unicast polls for rtPS flows if bandwidth is available
-                    if (ssRecord->GetHasServiceFlowRtps())
-                    {
-                        NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
-                                           << " offering rtps unicast polling");
-                        Ptr<UlJob> jobRTPSPoll =
-                            CreateUlJob(ssRecord, ServiceFlow::SF_TYPE_RTPS, UNICAST_POLLING);
-                        EnqueueJob(UlJob::HIGH, jobRTPSPoll);
-                    }
-
-                    if (ssRecord->GetHasServiceFlowNrtps())
-                    {
-                        NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
-                                           << " offering nrtps unicast polling");
-                        // allocate unicast polls for nrtPS flows if bandwidth is available
-                        Ptr<UlJob> jobNRTPSPoll =
-                            CreateUlJob(ssRecord, ServiceFlow::SF_TYPE_NRTPS, UNICAST_POLLING);
-                        EnqueueJob(UlJob::HIGH, jobNRTPSPoll);
-                    }
-
-                    if (ssRecord->GetHasServiceFlowBe())
-                    {
-                        NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
-                                           << " offering be unicast polling");
-                        // finally allocate unicast polls for BE flows if bandwidth is available
-                        Ptr<UlJob> jobBEPoll =
-                            CreateUlJob(ssRecord, ServiceFlow::SF_TYPE_BE, UNICAST_POLLING);
-                        EnqueueJob(UlJob::HIGH, jobBEPoll);
-                    }
-                }
-            }
-        }
-    }
-    NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " high queue has "
-                       << m_uplinkJobs_high.size() << " jobs - after sched");
-
-    uint32_t availableSymbolsAux = availableSymbols;
-    uint32_t symbolsUsed = 0;
-
-    symbolsUsed += CountSymbolsQueue(m_uplinkJobs_high);
-    availableSymbolsAux -= symbolsUsed;
-
-    // Step 2 - Check Deadline - Migrate requests with deadline expiring
-    CheckDeadline(availableSymbolsAux);
-
-    // Step 3 - Check Minimum Bandwidth
-    CheckMinimumBandwidth(availableSymbolsAux);
-
-    // Scheduling high priority queue
-    NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " high queue has "
-                       << m_uplinkJobs_high.size() << " jobs");
-    while ((availableSymbols) && (!m_uplinkJobs_high.empty()))
-    {
-        Ptr<UlJob> job = m_uplinkJobs_high.front();
-        OfdmUlMapIe ulMapIe;
-        SSRecord* ssRecord = job->GetSsRecord();
-        ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType();
-
-        Cid cid = ssRecord->GetBasicCid();
-        ulMapIe.SetCid(cid);
-        WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
-        // need to update because modulation/FEC to UIUC mapping may vary over time
-        ulMapIe.SetUiuc(
-            GetBs()->GetBurstProfileManager()->GetBurstProfile(modulationType,
-                                                               WimaxNetDevice::DIRECTION_UPLINK));
-
-        ReqType reqType = job->GetType();
-
-        if (reqType == UNICAST_POLLING)
-        {
-            ServiceUnsolicitedGrants(ssRecord,
-                                     schedulingType,
-                                     ulMapIe,
-                                     modulationType,
-                                     symbolsToAllocation,
-                                     availableSymbols);
-        }
-        else if (reqType == DATA)
-        {
-            ServiceFlow* serviceFlow = job->GetServiceFlow();
-            uint32_t allocSizeBytes = job->GetSize();
-            ServiceBandwidthRequestsBytes(serviceFlow,
-                                          schedulingType,
-                                          ulMapIe,
-                                          modulationType,
-                                          symbolsToAllocation,
-                                          availableSymbols,
-                                          allocSizeBytes);
-        }
-        m_uplinkJobs_high.pop_front();
-    }
-
-    NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " interqueue has "
-                       << m_uplinkJobs_inter.size() << " jobs");
-    /* Scheduling intermediate priority queue */
-    while ((availableSymbols) && (!m_uplinkJobs_inter.empty()))
-    {
-        NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " Scheduling interqueue");
-        Ptr<UlJob> job = m_uplinkJobs_inter.front();
-        OfdmUlMapIe ulMapIe;
-        SSRecord* ssRecord = job->GetSsRecord();
-        ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType();
-
-        Cid cid = ssRecord->GetBasicCid();
-        ulMapIe.SetCid(cid);
-        WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
-        // need to update because modulation/FEC to UIUC mapping may vary over time
-        ulMapIe.SetUiuc(
-            GetBs()->GetBurstProfileManager()->GetBurstProfile(modulationType,
-                                                               WimaxNetDevice::DIRECTION_UPLINK));
-
-        ReqType reqType = job->GetType();
-
-        if (reqType == DATA)
-        {
-            ServiceBandwidthRequests(ssRecord,
-                                     schedulingType,
-                                     ulMapIe,
-                                     modulationType,
-                                     symbolsToAllocation,
-                                     availableSymbols);
-        }
-        else
-        {
-            NS_FATAL_ERROR("Intermediate priority queue only should enqueue data packets.");
-        }
-        m_uplinkJobs_inter.pop_front();
-    }
-
-    /* Scheduling low priority queue */
-    while ((availableSymbols) && (!m_uplinkJobs_low.empty()))
-    {
-        Ptr<UlJob> job = m_uplinkJobs_low.front();
-        OfdmUlMapIe ulMapIe;
-        SSRecord* ssRecord = job->GetSsRecord();
-        ServiceFlow::SchedulingType schedulingType = job->GetSchedulingType();
-
-        Cid cid = ssRecord->GetBasicCid();
-        ulMapIe.SetCid(cid);
-        WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
-        // need to update because modulation/FEC to UIUC mapping may vary over time
-        ulMapIe.SetUiuc(
-            GetBs()->GetBurstProfileManager()->GetBurstProfile(modulationType,
-                                                               WimaxNetDevice::DIRECTION_UPLINK));
-
-        ReqType reqType = job->GetType();
-
-        if (reqType == DATA)
-        {
-            ServiceBandwidthRequests(ssRecord,
-                                     schedulingType,
-                                     ulMapIe,
-                                     modulationType,
-                                     symbolsToAllocation,
-                                     availableSymbols);
-        }
-        else
-        {
-            NS_FATAL_ERROR("Low priority queue only should enqueue data packets.");
-        }
-        m_uplinkJobs_low.pop_front();
-    }
-
-    OfdmUlMapIe ulMapIeEnd;
-    ulMapIeEnd.SetCid(Cid(0));
-    ulMapIeEnd.SetStartTime(symbolsToAllocation);
-    ulMapIeEnd.SetUiuc(OfdmUlBurstProfile::UIUC_END_OF_MAP);
-    ulMapIeEnd.SetDuration(0);
-    m_uplinkAllocations.push_back(ulMapIeEnd);
-
-    // setting DL/UL subframe allocation for the next frame
-    GetBs()->GetBandwidthManager()->SetSubframeRatio();
-}
-
-bool
-UplinkSchedulerMBQoS::ServiceBandwidthRequestsBytes(ServiceFlow* serviceFlow,
-                                                    ServiceFlow::SchedulingType schedulingType,
-                                                    OfdmUlMapIe& ulMapIe,
-                                                    const WimaxPhy::ModulationType modulationType,
-                                                    uint32_t& symbolsToAllocation,
-                                                    uint32_t& availableSymbols,
-                                                    uint32_t allocationSizeBytes)
-{
-    uint32_t allocSizeBytes = allocationSizeBytes;
-    uint32_t allocSizeSymbols = 0;
-
-    ServiceFlowRecord* record = serviceFlow->GetRecord();
-
-    uint32_t requiredBandwidth = record->GetRequestedBandwidth();
-
-    if (requiredBandwidth > 0)
-    {
-        allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(allocSizeBytes, modulationType);
-
-        if (availableSymbols < allocSizeSymbols)
-        {
-            allocSizeSymbols = availableSymbols;
-        }
-
-        if (availableSymbols >= allocSizeSymbols)
-        {
-            NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " BS uplink scheduler, "
-                               << serviceFlow->GetSchedulingTypeStr()
-                               << " allocation, size: " << allocSizeSymbols << " symbols"
-                               << ", CID: " << serviceFlow->GetConnection()->GetCid()
-                               << ", SFID: " << serviceFlow->GetSfid()
-                               << ", bw requested: " << record->GetRequestedBandwidth()
-                               << ", bw granted: " << allocSizeBytes << std::endl);
-
-            record->UpdateGrantedBandwidthTemp(allocSizeBytes);
-            record->UpdateGrantedBandwidth(allocSizeBytes);
-            record->UpdateRequestedBandwidth(-allocSizeBytes);
-
-            record->UpdateBwSinceLastExpiry(allocSizeBytes);
-
-            AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
-        }
-        else
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-uint32_t
-UplinkSchedulerMBQoS::CountSymbolsQueue(std::list<Ptr<UlJob>> jobs)
-{
-    uint32_t symbols = 0;
-    for (auto iter = jobs.begin(); iter != jobs.end(); ++iter)
-    {
-        Ptr<UlJob> job = *iter;
-
-        // count symbols
-        symbols += CountSymbolsJobs(job);
-    }
-    return symbols;
-}
-
-Ptr<UlJob>
-UplinkSchedulerMBQoS::CreateUlJob(SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedType,
-                                  ReqType reqType)
-{
-    Ptr<UlJob> job = CreateObject<UlJob>();
-    job->SetSsRecord(ssRecord);
-    job->SetSchedulingType(schedType);
-    job->SetServiceFlow(*(ssRecord->GetServiceFlows(schedType).begin()));
-    job->SetType(reqType);
-    return job;
-}
-
-uint32_t
-UplinkSchedulerMBQoS::CountSymbolsJobs(Ptr<UlJob> job)
-{
-    SSRecord* ssRecord = job->GetSsRecord();
-    ServiceFlow* serviceFlow = job->GetServiceFlow();
-    uint32_t allocationSize = 0;
-
-    if (job->GetType() == UNICAST_POLLING)
-    {
-        // if polling
-        Time currentTime = Simulator::Now();
-        allocationSize = 0;
-        if ((currentTime - serviceFlow->GetRecord()->GetGrantTimeStamp()).GetMilliSeconds() >=
-            serviceFlow->GetUnsolicitedPollingInterval())
-        {
-            allocationSize = GetBs()->GetBwReqOppSize();
-        }
-    }
-    else
-    {
-        // if data
-        uint16_t sduSize = serviceFlow->GetSduSize();
-        ServiceFlowRecord* record = serviceFlow->GetRecord();
-        uint32_t requiredBandwidth =
-            record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
-        if (requiredBandwidth > 0)
-        {
-            WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
-            if (sduSize > 0)
-            {
-                // if SDU size is mentioned, allocate grant of that size
-                allocationSize = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
-            }
-            else
-            {
-                allocationSize = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
-            }
-        }
-    }
-    return allocationSize;
-}
-
-void
-UplinkSchedulerMBQoS::EnqueueJob(UlJob::JobPriority priority, Ptr<UlJob> job)
-{
-    switch (priority)
-    {
-    case UlJob::HIGH:
-        m_uplinkJobs_high.push_back(job);
-        break;
-    case UlJob::INTERMEDIATE:
-        m_uplinkJobs_inter.push_back(job);
-        break;
-    case UlJob::LOW:
-        m_uplinkJobs_low.push_back(job);
-    }
-}
-
-Ptr<UlJob>
-UplinkSchedulerMBQoS::DequeueJob(UlJob::JobPriority priority)
-{
-    Ptr<UlJob> job_front;
-    switch (priority)
-    {
-    case UlJob::HIGH:
-        job_front = m_uplinkJobs_high.front();
-        m_uplinkJobs_high.pop_front();
-        break;
-    case UlJob::INTERMEDIATE:
-        job_front = m_uplinkJobs_inter.front();
-        m_uplinkJobs_inter.pop_front();
-        break;
-    case UlJob::LOW:
-        job_front = m_uplinkJobs_low.front();
-        m_uplinkJobs_low.pop_front();
-    }
-    return job_front;
-}
-
-void
-UplinkSchedulerMBQoS::CheckDeadline(uint32_t& availableSymbols)
-{
-    // for each request in the intermediate queue
-    if (!m_uplinkJobs_inter.empty())
-    {
-        auto iter = m_uplinkJobs_inter.begin();
-
-        while (iter != m_uplinkJobs_inter.end() && availableSymbols)
-        {
-            Ptr<UlJob> job = *iter;
-
-            // guarantee delay bound for rtps connections
-            if (job->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS)
-            {
-                Time deadline = job->GetDeadline();
-                Time frame_duration = GetBs()->GetPhy()->GetFrameDuration();
-
-                int64_t frame = ((deadline - Simulator::Now()) / frame_duration).GetHigh();
-
-                NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S) << " reserved traffic rate: "
-                                   << job->GetServiceFlow()->GetMinReservedTrafficRate()
-                                   << " deadline: " << job->GetDeadline().As(Time::S)
-                                   << " frame start: " << GetBs()->m_frameStartTime.As(Time::S)
-                                   << " frame duration: " << frame_duration);
-
-                // should be schedule in this frame to max latency
-                if (frame >= 3)
-                {
-                    if (availableSymbols)
-                    {
-                        uint32_t availableBytes =
-                            GetBs()->GetPhy()->GetNrBytes(availableSymbols,
-                                                          job->GetSsRecord()->GetModulationType());
-                        uint32_t allocationSize = job->GetSize();
-                        if (allocationSize > availableBytes)
-                        {
-                            allocationSize = availableBytes;
-                        }
-
-                        if (allocationSize == 0)
-                        {
-                            continue;
-                        }
-
-                        uint32_t symbolsToAllocate = GetBs()->GetPhy()->GetNrSymbols(
-                            allocationSize,
-                            job->GetSsRecord()->GetModulationType());
-                        if (symbolsToAllocate > availableSymbols)
-                        {
-                            symbolsToAllocate = availableSymbols;
-                            allocationSize = GetBs()->GetPhy()->GetNrBytes(
-                                symbolsToAllocate,
-                                job->GetSsRecord()->GetModulationType());
-                        }
-
-                        job->SetSize(job->GetSize() - allocationSize);
-
-                        Ptr<UlJob> newJob = CreateObject<UlJob>();
-                        // Record data in job
-                        newJob->SetSsRecord(job->GetSsRecord());
-                        newJob->SetServiceFlow(job->GetServiceFlow());
-                        newJob->SetSize(allocationSize);
-                        newJob->SetDeadline(job->GetDeadline());
-                        newJob->SetReleaseTime(job->GetReleaseTime());
-                        newJob->SetSchedulingType(job->GetSchedulingType());
-                        newJob->SetPeriod(job->GetPeriod());
-                        newJob->SetType(job->GetType());
-
-                        EnqueueJob(UlJob::HIGH, newJob);
-
-                        // migrate request
-                        iter++;
-                        if ((job->GetSize() - allocationSize) == 0)
-                        {
-                            m_uplinkJobs_inter.remove(job);
-                        }
-                    }
-                }
-                else
-                {
-                    iter++;
-                }
-            }
-            else
-            {
-                iter++;
-            }
-        }
-    }
-}
-
-void
-UplinkSchedulerMBQoS::CheckMinimumBandwidth(uint32_t& availableSymbols)
-{
-    std::list<Ptr<PriorityUlJob>> priorityUlJobs;
-
-    // For each connection of type rtPS or nrtPS
-    std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
-    for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-    {
-        SSRecord* ssRecord = *iter;
-        std::vector<ServiceFlow*> serviceFlows =
-            ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_ALL);
-        for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-        {
-            ServiceFlow* serviceFlow = *iter2;
-            if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS ||
-                serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS)
-            {
-                serviceFlow->GetRecord()->SetBackloggedTemp(
-                    serviceFlow->GetRecord()->GetBacklogged());
-                serviceFlow->GetRecord()->SetGrantedBandwidthTemp(
-                    serviceFlow->GetRecord()->GetBwSinceLastExpiry());
-            }
-        }
-    }
-
-    // for each request in the imermediate queue
-    for (auto iter = m_uplinkJobs_inter.begin(); iter != m_uplinkJobs_inter.end(); ++iter)
-    {
-        Ptr<UlJob> job = *iter;
-        // SSRecord ssRecord = job->GetSsRecord();
-        ServiceFlow* serviceFlow = job->GetServiceFlow();
-        if ((job->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS ||
-             job->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS) &&
-            (serviceFlow->GetRecord()->GetBacklogged() > 0))
-        {
-            uint32_t minReservedTrafficRate = serviceFlow->GetMinReservedTrafficRate();
-            uint32_t grantedBandwidth = serviceFlow->GetRecord()->GetBwSinceLastExpiry();
-
-            Ptr<PriorityUlJob> priorityUlJob = CreateObject<PriorityUlJob>();
-            priorityUlJob->SetUlJob(job);
-            // pri_array
-            if (minReservedTrafficRate <= grantedBandwidth)
-            {
-                priorityUlJob->SetPriority(-10000);
-            }
-            else
-            {
-                uint32_t allocationSize = serviceFlow->GetRecord()->GetRequestedBandwidth() -
-                                          serviceFlow->GetRecord()->GetGrantedBandwidth();
-                uint32_t sduSize = serviceFlow->GetSduSize();
-
-                if (allocationSize > 0)
-                {
-                    if (sduSize > 0)
-                    {
-                        // if SDU size is mentioned, grant of that size
-                        allocationSize = sduSize;
-                    }
-                }
-                int priority =
-                    serviceFlow->GetRecord()->GetBackloggedTemp() -
-                    (serviceFlow->GetRecord()->GetGrantedBandwidthTemp() - minReservedTrafficRate);
-                priorityUlJob->SetPriority(priority);
-                serviceFlow->GetRecord()->SetGrantedBandwidthTemp(
-                    serviceFlow->GetRecord()->GetGrantedBandwidthTemp() + allocationSize);
-                serviceFlow->GetRecord()->SetBackloggedTemp(
-                    serviceFlow->GetRecord()->GetBackloggedTemp() - allocationSize);
-            }
-
-            priorityUlJobs.push_back(priorityUlJob);
-        }
-    }
-
-    priorityUlJobs.sort(SortProcessPtr());
-
-    for (auto iter = priorityUlJobs.begin(); iter != priorityUlJobs.end(); ++iter)
-    {
-        Ptr<PriorityUlJob> priorityUlJob = *iter;
-        Ptr<UlJob> job_priority = priorityUlJob->GetUlJob();
-        Ptr<UlJob> job = job_priority;
-        if (availableSymbols)
-        {
-            availableSymbols -= CountSymbolsJobs(job);
-            // migrate request
-            m_uplinkJobs_inter.remove(job);
-            EnqueueJob(UlJob::HIGH, job);
-        }
-    }
-}
-
-void
-UplinkSchedulerMBQoS::ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                               ServiceFlow::SchedulingType schedulingType,
-                                               OfdmUlMapIe& ulMapIe,
-                                               const WimaxPhy::ModulationType modulationType,
-                                               uint32_t& symbolsToAllocation,
-                                               uint32_t& availableSymbols)
-{
-    uint32_t allocationSize = 0;      // size in symbols
-    uint8_t uiuc = ulMapIe.GetUiuc(); // SS's burst profile
-    std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        ServiceFlow* serviceFlow = *iter;
-
-        /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request
-         IEs, 6.3.7.4.3.1). in case of UGS, allocating grants for data transmission (Data Grant
-         Burst Type IEs, 6.3.7.4.3.3) (grant has been referred in this code by different names e.g.
-         transmission opportunity, slot, allocation, etc) */
-
-        allocationSize =
-            GetBs()->GetBandwidthManager()->CalculateAllocationSize(ssRecord, serviceFlow);
-
-        if (availableSymbols < allocationSize)
-        {
-            break;
-        }
-
-        if (allocationSize > 0)
-        {
-            ulMapIe.SetStartTime(symbolsToAllocation);
-            if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS)
-            {
-                // special burst profile with most robust modulation type is used for unicast polls
-                // (Request IEs)
-                ulMapIe.SetUiuc(OfdmUlBurstProfile::UIUC_REQ_REGION_FULL);
-            }
-        }
-        else
-        {
-            continue;
-        }
-
-        if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_UGS)
-        {
-            NS_LOG_DEBUG("BS uplink scheduler, UGS allocation, size: " << allocationSize
-                                                                       << " symbols");
-        }
-        else
-        {
-            NS_LOG_DEBUG("BS uplink scheduler, " << serviceFlow->GetSchedulingTypeStr()
-                                                 << " unicast poll, size: " << allocationSize
-                                                 << " symbols, modulation: BPSK 1/2");
-        }
-
-        NS_LOG_DEBUG(", CID: " << serviceFlow->GetConnection()->GetCid()
-                               << ", SFID: " << serviceFlow->GetSfid());
-
-        serviceFlow->GetRecord()->SetLastGrantTime(Simulator::Now());
-        AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
-        ulMapIe.SetUiuc(uiuc);
-    }
-}
-
-void
-UplinkSchedulerMBQoS::ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                               ServiceFlow::SchedulingType schedulingType,
-                                               OfdmUlMapIe& ulMapIe,
-                                               const WimaxPhy::ModulationType modulationType,
-                                               uint32_t& symbolsToAllocation,
-                                               uint32_t& availableSymbols)
-{
-    std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        if (!ServiceBandwidthRequests(*iter,
-                                      schedulingType,
-                                      ulMapIe,
-                                      modulationType,
-                                      symbolsToAllocation,
-                                      availableSymbols))
-        {
-            break;
-        }
-    }
-}
-
-bool
-UplinkSchedulerMBQoS::ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                               ServiceFlow::SchedulingType schedulingType,
-                                               OfdmUlMapIe& ulMapIe,
-                                               const WimaxPhy::ModulationType modulationType,
-                                               uint32_t& symbolsToAllocation,
-                                               uint32_t& availableSymbols)
-{
-    uint32_t allocSizeBytes = 0;
-    uint32_t allocSizeSymbols = 0;
-    uint16_t sduSize = 0;
-
-    ServiceFlowRecord* record = serviceFlow->GetRecord();
-    sduSize = serviceFlow->GetSduSize();
-
-    uint32_t requiredBandwidth = record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
-    if (requiredBandwidth > 0)
-    {
-        if (sduSize > 0)
-        {
-            // if SDU size is mentioned, allocate grant of that size
-            allocSizeBytes = sduSize;
-            allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
-        }
-        else
-        {
-            allocSizeBytes = requiredBandwidth;
-            allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
-        }
-
-        if (availableSymbols >= allocSizeSymbols)
-        {
-            NS_LOG_DEBUG("BS uplink scheduler, "
-                         << serviceFlow->GetSchedulingTypeStr()
-                         << " allocation, size: " << allocSizeSymbols << " symbols"
-                         << ", CID: " << serviceFlow->GetConnection()->GetCid()
-                         << ", SFID: " << serviceFlow->GetSfid()
-                         << ", bw requested: " << record->GetRequestedBandwidth()
-                         << ", bw granted: " << record->GetGrantedBandwidth());
-
-            record->UpdateGrantedBandwidth(allocSizeBytes);
-
-            record->SetBwSinceLastExpiry(allocSizeBytes);
-
-            if (serviceFlow->GetRecord()->GetBacklogged() < allocSizeBytes)
-            {
-                serviceFlow->GetRecord()->SetBacklogged(0);
-            }
-            else
-            {
-                serviceFlow->GetRecord()->IncreaseBacklogged(-allocSizeBytes);
-            }
-            serviceFlow->GetRecord()->SetLastGrantTime(Simulator::Now());
-
-            AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
-        }
-        else
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-void
-UplinkSchedulerMBQoS::AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                                     uint32_t& availableSymbols)
-{
-    Time ssUlStartTime =
-        Seconds(CalculateAllocationStartTime() * GetBs()->GetPsDuration().GetSeconds());
-    SetNrIrOppsAllocated(GetBs()->GetLinkManager()->CalculateRangingOppsToAllocate());
-    uint32_t allocationSize = GetNrIrOppsAllocated() * GetBs()->GetRangReqOppSize();
-    Time timeSinceLastIrInterval = Simulator::Now() - GetTimeStampIrInterval();
-
-    // adding one frame because may be the time has not elapsed now but will elapse before the next
-    // frame is sent
-    if (timeSinceLastIrInterval + GetBs()->GetPhy()->GetFrameDuration() >
-            GetBs()->GetInitialRangingInterval() &&
-        availableSymbols >= allocationSize)
-    {
-        SetIsIrIntrvlAllocated(true);
-        OfdmUlMapIe ulMapIeIr;
-        ulMapIeIr.SetCid((GetBs()->GetBroadcastConnection())->GetCid());
-        ulMapIeIr.SetStartTime(symbolsToAllocation);
-        ulMapIeIr.SetUiuc(OfdmUlBurstProfile::UIUC_INITIAL_RANGING);
-
-        NS_LOG_DEBUG("BS uplink scheduler, initial ranging allocation, size: "
-                     << allocationSize << " symbols, modulation: BPSK 1/2");
-
-        // marking start and end of each TO, only for debugging
-        for (uint8_t i = 0; i < GetNrIrOppsAllocated(); i++)
-        {
-            GetBs()->MarkRangingOppStart(
-                ssUlStartTime +
-                Seconds(symbolsToAllocation * GetBs()->GetSymbolDuration().GetSeconds()) +
-                Seconds(i * GetBs()->GetRangReqOppSize() *
-                        GetBs()->GetSymbolDuration().GetSeconds()));
-        }
-
-        AddUplinkAllocation(ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
-        SetTimeStampIrInterval(Simulator::Now());
-    }
-}
-
-void
-UplinkSchedulerMBQoS::SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow)
-{
-    uint8_t delayNrFrames = 1;
-    uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate();
-    WimaxPhy::ModulationType modulation;
-    uint32_t bytesPerFrame =
-        (uint32_t((double)(bitsPerSecond)*GetBs()->GetPhy()->GetFrameDuration().GetSeconds())) / 8;
-    uint32_t frameDurationMSec = GetBs()->GetPhy()->GetFrameDuration().GetMilliSeconds();
-
-    switch (serviceFlow->GetSchedulingType())
-    {
-    case ServiceFlow::SF_TYPE_UGS: {
-        if (serviceFlow->GetIsMulticast())
-        {
-            modulation = serviceFlow->GetModulation();
-        }
-        else
-        {
-            modulation = ssRecord->GetModulationType();
-        }
-        uint32_t grantSize = GetBs()->GetPhy()->GetNrSymbols(bytesPerFrame, modulation);
-        serviceFlow->GetRecord()->SetGrantSize(grantSize);
-
-        uint32_t toleratedJitter = serviceFlow->GetToleratedJitter();
-
-        if (toleratedJitter > frameDurationMSec)
-        {
-            delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
-        }
-
-        uint16_t interval = delayNrFrames * frameDurationMSec;
-        serviceFlow->SetUnsolicitedGrantInterval(interval);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_RTPS: {
-        serviceFlow->SetUnsolicitedPollingInterval(20);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_NRTPS: {
-        // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
-        uint16_t interval = 1000;
-        serviceFlow->SetUnsolicitedPollingInterval(interval);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_BE: {
-        // no real-time guarantees are given to BE, serviced based on available bandwidth
-    }
-    break;
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-    }
-}
-
-uint32_t
-UplinkSchedulerMBQoS::GetPendingSize(ServiceFlow* serviceFlow)
-{
-    uint32_t size = 0;
-    std::list<Ptr<PriorityUlJob>> priorityUlJobs;
-
-    // for each request in the imermediate queue
-    for (auto iter = m_uplinkJobs_inter.begin(); iter != m_uplinkJobs_inter.end(); ++iter)
-    {
-        Ptr<UlJob> job = *iter;
-
-        ServiceFlow* serviceFlowJob = job->GetServiceFlow();
-
-        if (serviceFlowJob == serviceFlow)
-        {
-            size += job->GetSize();
-        }
-    }
-    return size;
-}
-
-void
-UplinkSchedulerMBQoS::ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr)
-{
-    // Enqueue requests for uplink scheduler.
-    Ptr<UlJob> job = CreateObject<UlJob>();
-    Ptr<WimaxConnection> connection =
-        GetBs()->GetConnectionManager()->GetConnection(bwRequestHdr.GetCid());
-    SSRecord* ssRecord = GetBs()->GetSSManager()->GetSSRecord(connection->GetCid());
-    ServiceFlow* serviceFlow = connection->GetServiceFlow();
-
-    uint32_t size = bwRequestHdr.GetBr();
-    uint32_t pendingSize = GetPendingSize(serviceFlow);
-
-    if (size > pendingSize)
-    {
-        size -= pendingSize;
-    }
-    else
-    {
-        size = 0;
-    }
-
-    if (size == 0)
-    {
-        return;
-    }
-
-    Time deadline = DetermineDeadline(serviceFlow);
-    Time currentTime = Simulator::Now();
-    const Time& period = deadline; // So that deadline is properly updated..
-
-    NS_LOG_DEBUG("At " << Simulator::Now().As(Time::S)
-                       << " at BS uplink scheduler, processing bandwidth request from."
-                       << ssRecord->GetMacAddress() << " and sf "
-                       << serviceFlow->GetSchedulingType() << " with deadline in "
-                       << deadline.As(Time::S) << " and size " << size << " aggreg size "
-                       << bwRequestHdr.GetBr());
-
-    // Record data in job
-    job->SetSsRecord(ssRecord);
-    job->SetServiceFlow(serviceFlow);
-    job->SetSize(size);
-    job->SetDeadline(deadline);
-    job->SetReleaseTime(currentTime);
-    job->SetSchedulingType(serviceFlow->GetSchedulingType());
-    job->SetPeriod(period);
-    job->SetType(DATA);
-
-    // Enqueue job in Uplink Scheduler
-    switch (serviceFlow->GetSchedulingType())
-    {
-    case ServiceFlow::SF_TYPE_RTPS:
-    case ServiceFlow::SF_TYPE_NRTPS:
-        EnqueueJob(UlJob::INTERMEDIATE, job);
-        break;
-    case ServiceFlow::SF_TYPE_BE:
-    default:
-        EnqueueJob(UlJob::LOW, job);
-        break;
-    }
-}
-
-/*
- * Calculate Deadline of requests according to QoS parameter
- * */
-Time
-UplinkSchedulerMBQoS::DetermineDeadline(ServiceFlow* serviceFlow)
-{
-    uint32_t latency = serviceFlow->GetMaximumLatency();
-    Time lastGrantTime = serviceFlow->GetRecord()->GetLastGrantTime();
-    Time deadline = MilliSeconds(latency) + lastGrantTime;
-    return deadline;
-}
-
-void
-UplinkSchedulerMBQoS::OnSetRequestedBandwidth(ServiceFlowRecord* sfr)
-{
-    // virtual function on UplinkScheduler
-    // this is not necessary on this implementation
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler-mbqos.h ns-3.46/src/wimax/model/bs-uplink-scheduler-mbqos.h
--- ns-3.45/src/wimax/model/bs-uplink-scheduler-mbqos.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler-mbqos.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2009 INRIA/LRC - Computer Networks Laboratory
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Flavio Kobuta <flaviokubota@gmail.com>
- *
- */
-
-#ifndef UPLINK_SCHEDULER_MBQOS_H
-#define UPLINK_SCHEDULER_MBQOS_H
-
-#include "bs-uplink-scheduler.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ul-job.h"
-#include "ul-mac-messages.h"
-#include "wimax-phy.h"
-
-#include "ns3/nstime.h"
-#include "ns3/object.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class SSRecord;
-class ServiceFlow;
-class ServiceFlowRecord;
-class UlJob;
-
-/**
- * @ingroup wimax
- * @brief This class implements a Migration-based Quality of Service uplink scheduler(MBQoS).
- *
- * This uplink scheduler uses three queues, the low priority
- * queue, the intermediate queue and the high priority queue.
- * The scheduler serves the requests in strict priority order
- * from the high priority queue to the low priority queue. The
- * low priority queue stores the bandwidth requests of the BE
- * service flow. The intermediate queue holds bandwidth requests
- * sent by rtPS and by nrtPS connections. rtPS and nrtPS requests
- * can migrate to the high priority queue to guarantee that
- * their QoS requirements are met. Besides the requests migrated
- * from the intermediate queue, the high priority queue stores
- * periodic grants and unicast request opportunities that must be
- * scheduled in the following frame. To guarantee the maximum delay
- * requirement, the BS assigns a deadline to each rtPS bandwidth
- * request in the intermediate queue. The minimum bandwidth
- * requirement of both rtPS and nrtPS connections is guaranteed
- * over a window of duration T .
- * Implementation of uplink scheduler:
- * Freitag, J.; da Fonseca, N.L.S., "Uplink Scheduling with Quality of Service in IEEE 802.16
- * Networks," Global Telecommunications Conference, 2007. GLOBECOM '07. IEEE , vol., no.,
- * pp.2503-2508, 26-30 Nov. 2007 URL:
- * http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=4411386&isnumber=4410910
- */
-class UplinkSchedulerMBQoS : public UplinkScheduler
-{
-  public:
-    UplinkSchedulerMBQoS();
-    /**
-     * Constructor
-     *
-     * @param time the time
-     */
-    UplinkSchedulerMBQoS(Time time);
-    ~UplinkSchedulerMBQoS() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * Get uplink allocations
-     * @returns std::list<OfdmUlMapIe>
-     */
-    std::list<OfdmUlMapIe> GetUplinkAllocations() const override;
-
-    /**
-     * Determines if channel descriptors sent in the current frame are
-     * required to be updated
-     * @param updateDcd update DCD if true
-     * @param updateUcd update UCD if true
-     * @param sendDcd send DCD if true
-     * @param sendUcd send UCD if true
-     */
-    void GetChannelDescriptorsToUpdate(bool& updateDcd,
-                                       bool& updateUcd,
-                                       bool& sendDcd,
-                                       bool& sendUcd) override;
-    /**
-     * Calculate allocation start time
-     * @returns the allocation start time
-     */
-    uint32_t CalculateAllocationStartTime() override;
-    /**
-     * Add uplink allocation
-     * @param ulMapIe the UL map IE
-     * @param allocationSize the allocation size
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                             const uint32_t& allocationSize,
-                             uint32_t& symbolsToAllocation,
-                             uint32_t& availableSymbols) override;
-
-    /**
-     * Schedule function
-     */
-    void Schedule() override;
-    /**
-     * Service unsolicited grants
-     * @param ssRecord the SS record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Service bandwidth requests
-     * @param ssRecord the SS record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Service bandwidth requests
-     * @param serviceFlow the service flow
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     * @returns true if successful
-     */
-    bool ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Allocate initial ranging interval
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                        uint32_t& availableSymbols) override;
-    /**
-     * Setup service flow
-     * @param ssRecord the SS record
-     * @param serviceFlow the service flow
-     */
-    void SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow) override;
-
-    /**
-     * @param availableSymbols available symbols in the uplink frame
-     * @brief Check deadline from jobs. Migrate requests if necessary.
-     *
-     * This method verifies for each rtPS request whether it should be
-     * migrated to the high priority queue or not. The conditions for
-     * migration are: request deadline expires in the frame following
-     * the next one, and the amount of bandwidth requested is less than
-     * or equal to the amount of available bytes in the next uplink frame.
-     */
-    void CheckDeadline(uint32_t& availableSymbols);
-
-    /**
-     * @param availableSymbols available symbols in the uplink frame.
-     * @brief Check if Minimum bandwidth is guarantee. Migrate requests if necessary.
-     *
-     * This method first calculate a priority value for each request
-     * in the intermediate queue. Then, sorts the intermediate queue
-     * according to the priority values. Finally, while there is available
-     * bandwidth, the scheduler migrate the requests to the high priority queue.
-     */
-    void CheckMinimumBandwidth(uint32_t& availableSymbols);
-
-    /**
-     * @brief Reset the current window.
-     * According to a configured time, reset the window.
-     */
-    void UplinkSchedWindowTimer();
-
-    /**
-     * @param priority Priority of queue
-     * @param job job information
-     *
-     * @brief Enqueue a job in a priority queue.
-     */
-    void EnqueueJob(UlJob::JobPriority priority, Ptr<UlJob> job);
-
-    /**
-     * @param priority Priority of queue
-     * @return Ptr<UlJob>
-     *
-     * @brief Dequeue a job from a priority queue.
-     */
-    Ptr<UlJob> DequeueJob(UlJob::JobPriority priority);
-
-    void ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr) override;
-
-    /**
-     * @param serviceFlow Service flow of connection
-     * @return Time
-     *
-     * @brief Calculates deadline of a request.
-     */
-    Time DetermineDeadline(ServiceFlow* serviceFlow);
-
-    /**
-     * This method is called once to initialize window.
-     */
-    void InitOnce() override;
-
-    /**
-     * @param jobs List of jobs
-     * @returns the symbols count
-     *
-     * Sum the amount of symbols of each job of a queue
-     */
-    uint32_t CountSymbolsQueue(std::list<Ptr<UlJob>> jobs);
-
-    /**
-     * @param job job
-     * @returns the symbols count
-     *
-     * Count the amount of symbols of a job.
-     */
-    uint32_t CountSymbolsJobs(Ptr<UlJob> job);
-
-    /**
-     * Set requested bandwidth
-     * @param sfr the service flow record
-     */
-    void OnSetRequestedBandwidth(ServiceFlowRecord* sfr) override;
-
-    /**
-     * @param ssRecord Subscriber station record
-     * @param schedType Service flow type
-     * @param reqType Type of packet
-     * @return Ptr<UlJob>
-     *
-     * Create and fill information of a job.
-     */
-    Ptr<UlJob> CreateUlJob(SSRecord* ssRecord,
-                           ServiceFlow::SchedulingType schedType,
-                           ReqType reqType);
-
-    /**
-     * @param serviceFlow ServiceFlow
-     * @return Ptr<UlJob>
-     *
-     * Get pending size.
-     */
-    uint32_t GetPendingSize(ServiceFlow* serviceFlow);
-
-    /**
-     * Service bandwidth requests bytes.
-     * @param serviceFlow the service flow
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     * @param allocationSizeBytes the allocation size in bytes
-     * @returns true if successful
-     */
-    bool ServiceBandwidthRequestsBytes(ServiceFlow* serviceFlow,
-                                       ServiceFlow::SchedulingType schedulingType,
-                                       OfdmUlMapIe& ulMapIe,
-                                       const WimaxPhy::ModulationType modulationType,
-                                       uint32_t& symbolsToAllocation,
-                                       uint32_t& availableSymbols,
-                                       uint32_t allocationSizeBytes);
-
-  private:
-    std::list<OfdmUlMapIe> m_uplinkAllocations; ///< uplink allocations
-
-    // queues for scheduler
-    std::list<Ptr<UlJob>> m_uplinkJobs_high;  ///< uplink jobs high priority
-    std::list<Ptr<UlJob>> m_uplinkJobs_inter; ///< uplink jobs intermedite priority
-    std::list<Ptr<UlJob>> m_uplinkJobs_low;   ///< uplink jobs low priority
-
-    // interval to reset window
-    Time m_windowInterval; ///< windows interval
-};
-
-} // namespace ns3
-
-#endif /* UPLINK_SCHEDULER_MBQOS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler-rtps.cc ns-3.46/src/wimax/model/bs-uplink-scheduler-rtps.cc
--- ns-3.45/src/wimax/model/bs-uplink-scheduler-rtps.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler-rtps.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,738 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *               2009 TELEMATICS LAB, Politecnico di Bari
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Giuseppe Piro <g.piro@poliba.it>
- */
-
-#include "bs-uplink-scheduler-rtps.h"
-
-#include "bandwidth-manager.h"
-#include "bs-link-manager.h"
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("UplinkSchedulerRtps");
-
-NS_OBJECT_ENSURE_REGISTERED(UplinkSchedulerRtps);
-
-UplinkSchedulerRtps::UplinkSchedulerRtps()
-{
-    SetBs(nullptr);
-    SetTimeStampIrInterval(Seconds(0));
-    SetNrIrOppsAllocated(0);
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    SetDcdTimeStamp(Simulator::Now());
-    SetUcdTimeStamp(Simulator::Now());
-}
-
-UplinkSchedulerRtps::UplinkSchedulerRtps(Ptr<BaseStationNetDevice> bs)
-{
-    SetBs(bs);
-    SetTimeStampIrInterval(Seconds(0));
-    SetNrIrOppsAllocated(0);
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    SetDcdTimeStamp(Simulator::Now());
-    SetUcdTimeStamp(Simulator::Now());
-}
-
-UplinkSchedulerRtps::~UplinkSchedulerRtps()
-{
-    SetBs(nullptr);
-    m_uplinkAllocations.clear();
-}
-
-TypeId
-UplinkSchedulerRtps::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::UplinkSchedulerRtps")
-                            .SetParent<UplinkScheduler>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<UplinkSchedulerRtps>();
-    return tid;
-}
-
-std::list<OfdmUlMapIe>
-UplinkSchedulerRtps::GetUplinkAllocations() const
-{
-    return m_uplinkAllocations;
-}
-
-void
-UplinkSchedulerRtps::GetChannelDescriptorsToUpdate(bool& updateDcd,
-                                                   bool& updateUcd,
-                                                   bool& sendDcd,
-                                                   bool& sendUcd)
-{
-    /*DCD and UCD shall actually be updated when channel or burst profile definitions
-     change. burst profiles are updated based on number of SSs, network conditions and etc.
-     for now temporarily assuming DCD/UCD shall be updated every time */
-
-    uint32_t randNr = rand();
-    if (randNr % 5 == 0 || GetBs()->GetNrDcdSent() == 0)
-    {
-        sendDcd = true;
-    }
-
-    randNr = rand();
-    if (randNr % 5 == 0 || GetBs()->GetNrUcdSent() == 0)
-    {
-        sendUcd = true;
-    }
-
-    // -------------------------------------
-    // additional, just to send more frequently
-    if (!sendDcd)
-    {
-        randNr = rand();
-        if (randNr % 4 == 0)
-        {
-            sendDcd = true;
-        }
-    }
-
-    if (!sendUcd)
-    {
-        randNr = rand();
-        if (randNr % 4 == 0)
-        {
-            sendUcd = true;
-        }
-    }
-    // -------------------------------------
-
-    Time timeSinceLastDcd = Simulator::Now() - GetDcdTimeStamp();
-    Time timeSinceLastUcd = Simulator::Now() - GetUcdTimeStamp();
-
-    if (timeSinceLastDcd > GetBs()->GetDcdInterval())
-    {
-        sendDcd = true;
-        SetDcdTimeStamp(Simulator::Now());
-    }
-
-    if (timeSinceLastUcd > GetBs()->GetUcdInterval())
-    {
-        sendUcd = true;
-        SetUcdTimeStamp(Simulator::Now());
-    }
-}
-
-uint32_t
-UplinkSchedulerRtps::CalculateAllocationStartTime()
-{
-    return GetBs()->GetNrDlSymbols() * GetBs()->GetPhy()->GetPsPerSymbol() + GetBs()->GetTtg();
-}
-
-void
-UplinkSchedulerRtps::AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                                         const uint32_t& allocationSize,
-                                         uint32_t& symbolsToAllocation,
-                                         uint32_t& availableSymbols)
-{
-    ulMapIe.SetDuration(allocationSize);
-    ulMapIe.SetStartTime(symbolsToAllocation);
-    m_uplinkAllocations.push_back(ulMapIe);
-    symbolsToAllocation += allocationSize;
-    availableSymbols -= allocationSize;
-}
-
-void
-UplinkSchedulerRtps::Schedule()
-{
-    m_uplinkAllocations.clear();
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    bool allocationForDsa = false;
-
-    uint32_t symbolsToAllocation = 0;
-    uint32_t allocationSize = 0; // size in symbols
-    uint32_t availableSymbols = GetBs()->GetNrUlSymbols();
-
-    WimaxPhy::ModulationType modulationType;
-    Cid cid;
-
-    AllocateInitialRangingInterval(symbolsToAllocation, availableSymbols);
-
-    std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
-    NS_LOG_INFO("UL Scheduler start, availableSymbols = " << availableSymbols);
-
-    for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-    {
-        SSRecord* ssRecord = *iter;
-        if (ssRecord->GetIsBroadcastSS())
-        {
-            continue;
-        }
-        cid = ssRecord->GetBasicCid();
-        OfdmUlMapIe ulMapIe;
-        ulMapIe.SetCid(cid);
-
-        if (ssRecord->GetPollForRanging() &&
-            ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_CONTINUE)
-        {
-            // SS's ranging is not yet complete
-            // allocating invited initial ranging interval
-            ulMapIe.SetUiuc(OfdmUlBurstProfile::UIUC_INITIAL_RANGING);
-            allocationSize = GetBs()->GetRangReqOppSize();
-            SetIsInvIrIntrvlAllocated(true);
-
-            if (availableSymbols >= allocationSize)
-            {
-                AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
-            }
-            else
-            {
-                break;
-            }
-        }
-        else
-        {
-            modulationType = ssRecord->GetModulationType();
-
-            // need to update because modulation/FEC to UIUC mapping may vary over time
-            ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_UPLINK));
-
-            // establish service flows for SS
-            if (ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_SUCCESS &&
-                !ssRecord->GetAreServiceFlowsAllocated())
-            {
-                // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ
-                // and DSA-ACK only one DSA allocation per frame
-                if (!allocationForDsa)
-                {
-                    allocationSize =
-                        GetBs()->GetPhy()->GetNrSymbols(sizeof(DsaReq), modulationType);
-                    if (availableSymbols >= allocationSize)
-                    {
-                        AddUplinkAllocation(ulMapIe,
-                                            allocationSize,
-                                            symbolsToAllocation,
-                                            availableSymbols);
-                        allocationForDsa = true;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-            }
-            else
-            {
-                // all service flows associated to SS are established now
-
-                /*allocating grants for data transmission for UGS flows (Data Grant Burst Type
-                 IEs, 6.3.7.4.3.3) (grant has been referred by different names e.g. transmission
-                 opportunity, slot, uplink allocation, etc)*/
-                ServiceUnsolicitedGrants(ssRecord,
-                                         ServiceFlow::SF_TYPE_UGS,
-                                         ulMapIe,
-                                         modulationType,
-                                         symbolsToAllocation,
-                                         availableSymbols);
-
-                // allocate unicast polls for rtPS flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceUnsolicitedGrants(ssRecord,
-                                             ServiceFlow::SF_TYPE_RTPS,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-                // allocate unicast polls for nrtPS flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceUnsolicitedGrants(ssRecord,
-                                             ServiceFlow::SF_TYPE_NRTPS,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-                // finally allocate unicast polls for BE flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceUnsolicitedGrants(ssRecord,
-                                             ServiceFlow::SF_TYPE_BE,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-            }
-        }
-    }
-
-    /*
-     * Uplink Scheduler for rtPS Connection
-     */
-    if (availableSymbols)
-    {
-        ULSchedulerRTPSConnection(symbolsToAllocation, availableSymbols);
-    }
-
-    // UL Scheduler for nrtPS and BE flows
-    if (availableSymbols)
-    {
-        for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-        {
-            SSRecord* ssRecord = *iter;
-            if (ssRecord->GetIsBroadcastSS())
-            {
-                continue;
-            }
-            if (!ssRecord->GetPollForRanging() &&
-                ssRecord->GetRangingStatus() != WimaxNetDevice::RANGING_STATUS_CONTINUE &&
-                ssRecord->GetAreServiceFlowsAllocated())
-            {
-                OfdmUlMapIe ulMapIe;
-                cid = ssRecord->GetBasicCid();
-                ulMapIe.SetCid(cid);
-                modulationType = ssRecord->GetModulationType();
-                ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                    modulationType,
-                    WimaxNetDevice::DIRECTION_UPLINK));
-
-                // allocate unicast polls for nrtPS flows if bandwidth is available
-
-                ServiceBandwidthRequests(ssRecord,
-                                         ServiceFlow::SF_TYPE_NRTPS,
-                                         ulMapIe,
-                                         modulationType,
-                                         symbolsToAllocation,
-                                         availableSymbols);
-
-                // finally allocate unicast polls for BE flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceBandwidthRequests(ssRecord,
-                                             ServiceFlow::SF_TYPE_BE,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-            }
-        }
-    }
-
-    OfdmUlMapIe ulMapIeEnd;
-    ulMapIeEnd.SetCid(Cid::InitialRanging());
-    ulMapIeEnd.SetStartTime(symbolsToAllocation);
-    ulMapIeEnd.SetUiuc(OfdmUlBurstProfile::UIUC_END_OF_MAP);
-    ulMapIeEnd.SetDuration(0);
-    m_uplinkAllocations.push_back(ulMapIeEnd);
-
-    // setting DL/UL subframe allocation for the next frame
-    GetBs()->GetBandwidthManager()->SetSubframeRatio();
-}
-
-void
-UplinkSchedulerRtps::ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                              ServiceFlow::SchedulingType schedulingType,
-                                              OfdmUlMapIe& ulMapIe,
-                                              const WimaxPhy::ModulationType modulationType,
-                                              uint32_t& symbolsToAllocation,
-                                              uint32_t& availableSymbols)
-{
-    uint32_t allocationSize = 0;      // size in symbols
-    uint8_t uiuc = ulMapIe.GetUiuc(); // SS's burst profile
-    std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        ServiceFlow* serviceFlow = *iter;
-
-        /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request
-         IEs, 6.3.7.4.3.1). in case of UGS, allocating grants for data transmission (Data Grant
-         Burst Type IEs, 6.3.7.4.3.3) (grant has been referred in this code by different names e.g.
-         transmission opportunity, slot, allocation, etc) */
-
-        allocationSize =
-            GetBs()->GetBandwidthManager()->CalculateAllocationSize(ssRecord, serviceFlow);
-
-        // verifying that minimum reserved traffic rate of nrtPS flow is maintained
-        if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS)
-        {
-            Time currentTime = Simulator::Now();
-            ServiceFlowRecord* record = serviceFlow->GetRecord();
-            if (currentTime - record->GetGrantTimeStamp() > Seconds(1))
-            {
-                uint32_t bps = (record->GetBwSinceLastExpiry() * 8);
-                if (bps < serviceFlow->GetMinReservedTrafficRate())
-                {
-                    ServiceBandwidthRequests(serviceFlow,
-                                             schedulingType,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                    record->SetBwSinceLastExpiry(0);
-                    record->SetGrantTimeStamp(currentTime);
-                }
-            }
-        }
-
-        if (availableSymbols < allocationSize)
-        {
-            break;
-        }
-
-        if (allocationSize > 0)
-        {
-            ulMapIe.SetStartTime(symbolsToAllocation);
-            if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS)
-            {
-                // special burst profile with most robust modulation type is used for unicast polls
-                // (Request IEs)
-                ulMapIe.SetUiuc(OfdmUlBurstProfile::UIUC_REQ_REGION_FULL);
-            }
-        }
-        else
-        {
-            continue;
-        }
-
-        if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_UGS)
-        {
-            NS_LOG_DEBUG("BS uplink scheduler, UGS allocation, size: " << allocationSize
-                                                                       << " symbols");
-        }
-        else
-        {
-            NS_LOG_DEBUG("BS uplink scheduler, " << serviceFlow->GetSchedulingTypeStr()
-                                                 << " unicast poll, size: " << allocationSize
-                                                 << " symbols, modulation: BPSK 1/2");
-        }
-
-        NS_LOG_DEBUG(", CID: " << serviceFlow->GetConnection()->GetCid()
-                               << ", SFID: " << serviceFlow->GetSfid());
-
-        AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
-        ulMapIe.SetUiuc(uiuc);
-    }
-}
-
-void
-UplinkSchedulerRtps::ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                              ServiceFlow::SchedulingType schedulingType,
-                                              OfdmUlMapIe& ulMapIe,
-                                              const WimaxPhy::ModulationType modulationType,
-                                              uint32_t& symbolsToAllocation,
-                                              uint32_t& availableSymbols)
-{
-    std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        if (!ServiceBandwidthRequests(*iter,
-                                      schedulingType,
-                                      ulMapIe,
-                                      modulationType,
-                                      symbolsToAllocation,
-                                      availableSymbols))
-        {
-            break;
-        }
-    }
-}
-
-bool
-UplinkSchedulerRtps::ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                              ServiceFlow::SchedulingType schedulingType,
-                                              OfdmUlMapIe& ulMapIe,
-                                              const WimaxPhy::ModulationType modulationType,
-                                              uint32_t& symbolsToAllocation,
-                                              uint32_t& availableSymbols)
-{
-    uint32_t allocSizeBytes = 0;
-    uint32_t allocSizeSymbols = 0;
-    uint16_t sduSize = 0;
-
-    ServiceFlowRecord* record = serviceFlow->GetRecord();
-    sduSize = serviceFlow->GetSduSize();
-
-    uint32_t requiredBandwidth = record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
-    if (requiredBandwidth > 0)
-    {
-        if (sduSize > 0)
-        {
-            // if SDU size is mentioned, allocate grant of that size
-            allocSizeBytes = sduSize;
-            allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
-        }
-        else
-        {
-            allocSizeBytes = requiredBandwidth;
-            allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
-        }
-
-        if (availableSymbols >= allocSizeSymbols)
-        {
-            NS_LOG_DEBUG("BS uplink scheduler, "
-                         << serviceFlow->GetSchedulingTypeStr()
-                         << " allocation, size: " << allocSizeSymbols << " symbols"
-                         << ", CID: " << serviceFlow->GetConnection()->GetCid()
-                         << ", SFID: " << serviceFlow->GetSfid()
-                         << ", bw requested: " << record->GetRequestedBandwidth()
-                         << ", bw granted: " << record->GetGrantedBandwidth());
-
-            record->UpdateGrantedBandwidth(allocSizeBytes);
-
-            if (schedulingType == ServiceFlow::SF_TYPE_NRTPS)
-            {
-                record->SetBwSinceLastExpiry(allocSizeBytes);
-            }
-
-            AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
-        }
-        else
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-void
-UplinkSchedulerRtps::ULSchedulerRTPSConnection(uint32_t& symbolsToAllocation,
-                                               uint32_t& availableSymbols)
-{
-    NS_LOG_INFO("\tUL Scheduler for rtPS flows");
-    NS_LOG_INFO("\t\tavailableSymbols = " << availableSymbols);
-    ServiceFlowRecord* record_[100];
-    uint32_t allocSizeSymbols_[100]; // symbolsRequired for each SSRecord
-    OfdmUlMapIe ulMapIe_[100];
-    OfdmUlMapIe ulMapIe;
-    WimaxPhy::ModulationType modulationType_[100];
-    WimaxPhy::ModulationType modulationType;
-    int nbAllocation = 0;
-    uint32_t allocSizeBytes;
-    uint32_t totAllocSizeSymbols = 0;
-
-    Cid cid;
-    std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
-
-    for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-    {
-        SSRecord* ssRecord = *iter;
-        if (ssRecord->GetIsBroadcastSS())
-        {
-            continue;
-        }
-        if (!ssRecord->GetPollForRanging() &&
-            ssRecord->GetRangingStatus() != WimaxNetDevice::RANGING_STATUS_CONTINUE &&
-            ssRecord->GetAreServiceFlowsAllocated())
-        {
-            cid = ssRecord->GetBasicCid();
-            ulMapIe.SetCid(cid);
-            modulationType = ssRecord->GetModulationType();
-            ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_UPLINK));
-
-            std::vector<ServiceFlow*> serviceFlows =
-                ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_RTPS);
-            for (auto iter2 = serviceFlows.begin(); iter2 != serviceFlows.end(); ++iter2)
-            {
-                record_[nbAllocation] = (*iter2)->GetRecord();
-                uint32_t requiredBandwidth = record_[nbAllocation]->GetRequestedBandwidth() -
-                                             record_[nbAllocation]->GetGrantedBandwidth();
-
-                if (requiredBandwidth > 0)
-                {
-                    modulationType_[nbAllocation] = modulationType;
-                    ulMapIe_[nbAllocation] = ulMapIe;
-                    allocSizeBytes = requiredBandwidth;
-                    allocSizeSymbols_[nbAllocation] =
-                        GetBs()->GetPhy()->GetNrSymbols(allocSizeBytes,
-                                                        modulationType_[nbAllocation]);
-                    totAllocSizeSymbols += allocSizeSymbols_[nbAllocation];
-
-                    NS_LOG_INFO(
-                        "\t\tUL Scheduler for CID = " << (*iter2)->GetConnection()->GetCid());
-                    NS_LOG_INFO("\t\t\trequiredBandwidth = "
-                                << record_[nbAllocation]->GetRequestedBandwidth()
-                                << ", allocSizeSymbols = " << allocSizeSymbols_[nbAllocation]
-                                << ", modulationType = " << modulationType_[nbAllocation]);
-
-                    nbAllocation += 1;
-                }
-            }
-        }
-    }
-
-    NS_LOG_INFO("\t\ttotAllocSizeSymbols = " << totAllocSizeSymbols);
-
-    // Channel Saturation
-    while (totAllocSizeSymbols > availableSymbols)
-    {
-        NS_LOG_INFO("\tUL Channel Saturation: totAllocSizeSymbols > availableSymbols");
-        double delta = double(availableSymbols) / double(totAllocSizeSymbols);
-        NS_LOG_INFO("\t\tdelta = " << delta);
-        totAllocSizeSymbols = 0;
-        for (int i = 0; i < nbAllocation; i++)
-        {
-            NS_LOG_INFO("\t\tprevious allocSizeSymbols_[" << i << "] = " << allocSizeSymbols_[i]);
-            allocSizeSymbols_[i] = (uint32_t)std::floor(allocSizeSymbols_[i] * delta);
-            totAllocSizeSymbols += allocSizeSymbols_[i];
-            NS_LOG_INFO("\t\tnew allocSizeSymbols_[" << i << "] = " << allocSizeSymbols_[i]);
-        }
-        NS_LOG_INFO("\t\ttotAllocSizeSymbols = " << totAllocSizeSymbols);
-    }
-
-    // Uplink Bandwidth Allocation
-    for (int i = 0; i < nbAllocation; i++)
-    {
-        AddUplinkAllocation(ulMapIe_[i],
-                            allocSizeSymbols_[i],
-                            symbolsToAllocation,
-                            availableSymbols);
-        allocSizeBytes = GetBs()->GetPhy()->GetNrBytes(allocSizeSymbols_[i], modulationType_[i]);
-        NS_LOG_INFO("\t\tUpdateGrantedBandwidth for " << i << " = " << allocSizeBytes);
-        if (record_[i]->GetRequestedBandwidth() < allocSizeBytes)
-        {
-            // the flow need new poll to set the newer requiredBandwidth
-            record_[i]->SetGrantedBandwidth(0);
-            record_[i]->SetRequestedBandwidth(0);
-        }
-        else
-        {
-            record_[i]->UpdateGrantedBandwidth(allocSizeBytes);
-        }
-    }
-}
-
-void
-UplinkSchedulerRtps::AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                                    uint32_t& availableSymbols)
-{
-    Time ssUlStartTime =
-        Seconds(CalculateAllocationStartTime() * GetBs()->GetPsDuration().GetSeconds());
-    SetNrIrOppsAllocated(GetBs()->GetLinkManager()->CalculateRangingOppsToAllocate());
-    uint32_t allocationSize = GetNrIrOppsAllocated() * GetBs()->GetRangReqOppSize();
-    Time timeSinceLastIrInterval = Simulator::Now() - GetTimeStampIrInterval();
-
-    // adding one frame because may be the time has not elapsed now but will elapse before the next
-    // frame is sent
-    if (timeSinceLastIrInterval + GetBs()->GetPhy()->GetFrameDuration() >
-            GetBs()->GetInitialRangingInterval() &&
-        availableSymbols >= allocationSize)
-    {
-        SetIsIrIntrvlAllocated(true);
-        OfdmUlMapIe ulMapIeIr;
-        ulMapIeIr.SetCid(GetBs()->GetBroadcastConnection()->GetCid());
-        ulMapIeIr.SetStartTime(symbolsToAllocation);
-        ulMapIeIr.SetUiuc(OfdmUlBurstProfile::UIUC_INITIAL_RANGING);
-
-        NS_LOG_DEBUG("BS uplink scheduler, initial ranging allocation, size: "
-                     << allocationSize << " symbols, modulation: BPSK 1/2");
-
-        // marking start and end of each TO, only for debugging
-        for (uint8_t i = 0; i < GetNrIrOppsAllocated(); i++)
-        {
-            GetBs()->MarkRangingOppStart(
-                ssUlStartTime +
-                Seconds(symbolsToAllocation * GetBs()->GetSymbolDuration().GetSeconds()) +
-                Seconds(i * GetBs()->GetRangReqOppSize() *
-                        GetBs()->GetSymbolDuration().GetSeconds()));
-        }
-
-        AddUplinkAllocation(ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
-        SetTimeStampIrInterval(Simulator::Now());
-    }
-}
-
-void
-UplinkSchedulerRtps::SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow)
-{
-    uint8_t delayNrFrames = 1;
-    uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate();
-    WimaxPhy::ModulationType modulation;
-    uint32_t bytesPerFrame =
-        (uint32_t((double)(bitsPerSecond)*GetBs()->GetPhy()->GetFrameDuration().GetSeconds())) / 8;
-    uint32_t frameDurationMSec = GetBs()->GetPhy()->GetFrameDuration().GetMilliSeconds();
-
-    switch (serviceFlow->GetSchedulingType())
-    {
-    case ServiceFlow::SF_TYPE_UGS: {
-        if (serviceFlow->GetIsMulticast())
-        {
-            modulation = serviceFlow->GetModulation();
-        }
-        else
-        {
-            modulation = ssRecord->GetModulationType();
-        }
-        uint32_t grantSize = GetBs()->GetPhy()->GetNrSymbols(bytesPerFrame, modulation);
-        serviceFlow->GetRecord()->SetGrantSize(grantSize);
-
-        uint32_t toleratedJitter = serviceFlow->GetToleratedJitter();
-
-        if (toleratedJitter > frameDurationMSec)
-        {
-            delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
-        }
-
-        uint16_t interval = delayNrFrames * frameDurationMSec;
-        serviceFlow->SetUnsolicitedGrantInterval(interval);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_RTPS: {
-        if (serviceFlow->GetSduSize() > bytesPerFrame)
-        {
-            delayNrFrames = (uint8_t)(serviceFlow->GetSduSize() / bytesPerFrame);
-        }
-
-        uint16_t interval = delayNrFrames * frameDurationMSec;
-        serviceFlow->SetUnsolicitedPollingInterval(interval);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_NRTPS:
-        // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
-    case ServiceFlow::SF_TYPE_BE:
-        // no real-time guarantees are given to BE, serviced based on available bandwidth
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-    }
-}
-
-void
-UplinkSchedulerRtps::InitOnce()
-{
-}
-
-void
-UplinkSchedulerRtps::ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr)
-{
-}
-
-void
-UplinkSchedulerRtps::OnSetRequestedBandwidth(ServiceFlowRecord* sfr)
-{
-    // m_grantedBandwidth must be reset to zero
-    uint32_t grantedBandwidth = 0;
-    sfr->SetGrantedBandwidth(grantedBandwidth);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler-rtps.h ns-3.46/src/wimax/model/bs-uplink-scheduler-rtps.h
--- ns-3.45/src/wimax/model/bs-uplink-scheduler-rtps.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler-rtps.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Giuseppe Piro <g.piro@poliba.it>
- */
-
-#ifndef UPLINK_SCHEDULER_RTPS_H
-#define UPLINK_SCHEDULER_RTPS_H
-
-#include "bs-uplink-scheduler.h"
-#include "ul-mac-messages.h"
-#include "wimax-phy.h"
-
-#include "ns3/nstime.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class SSRecord;
-class ServiceFlow;
-
-/**
- * @ingroup wimax
- * @brief This class implements a simple uplink scheduler for rtPS flows.
- *
- * The UL-rtPS-Scheduler work in this way:
- * At the beginning of the UL sub-frame some symbols are allocated
- * to the rangingInterval Messages, DSA Messages, UGS grants and
- * UGS/rtPS/nrtPS/BE poll.
- * Then, the remaining available symbols are allocated to the all
- * rtPS flows according to their requestedBandwidth.
- * The bandwidth saturation control has been implemented to
- * redistribute the resource if the sum of requestedBandwidth exceed
- * the available bandwidth.
- * At the end, if there are some free symbols, their are allocated to
- * nrtPS and BE Connections.
- */
-
-class UplinkSchedulerRtps : public UplinkScheduler
-{
-  public:
-    UplinkSchedulerRtps();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    UplinkSchedulerRtps(Ptr<BaseStationNetDevice> bs);
-    ~UplinkSchedulerRtps() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief Get uplink allocations.
-     * @returns std::list<OfdmUlMapIe>
-     */
-    std::list<OfdmUlMapIe> GetUplinkAllocations() const override;
-
-    /**
-     * Determines if channel descriptors sent in the current frame are
-     * required to be updated
-     * @param updateDcd if true update DCD
-     * @param updateUcd if true update UCD
-     * @param sendDcd if true send DCD
-     * @param sendUcd if true send UCD
-     */
-    void GetChannelDescriptorsToUpdate(bool& updateDcd,
-                                       bool& updateUcd,
-                                       bool& sendDcd,
-                                       bool& sendUcd) override;
-    /**
-     * Calculate allocation start time function
-     * @returns the allocation start time value
-     */
-    uint32_t CalculateAllocationStartTime() override;
-    /**
-     * Add Uplink Allocation function
-     * @param ulMapIe the UL map IE
-     * @param allocationSize the allocation size
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                             const uint32_t& allocationSize,
-                             uint32_t& symbolsToAllocation,
-                             uint32_t& availableSymbols) override;
-    /**
-     * @brief Schedule function.
-     */
-    void Schedule() override;
-    /**
-     * Service Unsolicited Grants function
-     * @param ssRecord Subscriber station record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Service Bandwidth Requests function
-     * @param ssRecord Subscriber station record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Service bandwidth requests function
-     * @param serviceFlow the service flow
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     * @returns true if successful
-     */
-    bool ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * @brief Uplink Scheduler for rtPS connections.
-     *
-     * @param symbolsToAllocation symbols to allocation for UpLink Subframe
-     * @param availableSymbols available symbols for rtPS flows
-     *
-     * This method represent the UL Scheduler for rtPS  connections.
-     * The scheduler is designed to serve all rtPS connections that
-     * have at least one packet to transmit, every UL Subframe.
-     * The method selects all rtPS connection that have al least one
-     * packet to transmit. To each rtPS connections are allocated,
-     * at the beginning, the bandwidth to transmit a quota of data equal
-     * to (RequestedBandwidth - GrantedBandwidth).
-     * If the sum of all pre-allocated bandwidth exceed the available
-     * symbols for rtPS connections, the Channel Saturation Control function
-     * is called to redistribute the available bandwidth.
-     */
-    void ULSchedulerRTPSConnection(uint32_t& symbolsToAllocation, uint32_t& availableSymbols);
-    /**
-     * Allocate Initial Ranging Interval function
-     *
-     * @param symbolsToAllocation symbols to allocation for UpLink Subframe
-     * @param availableSymbols available symbols for rtPS flows
-     */
-    void AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                        uint32_t& availableSymbols) override;
-    /**
-     * Setup service flow function
-     * @param ssRecord Subscriber station record
-     * @param serviceFlow the service flow
-     */
-    void SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow) override;
-
-    /**
-     * Process bandwidth request function
-     * @param bwRequestHdr the bandwidth request header
-     */
-    void ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr) override;
-
-    /// Init once function
-    void InitOnce() override;
-
-    /**
-     * Set requested bandwidth function
-     * @param sfr the service flow record
-     */
-    void OnSetRequestedBandwidth(ServiceFlowRecord* sfr) override;
-
-  private:
-    std::list<OfdmUlMapIe> m_uplinkAllocations; ///< uplink allocations
-};
-
-} // namespace ns3
-
-#endif /* UPLINK_SCHEDULER_RTPS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler-simple.cc ns-3.46/src/wimax/model/bs-uplink-scheduler-simple.cc
--- ns-3.45/src/wimax/model/bs-uplink-scheduler-simple.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler-simple.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,585 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "bs-uplink-scheduler-simple.h"
-
-#include "bandwidth-manager.h"
-#include "bs-link-manager.h"
-#include "bs-net-device.h"
-#include "burst-profile-manager.h"
-#include "cid.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-record.h"
-
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("UplinkSchedulerSimple");
-
-NS_OBJECT_ENSURE_REGISTERED(UplinkSchedulerSimple);
-
-UplinkSchedulerSimple::UplinkSchedulerSimple()
-{
-    SetBs(nullptr);
-    SetTimeStampIrInterval(Seconds(0));
-    SetNrIrOppsAllocated(0);
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    SetDcdTimeStamp(Simulator::Now());
-    SetUcdTimeStamp(Simulator::Now());
-}
-
-UplinkSchedulerSimple::UplinkSchedulerSimple(Ptr<BaseStationNetDevice> bs)
-{
-    SetBs(bs);
-    SetTimeStampIrInterval(Seconds(0));
-    SetNrIrOppsAllocated(0);
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    SetDcdTimeStamp(Simulator::Now());
-    SetUcdTimeStamp(Simulator::Now());
-}
-
-UplinkSchedulerSimple::~UplinkSchedulerSimple()
-{
-    SetBs(nullptr);
-    m_uplinkAllocations.clear();
-}
-
-void
-UplinkSchedulerSimple::InitOnce()
-{
-}
-
-TypeId
-UplinkSchedulerSimple::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::UplinkSchedulerSimple")
-                            .SetParent<UplinkScheduler>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<UplinkSchedulerSimple>();
-    return tid;
-}
-
-std::list<OfdmUlMapIe>
-UplinkSchedulerSimple::GetUplinkAllocations() const
-{
-    return m_uplinkAllocations;
-}
-
-void
-UplinkSchedulerSimple::GetChannelDescriptorsToUpdate(bool& updateDcd,
-                                                     bool& updateUcd,
-                                                     bool& sendDcd,
-                                                     bool& sendUcd)
-{
-    /*DCD and UCD shall actually be updated when channel or burst profile definitions
-     change. burst profiles are updated based on number of SSs, network conditions and etc.
-     for now temporarily assuming DCD/UCD shall be updated every time */
-
-    uint32_t randNr = rand();
-    if (randNr % 5 == 0 || GetBs()->GetNrDcdSent() == 0)
-    {
-        sendDcd = true;
-    }
-
-    randNr = rand();
-    if (randNr % 5 == 0 || GetBs()->GetNrUcdSent() == 0)
-    {
-        sendUcd = true;
-    }
-
-    // -------------------------------------
-    // additional, just to send more frequently
-    if (!sendDcd)
-    {
-        randNr = rand();
-        if (randNr % 4 == 0)
-        {
-            sendDcd = true;
-        }
-    }
-
-    if (!sendUcd)
-    {
-        randNr = rand();
-        if (randNr % 4 == 0)
-        {
-            sendUcd = true;
-        }
-    }
-    // -------------------------------------
-
-    Time timeSinceLastDcd = Simulator::Now() - GetDcdTimeStamp();
-    Time timeSinceLastUcd = Simulator::Now() - GetUcdTimeStamp();
-
-    if (timeSinceLastDcd > GetBs()->GetDcdInterval())
-    {
-        sendDcd = true;
-        SetDcdTimeStamp(Simulator::Now());
-    }
-
-    if (timeSinceLastUcd > GetBs()->GetUcdInterval())
-    {
-        sendUcd = true;
-        SetUcdTimeStamp(Simulator::Now());
-    }
-}
-
-uint32_t
-UplinkSchedulerSimple::CalculateAllocationStartTime()
-{
-    return GetBs()->GetNrDlSymbols() * GetBs()->GetPhy()->GetPsPerSymbol() + GetBs()->GetTtg();
-}
-
-void
-UplinkSchedulerSimple::AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                                           const uint32_t& allocationSize,
-                                           uint32_t& symbolsToAllocation,
-                                           uint32_t& availableSymbols)
-{
-    ulMapIe.SetDuration(allocationSize);
-    ulMapIe.SetStartTime(symbolsToAllocation);
-    m_uplinkAllocations.push_back(ulMapIe);
-    symbolsToAllocation += allocationSize;
-    availableSymbols -= allocationSize;
-}
-
-void
-UplinkSchedulerSimple::Schedule()
-{
-    m_uplinkAllocations.clear();
-    SetIsIrIntrvlAllocated(false);
-    SetIsInvIrIntrvlAllocated(false);
-    bool allocationForDsa = false;
-
-    uint32_t symbolsToAllocation = 0;
-    uint32_t allocationSize = 0; // size in symbols
-    uint32_t availableSymbols = GetBs()->GetNrUlSymbols();
-
-    AllocateInitialRangingInterval(symbolsToAllocation, availableSymbols);
-
-    std::vector<SSRecord*>* ssRecords = GetBs()->GetSSManager()->GetSSRecords();
-    for (auto iter = ssRecords->begin(); iter != ssRecords->end(); ++iter)
-    {
-        SSRecord* ssRecord = *iter;
-
-        if (ssRecord->GetIsBroadcastSS())
-        {
-            continue;
-        }
-        Cid cid = ssRecord->GetBasicCid();
-        OfdmUlMapIe ulMapIe;
-        ulMapIe.SetCid(cid);
-
-        if (ssRecord->GetPollForRanging() &&
-            ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_CONTINUE)
-        {
-            // SS's ranging is not yet complete
-            // allocating invited initial ranging interval
-            ulMapIe.SetUiuc(OfdmUlBurstProfile::UIUC_INITIAL_RANGING);
-            allocationSize = GetBs()->GetRangReqOppSize();
-            SetIsInvIrIntrvlAllocated(true);
-
-            if (availableSymbols >= allocationSize)
-            {
-                AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
-            }
-            else
-            {
-                break;
-            }
-        }
-        else
-        {
-            WimaxPhy::ModulationType modulationType = ssRecord->GetModulationType();
-
-            // need to update because modulation/FEC to UIUC mapping may vary over time
-            ulMapIe.SetUiuc(GetBs()->GetBurstProfileManager()->GetBurstProfile(
-                modulationType,
-                WimaxNetDevice::DIRECTION_UPLINK));
-
-            // establish service flows for SS
-            if (ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_SUCCESS &&
-                !ssRecord->GetAreServiceFlowsAllocated())
-            {
-                // allocating grant (with arbitrary size) to allow SS to send DSA messages DSA-REQ
-                // and DSA-ACK only one DSA allocation per frame
-                if (!allocationForDsa)
-                {
-                    allocationSize =
-                        GetBs()->GetPhy()->GetNrSymbols(sizeof(DsaReq), modulationType);
-
-                    if (availableSymbols >= allocationSize)
-                    {
-                        AddUplinkAllocation(ulMapIe,
-                                            allocationSize,
-                                            symbolsToAllocation,
-                                            availableSymbols);
-                        allocationForDsa = true;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-            }
-            else
-            {
-                // all service flows associated to SS are established now
-
-                /*allocating grants for data transmission for UGS flows (Data Grant Burst Type
-                 IEs, 6.3.7.4.3.3) (grant has been referred by different names e.g. transmission
-                 opportunity, slot, uplink allocation, etc)*/
-                ServiceUnsolicitedGrants(ssRecord,
-                                         ServiceFlow::SF_TYPE_UGS,
-                                         ulMapIe,
-                                         modulationType,
-                                         symbolsToAllocation,
-                                         availableSymbols);
-
-                // allocate unicast polls for rtPS flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceUnsolicitedGrants(ssRecord,
-                                             ServiceFlow::SF_TYPE_RTPS,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-                // allocate unicast polls for nrtPS flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceUnsolicitedGrants(ssRecord,
-                                             ServiceFlow::SF_TYPE_NRTPS,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-                // finally allocate unicast polls for BE flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceUnsolicitedGrants(ssRecord,
-                                             ServiceFlow::SF_TYPE_BE,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-
-                // now allocating grants for non-UGS flows (i.e., in response of bandwidth requests)
-
-                if (availableSymbols)
-                {
-                    ServiceBandwidthRequests(ssRecord,
-                                             ServiceFlow::SF_TYPE_RTPS,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-                // allocate unicast polls for nrtPS flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceBandwidthRequests(ssRecord,
-                                             ServiceFlow::SF_TYPE_NRTPS,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-                // finally allocate unicast polls for BE flows if bandwidth is available
-                if (availableSymbols)
-                {
-                    ServiceBandwidthRequests(ssRecord,
-                                             ServiceFlow::SF_TYPE_BE,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                }
-            }
-        }
-    }
-    OfdmUlMapIe ulMapIeEnd;
-
-    ulMapIeEnd.SetCid(Cid::InitialRanging());
-    ulMapIeEnd.SetStartTime(symbolsToAllocation);
-    ulMapIeEnd.SetUiuc(OfdmUlBurstProfile::UIUC_END_OF_MAP);
-    ulMapIeEnd.SetDuration(0);
-    m_uplinkAllocations.push_back(ulMapIeEnd);
-
-    // setting DL/UL subframe allocation for the next frame
-    GetBs()->GetBandwidthManager()->SetSubframeRatio();
-}
-
-void
-UplinkSchedulerSimple::ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                                ServiceFlow::SchedulingType schedulingType,
-                                                OfdmUlMapIe& ulMapIe,
-                                                const WimaxPhy::ModulationType modulationType,
-                                                uint32_t& symbolsToAllocation,
-                                                uint32_t& availableSymbols)
-{
-    uint32_t allocationSize = 0;      // size in symbols
-    uint8_t uiuc = ulMapIe.GetUiuc(); // SS's burst profile
-    std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        ServiceFlow* serviceFlow = *iter;
-
-        /* in case of rtPS, nrtPS and BE, allocating unicast polls for bandwidth requests (Request
-         IEs, 6.3.7.4.3.1). in case of UGS, allocating grants for data transmission (Data Grant
-         Burst Type IEs, 6.3.7.4.3.3) (grant has been referred in this code by different names e.g.
-         transmission opportunity, slot, allocation, etc) */
-
-        allocationSize =
-            GetBs()->GetBandwidthManager()->CalculateAllocationSize(ssRecord, serviceFlow);
-        // verifying that minimum reserved traffic rate of nrtPS flow is maintained
-        if (serviceFlow->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS)
-        {
-            Time currentTime = Simulator::Now();
-            ServiceFlowRecord* record = serviceFlow->GetRecord();
-            if (currentTime - record->GetGrantTimeStamp() > Seconds(1))
-            {
-                uint32_t bps = (record->GetBwSinceLastExpiry() * 8);
-                if (bps < serviceFlow->GetMinReservedTrafficRate())
-                {
-                    ServiceBandwidthRequests(serviceFlow,
-                                             schedulingType,
-                                             ulMapIe,
-                                             modulationType,
-                                             symbolsToAllocation,
-                                             availableSymbols);
-                    record->SetBwSinceLastExpiry(0);
-                    record->SetGrantTimeStamp(currentTime);
-                }
-            }
-        }
-
-        if (availableSymbols < allocationSize)
-        {
-            break;
-        }
-
-        if (allocationSize > 0)
-        {
-            ulMapIe.SetStartTime(symbolsToAllocation);
-            if (serviceFlow->GetSchedulingType() != ServiceFlow::SF_TYPE_UGS)
-            {
-                // special burst profile with most robust modulation type is used for unicast polls
-                // (Request IEs)
-                ulMapIe.SetUiuc(OfdmUlBurstProfile::UIUC_REQ_REGION_FULL);
-            }
-        }
-        else
-        {
-            continue;
-        }
-
-        NS_LOG_DEBUG(", CID: " << serviceFlow->GetConnection()->GetCid()
-                               << ", SFID: " << serviceFlow->GetSfid());
-
-        AddUplinkAllocation(ulMapIe, allocationSize, symbolsToAllocation, availableSymbols);
-        ulMapIe.SetUiuc(uiuc);
-    }
-}
-
-void
-UplinkSchedulerSimple::ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                                ServiceFlow::SchedulingType schedulingType,
-                                                OfdmUlMapIe& ulMapIe,
-                                                const WimaxPhy::ModulationType modulationType,
-                                                uint32_t& symbolsToAllocation,
-                                                uint32_t& availableSymbols)
-{
-    std::vector<ServiceFlow*> serviceFlows = ssRecord->GetServiceFlows(schedulingType);
-
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        if (!ServiceBandwidthRequests(*iter,
-                                      schedulingType,
-                                      ulMapIe,
-                                      modulationType,
-                                      symbolsToAllocation,
-                                      availableSymbols))
-        {
-            break;
-        }
-    }
-}
-
-bool
-UplinkSchedulerSimple::ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                                ServiceFlow::SchedulingType schedulingType,
-                                                OfdmUlMapIe& ulMapIe,
-                                                const WimaxPhy::ModulationType modulationType,
-                                                uint32_t& symbolsToAllocation,
-                                                uint32_t& availableSymbols)
-{
-    uint32_t allocSizeBytes = 0;
-    uint32_t allocSizeSymbols = 0;
-    uint16_t sduSize = 0;
-
-    ServiceFlowRecord* record = serviceFlow->GetRecord();
-    sduSize = serviceFlow->GetSduSize();
-
-    uint32_t requiredBandwidth = record->GetRequestedBandwidth() - record->GetGrantedBandwidth();
-    if (requiredBandwidth > 0)
-    {
-        if (sduSize > 0)
-        {
-            // if SDU size is mentioned, allocate grant of that size
-            allocSizeBytes = sduSize;
-            allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(sduSize, modulationType);
-        }
-        else
-        {
-            allocSizeBytes = requiredBandwidth;
-            allocSizeSymbols = GetBs()->GetPhy()->GetNrSymbols(requiredBandwidth, modulationType);
-        }
-
-        if (availableSymbols >= allocSizeSymbols)
-        {
-            record->UpdateGrantedBandwidth(allocSizeBytes);
-
-            if (schedulingType == ServiceFlow::SF_TYPE_NRTPS)
-            {
-                record->SetBwSinceLastExpiry(allocSizeBytes);
-            }
-
-            AddUplinkAllocation(ulMapIe, allocSizeSymbols, symbolsToAllocation, availableSymbols);
-        }
-        else
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-void
-UplinkSchedulerSimple::AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                                      uint32_t& availableSymbols)
-{
-    Time ssUlStartTime =
-        Seconds(CalculateAllocationStartTime() * GetBs()->GetPsDuration().GetSeconds());
-    SetNrIrOppsAllocated(GetBs()->GetLinkManager()->CalculateRangingOppsToAllocate());
-    uint32_t allocationSize = GetNrIrOppsAllocated() * GetBs()->GetRangReqOppSize();
-    Time timeSinceLastIrInterval = Simulator::Now() - GetTimeStampIrInterval();
-
-    // adding one frame because may be the time has not elapsed now but will elapse before the next
-    // frame is sent
-    if (timeSinceLastIrInterval + GetBs()->GetPhy()->GetFrameDuration() >
-            GetBs()->GetInitialRangingInterval() &&
-        availableSymbols >= allocationSize)
-    {
-        SetIsIrIntrvlAllocated(true);
-        OfdmUlMapIe ulMapIeIr;
-        ulMapIeIr.SetCid((GetBs()->GetBroadcastConnection())->GetCid());
-        ulMapIeIr.SetStartTime(symbolsToAllocation);
-        ulMapIeIr.SetUiuc(OfdmUlBurstProfile::UIUC_INITIAL_RANGING);
-
-        NS_LOG_DEBUG("BS uplink scheduler, initial ranging allocation, size: "
-                     << allocationSize << " symbols, modulation: BPSK 1/2");
-
-        // marking start and end of each TO, only for debugging
-        for (uint8_t i = 0; i < GetNrIrOppsAllocated(); i++)
-        {
-            GetBs()->MarkRangingOppStart(
-                ssUlStartTime +
-                Seconds(symbolsToAllocation * GetBs()->GetSymbolDuration().GetSeconds()) +
-                Seconds(i * GetBs()->GetRangReqOppSize() *
-                        GetBs()->GetSymbolDuration().GetSeconds()));
-        }
-
-        AddUplinkAllocation(ulMapIeIr, allocationSize, symbolsToAllocation, availableSymbols);
-        SetTimeStampIrInterval(Simulator::Now());
-    }
-}
-
-void
-UplinkSchedulerSimple::SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow)
-{
-    uint8_t delayNrFrames = 1;
-    uint32_t bitsPerSecond = serviceFlow->GetMinReservedTrafficRate();
-    WimaxPhy::ModulationType modulation;
-    uint32_t bytesPerFrame =
-        (uint32_t((double)(bitsPerSecond)*GetBs()->GetPhy()->GetFrameDuration().GetSeconds())) / 8;
-    uint32_t frameDurationMSec = GetBs()->GetPhy()->GetFrameDuration().GetMilliSeconds();
-
-    switch (serviceFlow->GetSchedulingType())
-    {
-    case ServiceFlow::SF_TYPE_UGS: {
-        if (serviceFlow->GetIsMulticast())
-        {
-            modulation = serviceFlow->GetModulation();
-        }
-        else
-        {
-            modulation = ssRecord->GetModulationType();
-        }
-        uint32_t grantSize = GetBs()->GetPhy()->GetNrSymbols(bytesPerFrame, modulation);
-        serviceFlow->GetRecord()->SetGrantSize(grantSize);
-
-        uint32_t toleratedJitter = serviceFlow->GetToleratedJitter();
-
-        if (toleratedJitter > frameDurationMSec)
-        {
-            delayNrFrames = (uint8_t)(toleratedJitter / frameDurationMSec);
-        }
-
-        uint16_t interval = delayNrFrames * frameDurationMSec;
-        serviceFlow->SetUnsolicitedGrantInterval(interval);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_RTPS: {
-        if (serviceFlow->GetSduSize() > bytesPerFrame)
-        {
-            delayNrFrames = (uint8_t)(serviceFlow->GetSduSize() / bytesPerFrame);
-        }
-
-        uint16_t interval = delayNrFrames * frameDurationMSec;
-        serviceFlow->SetUnsolicitedPollingInterval(interval);
-    }
-    break;
-    case ServiceFlow::SF_TYPE_NRTPS:
-        // no real-time guarantees are given to NRTPS, serviced based on available bandwidth
-    case ServiceFlow::SF_TYPE_BE:
-        // no real-time guarantees are given to BE, serviced based on available bandwidth
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-    }
-}
-
-void
-UplinkSchedulerSimple::ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr)
-{
-    // virtual function on UplinkScheduler
-    // this is not necessary on this implementation
-}
-
-void
-UplinkSchedulerSimple::OnSetRequestedBandwidth(ServiceFlowRecord* sfr)
-{
-    // m_grantedBandwidth must be reset to zero
-    uint32_t grantedBandwidth = 0;
-    sfr->SetGrantedBandwidth(grantedBandwidth);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bs-uplink-scheduler-simple.h ns-3.46/src/wimax/model/bs-uplink-scheduler-simple.h
--- ns-3.45/src/wimax/model/bs-uplink-scheduler-simple.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bs-uplink-scheduler-simple.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef UPLINK_SCHEDULER_SIMPLE_H
-#define UPLINK_SCHEDULER_SIMPLE_H
-
-#include "bs-uplink-scheduler.h"
-#include "service-flow.h"
-#include "ul-mac-messages.h"
-#include "wimax-phy.h"
-
-#include "ns3/nstime.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class BaseStationNetDevice;
-class SSRecord;
-class ServiceFlow;
-
-/**
- * @ingroup wimax
- *
- * Uplink Scheduler - simplified
- */
-class UplinkSchedulerSimple : public UplinkScheduler
-{
-  public:
-    UplinkSchedulerSimple();
-    /**
-     * Constructor
-     *
-     * @param bs base station device
-     */
-    UplinkSchedulerSimple(Ptr<BaseStationNetDevice> bs);
-    ~UplinkSchedulerSimple() override;
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    std::list<OfdmUlMapIe> GetUplinkAllocations() const override;
-
-    /**
-     * @brief Determines if channel descriptors sent in the current frame are
-     * required to be updated
-     *
-     * @param updateDcd currently unused (assume true)
-     * @param updateUcd currently unused (assume true)
-     * @param [out] sendDcd DCD must be updated
-     * @param [out] sendUcd UCD must be updated
-     *
-     */
-    void GetChannelDescriptorsToUpdate(bool& updateDcd,
-                                       bool& updateUcd,
-                                       bool& sendDcd,
-                                       bool& sendUcd) override;
-    uint32_t CalculateAllocationStartTime() override;
-    void AddUplinkAllocation(OfdmUlMapIe& ulMapIe,
-                             const uint32_t& allocationSize,
-                             uint32_t& symbolsToAllocation,
-                             uint32_t& availableSymbols) override;
-    void Schedule() override;
-    /**
-     * Service Unsolicited Grants function
-     * @param ssRecord Subscriber station record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void ServiceUnsolicitedGrants(const SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Service Bandwidth Requests function
-     * @param ssRecord Subscriber station record
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     */
-    void ServiceBandwidthRequests(const SSRecord* ssRecord,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Service bandwidth requests function
-     * @param serviceFlow the service flow
-     * @param schedulingType the scheduling type
-     * @param ulMapIe the UL map IE
-     * @param modulationType the modulation type
-     * @param symbolsToAllocation the symbols to allocation
-     * @param availableSymbols the available symbols
-     * @returns true if successful
-     */
-    bool ServiceBandwidthRequests(ServiceFlow* serviceFlow,
-                                  ServiceFlow::SchedulingType schedulingType,
-                                  OfdmUlMapIe& ulMapIe,
-                                  const WimaxPhy::ModulationType modulationType,
-                                  uint32_t& symbolsToAllocation,
-                                  uint32_t& availableSymbols) override;
-    /**
-     * Allocate Initial Ranging Interval function
-     *
-     * @param symbolsToAllocation symbols to allocation for UpLink Subframe
-     * @param availableSymbols available symbols for rtPS flows
-     */
-    void AllocateInitialRangingInterval(uint32_t& symbolsToAllocation,
-                                        uint32_t& availableSymbols) override;
-    /**
-     * Setup service flow function
-     * @param ssRecord Subscriber station record
-     * @param serviceFlow the service flow
-     */
-    void SetupServiceFlow(SSRecord* ssRecord, ServiceFlow* serviceFlow) override;
-
-    /**
-     * Process bandwidth request function
-     * @param bwRequestHdr the bandwidth request header
-     */
-    void ProcessBandwidthRequest(const BandwidthRequestHeader& bwRequestHdr) override;
-
-    /// Init once function
-    void InitOnce() override;
-
-    /**
-     * Set requested bandwidth function
-     * @param sfr the service flow record
-     */
-    void OnSetRequestedBandwidth(ServiceFlowRecord* sfr) override;
-
-  private:
-    std::list<OfdmUlMapIe> m_uplinkAllocations; ///< uplink allocations
-};
-
-} // namespace ns3
-
-#endif /* UPLINK_SCHEDULER_SIMPLE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/burst-profile-manager.cc ns-3.46/src/wimax/model/burst-profile-manager.cc
--- ns-3.45/src/wimax/model/burst-profile-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/burst-profile-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "burst-profile-manager.h"
-
-#include "bs-net-device.h"
-#include "mac-messages.h"
-#include "ss-manager.h"
-#include "ss-net-device.h"
-#include "ss-record.h"
-
-#include "ns3/log.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("BurstProfileManager");
-
-NS_OBJECT_ENSURE_REGISTERED(BurstProfileManager);
-
-TypeId
-BurstProfileManager::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::BurstProfileManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-BurstProfileManager::BurstProfileManager(Ptr<WimaxNetDevice> device)
-    : m_device(device)
-{
-}
-
-BurstProfileManager::~BurstProfileManager()
-{
-    m_device = nullptr;
-}
-
-void
-BurstProfileManager::DoDispose()
-{
-    m_device = nullptr;
-}
-
-uint16_t
-BurstProfileManager::GetNrBurstProfilesToDefine()
-{
-    /*
-     * 7 modulation types
-     */
-    return 7;
-}
-
-WimaxPhy::ModulationType
-BurstProfileManager::GetModulationType(uint8_t iuc, WimaxNetDevice::Direction direction) const
-{
-    if (direction == WimaxNetDevice::DIRECTION_DOWNLINK)
-    {
-        std::vector<OfdmDlBurstProfile> dlBurstProfiles =
-            m_device->GetCurrentDcd().GetDlBurstProfiles();
-        for (auto iter = dlBurstProfiles.begin(); iter != dlBurstProfiles.end(); ++iter)
-        {
-            if (iter->GetDiuc() == iuc)
-            {
-                return (WimaxPhy::ModulationType)iter->GetFecCodeType();
-            }
-        }
-    }
-    else
-    {
-        std::vector<OfdmUlBurstProfile> ulBurstProfiles =
-            m_device->GetCurrentUcd().GetUlBurstProfiles();
-        for (auto iter = ulBurstProfiles.begin(); iter != ulBurstProfiles.end(); ++iter)
-        {
-            if (iter->GetUiuc() == iuc)
-            {
-                return (WimaxPhy::ModulationType)iter->GetFecCodeType();
-            }
-        }
-    }
-
-    // burst profile got to be there in DCD/UCD, assuming always all profiles are defined in DCD/UCD
-    NS_FATAL_ERROR("burst profile got to be there in DCD/UCD");
-
-    return (WimaxPhy::ModulationType)-1;
-}
-
-uint8_t
-BurstProfileManager::GetBurstProfile(WimaxPhy::ModulationType modulationType,
-                                     WimaxNetDevice::Direction direction) const
-{
-    if (direction == WimaxNetDevice::DIRECTION_DOWNLINK)
-    {
-        std::vector<OfdmDlBurstProfile> dlBurstProfiles =
-            m_device->GetCurrentDcd().GetDlBurstProfiles();
-        for (auto iter = dlBurstProfiles.begin(); iter != dlBurstProfiles.end(); ++iter)
-        {
-            if (iter->GetFecCodeType() == modulationType)
-            {
-                return iter->GetDiuc();
-            }
-        }
-    }
-    else
-    {
-        std::vector<OfdmUlBurstProfile> ulBurstProfiles =
-            m_device->GetCurrentUcd().GetUlBurstProfiles();
-        for (auto iter = ulBurstProfiles.begin(); iter != ulBurstProfiles.end(); ++iter)
-        {
-            if (iter->GetFecCodeType() == modulationType)
-            {
-                return iter->GetUiuc();
-            }
-        }
-    }
-
-    // burst profile got to be there in DCD/UCD, assuming always all profiles are defined in DCD/UCD
-    NS_FATAL_ERROR("burst profile got to be there in DCD/UCD");
-
-    return ~0;
-}
-
-uint8_t
-BurstProfileManager::GetBurstProfileForSS(const SSRecord* ssRecord,
-                                          const RngReq* rngreq,
-                                          WimaxPhy::ModulationType& modulationType) const
-{
-    /*during initial ranging or periodic ranging (or when RNG-REQ is used instead of
-     DBPC) calculates the least robust burst profile for SS, e.g., based on distance,
-     power, signal etc, temporarily choosing same burst profile SS requested in RNG-REQ*/
-
-    modulationType = GetModulationTypeForSS(ssRecord, rngreq);
-    return GetBurstProfile(modulationType, WimaxNetDevice::DIRECTION_DOWNLINK);
-}
-
-WimaxPhy::ModulationType
-BurstProfileManager::GetModulationTypeForSS(const SSRecord* ssRecord, const RngReq* rngreq) const
-{
-    return GetModulationType(rngreq->GetReqDlBurstProfile(), WimaxNetDevice::DIRECTION_DOWNLINK);
-}
-
-uint8_t
-BurstProfileManager::GetBurstProfileToRequest()
-{
-    /*modulation type is currently set by user in simulation script, shall
-     actually be determined based on SS's distance, power, signal etc*/
-
-    return GetBurstProfile(m_device->GetObject<SubscriberStationNetDevice>()->GetModulationType(),
-                           WimaxNetDevice::DIRECTION_DOWNLINK);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/burst-profile-manager.h ns-3.46/src/wimax/model/burst-profile-manager.h
--- ns-3.45/src/wimax/model/burst-profile-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/burst-profile-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef BURST_PROFILE_MANAGER_H
-#define BURST_PROFILE_MANAGER_H
-
-#include "cid.h"
-#include "wimax-net-device.h"
-#include "wimax-phy.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class SSRecord;
-class RngReq;
-
-/**
- * @ingroup wimax
- *
- * Profile manager for burst communications
- */
-class BurstProfileManager : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    /**
-     * Constructor
-     *
-     * @param device WIMAX device
-     */
-    BurstProfileManager(Ptr<WimaxNetDevice> device);
-    ~BurstProfileManager() override;
-
-    // Delete copy constructor and assignment operator to avoid misuse
-    BurstProfileManager(const BurstProfileManager&) = delete;
-    BurstProfileManager& operator=(const BurstProfileManager&) = delete;
-
-    void DoDispose() override;
-    /**
-     * @returns the number of available burst profile
-     */
-    uint16_t GetNrBurstProfilesToDefine();
-
-    /**
-     * @brief returns the modulation type of a given iuc
-     * @param direction should be uplink or downlink
-     * @param iuc the iuc
-     * @returns the modulation type of the selected iuc
-     */
-    WimaxPhy::ModulationType GetModulationType(uint8_t iuc,
-                                               WimaxNetDevice::Direction direction) const;
-
-    /**
-     * @brief returns the burst profile
-     * @param modulationType
-     * @param direction should be uplink or downlink
-     * @returns the modulation type of the selected iuc
-     */
-    uint8_t GetBurstProfile(WimaxPhy::ModulationType modulationType,
-                            WimaxNetDevice::Direction direction) const;
-
-    /**
-     * @brief Get burst profile for SS
-     * @param modulationType
-     * @param ssRecord
-     * @param rngreq
-     * @returns the burst profile for SS
-     */
-    uint8_t GetBurstProfileForSS(const SSRecord* ssRecord,
-                                 const RngReq* rngreq,
-                                 WimaxPhy::ModulationType& modulationType) const;
-    /**
-     * @brief Get module ation type for SS
-     * @param ssRecord
-     * @param rngreq
-     * @returns the burst profile for SS
-     */
-    WimaxPhy::ModulationType GetModulationTypeForSS(const SSRecord* ssRecord,
-                                                    const RngReq* rngreq) const;
-    /**
-     * @brief Get burst profile to request
-     * @returns the burst profile for SS
-     */
-    uint8_t GetBurstProfileToRequest();
-
-  private:
-    Ptr<WimaxNetDevice> m_device; ///< the device
-};
-
-} // namespace ns3
-
-#endif /* BURST_PROFILE_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/bvec.h ns-3.46/src/wimax/model/bvec.h
--- ns-3.45/src/wimax/model/bvec.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/bvec.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,21 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef BVEC_H
-#define BVEC_H
-
-#include <vector>
-
-namespace ns3
-{
-/// boolean vector typedef
-typedef std::vector<bool> Bvec;
-} // namespace ns3
-
-#endif /* BVEC_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/cid.cc ns-3.46/src/wimax/model/cid.cc
--- ns-3.45/src/wimax/model/cid.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/cid.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "cid.h"
-
-// 0 will match IR CID, -1 will match broadcast CID 0xFFFF, hence 60000
-#define CID_UNINITIALIZED 60000
-
-namespace ns3
-{
-
-Cid::Cid()
-{
-    m_identifier = CID_UNINITIALIZED;
-}
-
-Cid::Cid(uint16_t identifier)
-{
-    m_identifier = identifier;
-}
-
-Cid::~Cid()
-{
-}
-
-uint16_t
-Cid::GetIdentifier() const
-{
-    return m_identifier;
-}
-
-bool
-Cid::IsMulticast() const
-{
-    return m_identifier >= 0xff00 && m_identifier <= 0xfffd;
-}
-
-bool
-Cid::IsBroadcast() const
-{
-    return *this == Broadcast();
-}
-
-bool
-Cid::IsPadding() const
-{
-    return *this == Padding();
-}
-
-bool
-Cid::IsInitialRanging() const
-{
-    return *this == InitialRanging();
-}
-
-Cid
-Cid::Broadcast()
-{
-    return 0xffff;
-}
-
-Cid
-Cid::Padding()
-{
-    return 0xfffe;
-}
-
-Cid
-Cid::InitialRanging()
-{
-    return 0;
-}
-
-/**
- * @brief equality operator
- * @param lhs left hand side
- * @param rhs right hand side
- * @returns true if equal
- */
-bool
-operator==(const Cid& lhs, const Cid& rhs)
-{
-    return lhs.m_identifier == rhs.m_identifier;
-}
-
-/**
- * @brief inequality operator
- * @param lhs left hand side
- * @param rhs right hand side
- * @returns true if not equal
- */
-bool
-operator!=(const Cid& lhs, const Cid& rhs)
-{
-    return !(lhs == rhs);
-}
-
-/**
- * @brief output stream output operator
- * @param os output stream
- * @param cid CID
- * @returns output stream
- */
-std::ostream&
-operator<<(std::ostream& os, const Cid& cid)
-{
-    os << cid.GetIdentifier();
-    return os;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/cid-factory.cc ns-3.46/src/wimax/model/cid-factory.cc
--- ns-3.45/src/wimax/model/cid-factory.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/cid-factory.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "cid-factory.h"
-
-#include "ns3/uinteger.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-CidFactory::CidFactory()
-    : m_m(0x5500),
-      // this is an arbitrary default
-      m_basicIdentifier(1),
-      m_primaryIdentifier(m_m + 1),
-      m_transportOrSecondaryIdentifier(2 * m_m + 1),
-      m_multicastPollingIdentifier(0xff00)
-{
-}
-
-Cid
-CidFactory::AllocateBasic()
-{
-    NS_ASSERT(m_basicIdentifier < m_m);
-    m_basicIdentifier++;
-    return Cid(m_basicIdentifier);
-}
-
-Cid
-CidFactory::AllocatePrimary()
-{
-    NS_ASSERT(m_primaryIdentifier < 2 * m_m);
-    m_primaryIdentifier++;
-    return Cid(m_primaryIdentifier);
-}
-
-Cid
-CidFactory::AllocateTransportOrSecondary()
-{
-    NS_ASSERT(m_transportOrSecondaryIdentifier < 0xfefe);
-    m_transportOrSecondaryIdentifier++;
-    return Cid(m_transportOrSecondaryIdentifier);
-}
-
-Cid
-CidFactory::AllocateMulticast()
-{
-    NS_ASSERT(m_multicastPollingIdentifier < 0xfffd);
-    m_multicastPollingIdentifier++;
-    return Cid(m_multicastPollingIdentifier);
-}
-
-Cid
-CidFactory::Allocate(Cid::Type type)
-{
-    switch (type)
-    {
-    case Cid::BROADCAST:
-        return Cid::Broadcast();
-    case Cid::INITIAL_RANGING:
-        return Cid::InitialRanging();
-    case Cid::BASIC:
-        return AllocateBasic();
-    case Cid::PRIMARY:
-        return AllocatePrimary();
-    case Cid::TRANSPORT:
-        return AllocateTransportOrSecondary();
-    case Cid::MULTICAST:
-        return AllocateMulticast();
-    case Cid::PADDING:
-        return Cid::Padding();
-    default:
-        NS_FATAL_ERROR("Cannot be reached");
-        return 0; // quiet compiler
-    }
-}
-
-bool
-CidFactory::IsTransport(Cid cid) const
-{
-    int id = cid.m_identifier;
-    return (id - 2 * m_m > 0) && (id <= 0xfefe);
-}
-
-bool
-CidFactory::IsPrimary(Cid cid) const
-{
-    int id = cid.m_identifier;
-    return (id - m_m > 0) && (id <= 2 * m_m);
-}
-
-bool
-CidFactory::IsBasic(Cid cid) const
-{
-    uint16_t id = cid.m_identifier;
-    return id >= 1 && id <= m_m;
-}
-
-void
-CidFactory::FreeCid(Cid cid)
-{
-    /// @todo We need to update the cid bitmap properly here.
-    NS_FATAL_ERROR(
-        "TODO: Update the cid bitmap properly here-- please implement and contribute a patch");
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/cid-factory.h ns-3.46/src/wimax/model/cid-factory.h
--- ns-3.45/src/wimax/model/cid-factory.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/cid-factory.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef CONNECTION_IDENTIFIER_FACTORY_H
-#define CONNECTION_IDENTIFIER_FACTORY_H
-
-#include "cid.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class is used exclusively by the BS to allocate CIDs to new connections.
- * This class uses the definitions from Table 345 in ieee-802.16-2004 to
- * allocate cids in different integer ranges according to their type.
- * The relative allocation of the ranges is controlled by the parameter 'm'
- * introduced in the above-mentioned table.
- *
- * Note: The current implementation merely allocates cids sequentially from
- * the start of the allowed range. A proper implementation would be able
- * to recycle cids from previous dead connections and should instead look
- * at a bitmap of free cids. Some other day :)
- */
-class CidFactory
-{
-  public:
-    /**
-     * Create a cid factory with a default value for m of 0x5500.
-     */
-    CidFactory();
-    /**
-     * @brief This function returns the next basic CID.
-     * @returns the next basic CID.
-     */
-    Cid AllocateBasic();
-    /**
-     * @brief This function returns the next primary basic CID.
-     * @returns the next primary CID.
-     */
-    Cid AllocatePrimary();
-    /**
-     * @brief This function returns the next Transport (or Secondary) CID.
-     * @returns the next Transport (or Secondary) CID.
-     */
-    Cid AllocateTransportOrSecondary();
-    /**
-     * @brief This function returns the next Multicast CID.
-     * @returns the next Multicast CID.
-     */
-    Cid AllocateMulticast();
-    /**
-     * @brief This function returns the next CID for the specified type.
-     * @param type CID type
-     * @returns the next CID.
-     */
-    Cid Allocate(Cid::Type type);
-
-    /**
-     * @brief This function determines if the CID is a transport.
-     * @param cid CID type
-     * @returns true if the CID is a transport.
-     */
-    bool IsTransport(Cid cid) const;
-    /**
-     * @brief This function determines if the CID is primary.
-     * @param cid CID type
-     * @returns true if the CID is primary.
-     */
-    bool IsPrimary(Cid cid) const;
-    /**
-     * @brief This function determines if the CID is basic.
-     * @param cid CID type
-     * @returns true if the CID is basic.
-     */
-    bool IsBasic(Cid cid) const;
-
-    /**
-     * Notify the factory that the connection associated to this
-     * cid has been killed and that this cid can be reused.
-     * @param cid CID type
-     */
-    void FreeCid(Cid cid);
-
-  private:
-    uint16_t m_m; ///< m
-
-    uint16_t m_basicIdentifier;                ///< basic identifier
-    uint16_t m_primaryIdentifier;              ///< primary identifier
-    uint16_t m_transportOrSecondaryIdentifier; ///< transport or secondary identifier
-    uint16_t m_multicastPollingIdentifier;     ///< multicast polling identifier
-};
-
-} // namespace ns3
-
-#endif /* CONNECTION_IDENTIFIER_FACTORY_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/cid.h ns-3.46/src/wimax/model/cid.h
--- ns-3.45/src/wimax/model/cid.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/cid.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef CID_H
-#define CID_H
-
-#include <ostream>
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @class Cid
- * @brief Cid class
- */
-class Cid
-{
-  public:
-    /// Type enumeration
-    enum Type
-    {
-        BROADCAST = 1,
-        INITIAL_RANGING,
-        BASIC,
-        PRIMARY,
-        TRANSPORT,
-        MULTICAST,
-        PADDING
-    };
-
-    /// Create a cid of unknown type
-    Cid();
-    /**
-     * Constructor
-     *
-     * @param cid
-     */
-    Cid(uint16_t cid);
-    ~Cid();
-    /**
-     * @return the identifier of the cid
-     */
-    uint16_t GetIdentifier() const;
-    /**
-     * @return true if the cid is a multicast cid, false otherwise
-     */
-    bool IsMulticast() const;
-    /**
-     * @return true if the cid is a broadcast cid, false otherwise
-     */
-    bool IsBroadcast() const;
-    /**
-     * @return true if the cid is a padding cid, false otherwise
-     */
-    bool IsPadding() const;
-    /**
-     * @return true if the cid is an initial ranging cid, false otherwise
-     */
-    bool IsInitialRanging() const;
-    /**
-     * @return the broadcast cid
-     */
-    static Cid Broadcast();
-    /**
-     * @return the padding cid
-     */
-    static Cid Padding();
-    /**
-     * @return the initial ranging cid
-     */
-    static Cid InitialRanging();
-
-  private:
-    /// allow CidFactory class friend access
-    friend class CidFactory;
-    /// equality operator
-    friend bool operator==(const Cid& lhs, const Cid& rhs);
-    uint16_t m_identifier; ///< identiifier
-};
-
-bool operator==(const Cid& lhs, const Cid& rhs);
-bool operator!=(const Cid& lhs, const Cid& rhs);
-
-std::ostream& operator<<(std::ostream& os, const Cid& cid);
-
-} // namespace ns3
-
-#endif /* CID_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/connection-manager.cc ns-3.46/src/wimax/model/connection-manager.cc
--- ns-3.45/src/wimax/model/connection-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/connection-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "connection-manager.h"
-
-#include "bs-net-device.h"
-#include "cid-factory.h"
-#include "mac-messages.h"
-#include "service-flow.h"
-#include "ss-net-device.h"
-#include "ss-record.h"
-
-#include "ns3/enum.h"
-#include "ns3/log.h"
-#include "ns3/pointer.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("ConnectionManager");
-
-NS_OBJECT_ENSURE_REGISTERED(ConnectionManager);
-
-TypeId
-ConnectionManager::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::ConnectionManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-ConnectionManager::ConnectionManager()
-    : m_cidFactory(nullptr)
-{
-}
-
-void
-ConnectionManager::DoDispose()
-{
-}
-
-ConnectionManager::~ConnectionManager()
-{
-}
-
-void
-ConnectionManager::SetCidFactory(CidFactory* cidFactory)
-{
-    m_cidFactory = cidFactory;
-}
-
-void
-ConnectionManager::AllocateManagementConnections(SSRecord* ssRecord, RngRsp* rngrsp)
-{
-    Ptr<WimaxConnection> basicConnection = CreateConnection(Cid::BASIC);
-    ssRecord->SetBasicCid(basicConnection->GetCid());
-
-    Ptr<WimaxConnection> primaryConnection = CreateConnection(Cid::PRIMARY);
-    ssRecord->SetPrimaryCid(primaryConnection->GetCid());
-
-    rngrsp->SetBasicCid(basicConnection->GetCid());
-    rngrsp->SetPrimaryCid(primaryConnection->GetCid());
-}
-
-Ptr<WimaxConnection>
-ConnectionManager::CreateConnection(Cid::Type type)
-{
-    Cid cid;
-    switch (type)
-    {
-    case Cid::BASIC:
-    case Cid::MULTICAST:
-    case Cid::PRIMARY:
-        cid = m_cidFactory->Allocate(type);
-        break;
-    case Cid::TRANSPORT:
-        cid = m_cidFactory->AllocateTransportOrSecondary();
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid connection type");
-        break;
-    }
-    Ptr<WimaxConnection> connection = CreateObject<WimaxConnection>(cid, type);
-    AddConnection(connection, type);
-    return connection;
-}
-
-void
-ConnectionManager::AddConnection(Ptr<WimaxConnection> connection, Cid::Type type)
-{
-    switch (type)
-    {
-    case Cid::BASIC:
-        m_basicConnections.push_back(connection);
-        break;
-    case Cid::PRIMARY:
-        m_primaryConnections.push_back(connection);
-        break;
-    case Cid::TRANSPORT:
-        m_transportConnections.push_back(connection);
-        break;
-    case Cid::MULTICAST:
-        m_multicastConnections.push_back(connection);
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid connection type");
-        break;
-    }
-}
-
-Ptr<WimaxConnection>
-ConnectionManager::GetConnection(Cid cid)
-{
-    for (auto iter = m_basicConnections.begin(); iter != m_basicConnections.end(); ++iter)
-    {
-        if ((*iter)->GetCid() == cid)
-        {
-            return *iter;
-        }
-    }
-
-    for (auto iter = m_primaryConnections.begin(); iter != m_primaryConnections.end(); ++iter)
-    {
-        if ((*iter)->GetCid() == cid)
-        {
-            return *iter;
-        }
-    }
-
-    for (auto iter = m_transportConnections.begin(); iter != m_transportConnections.end(); ++iter)
-    {
-        if ((*iter)->GetCid() == cid)
-        {
-            return *iter;
-        }
-    }
-
-    return nullptr;
-}
-
-std::vector<Ptr<WimaxConnection>>
-ConnectionManager::GetConnections(Cid::Type type) const
-{
-    std::vector<Ptr<WimaxConnection>> connections;
-
-    switch (type)
-    {
-    case Cid::BASIC:
-        connections = m_basicConnections;
-        break;
-    case Cid::PRIMARY:
-        connections = m_primaryConnections;
-        break;
-    case Cid::TRANSPORT:
-        connections = m_transportConnections;
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid connection type");
-        break;
-    }
-
-    return connections;
-}
-
-uint32_t
-ConnectionManager::GetNPackets(Cid::Type type, ServiceFlow::SchedulingType schedulingType) const
-{
-    uint32_t nrPackets = 0;
-
-    switch (type)
-    {
-    case Cid::BASIC: {
-        for (auto iter = m_basicConnections.begin(); iter != m_basicConnections.end(); ++iter)
-        {
-            nrPackets += (*iter)->GetQueue()->GetSize();
-        }
-        break;
-    }
-    case Cid::PRIMARY: {
-        for (auto iter = m_primaryConnections.begin(); iter != m_primaryConnections.end(); ++iter)
-        {
-            nrPackets += (*iter)->GetQueue()->GetSize();
-        }
-        break;
-    }
-    case Cid::TRANSPORT: {
-        for (auto iter = m_transportConnections.begin(); iter != m_transportConnections.end();
-             ++iter)
-        {
-            if (schedulingType == ServiceFlow::SF_TYPE_ALL ||
-                (*iter)->GetSchedulingType() == schedulingType)
-            {
-                nrPackets += (*iter)->GetQueue()->GetSize();
-            }
-        }
-        break;
-    }
-    default:
-        NS_FATAL_ERROR("Invalid connection type");
-        break;
-    }
-
-    return nrPackets;
-}
-
-bool
-ConnectionManager::HasPackets() const
-{
-    for (auto iter = m_basicConnections.begin(); iter != m_basicConnections.end(); ++iter)
-    {
-        if ((*iter)->HasPackets())
-        {
-            return true;
-        }
-    }
-
-    for (auto iter = m_primaryConnections.begin(); iter != m_primaryConnections.end(); ++iter)
-    {
-        if ((*iter)->HasPackets())
-        {
-            return true;
-        }
-    }
-
-    for (auto iter = m_transportConnections.begin(); iter != m_transportConnections.end(); ++iter)
-    {
-        if ((*iter)->HasPackets())
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/connection-manager.h ns-3.46/src/wimax/model/connection-manager.h
--- ns-3.45/src/wimax/model/connection-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/connection-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef CONNECTION_MANAGER_H
-#define CONNECTION_MANAGER_H
-
-#include "cid.h"
-#include "wimax-connection.h"
-
-#include "ns3/mac48-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class CidFactory;
-class SSRecord;
-class RngRsp;
-class WimaxNetDevice;
-class SubscriberStationNetDevice;
-
-/**
- * @ingroup wimax
- * The same connection manager class serves both for BS and SS though some functions are exclusive
- * to only one of them.
- */
-
-class ConnectionManager : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    ConnectionManager();
-    ~ConnectionManager() override;
-    void DoDispose() override;
-    /**
-     * Set CID factory
-     * @param cidFactory the CID factory
-     */
-    void SetCidFactory(CidFactory* cidFactory);
-    /**
-     * @brief allocates the management connection for an ss record. This method is only used by BS
-     * @param ssRecord the ss record to which the management connection will be allocated
-     * @param rngrsp the ranging response message
-     */
-    void AllocateManagementConnections(SSRecord* ssRecord, RngRsp* rngrsp);
-    /**
-     * @brief create a connection of type type
-     * @param type type of the connection to create
-     * @return a smart pointer to the created WimaxConnection
-     */
-    Ptr<WimaxConnection> CreateConnection(Cid::Type type);
-    /**
-     * @brief add a connection to the list of managed connections
-     * @param connection the connection to add
-     * @param type the type of connection to add
-     */
-    void AddConnection(Ptr<WimaxConnection> connection, Cid::Type type);
-    /**
-     * @param cid the connection identifier
-     * @return the connection corresponding to cid
-     */
-    Ptr<WimaxConnection> GetConnection(Cid cid);
-    /**
-     * @param type the type of connection to add
-     * @return a vector of all connections matching the input type
-     */
-    std::vector<Ptr<WimaxConnection>> GetConnections(Cid::Type type) const;
-    /**
-     * @brief get number of packets
-     * @param type the type of connection to add
-     * @param schedulingType the scheduling type
-     * @returns number of packets
-     */
-    uint32_t GetNPackets(Cid::Type type, ServiceFlow::SchedulingType schedulingType) const;
-    /**
-     * @return true if one of the managed connection has at least one packet to send, false
-     * otherwise
-     */
-    bool HasPackets() const;
-
-  private:
-    std::vector<Ptr<WimaxConnection>> m_basicConnections;     ///< basic connections
-    std::vector<Ptr<WimaxConnection>> m_primaryConnections;   ///< primary connections
-    std::vector<Ptr<WimaxConnection>> m_transportConnections; ///< transport connections
-    std::vector<Ptr<WimaxConnection>> m_multicastConnections; ///< multicast connections
-    // only for BS
-    CidFactory* m_cidFactory; ///< the factory
-};
-
-} // namespace ns3
-
-#endif /* CONNECTION_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/crc8.cc ns-3.46/src/wimax/model/crc8.cc
--- ns-3.45/src/wimax/model/crc8.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/crc8.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-#include <stdint.h>
-
-namespace ns3
-{
-
-/*
- *   CRC8 table on the polynomial:
- *  x^8 + x^2 + x^1 + x^0
- */
-
-/// crc8 table
-static uint8_t crc8table[256] = {
-    0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
-    0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
-    0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
-    0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
-    0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
-    0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
-    0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
-    0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
-    0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
-    0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
-    0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
-    0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
-    0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
-    0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
-    0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
-    0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3,
-};
-
-uint8_t
-CRC8Calculate(const uint8_t* data, int length)
-{
-    uint8_t crc = 0;
-    for (int i = 0; i < length; i++)
-    {
-        crc = crc8table[data[i] ^ crc];
-    }
-    return crc;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/crc8.h ns-3.46/src/wimax/model/crc8.h
--- ns-3.45/src/wimax/model/crc8.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/crc8.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-#ifndef CRC8_H
-#define CRC8_H
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @param data buffer to calculate the checksum for
- * @param length the length of the buffer (bytes)
- * @returns the computed crc.
- *
- */
-uint8_t CRC8Calculate(const uint8_t* data, int length);
-
-} // namespace ns3
-
-#endif
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/cs-parameters.cc ns-3.46/src/wimax/model/cs-parameters.cc
--- ns-3.45/src/wimax/model/cs-parameters.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/cs-parameters.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,86 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-#include "cs-parameters.h"
-
-#include "wimax-tlv.h"
-
-namespace ns3
-{
-CsParameters::CsParameters()
-{
-    m_classifierDscAction = CsParameters::ADD;
-}
-
-CsParameters::~CsParameters()
-{
-}
-
-CsParameters::CsParameters(Tlv tlv)
-{
-    NS_ASSERT_MSG(tlv.GetType() == SfVectorTlvValue::IPV4_CS_Parameters, "Invalid TLV");
-    CsParamVectorTlvValue* param = ((CsParamVectorTlvValue*)(tlv.PeekValue()));
-
-    for (auto iter = param->Begin(); iter != param->End(); ++iter)
-    {
-        switch ((*iter)->GetType())
-        {
-        case CsParamVectorTlvValue::Classifier_DSC_Action: {
-            m_classifierDscAction =
-                (CsParameters::Action)((U8TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case CsParamVectorTlvValue::Packet_Classification_Rule: {
-            m_packetClassifierRule = IpcsClassifierRecord(*(*iter));
-            break;
-        }
-        }
-    }
-}
-
-CsParameters::CsParameters(CsParameters::Action classifierDscAction,
-                           IpcsClassifierRecord classifier)
-{
-    m_classifierDscAction = classifierDscAction;
-    m_packetClassifierRule = classifier;
-}
-
-void
-CsParameters::SetClassifierDscAction(CsParameters::Action action)
-{
-    m_classifierDscAction = action;
-}
-
-void
-CsParameters::SetPacketClassifierRule(IpcsClassifierRecord packetClassifierRule)
-{
-    m_packetClassifierRule = packetClassifierRule;
-}
-
-CsParameters::Action
-CsParameters::GetClassifierDscAction() const
-{
-    return m_classifierDscAction;
-}
-
-IpcsClassifierRecord
-CsParameters::GetPacketClassifierRule() const
-{
-    return m_packetClassifierRule;
-}
-
-Tlv
-CsParameters::ToTlv() const
-{
-    CsParamVectorTlvValue tmp;
-    tmp.Add(
-        Tlv(CsParamVectorTlvValue::Classifier_DSC_Action, 1, U8TlvValue(m_classifierDscAction)));
-    tmp.Add(m_packetClassifierRule.ToTlv());
-    return Tlv(SfVectorTlvValue::IPV4_CS_Parameters, tmp.GetSerializedSize(), tmp);
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/cs-parameters.h ns-3.46/src/wimax/model/cs-parameters.h
--- ns-3.45/src/wimax/model/cs-parameters.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/cs-parameters.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,79 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- *
- */
-
-#ifndef WIMAX_CS_PARAMETERS_H
-#define WIMAX_CS_PARAMETERS_H
-
-#include "ipcs-classifier-record.h"
-#include "wimax-tlv.h"
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief CsParameters class
- */
-class CsParameters
-{
-  public:
-    /// Action enumeration
-    enum Action
-    {
-        ADD = 0,
-        REPLACE = 1,
-        DELETE = 2
-    };
-
-    CsParameters();
-    ~CsParameters();
-    /**
-     * @brief creates a convergence sub-layer parameters from a tlv
-     * @param tlv the TLV
-     */
-    CsParameters(Tlv tlv);
-    /**
-     * @brief creates a convergence sub-layer parameters from an ipcs classifier record
-     * @param classifierDscAction the DCS action type
-     * @param classifier the IPCS classifier record
-     */
-    CsParameters(Action classifierDscAction, IpcsClassifierRecord classifier);
-    /**
-     * @brief sets the dynamic service classifier action to ADD, Change or delete. Only ADD is
-     * supported
-     * @param action the action enumeration
-     */
-    void SetClassifierDscAction(Action action);
-    /**
-     * @brief sets the packet classifier rules
-     * @param packetClassifierRule the IPCS classifier record
-     */
-    void SetPacketClassifierRule(IpcsClassifierRecord packetClassifierRule);
-    /**
-     * @return the  dynamic service classifier action
-     */
-    Action GetClassifierDscAction() const;
-    /**
-     * @return the  the packet classifier rules
-     */
-    IpcsClassifierRecord GetPacketClassifierRule() const;
-    /**
-     * @brief creates a tlv from the classifier record
-     * @return the created tlv
-     */
-    Tlv ToTlv() const;
-
-  private:
-    Action m_classifierDscAction;                ///< classifier DSC action
-    IpcsClassifierRecord m_packetClassifierRule; ///< packet classifier rule
-};
-
-} // namespace ns3
-#endif /* WIMAX_CS_PARAMETERS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/default-traces.h ns-3.46/src/wimax/model/default-traces.h
--- ns-3.45/src/wimax/model/default-traces.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/default-traces.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,1183 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef WIMAX_DEFAULT_TRACES_H
-#define WIMAX_DEFAULT_TRACES_H
-
-namespace ns3
-{
-
-/**
- * @brief These represent default traces, providing a number of
- * parameters for each SNR value.
- *
- * The parameters provided are (in order):
- *
- * -#  The SNR value,
- * -#  The bit error rate BER,
- * -#  The block error rate BlcERm,
- * -#  The standard deviation on block error rate,
- * -#  The lower bound confidence interval for a given modulation, and
- * -#  The upper bound confidence interval for a given modulation.
- *
- * It is made of 7 tables: one for each modulation and coding scheme.
- * Each table is made of 6 columns, as listed above.
- *
- * These traces are generated by an external OFDM simulator: It is based
- * on an external mathematics and signal processing library IT++ and includes:
- *
- * *  A random block generator,
- * *  A Reed Solomon (RS) coder,
- * *  A convolutional coder,
- * *  an interleaver,
- * *  A 256 FFT-based OFDM modulator,
- * *  A multi-path channel simulator, and
- * *  An equalizer.
- *
- * The multipath channel is simulated using the TDL_channel class of
- * the IT++ library.
- *
- *
- * The file format should be as follows
- *
- * SNR_value1   BER  Blc_ER  STANDARD_DEVIATION  CONFIDENCE_INTERVAL1  CONFIDENCE_INTERVAL2
- * SNR_value2   BER  Blc_ER  STANDARD_DEVIATION  CONFIDENCE_INTERVAL1  CONFIDENCE_INTERVAL2
- *  ...          ...  ...     ...                 ...                   ...
- *
- *
- *  Additional notes: from Esteban Municio   <esteban.municio@urjc.es>
- *
- *  This trace file has been edited for the 16 QAM 3/4 modulation (modulation4) since the original
- * SNR traces for this modulation were not long enough, giving inflated BER and BLER figures for
- * typical SNR values. Due to the impossibility to get the original IT++ environment used for the
- * original traces by the previous authors, the traces of modulation4 have been generated using a
- * simple IT++ program simulating the theoretical model of a AWGN channel given
- * BER=3/2*erfc(sqrt(k*0.1*(Eb_N0_dB)));
- *
- * @relates ns3::SNRToBlockErrorRateManager
- * @hideinitializer
- * @{
- */
-
-static const double modulation0[6][29] = {
-
-    {0.00, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40,
-     1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80},
-
-    {0.50798, 0.50862, 0.50517, 0.49325, 0.45741, 0.39430, 0.30345, 0.20492, 0.12126, 0.06741,
-     0.03429, 0.01710, 0.00865, 0.00419, 0.00223, 0.00098, 0.00065, 0.00028, 0.00013, 0.00006,
-     0.00005, 0.00001, 0.00002, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000},
-
-    {1.00000, 1.00000, 1.00000, 1.00000, 0.99870, 0.98730, 0.93240, 0.81330, 0.62730, 0.45400,
-     0.29000, 0.17620, 0.09950, 0.05670, 0.03350, 0.01640, 0.01120, 0.00520, 0.00320, 0.00160,
-     0.00110, 0.00060, 0.00040, 0.00010, 0.00010, 0.00010, 0.00000, 0.00000, 0.00000},
-
-    {0.00000, 0.00000, 0.00000, 0.00000, 0.00130, 0.01254, 0.06303, 0.15184, 0.23380, 0.24788,
-     0.20590, 0.14515, 0.08960, 0.05348, 0.03238, 0.01613, 0.01107, 0.00517, 0.00319, 0.00160,
-     0.00110, 0.00020, 0.00060, 0.00000, 0.00010, 0.00010, 0.00000, 0.00000, 0.00000},
-
-    {1.00000, 1.00000, 1.00000, 1.00000, 0.99799, 0.98511, 0.92748, 0.80566, 0.61782, 0.44424,
-     0.28111, 0.16873, 0.09363, 0.05217, 0.02997, 0.01391, 0.00914, 0.00379, 0.00209, 0.00082,
-     0.00045, 0.00008, 0.00012, 0.00000, 0.00010, 0.00010, 0.00000, 0.00000, 0.00000},
-
-    {1.00000, 1.00000, 1.00000, 1.00000, 0.99941, 0.98950, 0.93732, 0.82094, 0.63678, 0.46376,
-     0.29889, 0.18367, 0.10537, 0.06123, 0.03703, 0.01889, 0.01326, 0.00661, 0.00431, 0.00238,
-     0.00175, 0.00048, 0.00108, 0.00000, 0.00030, 0.00030, 0.00000, 0.00000, 0.00000},
-};
-
-static const double modulation1[6][42] = {
-
-    {2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30,
-     3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70,
-     4.80, 4.90, 5.00, 5.10, 5.20, 5.30, 5.40, 5.50, 5.60, 5.70, 5.80, 5.90, 6.00, 6.10},
-
-    {0.45604, 0.43627, 0.41185, 0.38360, 0.34393, 0.30548, 0.26033, 0.22148, 0.18646,
-     0.14898, 0.11921, 0.09493, 0.07055, 0.05625, 0.04178, 0.03245, 0.02613, 0.01733,
-     0.01415, 0.01151, 0.00834, 0.00506, 0.00450, 0.00349, 0.00213, 0.00158, 0.00162,
-     0.00078, 0.00070, 0.00039, 0.00039, 0.00059, 0.00049, 0.00005, 0.00015, 0.00010,
-     0.00000, 0.00029, 0.00005, 0.00000, 0.00005, 0.00000},
-
-    {0.95150, 0.91120, 0.86240, 0.80300, 0.72060, 0.64010, 0.54740, 0.46440, 0.39190,
-     0.31310, 0.25110, 0.19930, 0.14830, 0.11820, 0.08800, 0.06890, 0.05520, 0.03650,
-     0.02980, 0.02440, 0.01770, 0.01090, 0.00920, 0.00730, 0.00460, 0.00340, 0.00340,
-     0.00160, 0.00160, 0.00150, 0.00140, 0.00120, 0.00100, 0.00090, 0.00060, 0.00040,
-     0.00020, 0.00010, 0.00005, 0.00004, 0.00003, 0.00000},
-
-    {0.04615, 0.08092, 0.11867, 0.15819, 0.20134, 0.23037, 0.24775, 0.24873, 0.23831,
-     0.21507, 0.18805, 0.15958, 0.12631, 0.10423, 0.08026, 0.06415, 0.05215, 0.03517,
-     0.02891, 0.02380, 0.01739, 0.01078, 0.00911, 0.00725, 0.00458, 0.00339, 0.00339,
-     0.00160, 0.00160, 0.00080, 0.00080, 0.00120, 0.00100, 0.00010, 0.00030, 0.00020,
-     0.00000, 0.00060, 0.00010, 0.00000, 0.00010, 0.00000},
-
-    {0.94729, 0.90563, 0.85565, 0.79520, 0.71181, 0.63069, 0.53764, 0.45463, 0.38233,
-     0.30401, 0.24260, 0.19147, 0.14133, 0.11187, 0.08245, 0.06394, 0.05072, 0.03282,
-     0.02647, 0.02138, 0.01512, 0.00886, 0.00733, 0.00563, 0.00327, 0.00226, 0.00226,
-     0.00082, 0.00082, 0.00025, 0.00025, 0.00052, 0.00038, 0.00010, 0.00004, 0.00008,
-     0.00000, 0.00012, 0.00010, 0.00000, 0.00010, 0.00000},
-
-    {0.95571, 0.91678, 0.86915, 0.81080, 0.72940, 0.64951, 0.55716, 0.47418, 0.40147,
-     0.32219, 0.25960, 0.20713, 0.15527, 0.12453, 0.09355, 0.07386, 0.05968, 0.04018,
-     0.03313, 0.02742, 0.02028, 0.01294, 0.01107, 0.00897, 0.00593, 0.00454, 0.00454,
-     0.00238, 0.00238, 0.00135, 0.00135, 0.00188, 0.00162, 0.00030, 0.00064, 0.00048,
-     0.00000, 0.00108, 0.00030, 0.00000, 0.00030, 0.00000},
-};
-
-static const double modulation2[6][96] = {
-
-    {3.00,  3.10,  3.20,  3.30,  3.40,  3.50,  3.60,  3.70,  3.80,  3.90,  4.00,  4.10,
-     4.20,  4.30,  4.40,  4.50,  4.60,  4.70,  4.80,  4.90,  5.00,  5.10,  5.20,  5.30,
-     5.40,  5.50,  5.60,  5.70,  5.80,  5.90,  6.00,  6.10,  6.20,  6.30,  6.40,  6.50,
-     6.60,  6.70,  6.80,  6.90,  7.00,  7.10,  7.20,  7.30,  7.40,  7.50,  7.60,  7.70,
-     7.80,  7.90,  8.00,  8.10,  8.20,  8.30,  8.40,  8.50,  8.60,  8.70,  8.80,  8.90,
-     9.00,  9.10,  9.20,  9.30,  9.40,  9.50,  9.60,  9.70,  9.80,  9.90,  10.00, 10.10,
-     10.20, 10.30, 10.40, 10.50, 10.60, 10.70, 10.80, 10.90, 11.00, 11.10, 11.20, 11.30,
-     11.40, 11.50, 11.60, 11.70, 11.80, 11.90, 12.00, 12.10, 12.20, 12.30, 12.40, 12.50},
-
-    {0.36630, 0.35317, 0.34175, 0.33351, 0.31776, 0.30292, 0.28624, 0.27526, 0.26174, 0.24856,
-     0.23007, 0.21865, 0.19945, 0.18414, 0.16967, 0.15747, 0.14530, 0.13298, 0.11771, 0.11115,
-     0.09713, 0.09123, 0.08231, 0.07267, 0.06616, 0.05673, 0.05156, 0.04577, 0.04282, 0.03866,
-     0.03513, 0.02856, 0.02680, 0.02406, 0.01948, 0.01927, 0.01580, 0.01473, 0.01292, 0.01266,
-     0.01108, 0.00937, 0.00735, 0.00675, 0.00582, 0.00612, 0.00496, 0.00471, 0.00386, 0.00412,
-     0.00333, 0.00387, 0.00234, 0.00257, 0.00204, 0.00161, 0.00179, 0.00128, 0.00114, 0.00136,
-     0.00102, 0.00133, 0.00087, 0.00066, 0.00075, 0.00066, 0.00069, 0.00041, 0.00051, 0.00035,
-     0.00033, 0.00034, 0.00025, 0.00033, 0.00038, 0.00036, 0.00012, 0.00005, 0.00024, 0.00015,
-     0.00010, 0.00000, 0.00011, 0.00001, 0.00024, 0.00001, 0.00001, 0.00005, 0.00001, 0.00005,
-     0.00010, 0.00005, 0.00009, 0.00000, 0.00000, 0.00000},
-
-    {0.99130, 0.98790, 0.97490, 0.96360, 0.94840, 0.92520, 0.89860, 0.87960, 0.84970, 0.81960,
-     0.76860, 0.72540, 0.69130, 0.63620, 0.58540, 0.54710, 0.51010, 0.47450, 0.42570, 0.39700,
-     0.34730, 0.32840, 0.29360, 0.25990, 0.23970, 0.20910, 0.18810, 0.16480, 0.15410, 0.14130,
-     0.12570, 0.10670, 0.09940, 0.08810, 0.07330, 0.06930, 0.05720, 0.05530, 0.04630, 0.04460,
-     0.04070, 0.03310, 0.02810, 0.02680, 0.02290, 0.02260, 0.01700, 0.01740, 0.01320, 0.01490,
-     0.01210, 0.01320, 0.00820, 0.00850, 0.00840, 0.00640, 0.00590, 0.00480, 0.00450, 0.00490,
-     0.00410, 0.00420, 0.00340, 0.00250, 0.00240, 0.00240, 0.00210, 0.00190, 0.00160, 0.00140,
-     0.00120, 0.00110, 0.00100, 0.00100, 0.00100, 0.00100, 0.00080, 0.00070, 0.00050, 0.00050,
-     0.00040, 0.00040, 0.00030, 0.00030, 0.00020, 0.00020, 0.00010, 0.00008, 0.00007, 0.00005,
-     0.00004, 0.00003, 0.00003, 0.00003, 0.00002, 0.00000},
-
-    {0.00862, 0.01195, 0.02447, 0.03508, 0.04894, 0.06921, 0.09112, 0.10590, 0.12771, 0.14786,
-     0.17785, 0.19920, 0.21340, 0.23145, 0.24271, 0.24778, 0.24990, 0.24935, 0.24448, 0.23939,
-     0.22668, 0.22055, 0.20740, 0.19235, 0.18224, 0.16538, 0.15272, 0.13764, 0.13035, 0.12133,
-     0.10990, 0.09531, 0.08952, 0.08034, 0.06793, 0.06450, 0.05393, 0.05224, 0.04416, 0.04261,
-     0.03904, 0.03200, 0.02731, 0.02608, 0.02238, 0.02209, 0.01671, 0.01710, 0.01303, 0.01468,
-     0.01195, 0.01303, 0.00813, 0.00843, 0.00833, 0.00636, 0.00587, 0.00478, 0.00448, 0.00488,
-     0.00408, 0.00418, 0.00339, 0.00230, 0.00239, 0.00239, 0.00210, 0.00110, 0.00190, 0.00120,
-     0.00160, 0.00100, 0.00110, 0.00150, 0.00100, 0.00120, 0.00070, 0.00020, 0.00080, 0.00050,
-     0.00030, 0.00000, 0.00050, 0.00010, 0.00050, 0.00010, 0.00010, 0.00010, 0.00020, 0.00020,
-     0.00030, 0.00010, 0.00020, 0.00000, 0.00000, 0.00000},
-
-    {0.98948, 0.98576, 0.97183, 0.95993, 0.94406, 0.92004, 0.89268, 0.87322, 0.84270, 0.81206,
-     0.76033, 0.71665, 0.68225, 0.62677, 0.57574, 0.53734, 0.50030, 0.46471, 0.41601, 0.38741,
-     0.33797, 0.31920, 0.28467, 0.25130, 0.23133, 0.20113, 0.18044, 0.15753, 0.14702, 0.13447,
-     0.11920, 0.10065, 0.09354, 0.08254, 0.06819, 0.06432, 0.05265, 0.05082, 0.04218, 0.04055,
-     0.03683, 0.02959, 0.02486, 0.02363, 0.01997, 0.01969, 0.01447, 0.01484, 0.01096, 0.01252,
-     0.00996, 0.01096, 0.00643, 0.00670, 0.00661, 0.00484, 0.00440, 0.00345, 0.00319, 0.00353,
-     0.00285, 0.00293, 0.00226, 0.00136, 0.00144, 0.00144, 0.00120, 0.00045, 0.00105, 0.00052,
-     0.00082, 0.00038, 0.00045, 0.00074, 0.00038, 0.00052, 0.00018, 0.00008, 0.00025, 0.00006,
-     0.00004, 0.00000, 0.00006, 0.00010, 0.00006, 0.00010, 0.00010, 0.00010, 0.00008, 0.00008,
-     0.00004, 0.00010, 0.00008, 0.00000, 0.00000, 0.00000},
-
-    {0.99312, 0.99004, 0.97797, 0.96727, 0.95274, 0.93036, 0.90452, 0.88598, 0.85670, 0.82714,
-     0.77687, 0.73415, 0.70035, 0.64563, 0.59506, 0.55686, 0.51990, 0.48429, 0.43539, 0.40659,
-     0.35663, 0.33760, 0.30253, 0.26850, 0.24807, 0.21707, 0.19576, 0.17207, 0.16118, 0.14813,
-     0.13220, 0.11275, 0.10526, 0.09366, 0.07841, 0.07428, 0.06175, 0.05978, 0.05042, 0.04865,
-     0.04457, 0.03661, 0.03134, 0.02996, 0.02583, 0.02551, 0.01953, 0.01996, 0.01544, 0.01727,
-     0.01424, 0.01544, 0.00997, 0.01030, 0.01019, 0.00796, 0.00740, 0.00615, 0.00581, 0.00627,
-     0.00535, 0.00547, 0.00454, 0.00324, 0.00336, 0.00336, 0.00300, 0.00175, 0.00275, 0.00188,
-     0.00238, 0.00162, 0.00175, 0.00226, 0.00162, 0.00188, 0.00122, 0.00048, 0.00135, 0.00094,
-     0.00064, 0.00000, 0.00094, 0.00030, 0.00094, 0.00030, 0.00030, 0.00030, 0.00048, 0.00048,
-     0.00064, 0.00030, 0.00048, 0.00000, 0.00000, 0.00000},
-};
-
-static const double modulation3[6][117] = {
-
-    {10.00, 10.10, 10.20, 10.30, 10.40, 10.50, 10.60, 10.70, 10.80, 10.90, 11.00, 11.10, 11.20,
-     11.30, 11.40, 11.50, 11.60, 11.70, 11.80, 11.90, 12.00, 12.10, 12.20, 12.30, 12.40, 12.50,
-     12.60, 12.70, 12.80, 12.90, 13.00, 13.10, 13.20, 13.30, 13.40, 13.50, 13.60, 13.70, 13.80,
-     13.90, 14.00, 14.10, 14.20, 14.30, 14.40, 14.50, 14.60, 14.70, 14.90, 15.00, 15.10, 15.20,
-     15.30, 15.40, 15.50, 15.60, 15.70, 15.80, 15.90, 16.00, 16.10, 16.20, 16.30, 16.40, 16.50,
-     16.60, 16.70, 16.80, 16.90, 17.10, 17.20, 17.30, 17.40, 17.50, 17.60, 17.70, 17.80, 17.90,
-     18.00, 18.10, 18.20, 18.30, 18.40, 18.50, 18.60, 18.70, 18.80, 18.90, 19.00, 19.10, 19.20,
-     19.30, 19.40, 19.50, 19.60, 19.70, 19.80, 19.90, 20.00, 20.10, 20.20, 20.30, 20.40, 20.50,
-     20.60, 20.70, 20.80, 20.90, 21.00, 21.10, 21.20, 21.30, 21.40, 21.50, 21.60, 21.70, 21.80},
-
-    {0.39109, 0.37994, 0.36904, 0.36186, 0.35172, 0.34069, 0.32445, 0.31707, 0.30757, 0.28951,
-     0.27937, 0.26696, 0.25737, 0.24826, 0.23413, 0.22045, 0.21144, 0.20244, 0.19049, 0.17783,
-     0.16793, 0.15746, 0.14697, 0.13387, 0.12757, 0.12354, 0.11370, 0.10474, 0.09701, 0.09219,
-     0.08535, 0.07516, 0.07240, 0.06492, 0.06394, 0.05577, 0.05399, 0.05040, 0.04632, 0.04287,
-     0.03918, 0.03327, 0.03376, 0.02855, 0.02791, 0.02417, 0.02412, 0.02111, 0.01801, 0.01482,
-     0.01486, 0.01324, 0.01167, 0.01137, 0.01127, 0.00911, 0.00930, 0.00650, 0.00748, 0.00615,
-     0.00610, 0.00487, 0.00492, 0.00364, 0.00448, 0.00477, 0.00231, 0.00295, 0.00256, 0.00266,
-     0.00182, 0.00192, 0.00182, 0.00123, 0.00158, 0.00153, 0.00153, 0.00093, 0.00093, 0.00064,
-     0.00064, 0.00059, 0.00069, 0.00034, 0.00034, 0.00054, 0.00039, 0.00010, 0.00025, 0.00049,
-     0.00030, 0.00034, 0.00015, 0.00034, 0.00030, 0.00034, 0.00005, 0.00020, 0.00020, 0.00015,
-     0.00010, 0.00010, 0.00010, 0.00010, 0.00010, 0.00020, 0.00000, 0.00005, 0.00000, 0.00005,
-     0.00010, 0.00020, 0.00010, 0.00005, 0.00005, 0.00020, 0.00000},
-
-    {0.79460, 0.77200, 0.74980, 0.73520, 0.71470, 0.69220, 0.65920, 0.64420, 0.62490, 0.58830,
-     0.56760, 0.54240, 0.52290, 0.50440, 0.47570, 0.44790, 0.42960, 0.41130, 0.38710, 0.36140,
-     0.34120, 0.32000, 0.29860, 0.27200, 0.25920, 0.25100, 0.23100, 0.21280, 0.19710, 0.18730,
-     0.17340, 0.15270, 0.14710, 0.13190, 0.12990, 0.11330, 0.10970, 0.10240, 0.09410, 0.08710,
-     0.07960, 0.06760, 0.06860, 0.05800, 0.05670, 0.04910, 0.04900, 0.04290, 0.03660, 0.03010,
-     0.03020, 0.02690, 0.02370, 0.02310, 0.02290, 0.01850, 0.01890, 0.01520, 0.01320, 0.01250,
-     0.01240, 0.01000, 0.01000, 0.00940, 0.00910, 0.00970, 0.00700, 0.00600, 0.00520, 0.00540,
-     0.00390, 0.00390, 0.00370, 0.00320, 0.00320, 0.00310, 0.00310, 0.00190, 0.00190, 0.00130,
-     0.00130, 0.00120, 0.00140, 0.00090, 0.00080, 0.00070, 0.00070, 0.00070, 0.00060, 0.00060,
-     0.00060, 0.00050, 0.00050, 0.00050, 0.00040, 0.00040, 0.00040, 0.00040, 0.00040, 0.00030,
-     0.00020, 0.00020, 0.00020, 0.00020, 0.00020, 0.00015, 0.00014, 0.00013, 0.00012, 0.00011,
-     0.00010, 0.00009, 0.00008, 0.00007, 0.00006, 0.00005, 0.00000},
-
-    {0.16321, 0.17602, 0.18760, 0.19468, 0.20390, 0.21306, 0.22465, 0.22921, 0.23440, 0.24220,
-     0.24543, 0.24820, 0.24948, 0.24998, 0.24941, 0.24729, 0.24504, 0.24213, 0.23725, 0.23079,
-     0.22478, 0.21760, 0.20944, 0.19802, 0.19201, 0.18800, 0.17764, 0.16752, 0.15825, 0.15222,
-     0.14333, 0.12938, 0.12546, 0.11450, 0.11303, 0.10046, 0.09767, 0.09191, 0.08525, 0.07951,
-     0.07326, 0.06303, 0.06389, 0.05464, 0.05348, 0.04669, 0.04660, 0.04106, 0.03526, 0.02919,
-     0.02929, 0.02618, 0.02314, 0.02257, 0.02238, 0.01816, 0.01854, 0.01303, 0.01497, 0.01234,
-     0.01225, 0.00980, 0.00990, 0.00734, 0.00902, 0.00961, 0.00468, 0.00596, 0.00517, 0.00537,
-     0.00369, 0.00388, 0.00369, 0.00249, 0.00319, 0.00309, 0.00309, 0.00190, 0.00190, 0.00130,
-     0.00130, 0.00120, 0.00140, 0.00070, 0.00070, 0.00110, 0.00080, 0.00020, 0.00050, 0.00100,
-     0.00060, 0.00070, 0.00030, 0.00070, 0.00060, 0.00070, 0.00010, 0.00040, 0.00040, 0.00030,
-     0.00020, 0.00020, 0.00020, 0.00020, 0.00020, 0.00040, 0.00000, 0.00010, 0.00000, 0.00010,
-     0.00020, 0.00040, 0.00020, 0.00010, 0.00010, 0.00040, 0.00000},
-
-    {0.78668, 0.76378, 0.74131, 0.72655, 0.70585, 0.68315, 0.64991, 0.63482, 0.61541, 0.57865,
-     0.55789, 0.53263, 0.51311, 0.49460, 0.46591, 0.43815, 0.41990, 0.40165, 0.37755, 0.35198,
-     0.33191, 0.31086, 0.28963, 0.26328, 0.25061, 0.24250, 0.22274, 0.20478, 0.18930, 0.17965,
-     0.16598, 0.14565, 0.14016, 0.12527, 0.12331, 0.10709, 0.10358, 0.09646, 0.08838, 0.08157,
-     0.07429, 0.06268, 0.06365, 0.05342, 0.05217, 0.04487, 0.04477, 0.03893, 0.03292, 0.02675,
-     0.02685, 0.02373, 0.02072, 0.02016, 0.01997, 0.01586, 0.01623, 0.01096, 0.01280, 0.01032,
-     0.01023, 0.00796, 0.00805, 0.00572, 0.00724, 0.00778, 0.00336, 0.00449, 0.00379, 0.00396,
-     0.00251, 0.00268, 0.00251, 0.00152, 0.00209, 0.00201, 0.00201, 0.00105, 0.00105, 0.00059,
-     0.00059, 0.00052, 0.00067, 0.00018, 0.00018, 0.00045, 0.00025, 0.00008, 0.00006, 0.00038,
-     0.00012, 0.00018, 0.00004, 0.00018, 0.00012, 0.00018, 0.00010, 0.00001, 0.00001, 0.00004,
-     0.00008, 0.00008, 0.00008, 0.00008, 0.00008, 0.00001, 0.00000, 0.00010, 0.00000, 0.00010,
-     0.00008, 0.00001, 0.00008, 0.00010, 0.00010, 0.00001, 0.00000},
-
-    {0.80252, 0.78022, 0.75829, 0.74385, 0.72355, 0.70125, 0.66849, 0.65358, 0.63439, 0.59795,
-     0.57731, 0.55217, 0.53269, 0.51420, 0.48549, 0.45765, 0.43930, 0.42095, 0.39665, 0.37082,
-     0.35049, 0.32914, 0.30757, 0.28072, 0.26779, 0.25950, 0.23926, 0.22082, 0.20490, 0.19495,
-     0.18082, 0.15975, 0.15404, 0.13853, 0.13649, 0.11951, 0.11582, 0.10834, 0.09982, 0.09263,
-     0.08490, 0.07252, 0.07355, 0.06258, 0.06123, 0.05334, 0.05323, 0.04687, 0.04028, 0.03345,
-     0.03355, 0.03007, 0.02668, 0.02604, 0.02583, 0.02114, 0.02157, 0.01544, 0.01760, 0.01468,
-     0.01457, 0.01184, 0.01195, 0.00908, 0.01096, 0.01162, 0.00604, 0.00751, 0.00661, 0.00684,
-     0.00489, 0.00512, 0.00489, 0.00348, 0.00431, 0.00419, 0.00419, 0.00275, 0.00275, 0.00201,
-     0.00201, 0.00188, 0.00213, 0.00122, 0.00122, 0.00175, 0.00135, 0.00048, 0.00094, 0.00162,
-     0.00108, 0.00122, 0.00064, 0.00122, 0.00108, 0.00122, 0.00030, 0.00079, 0.00079, 0.00064,
-     0.00048, 0.00048, 0.00048, 0.00048, 0.00048, 0.00079, 0.00000, 0.00030, 0.00000, 0.00030,
-     0.00048, 0.00079, 0.00048, 0.00030, 0.00030, 0.00079, 0.00000},
-};
-
-static const double modulation4[6][331] = {
-
-    {20,   20.1, 20.2, 20.3, 20.4, 20.5, 20.6, 20.7, 20.8, 20.9, 21,   21.1, 21.2, 21.3, 21.4, 21.5,
-     21.6, 21.7, 21.8, 21.9, 22,   22.1, 22.2, 22.3, 22.4, 22.5, 22.6, 22.7, 22.8, 22.9, 23,   23.1,
-     23.2, 23.3, 23.4, 23.5, 23.6, 23.7, 23.8, 23.9, 24,   24.1, 24.2, 24.3, 24.4, 24.5, 24.6, 24.7,
-     24.8, 24.9, 25,   25.1, 25.2, 25.3, 25.4, 25.5, 25.6, 25.7, 25.8, 25.9, 26,   26.1, 26.2, 26.3,
-     26.4, 26.5, 26.6, 26.7, 26.8, 26.9, 27,   27.1, 27.2, 27.3, 27.4, 27.5, 27.6, 27.7, 27.8, 27.9,
-     28,   28.1, 28.2, 28.3, 28.4, 28.5, 28.6, 28.7, 28.8, 28.9, 29,   29.1, 29.2, 29.3, 29.4, 29.5,
-     29.6, 29.7, 29.8, 29.9, 30,   30.1, 30.2, 30.3, 30.4, 30.5, 30.6, 30.7, 30.8, 30.9, 31,   31.1,
-     31.2, 31.3, 31.4, 31.5, 31.6, 31.7, 31.8, 31.9, 32,   32.1, 32.2, 32.3, 32.4, 32.5, 32.6, 32.7,
-     32.8, 32.9, 33,   33.1, 33.2, 33.3, 33.4, 33.5, 33.6, 33.7, 33.8, 33.9, 34,   34.1, 34.2, 34.3,
-     34.4, 34.5, 34.6, 34.7, 34.8, 34.9, 35,   35.1, 35.2, 35.3, 35.4, 35.5, 35.6, 35.7, 35.8, 35.9,
-     36,   36.1, 36.2, 36.3, 36.4, 36.5, 36.6, 36.7, 36.8, 36.9, 37,   37.1, 37.2, 37.3, 37.4, 37.5,
-     37.6, 37.7, 37.8, 37.9, 38,   38.1, 38.2, 38.3, 38.4, 38.5, 38.6, 38.7, 38.8, 38.9, 39,   39.1,
-     39.2, 39.3, 39.4, 39.5, 39.6, 39.7, 39.8, 39.9, 40,   40.1, 40.2, 40.3, 40.4, 40.5, 40.6, 40.7,
-     40.8, 40.9, 41,   41.1, 41.2, 41.3, 41.4, 41.5, 41.6, 41.7, 41.8, 41.9, 42,   42.1, 42.2, 42.3,
-     42.4, 42.5, 42.6, 42.7, 42.8, 42.9, 43,   43.1, 43.2, 43.3, 43.4, 43.5, 43.6, 43.7, 43.8, 43.9,
-     44,   44.1, 44.2, 44.3, 44.4, 44.5, 44.6, 44.7, 44.8, 44.9, 45,   45.1, 45.2, 45.3, 45.4, 45.5,
-     45.6, 45.7, 45.8, 45.9, 46,   46.1, 46.2, 46.3, 46.4, 46.5, 46.6, 46.7, 46.8, 46.9, 47,   47.1,
-     47.2, 47.3, 47.4, 47.5, 47.6, 47.7, 47.8, 47.9, 48,   48.1, 48.2, 48.3, 48.4, 48.5, 48.6, 48.7,
-     48.8, 48.9, 49,   49.1, 49.2, 49.3, 49.4, 49.5, 49.6, 49.7, 49.8, 49.9, 50,   50.1, 50.2, 50.3,
-     50.4, 50.5, 50.6, 50.7, 50.8, 50.9, 51,   51.1, 51.2, 51.3, 51.4, 51.5, 51.6, 51.7, 51.8, 51.9,
-     52,   52.1, 52.2, 52.3, 52.4, 52.5, 52.6, 52.7, 52.8, 52.9, 53},
-
-    {0.473383, 0.465027, 0.456673, 0.448325, 0.439984, 0.431653, 0.423335, 0.415032, 0.406746,
-     0.398480, 0.390237, 0.382020, 0.373830, 0.365672, 0.357547, 0.349458, 0.341409, 0.333402,
-     0.325439, 0.317525, 0.309662, 0.301852, 0.294099, 0.286406, 0.278776, 0.271211, 0.263714,
-     0.256290, 0.248939, 0.241667, 0.234474, 0.227364, 0.220341, 0.213406, 0.206562, 0.199813,
-     0.193161, 0.186608, 0.180156, 0.173809, 0.167569, 0.161438, 0.155418, 0.149511, 0.143719,
-     0.138045, 0.132489, 0.127053, 0.121740, 0.116550, 0.111485, 0.106546, 0.101733, 0.097049,
-     0.092492, 0.088064, 0.083766, 0.079597, 0.075558, 0.071648, 0.067867, 0.064215, 0.060691,
-     0.057295, 0.054025, 0.050880, 0.047860, 0.044962, 0.042185, 0.039528, 0.036989, 0.034565,
-     0.032255, 0.030056, 0.027965, 0.025981, 0.024101, 0.022322, 0.020641, 0.019055, 0.017561,
-     0.016157, 0.014839, 0.013604, 0.012449, 0.011371, 0.010366, 0.009431, 0.008563, 0.007760,
-     0.007017, 0.006331, 0.005700, 0.005120, 0.004589, 0.004103, 0.003660, 0.003256, 0.002890,
-     0.002558, 0.002259, 0.001989, 0.001747, 0.001529, 0.001335, 0.001162, 0.001009, 0.000873,
-     0.000753, 0.000647, 0.000555, 0.000474, 0.000403, 0.000342, 0.000289, 0.000243, 0.000204,
-     0.000170, 0.000142, 0.000117, 0.000097, 0.000080, 0.000065, 0.000053, 0.000043, 0.000035,
-     0.000028, 0.000022, 0.000018, 0.000014, 0.000011, 0.000009, 0.000007, 0.000005, 0.000004,
-     0.000003, 0.000002, 0.000002, 0.000001, 0.000001, 0.000001, 0.000001, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
-
-    {0.899428, 0.883551, 0.867679, 0.851817, 0.835970, 0.820141, 0.804337, 0.788561, 0.772818,
-     0.757113, 0.741451, 0.725838, 0.710278, 0.694776, 0.679339, 0.663970, 0.648677, 0.633463,
-     0.618335, 0.603298, 0.588357, 0.573519, 0.558789, 0.544172, 0.529674, 0.515300, 0.501058,
-     0.486950, 0.472985, 0.459166, 0.445500, 0.431992, 0.418647, 0.405471, 0.392468, 0.379645,
-     0.367005, 0.354554, 0.342297, 0.330238, 0.318382, 0.306732, 0.295294, 0.284071, 0.273066,
-     0.262285, 0.251729, 0.241402, 0.231306, 0.221446, 0.211822, 0.202437, 0.193293, 0.184392,
-     0.175735, 0.167322, 0.159155, 0.151234, 0.143559, 0.136131, 0.128947, 0.122008, 0.115313,
-     0.108860, 0.102647, 0.096672, 0.090933, 0.085428, 0.080152, 0.075104, 0.070279, 0.065674,
-     0.061284, 0.057106, 0.053134, 0.049364, 0.045792, 0.042411, 0.039217, 0.036204, 0.033367,
-     0.030699, 0.028194, 0.025848, 0.023653, 0.021604, 0.019695, 0.017919, 0.016271, 0.014743,
-     0.013332, 0.012029, 0.010830, 0.009728, 0.008719, 0.007796, 0.006953, 0.006187, 0.005491,
-     0.004861, 0.004292, 0.003779, 0.003318, 0.002906, 0.002537, 0.002209, 0.001917, 0.001659,
-     0.001430, 0.001230, 0.001054, 0.000900, 0.000766, 0.000649, 0.000549, 0.000462, 0.000387,
-     0.000324, 0.000269, 0.000223, 0.000184, 0.000151, 0.000124, 0.000101, 0.000082, 0.000066,
-     0.000053, 0.000042, 0.000034, 0.000027, 0.000021, 0.000016, 0.000013, 0.000010, 0.000008,
-     0.000006, 0.000004, 0.000003, 0.000003, 0.000002, 0.000001, 0.000001, 0.000001, 0.000001,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
-
-    {0.163210, 0.176020, 0.187600, 0.194680, 0.203900, 0.213060, 0.224650, 0.229210, 0.234400,
-     0.242200, 0.245430, 0.248200, 0.249480, 0.249980, 0.249410, 0.247290, 0.245040, 0.242130,
-     0.237250, 0.230790, 0.224780, 0.217600, 0.209440, 0.198020, 0.192010, 0.188000, 0.177640,
-     0.167520, 0.158250, 0.152220, 0.143330, 0.129380, 0.125460, 0.114500, 0.113030, 0.100460,
-     0.097670, 0.091910, 0.085250, 0.079510, 0.073260, 0.063030, 0.063890, 0.054640, 0.053480,
-     0.046690, 0.046600, 0.041060, 0.035260, 0.029190, 0.029290, 0.026180, 0.023140, 0.022570,
-     0.022380, 0.018160, 0.018540, 0.013030, 0.014970, 0.012340, 0.012250, 0.009800, 0.009900,
-     0.007340, 0.009020, 0.009610, 0.004680, 0.005960, 0.005170, 0.005370, 0.003690, 0.003880,
-     0.003690, 0.002490, 0.003190, 0.003090, 0.003090, 0.001900, 0.001900, 0.001300, 0.001300,
-     0.001200, 0.001400, 0.000700, 0.000700, 0.001100, 0.000800, 0.000200, 0.000500, 0.001000,
-     0.000600, 0.000700, 0.000300, 0.000700, 0.000600, 0.000700, 0.000100, 0.000400, 0.000400,
-     0.000300, 0.000200, 0.000200, 0.000200, 0.000200, 0.000200, 0.000400, 0.000000, 0.000100,
-     0.000000, 0.000100, 0.000200, 0.000400, 0.000200, 0.000100, 0.000100, 0.000400, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
-
-    {0.890434, 0.874715, 0.859002, 0.843299, 0.827610, 0.811940, 0.796293, 0.780675, 0.765089,
-     0.749542, 0.734037, 0.718579, 0.703175, 0.687828, 0.672545, 0.657331, 0.642190, 0.627128,
-     0.612151, 0.597265, 0.582474, 0.567784, 0.553201, 0.538730, 0.524377, 0.510147, 0.496047,
-     0.482081, 0.468255, 0.454575, 0.441045, 0.427672, 0.414461, 0.401416, 0.388544, 0.375848,
-     0.363335, 0.351009, 0.338874, 0.326936, 0.315198, 0.303665, 0.292341, 0.281230, 0.270336,
-     0.259662, 0.249211, 0.238988, 0.228993, 0.219231, 0.209704, 0.200413, 0.191361, 0.182548,
-     0.173977, 0.165649, 0.157564, 0.149722, 0.142124, 0.134769, 0.127658, 0.120788, 0.114160,
-     0.107771, 0.101620, 0.095705, 0.090024, 0.084573, 0.079351, 0.074353, 0.069576, 0.065017,
-     0.060671, 0.056535, 0.052603, 0.048871, 0.045334, 0.041987, 0.038825, 0.035842, 0.033033,
-     0.030392, 0.027912, 0.025589, 0.023417, 0.021388, 0.019498, 0.017740, 0.016108, 0.014596,
-     0.013198, 0.011909, 0.010722, 0.009631, 0.008632, 0.007718, 0.006884, 0.006125, 0.005436,
-     0.004812, 0.004249, 0.003741, 0.003285, 0.002877, 0.002512, 0.002187, 0.001898, 0.001642,
-     0.001416, 0.001218, 0.001043, 0.000891, 0.000758, 0.000643, 0.000543, 0.000457, 0.000384,
-     0.000320, 0.000267, 0.000221, 0.000182, 0.000150, 0.000123, 0.000100, 0.000081, 0.000065,
-     0.000052, 0.000042, 0.000033, 0.000026, 0.000021, 0.000016, 0.000013, 0.000010, 0.000008,
-     0.000006, 0.000004, 0.000003, 0.000003, 0.000002, 0.000001, 0.000001, 0.000001, 0.000001,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
-
-    {0.908423, 0.892386, 0.876356, 0.860335, 0.844330, 0.828343, 0.812380, 0.796446, 0.780546,
-     0.764684, 0.748866, 0.733096, 0.717380, 0.701724, 0.686132, 0.670610, 0.655163, 0.639798,
-     0.624518, 0.609331, 0.594241, 0.579254, 0.564377, 0.549613, 0.534970, 0.520453, 0.506068,
-     0.491820, 0.477715, 0.463758, 0.449955, 0.436312, 0.422834, 0.409526, 0.396393, 0.383441,
-     0.370675, 0.358100, 0.345720, 0.333540, 0.321565, 0.309799, 0.298247, 0.286911, 0.275797,
-     0.264907, 0.254246, 0.243816, 0.233619, 0.223660, 0.213940, 0.204462, 0.195226, 0.186236,
-     0.177492, 0.168995, 0.160747, 0.152747, 0.144995, 0.137492, 0.130237, 0.123228, 0.116466,
-     0.109948, 0.103673, 0.097639, 0.091843, 0.086282, 0.080954, 0.075855, 0.070982, 0.066330,
-     0.061897, 0.057677, 0.053665, 0.049858, 0.046250, 0.042835, 0.039609, 0.036566, 0.033700,
-     0.031006, 0.028476, 0.026106, 0.023890, 0.021820, 0.019892, 0.018098, 0.016433, 0.014891,
-     0.013465, 0.012149, 0.010938, 0.009826, 0.008806, 0.007873, 0.007023, 0.006249, 0.005546,
-     0.004910, 0.004335, 0.003817, 0.003352, 0.002935, 0.002562, 0.002231, 0.001936, 0.001675,
-     0.001445, 0.001242, 0.001064, 0.000909, 0.000774, 0.000656, 0.000554, 0.000467, 0.000391,
-     0.000327, 0.000272, 0.000225, 0.000186, 0.000153, 0.000125, 0.000102, 0.000083, 0.000067,
-     0.000054, 0.000043, 0.000034, 0.000027, 0.000021, 0.000017, 0.000013, 0.000010, 0.000008,
-     0.000006, 0.000004, 0.000003, 0.000003, 0.000002, 0.000001, 0.000001, 0.000001, 0.000001,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
-     0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000},
-};
-
-static const double modulation5[6][547] = {
-
-    {50.00,  50.10,  50.20,  50.30,  50.40,  50.50,  50.60,  50.70,  50.80,  50.90,  51.00,  51.10,
-     51.20,  51.30,  51.40,  51.50,  51.60,  51.70,  51.80,  51.90,  52.00,  52.10,  52.20,  52.30,
-     52.40,  52.50,  52.60,  52.70,  52.80,  52.90,  53.00,  53.10,  53.20,  53.30,  53.40,  53.50,
-     53.60,  53.70,  53.80,  53.90,  54.00,  54.10,  54.20,  54.30,  54.40,  54.50,  54.60,  54.70,
-     54.80,  54.90,  55.00,  55.10,  55.20,  55.30,  55.40,  55.50,  55.60,  55.70,  55.80,  55.90,
-     56.00,  56.10,  56.20,  56.30,  56.40,  56.50,  56.60,  56.70,  56.80,  56.90,  57.00,  57.10,
-     57.20,  57.30,  57.40,  57.50,  57.60,  57.70,  57.80,  57.90,  58.00,  58.10,  58.20,  58.30,
-     58.40,  58.50,  58.60,  58.70,  58.80,  58.90,  59.00,  59.10,  59.20,  59.30,  59.40,  59.50,
-     59.60,  59.70,  59.80,  59.90,  60.00,  60.10,  60.20,  60.30,  60.40,  60.50,  60.60,  60.70,
-     60.80,  60.90,  61.00,  61.10,  61.20,  61.30,  61.40,  61.50,  61.60,  61.70,  61.80,  61.90,
-     62.00,  62.10,  62.20,  62.30,  62.40,  62.50,  62.60,  62.70,  62.80,  62.90,  63.00,  63.10,
-     63.20,  63.30,  63.40,  63.50,  63.60,  63.70,  63.80,  63.90,  64.00,  64.10,  64.20,  64.30,
-     64.40,  64.50,  64.60,  64.70,  64.80,  64.90,  65.00,  65.10,  65.20,  65.30,  65.40,  65.50,
-     65.60,  65.70,  65.80,  65.90,  66.00,  66.10,  66.20,  66.30,  66.40,  66.50,  66.60,  66.70,
-     66.80,  66.90,  67.00,  67.10,  67.20,  67.30,  67.40,  67.50,  67.60,  67.70,  67.80,  67.90,
-     68.00,  68.10,  68.20,  68.30,  68.40,  68.50,  68.60,  68.70,  68.80,  68.90,  69.00,  69.10,
-     69.20,  69.30,  69.40,  69.50,  69.60,  69.70,  69.80,  69.90,  70.00,  70.10,  70.20,  70.30,
-     70.40,  70.50,  70.60,  70.70,  70.80,  70.90,  71.00,  71.10,  71.20,  71.30,  71.40,  71.50,
-     71.60,  71.70,  71.80,  71.90,  72.00,  72.10,  72.20,  72.30,  72.40,  72.50,  72.60,  72.70,
-     72.80,  72.90,  73.00,  73.10,  73.20,  73.30,  73.40,  73.50,  73.60,  73.70,  73.80,  73.90,
-     74.00,  74.10,  74.20,  74.30,  74.40,  74.50,  74.60,  74.70,  74.80,  74.90,  75.00,  75.10,
-     75.20,  75.30,  75.40,  75.50,  75.60,  75.70,  75.80,  75.90,  76.00,  76.10,  76.20,  76.30,
-     76.40,  76.50,  76.60,  76.70,  76.80,  76.90,  77.00,  77.10,  77.20,  77.30,  77.40,  77.50,
-     77.60,  77.70,  77.80,  77.90,  78.00,  78.10,  78.20,  78.30,  78.40,  78.50,  78.60,  78.70,
-     78.80,  78.90,  79.00,  79.10,  79.20,  79.30,  79.40,  79.50,  79.60,  79.70,  79.80,  79.90,
-     80.00,  80.10,  80.20,  80.30,  80.40,  80.50,  80.60,  80.70,  80.80,  80.90,  81.00,  81.10,
-     81.20,  81.30,  81.40,  81.50,  81.60,  81.70,  81.80,  81.90,  82.00,  82.10,  82.20,  82.30,
-     82.40,  82.50,  82.60,  82.70,  82.80,  82.90,  83.00,  83.10,  83.20,  83.30,  83.40,  83.50,
-     83.60,  83.70,  83.80,  83.90,  84.00,  84.10,  84.20,  84.30,  84.40,  84.50,  84.60,  84.70,
-     84.80,  84.90,  85.00,  85.10,  85.20,  85.30,  85.40,  85.50,  85.60,  85.70,  85.80,  85.90,
-     86.00,  86.10,  86.20,  86.30,  86.40,  86.50,  86.60,  86.70,  86.80,  86.90,  87.00,  87.10,
-     87.20,  87.30,  87.40,  87.50,  87.60,  87.70,  87.80,  87.90,  88.00,  88.10,  88.20,  88.30,
-     88.40,  88.50,  88.60,  88.70,  88.80,  88.90,  89.00,  89.10,  89.20,  89.30,  89.40,  89.50,
-     89.60,  89.70,  89.80,  89.90,  90.00,  90.10,  90.20,  90.30,  90.40,  90.50,  90.60,  90.70,
-     90.80,  90.90,  91.00,  91.10,  91.20,  91.30,  91.40,  91.50,  91.60,  91.70,  91.80,  91.90,
-     92.00,  92.10,  92.20,  92.30,  92.40,  92.50,  92.60,  92.70,  92.80,  92.90,  93.00,  93.10,
-     93.20,  93.30,  93.40,  93.50,  93.60,  93.70,  93.80,  93.90,  94.00,  94.10,  94.20,  94.30,
-     94.40,  94.50,  94.60,  94.70,  94.80,  94.90,  95.00,  96.00,  96.10,  96.20,  96.30,  96.40,
-     96.50,  96.60,  96.70,  96.80,  96.90,  97.00,  97.10,  97.20,  97.30,  97.40,  97.50,  97.60,
-     97.70,  97.80,  97.90,  98.00,  98.10,  98.20,  98.30,  98.40,  98.50,  98.60,  98.70,  98.80,
-     98.90,  99.00,  99.10,  99.20,  99.30,  99.40,  99.50,  99.60,  99.70,  99.80,  99.90,  100.00,
-     100.10, 100.20, 100.30, 100.40, 100.50, 100.60, 100.70, 100.80, 100.90, 101.00, 101.10, 101.20,
-     101.30, 101.40, 101.50, 101.60, 101.70, 101.80, 101.90, 102.00, 102.10, 102.20, 102.30, 102.40,
-     102.50, 102.60, 102.70, 102.80, 102.90, 103.00, 103.10, 103.20, 103.30, 103.40, 103.50, 103.60,
-     103.70, 103.80, 103.90, 104.00, 104.10, 104.20, 104.30, 104.40, 104.50, 104.60, 104.70, 104.80,
-     104.90, 105.00},
-
-    {0.46874, 0.46753, 0.46863, 0.46778, 0.46771, 0.46740, 0.46399, 0.46725, 0.46422, 0.46493,
-     0.46519, 0.46289, 0.46231, 0.46265, 0.46173, 0.46049, 0.45981, 0.45721, 0.45743, 0.45867,
-     0.45599, 0.45719, 0.45515, 0.45272, 0.45396, 0.45432, 0.45263, 0.44926, 0.44898, 0.45062,
-     0.45024, 0.44840, 0.44469, 0.44360, 0.44467, 0.44375, 0.44466, 0.44159, 0.44011, 0.43992,
-     0.43979, 0.43863, 0.44184, 0.43579, 0.43560, 0.43449, 0.43185, 0.43021, 0.43098, 0.42802,
-     0.42823, 0.42574, 0.42867, 0.42309, 0.42344, 0.42089, 0.42158, 0.41947, 0.41761, 0.41779,
-     0.41695, 0.41723, 0.41540, 0.40973, 0.41315, 0.40834, 0.40579, 0.40460, 0.40443, 0.40311,
-     0.39945, 0.40115, 0.40351, 0.39952, 0.39711, 0.39469, 0.39120, 0.39256, 0.39325, 0.39029,
-     0.38713, 0.38405, 0.38310, 0.38170, 0.38153, 0.38150, 0.37932, 0.37625, 0.37639, 0.37513,
-     0.36934, 0.37158, 0.36743, 0.36725, 0.36754, 0.36367, 0.36349, 0.36127, 0.35845, 0.35664,
-     0.35571, 0.34821, 0.35324, 0.34971, 0.34971, 0.35046, 0.34550, 0.34232, 0.34107, 0.33753,
-     0.34123, 0.33774, 0.33267, 0.33334, 0.32925, 0.32793, 0.32465, 0.32587, 0.32283, 0.32465,
-     0.31899, 0.31939, 0.31609, 0.31355, 0.31146, 0.30996, 0.30590, 0.30941, 0.30495, 0.30232,
-     0.30000, 0.30592, 0.30067, 0.29949, 0.29367, 0.29305, 0.29100, 0.28859, 0.28693, 0.28460,
-     0.28802, 0.28214, 0.28012, 0.27655, 0.27398, 0.27489, 0.27265, 0.27207, 0.27215, 0.26801,
-     0.27007, 0.26242, 0.26167, 0.25807, 0.26060, 0.25424, 0.25617, 0.25184, 0.25211, 0.24963,
-     0.24654, 0.24889, 0.24176, 0.24156, 0.24427, 0.23891, 0.23345, 0.23369, 0.23111, 0.22584,
-     0.22942, 0.22945, 0.22418, 0.22058, 0.22445, 0.21787, 0.22024, 0.22024, 0.21310, 0.21312,
-     0.21306, 0.21014, 0.21204, 0.20921, 0.20454, 0.20235, 0.20241, 0.19851, 0.20200, 0.19926,
-     0.19586, 0.19828, 0.19279, 0.19168, 0.18899, 0.18156, 0.18563, 0.18633, 0.18394, 0.18089,
-     0.17964, 0.17685, 0.17630, 0.17696, 0.17502, 0.17138, 0.17179, 0.17177, 0.16918, 0.16656,
-     0.16816, 0.16230, 0.16106, 0.15727, 0.15690, 0.15554, 0.15106, 0.15557, 0.14960, 0.15174,
-     0.14814, 0.14777, 0.14698, 0.14451, 0.14344, 0.14489, 0.14124, 0.14074, 0.13459, 0.13994,
-     0.13606, 0.13941, 0.13231, 0.13203, 0.12701, 0.13091, 0.12635, 0.12740, 0.12701, 0.12425,
-     0.12362, 0.12399, 0.12174, 0.12099, 0.11940, 0.11865, 0.11551, 0.11818, 0.11366, 0.11303,
-     0.11050, 0.10948, 0.11105, 0.10813, 0.11124, 0.10642, 0.10827, 0.11041, 0.10285, 0.10473,
-     0.09880, 0.10248, 0.09540, 0.09905, 0.09991, 0.09618, 0.09506, 0.09641, 0.09405, 0.09332,
-     0.09131, 0.09068, 0.09243, 0.08471, 0.08641, 0.08408, 0.08723, 0.08609, 0.08705, 0.08511,
-     0.08122, 0.08053, 0.07947, 0.07747, 0.08165, 0.07549, 0.07670, 0.07824, 0.07534, 0.07525,
-     0.07588, 0.07390, 0.07203, 0.07413, 0.07441, 0.06786, 0.07505, 0.06733, 0.06543, 0.06713,
-     0.06481, 0.06620, 0.06451, 0.06596, 0.06732, 0.06286, 0.06340, 0.06110, 0.06586, 0.05799,
-     0.06174, 0.05731, 0.06178, 0.05907, 0.05567, 0.05586, 0.05653, 0.05728, 0.05270, 0.05378,
-     0.05503, 0.05143, 0.05158, 0.05056, 0.04994, 0.04988, 0.04934, 0.05066, 0.04965, 0.04614,
-     0.04920, 0.04983, 0.04556, 0.04978, 0.04673, 0.04594, 0.04701, 0.04590, 0.04294, 0.04526,
-     0.04284, 0.04478, 0.04237, 0.03920, 0.03740, 0.03988, 0.04055, 0.03832, 0.03959, 0.03906,
-     0.03856, 0.03672, 0.03585, 0.03492, 0.03618, 0.03672, 0.03633, 0.03628, 0.03366, 0.03619,
-     0.03560, 0.03449, 0.03371, 0.03517, 0.03176, 0.03113, 0.03128, 0.03226, 0.03109, 0.03163,
-     0.02916, 0.02963, 0.03264, 0.03274, 0.02953, 0.02802, 0.02895, 0.02822, 0.03060, 0.02658,
-     0.02759, 0.02779, 0.02575, 0.02637, 0.02603, 0.02783, 0.02525, 0.02744, 0.02429, 0.02613,
-     0.02264, 0.02385, 0.02370, 0.02473, 0.02229, 0.02346, 0.02491, 0.02229, 0.02040, 0.02307,
-     0.02292, 0.02118, 0.02177, 0.02030, 0.02219, 0.01899, 0.02055, 0.01909, 0.01870, 0.01938,
-     0.01836, 0.01850, 0.01899, 0.01918, 0.01671, 0.01957, 0.01603, 0.01816, 0.01700, 0.01559,
-     0.01773, 0.01773, 0.01685, 0.01530, 0.01612, 0.01622, 0.01467, 0.01627, 0.01564, 0.01448,
-     0.01467, 0.01612, 0.01467, 0.01565, 0.01516, 0.01394, 0.01394, 0.01477, 0.01428, 0.01302,
-     0.01423, 0.01146, 0.01311, 0.01418, 0.01302, 0.01224, 0.01269, 0.01190, 0.01055, 0.01258,
-     0.01185, 0.01088, 0.01122, 0.01059, 0.01035, 0.01132, 0.00947, 0.01234, 0.00914, 0.01054,
-     0.01054, 0.00918, 0.00841, 0.00987, 0.01030, 0.00972, 0.01035, 0.00743, 0.00860, 0.00923,
-     0.00894, 0.00948, 0.00908, 0.00801, 0.00792, 0.00826, 0.00724, 0.00801, 0.00728, 0.00782,
-     0.00724, 0.00777, 0.00694, 0.00811, 0.00796, 0.00665, 0.00753, 0.00724, 0.00583, 0.00656,
-     0.00675, 0.00646, 0.00787, 0.00719, 0.00660, 0.00796, 0.00568, 0.00787, 0.00622, 0.00690,
-     0.00694, 0.00563, 0.00597, 0.00627, 0.00660, 0.00578, 0.00719, 0.00442, 0.00524, 0.00583,
-     0.00617, 0.00622, 0.00612, 0.00583, 0.00554, 0.00481, 0.00432, 0.00476, 0.00403, 0.00534,
-     0.00418, 0.00490, 0.00466, 0.00534, 0.00520, 0.00379, 0.00510, 0.00422, 0.00335, 0.00427,
-     0.00437, 0.00452, 0.00374, 0.00524, 0.00442, 0.00320, 0.00403, 0.00388, 0.00461, 0.00379,
-     0.00345, 0.00364},
-
-    {0.96640, 0.96400, 0.96580, 0.96400, 0.96420, 0.96330, 0.95670, 0.96270, 0.95660, 0.95880,
-     0.95890, 0.95390, 0.95320, 0.95380, 0.95170, 0.94910, 0.94770, 0.94270, 0.94250, 0.94510,
-     0.93970, 0.94230, 0.93810, 0.93310, 0.93570, 0.93640, 0.93310, 0.92610, 0.92570, 0.92820,
-     0.92750, 0.92470, 0.91640, 0.91400, 0.91720, 0.91460, 0.91660, 0.91030, 0.90710, 0.90660,
-     0.90650, 0.90360, 0.91050, 0.89860, 0.89820, 0.89550, 0.89050, 0.88670, 0.88830, 0.88260,
-     0.88290, 0.87750, 0.88350, 0.87280, 0.87280, 0.86770, 0.86900, 0.86460, 0.86070, 0.86080,
-     0.85960, 0.85980, 0.85630, 0.84450, 0.85140, 0.84130, 0.83630, 0.83390, 0.83410, 0.83120,
-     0.82320, 0.82660, 0.83190, 0.82300, 0.81830, 0.81350, 0.80630, 0.80950, 0.81020, 0.80420,
-     0.79810, 0.79170, 0.78960, 0.78720, 0.78590, 0.78610, 0.78180, 0.77540, 0.77590, 0.77300,
-     0.76140, 0.76630, 0.75710, 0.75710, 0.75770, 0.74930, 0.74910, 0.74500, 0.73840, 0.73500,
-     0.73370, 0.71750, 0.72810, 0.72090, 0.72030, 0.72250, 0.71240, 0.70560, 0.70260, 0.69540,
-     0.70310, 0.69620, 0.68590, 0.68740, 0.67870, 0.67590, 0.66930, 0.67200, 0.66590, 0.66930,
-     0.65740, 0.65780, 0.65160, 0.64690, 0.64180, 0.63860, 0.63080, 0.63760, 0.62840, 0.62330,
-     0.61840, 0.63040, 0.61950, 0.61740, 0.60520, 0.60400, 0.60050, 0.59470, 0.59160, 0.58650,
-     0.59390, 0.58170, 0.57710, 0.57010, 0.56440, 0.56660, 0.56190, 0.56080, 0.56090, 0.55270,
-     0.55660, 0.54050, 0.53990, 0.53180, 0.53700, 0.52390, 0.52790, 0.51930, 0.51950, 0.51460,
-     0.50850, 0.51290, 0.49840, 0.49800, 0.50330, 0.49200, 0.48130, 0.48150, 0.47620, 0.46580,
-     0.47300, 0.47270, 0.46220, 0.45480, 0.46250, 0.44910, 0.45430, 0.45400, 0.43910, 0.43900,
-     0.43930, 0.43380, 0.43720, 0.43110, 0.42150, 0.41690, 0.41710, 0.40910, 0.41680, 0.41090,
-     0.40370, 0.40880, 0.39740, 0.39520, 0.38930, 0.37410, 0.38230, 0.38400, 0.37900, 0.37280,
-     0.37040, 0.36430, 0.36310, 0.36480, 0.36080, 0.35330, 0.35380, 0.35410, 0.34870, 0.34340,
-     0.34650, 0.33470, 0.33180, 0.32400, 0.32350, 0.32060, 0.31130, 0.32040, 0.30830, 0.31290,
-     0.30530, 0.30480, 0.30300, 0.29800, 0.29560, 0.29850, 0.29100, 0.29050, 0.27730, 0.28850,
-     0.28050, 0.28740, 0.27250, 0.27230, 0.26170, 0.26980, 0.26060, 0.26240, 0.26170, 0.25610,
-     0.25490, 0.25530, 0.25110, 0.24920, 0.24610, 0.24430, 0.23820, 0.24380, 0.23420, 0.23300,
-     0.22770, 0.22570, 0.22910, 0.22300, 0.22930, 0.21930, 0.22310, 0.22770, 0.21230, 0.21590,
-     0.20360, 0.21110, 0.19670, 0.20420, 0.20590, 0.19840, 0.19580, 0.19860, 0.19390, 0.19240,
-     0.18810, 0.18680, 0.19040, 0.17470, 0.17800, 0.17330, 0.17970, 0.17770, 0.17960, 0.17560,
-     0.16750, 0.16600, 0.16380, 0.15960, 0.16820, 0.15580, 0.15800, 0.16110, 0.15540, 0.15520,
-     0.15650, 0.15270, 0.14830, 0.15290, 0.15340, 0.13980, 0.15480, 0.13890, 0.13490, 0.13830,
-     0.13390, 0.13630, 0.13300, 0.13590, 0.13870, 0.12970, 0.13070, 0.12580, 0.13560, 0.11940,
-     0.12720, 0.11800, 0.12730, 0.12190, 0.11480, 0.11510, 0.11640, 0.11820, 0.10860, 0.11100,
-     0.11340, 0.10590, 0.10620, 0.10410, 0.10300, 0.10270, 0.10160, 0.10430, 0.10240, 0.09500,
-     0.10140, 0.10260, 0.09380, 0.10250, 0.09630, 0.09460, 0.09680, 0.09460, 0.08860, 0.09320,
-     0.08820, 0.09230, 0.08740, 0.08080, 0.07720, 0.08220, 0.08350, 0.07900, 0.08160, 0.08060,
-     0.07940, 0.07570, 0.07390, 0.07190, 0.07450, 0.07560, 0.07490, 0.07470, 0.06940, 0.07460,
-     0.07330, 0.07110, 0.06940, 0.07250, 0.06540, 0.06410, 0.06440, 0.06660, 0.06410, 0.06520,
-     0.06030, 0.06100, 0.06720, 0.06740, 0.06080, 0.05770, 0.05960, 0.05810, 0.06310, 0.05490,
-     0.05680, 0.05730, 0.05310, 0.05430, 0.05360, 0.05730, 0.05200, 0.05650, 0.05010, 0.05380,
-     0.04670, 0.04920, 0.04880, 0.05110, 0.04590, 0.04830, 0.05130, 0.04590, 0.04210, 0.04750,
-     0.04720, 0.04370, 0.04500, 0.04180, 0.04570, 0.03910, 0.04240, 0.03930, 0.03850, 0.03990,
-     0.03780, 0.03810, 0.03910, 0.03950, 0.03440, 0.04030, 0.03310, 0.03740, 0.03500, 0.03210,
-     0.03650, 0.03650, 0.03470, 0.03150, 0.03320, 0.03350, 0.03020, 0.03350, 0.03220, 0.02990,
-     0.03020, 0.03320, 0.03020, 0.03240, 0.03130, 0.02870, 0.02870, 0.03040, 0.02940, 0.02680,
-     0.02930, 0.02360, 0.02700, 0.02920, 0.02680, 0.02520, 0.02630, 0.02450, 0.02180, 0.02590,
-     0.02450, 0.02240, 0.02310, 0.02190, 0.02130, 0.02330, 0.01950, 0.02550, 0.01890, 0.02170,
-     0.02170, 0.01890, 0.01740, 0.02040, 0.02120, 0.02010, 0.02140, 0.01530, 0.01770, 0.01900,
-     0.01840, 0.01960, 0.01870, 0.01650, 0.01630, 0.01700, 0.01500, 0.01650, 0.01500, 0.01610,
-     0.01490, 0.01600, 0.01430, 0.01670, 0.01640, 0.01370, 0.01550, 0.01490, 0.01200, 0.01350,
-     0.01390, 0.01330, 0.01620, 0.01490, 0.01360, 0.01640, 0.01170, 0.01620, 0.01290, 0.01420,
-     0.01430, 0.01160, 0.01230, 0.01300, 0.01360, 0.01190, 0.01490, 0.00910, 0.01080, 0.01200,
-     0.01270, 0.01280, 0.01260, 0.01200, 0.01140, 0.00990, 0.00890, 0.00980, 0.00830, 0.01100,
-     0.00860, 0.01010, 0.00960, 0.01100, 0.01070, 0.00780, 0.01050, 0.00870, 0.00690, 0.00880,
-     0.00900, 0.00930, 0.00780, 0.01080, 0.00920, 0.00660, 0.00830, 0.00800, 0.00950, 0.00780,
-     0.00710, 0.00750},
-
-    {0.03247, 0.03470, 0.03303, 0.03470, 0.03452, 0.03535, 0.04142, 0.03591, 0.04152, 0.03950,
-     0.03941, 0.04398, 0.04461, 0.04407, 0.04597, 0.04831, 0.04956, 0.05402, 0.05419, 0.05189,
-     0.05666, 0.05437, 0.05807, 0.06242, 0.06017, 0.05955, 0.06242, 0.06844, 0.06878, 0.06664,
-     0.06724, 0.06963, 0.07661, 0.07860, 0.07594, 0.07811, 0.07644, 0.08165, 0.08427, 0.08468,
-     0.08476, 0.08711, 0.08149, 0.09112, 0.09144, 0.09358, 0.09751, 0.10046, 0.09922, 0.10362,
-     0.10339, 0.10749, 0.10293, 0.11102, 0.11102, 0.11480, 0.11384, 0.11707, 0.11990, 0.11982,
-     0.12069, 0.12054, 0.12305, 0.13132, 0.12652, 0.13351, 0.13690, 0.13851, 0.13838, 0.14031,
-     0.14554, 0.14333, 0.13984, 0.14567, 0.14869, 0.15172, 0.15618, 0.15421, 0.15378, 0.15746,
-     0.16114, 0.16491, 0.16613, 0.16752, 0.16826, 0.16815, 0.17059, 0.17416, 0.17388, 0.17547,
-     0.18167, 0.17908, 0.18390, 0.18390, 0.18359, 0.18785, 0.18795, 0.18998, 0.19317, 0.19478,
-     0.19538, 0.20269, 0.19797, 0.20120, 0.20147, 0.20049, 0.20489, 0.20773, 0.20895, 0.21182,
-     0.20875, 0.21151, 0.21544, 0.21488, 0.21807, 0.21906, 0.22134, 0.22042, 0.22248, 0.22134,
-     0.22523, 0.22510, 0.22702, 0.22842, 0.22989, 0.23079, 0.23289, 0.23107, 0.23351, 0.23480,
-     0.23598, 0.23300, 0.23572, 0.23622, 0.23893, 0.23918, 0.23990, 0.24103, 0.24161, 0.24252,
-     0.24118, 0.24333, 0.24406, 0.24509, 0.24585, 0.24556, 0.24617, 0.24630, 0.24629, 0.24722,
-     0.24680, 0.24836, 0.24841, 0.24899, 0.24863, 0.24943, 0.24922, 0.24963, 0.24962, 0.24979,
-     0.24993, 0.24983, 0.25000, 0.25000, 0.24999, 0.24994, 0.24965, 0.24966, 0.24943, 0.24883,
-     0.24927, 0.24926, 0.24857, 0.24796, 0.24859, 0.24741, 0.24791, 0.24788, 0.24629, 0.24628,
-     0.24632, 0.24562, 0.24606, 0.24525, 0.24384, 0.24309, 0.24313, 0.24174, 0.24308, 0.24206,
-     0.24073, 0.24168, 0.23947, 0.23902, 0.23775, 0.23415, 0.23615, 0.23654, 0.23536, 0.23382,
-     0.23320, 0.23159, 0.23126, 0.23172, 0.23062, 0.22848, 0.22863, 0.22871, 0.22711, 0.22548,
-     0.22644, 0.22268, 0.22171, 0.21902, 0.21885, 0.21782, 0.21439, 0.21774, 0.21325, 0.21499,
-     0.21209, 0.21190, 0.21119, 0.20920, 0.20822, 0.20940, 0.20632, 0.20611, 0.20040, 0.20527,
-     0.20182, 0.20480, 0.19824, 0.19815, 0.19321, 0.19701, 0.19269, 0.19355, 0.19321, 0.19051,
-     0.18993, 0.19012, 0.18805, 0.18710, 0.18554, 0.18462, 0.18146, 0.18436, 0.17935, 0.17871,
-     0.17585, 0.17476, 0.17661, 0.17327, 0.17672, 0.17121, 0.17333, 0.17585, 0.16723, 0.16929,
-     0.16215, 0.16654, 0.15801, 0.16250, 0.16351, 0.15904, 0.15746, 0.15916, 0.15630, 0.15538,
-     0.15272, 0.15191, 0.15415, 0.14418, 0.14632, 0.14327, 0.14741, 0.14612, 0.14734, 0.14477,
-     0.13944, 0.13844, 0.13697, 0.13413, 0.13991, 0.13153, 0.13304, 0.13515, 0.13125, 0.13111,
-     0.13201, 0.12938, 0.12631, 0.12952, 0.12987, 0.12026, 0.13084, 0.11961, 0.11670, 0.11917,
-     0.11597, 0.11772, 0.11531, 0.11743, 0.11946, 0.11288, 0.11362, 0.10997, 0.11721, 0.10514,
-     0.11102, 0.10408, 0.11109, 0.10704, 0.10162, 0.10185, 0.10285, 0.10423, 0.09681, 0.09868,
-     0.10054, 0.09469, 0.09492, 0.09326, 0.09239, 0.09215, 0.09128, 0.09342, 0.09191, 0.08597,
-     0.09112, 0.09207, 0.08500, 0.09199, 0.08703, 0.08565, 0.08743, 0.08565, 0.08075, 0.08451,
-     0.08042, 0.08378, 0.07976, 0.07427, 0.07124, 0.07544, 0.07653, 0.07276, 0.07494, 0.07410,
-     0.07310, 0.06997, 0.06844, 0.06673, 0.06895, 0.06989, 0.06929, 0.06912, 0.06458, 0.06903,
-     0.06793, 0.06605, 0.06458, 0.06724, 0.06112, 0.05999, 0.06025, 0.06216, 0.05999, 0.06095,
-     0.05666, 0.05728, 0.06268, 0.06286, 0.05710, 0.05437, 0.05605, 0.05472, 0.05912, 0.05189,
-     0.05357, 0.05402, 0.05028, 0.05135, 0.05073, 0.05402, 0.04930, 0.05331, 0.04759, 0.05091,
-     0.04452, 0.04678, 0.04642, 0.04849, 0.04379, 0.04597, 0.04867, 0.04379, 0.04033, 0.04524,
-     0.04497, 0.04179, 0.04297, 0.04005, 0.04361, 0.03757, 0.04060, 0.03776, 0.03702, 0.03831,
-     0.03637, 0.03665, 0.03757, 0.03794, 0.03322, 0.03868, 0.03200, 0.03600, 0.03377, 0.03107,
-     0.03517, 0.03517, 0.03350, 0.03051, 0.03210, 0.03238, 0.02929, 0.03238, 0.03116, 0.02901,
-     0.02929, 0.03210, 0.02929, 0.03135, 0.03032, 0.02788, 0.02788, 0.02948, 0.02854, 0.02608,
-     0.02844, 0.02304, 0.02627, 0.02835, 0.02608, 0.02457, 0.02561, 0.02390, 0.02133, 0.02523,
-     0.02390, 0.02190, 0.02257, 0.02142, 0.02085, 0.02276, 0.01912, 0.02485, 0.01854, 0.02123,
-     0.02123, 0.01854, 0.01710, 0.01998, 0.02075, 0.01970, 0.02094, 0.01507, 0.01739, 0.01864,
-     0.01806, 0.01922, 0.01835, 0.01623, 0.01603, 0.01671, 0.01477, 0.01623, 0.01477, 0.01584,
-     0.01468, 0.01574, 0.01410, 0.01642, 0.01613, 0.01351, 0.01526, 0.01468, 0.01186, 0.01332,
-     0.01371, 0.01312, 0.01594, 0.01468, 0.01341, 0.01613, 0.01156, 0.01594, 0.01273, 0.01400,
-     0.01410, 0.01146, 0.01215, 0.01283, 0.01341, 0.01176, 0.01468, 0.00902, 0.01068, 0.01186,
-     0.01254, 0.01264, 0.01244, 0.01186, 0.01127, 0.00980, 0.00882, 0.00970, 0.00823, 0.01088,
-     0.00853, 0.01000, 0.00951, 0.01088, 0.01059, 0.00774, 0.01039, 0.00862, 0.00685, 0.00872,
-     0.00892, 0.00921, 0.00774, 0.01068, 0.00911, 0.00656, 0.00823, 0.00794, 0.00941, 0.00774,
-     0.00705, 0.00744},
-
-    {0.96287, 0.96035, 0.96224, 0.96035, 0.96056, 0.95961, 0.95271, 0.95899, 0.95261, 0.95490,
-     0.95501, 0.94979, 0.94906, 0.94969, 0.94750, 0.94479, 0.94334, 0.93815, 0.93794, 0.94063,
-     0.93503, 0.93773, 0.93338, 0.92820, 0.93089, 0.93162, 0.92820, 0.92097, 0.92056, 0.92314,
-     0.92242, 0.91953, 0.91097, 0.90851, 0.91180, 0.90912, 0.91118, 0.90470, 0.90141, 0.90090,
-     0.90079, 0.89782, 0.90490, 0.89268, 0.89227, 0.88950, 0.88438, 0.88049, 0.88213, 0.87629,
-     0.87660, 0.87107, 0.87721, 0.86627, 0.86627, 0.86106, 0.86239, 0.85789, 0.85391, 0.85401,
-     0.85279, 0.85299, 0.84942, 0.83740, 0.84443, 0.83414, 0.82905, 0.82661, 0.82681, 0.82386,
-     0.81572, 0.81918, 0.82457, 0.81552, 0.81074, 0.80587, 0.79855, 0.80180, 0.80251, 0.79642,
-     0.79023, 0.78374, 0.78161, 0.77918, 0.77786, 0.77806, 0.77370, 0.76722, 0.76773, 0.76479,
-     0.75305, 0.75801, 0.74869, 0.74869, 0.74930, 0.74081, 0.74060, 0.73646, 0.72979, 0.72635,
-     0.72504, 0.70868, 0.71938, 0.71211, 0.71150, 0.71372, 0.70353, 0.69667, 0.69364, 0.68638,
-     0.69415, 0.68719, 0.67680, 0.67831, 0.66955, 0.66673, 0.66008, 0.66280, 0.65665, 0.66008,
-     0.64810, 0.64850, 0.64226, 0.63753, 0.63240, 0.62918, 0.62134, 0.62818, 0.61893, 0.61380,
-     0.60888, 0.62094, 0.60998, 0.60787, 0.59562, 0.59441, 0.59090, 0.58508, 0.58197, 0.57685,
-     0.58427, 0.57203, 0.56742, 0.56040, 0.55468, 0.55689, 0.55217, 0.55107, 0.55117, 0.54295,
-     0.54686, 0.53073, 0.53013, 0.52202, 0.52723, 0.51411, 0.51811, 0.50951, 0.50971, 0.50480,
-     0.49870, 0.50310, 0.48860, 0.48820, 0.49350, 0.48220, 0.47151, 0.47171, 0.46641, 0.45602,
-     0.46321, 0.46292, 0.45243, 0.44504, 0.45273, 0.43935, 0.44454, 0.44424, 0.42937, 0.42927,
-     0.42957, 0.42409, 0.42748, 0.42139, 0.41182, 0.40724, 0.40744, 0.39946, 0.40714, 0.40126,
-     0.39408, 0.39916, 0.38781, 0.38562, 0.37974, 0.36462, 0.37278, 0.37447, 0.36949, 0.36332,
-     0.36094, 0.35487, 0.35367, 0.35536, 0.35139, 0.34393, 0.34443, 0.34473, 0.33936, 0.33409,
-     0.33717, 0.32545, 0.32257, 0.31483, 0.31433, 0.31145, 0.30223, 0.31125, 0.29925, 0.30381,
-     0.29627, 0.29578, 0.29399, 0.28903, 0.28666, 0.28953, 0.28210, 0.28160, 0.26853, 0.27962,
-     0.27170, 0.27853, 0.26377, 0.26358, 0.25309, 0.26110, 0.25200, 0.25378, 0.25309, 0.24754,
-     0.24636, 0.24675, 0.24260, 0.24072, 0.23766, 0.23588, 0.22985, 0.23538, 0.22590, 0.22471,
-     0.21948, 0.21751, 0.22086, 0.21484, 0.22106, 0.21119, 0.21494, 0.21948, 0.20428, 0.20784,
-     0.19571, 0.20310, 0.18891, 0.19630, 0.19798, 0.19058, 0.18802, 0.19078, 0.18615, 0.18467,
-     0.18044, 0.17916, 0.18271, 0.16726, 0.17050, 0.16588, 0.17217, 0.17021, 0.17208, 0.16814,
-     0.16018, 0.15871, 0.15655, 0.15242, 0.16087, 0.14869, 0.15085, 0.15390, 0.14830, 0.14810,
-     0.14938, 0.14565, 0.14133, 0.14585, 0.14634, 0.13300, 0.14771, 0.13212, 0.12820, 0.13153,
-     0.12723, 0.12957, 0.12634, 0.12918, 0.13193, 0.12312, 0.12409, 0.11930, 0.12889, 0.11305,
-     0.12067, 0.11168, 0.12077, 0.11549, 0.10855, 0.10884, 0.11011, 0.11187, 0.10250, 0.10484,
-     0.10719, 0.09987, 0.10016, 0.09811, 0.09704, 0.09675, 0.09568, 0.09831, 0.09646, 0.08925,
-     0.09548, 0.09665, 0.08809, 0.09656, 0.09052, 0.08886, 0.09101, 0.08886, 0.08303, 0.08750,
-     0.08264, 0.08663, 0.08186, 0.07546, 0.07197, 0.07682, 0.07808, 0.07371, 0.07623, 0.07526,
-     0.07410, 0.07051, 0.06877, 0.06684, 0.06935, 0.07042, 0.06974, 0.06955, 0.06442, 0.06945,
-     0.06819, 0.06606, 0.06442, 0.06742, 0.06055, 0.05930, 0.05959, 0.06171, 0.05930, 0.06036,
-     0.05563, 0.05631, 0.06229, 0.06249, 0.05612, 0.05313, 0.05496, 0.05352, 0.05833, 0.05044,
-     0.05226, 0.05275, 0.04870, 0.04986, 0.04919, 0.05275, 0.04765, 0.05198, 0.04582, 0.04938,
-     0.04256, 0.04496, 0.04458, 0.04678, 0.04180, 0.04410, 0.04698, 0.04180, 0.03816, 0.04333,
-     0.04304, 0.03969, 0.04094, 0.03788, 0.04161, 0.03530, 0.03845, 0.03549, 0.03473, 0.03606,
-     0.03406, 0.03435, 0.03530, 0.03568, 0.03083, 0.03644, 0.02959, 0.03368, 0.03140, 0.02865,
-     0.03282, 0.03282, 0.03111, 0.02808, 0.02969, 0.02997, 0.02685, 0.02997, 0.02874, 0.02656,
-     0.02685, 0.02969, 0.02685, 0.02893, 0.02789, 0.02543, 0.02543, 0.02704, 0.02609, 0.02363,
-     0.02600, 0.02063, 0.02382, 0.02590, 0.02363, 0.02213, 0.02316, 0.02147, 0.01894, 0.02279,
-     0.02147, 0.01950, 0.02016, 0.01903, 0.01847, 0.02034, 0.01679, 0.02241, 0.01623, 0.01884,
-     0.01884, 0.01623, 0.01484, 0.01763, 0.01838, 0.01735, 0.01856, 0.01289, 0.01512, 0.01632,
-     0.01577, 0.01688, 0.01605, 0.01400, 0.01382, 0.01447, 0.01262, 0.01400, 0.01262, 0.01363,
-     0.01252, 0.01354, 0.01197, 0.01419, 0.01391, 0.01142, 0.01308, 0.01252, 0.00987, 0.01124,
-     0.01161, 0.01106, 0.01373, 0.01252, 0.01133, 0.01391, 0.00959, 0.01373, 0.01069, 0.01188,
-     0.01197, 0.00950, 0.01014, 0.01078, 0.01133, 0.00978, 0.01252, 0.00724, 0.00877, 0.00987,
-     0.01051, 0.01060, 0.01041, 0.00987, 0.00932, 0.00796, 0.00706, 0.00787, 0.00652, 0.00896,
-     0.00679, 0.00814, 0.00769, 0.00896, 0.00868, 0.00608, 0.00850, 0.00688, 0.00528, 0.00697,
-     0.00715, 0.00742, 0.00608, 0.00877, 0.00733, 0.00501, 0.00652, 0.00625, 0.00760, 0.00608,
-     0.00545, 0.00581},
-
-    {0.96993, 0.96765, 0.96936, 0.96765, 0.96784, 0.96698, 0.96069, 0.96641, 0.96059, 0.96270,
-     0.96279, 0.95801, 0.95734, 0.95791, 0.95590, 0.95341, 0.95206, 0.94725, 0.94706, 0.94956,
-     0.94437, 0.94687, 0.94282, 0.93800, 0.94051, 0.94118, 0.93800, 0.93123, 0.93084, 0.93326,
-     0.93258, 0.92987, 0.92183, 0.91949, 0.92260, 0.92008, 0.92202, 0.91590, 0.91279, 0.91230,
-     0.91221, 0.90938, 0.91609, 0.90452, 0.90413, 0.90150, 0.89662, 0.89291, 0.89447, 0.88891,
-     0.88920, 0.88393, 0.88979, 0.87933, 0.87933, 0.87434, 0.87561, 0.87131, 0.86749, 0.86759,
-     0.86641, 0.86660, 0.86318, 0.85160, 0.85837, 0.84846, 0.84355, 0.84120, 0.84139, 0.83854,
-     0.83068, 0.83402, 0.83923, 0.83048, 0.82586, 0.82113, 0.81405, 0.81720, 0.81789, 0.81198,
-     0.80597, 0.79966, 0.79759, 0.79522, 0.79394, 0.79414, 0.78990, 0.78358, 0.78407, 0.78121,
-     0.76975, 0.77459, 0.76550, 0.76550, 0.76610, 0.75779, 0.75760, 0.75354, 0.74701, 0.74365,
-     0.74236, 0.72632, 0.73682, 0.72969, 0.72910, 0.73128, 0.72127, 0.71453, 0.71156, 0.70442,
-     0.71205, 0.70521, 0.69500, 0.69649, 0.68785, 0.68507, 0.67852, 0.68120, 0.67514, 0.67852,
-     0.66670, 0.66710, 0.66094, 0.65627, 0.65120, 0.64802, 0.64026, 0.64702, 0.63787, 0.63280,
-     0.62792, 0.63986, 0.62902, 0.62693, 0.61478, 0.61359, 0.61010, 0.60432, 0.60123, 0.59615,
-     0.60353, 0.59137, 0.58678, 0.57980, 0.57412, 0.57631, 0.57163, 0.57053, 0.57063, 0.56244,
-     0.56634, 0.55027, 0.54967, 0.54158, 0.54677, 0.53369, 0.53768, 0.52909, 0.52929, 0.52440,
-     0.51830, 0.52270, 0.50820, 0.50780, 0.51310, 0.50180, 0.49109, 0.49129, 0.48599, 0.47558,
-     0.48279, 0.48248, 0.47197, 0.46456, 0.47227, 0.45885, 0.46406, 0.46376, 0.44883, 0.44873,
-     0.44903, 0.44351, 0.44692, 0.44081, 0.43118, 0.42656, 0.42676, 0.41874, 0.42646, 0.42054,
-     0.41332, 0.41844, 0.40699, 0.40478, 0.39886, 0.38358, 0.39182, 0.39353, 0.38851, 0.38228,
-     0.37987, 0.37373, 0.37253, 0.37423, 0.37021, 0.36267, 0.36317, 0.36347, 0.35804, 0.35271,
-     0.35583, 0.34395, 0.34103, 0.33317, 0.33267, 0.32975, 0.32038, 0.32955, 0.31735, 0.32199,
-     0.31433, 0.31382, 0.31201, 0.30696, 0.30454, 0.30747, 0.29990, 0.29940, 0.28607, 0.29738,
-     0.28930, 0.29627, 0.28123, 0.28103, 0.27032, 0.27850, 0.26920, 0.27102, 0.27032, 0.26465,
-     0.26344, 0.26385, 0.25960, 0.25768, 0.25454, 0.25272, 0.24655, 0.25222, 0.24250, 0.24129,
-     0.23592, 0.23389, 0.23734, 0.23116, 0.23754, 0.22741, 0.23126, 0.23592, 0.22032, 0.22396,
-     0.21149, 0.21910, 0.20449, 0.21210, 0.21382, 0.20622, 0.20358, 0.20642, 0.20165, 0.20013,
-     0.19576, 0.19444, 0.19809, 0.18214, 0.18550, 0.18072, 0.18723, 0.18519, 0.18712, 0.18306,
-     0.17482, 0.17329, 0.17105, 0.16678, 0.17553, 0.16291, 0.16515, 0.16831, 0.16250, 0.16230,
-     0.16362, 0.15975, 0.15527, 0.15995, 0.16046, 0.14660, 0.16189, 0.14568, 0.14160, 0.14507,
-     0.14058, 0.14303, 0.13966, 0.14262, 0.14547, 0.13628, 0.13731, 0.13230, 0.14231, 0.12576,
-     0.13373, 0.12432, 0.13383, 0.12831, 0.12105, 0.12136, 0.12269, 0.12453, 0.11470, 0.11716,
-     0.11961, 0.11193, 0.11224, 0.11009, 0.10896, 0.10865, 0.10752, 0.11029, 0.10834, 0.10075,
-     0.10732, 0.10855, 0.09951, 0.10844, 0.10208, 0.10034, 0.10260, 0.10034, 0.09417, 0.09890,
-     0.09376, 0.09797, 0.09294, 0.08614, 0.08243, 0.08758, 0.08892, 0.08429, 0.08697, 0.08594,
-     0.08470, 0.08088, 0.07903, 0.07696, 0.07965, 0.08078, 0.08006, 0.07985, 0.07438, 0.07975,
-     0.07841, 0.07614, 0.07438, 0.07758, 0.07025, 0.06890, 0.06921, 0.07149, 0.06890, 0.07004,
-     0.06497, 0.06569, 0.07211, 0.07231, 0.06548, 0.06227, 0.06424, 0.06269, 0.06787, 0.05937,
-     0.06134, 0.06186, 0.05749, 0.05874, 0.05801, 0.06186, 0.05635, 0.06103, 0.05438, 0.05822,
-     0.05084, 0.05344, 0.05302, 0.05542, 0.05000, 0.05250, 0.05562, 0.05000, 0.04604, 0.05167,
-     0.05136, 0.04771, 0.04906, 0.04572, 0.04979, 0.04290, 0.04635, 0.04311, 0.04227, 0.04374,
-     0.04154, 0.04185, 0.04290, 0.04332, 0.03797, 0.04415, 0.03661, 0.04112, 0.03860, 0.03556,
-     0.04018, 0.04018, 0.03829, 0.03492, 0.03671, 0.03703, 0.03355, 0.03703, 0.03566, 0.03324,
-     0.03355, 0.03671, 0.03355, 0.03587, 0.03471, 0.03197, 0.03197, 0.03377, 0.03271, 0.02996,
-     0.03261, 0.02658, 0.03018, 0.03250, 0.02996, 0.02827, 0.02944, 0.02753, 0.02466, 0.02901,
-     0.02753, 0.02530, 0.02604, 0.02477, 0.02413, 0.02626, 0.02221, 0.02859, 0.02157, 0.02456,
-     0.02456, 0.02157, 0.01996, 0.02317, 0.02402, 0.02285, 0.02424, 0.01771, 0.02028, 0.02168,
-     0.02103, 0.02232, 0.02135, 0.01900, 0.01878, 0.01953, 0.01738, 0.01900, 0.01738, 0.01857,
-     0.01727, 0.01846, 0.01663, 0.01921, 0.01889, 0.01598, 0.01792, 0.01727, 0.01413, 0.01576,
-     0.01620, 0.01554, 0.01867, 0.01727, 0.01587, 0.01889, 0.01381, 0.01867, 0.01511, 0.01652,
-     0.01663, 0.01370, 0.01446, 0.01522, 0.01587, 0.01402, 0.01727, 0.01096, 0.01283, 0.01413,
-     0.01490, 0.01500, 0.01479, 0.01413, 0.01348, 0.01184, 0.01074, 0.01173, 0.01008, 0.01304,
-     0.01041, 0.01206, 0.01151, 0.01304, 0.01272, 0.00952, 0.01250, 0.01052, 0.00852, 0.01063,
-     0.01085, 0.01118, 0.00952, 0.01283, 0.01107, 0.00819, 0.01008, 0.00975, 0.01140, 0.00952,
-     0.00875, 0.00919},
-};
-
-static const double modulation6[6][626] = {
-
-    {65.00,  65.10,  65.20,  65.30,  65.40,  65.50,  65.60,  65.70,  65.80,  65.90,  66.00,  66.10,
-     66.20,  66.30,  66.40,  66.50,  66.60,  66.70,  66.80,  66.90,  67.00,  67.10,  67.20,  67.30,
-     67.40,  67.50,  67.60,  67.70,  67.80,  67.90,  68.00,  68.10,  68.20,  68.30,  68.40,  68.50,
-     68.60,  68.70,  68.80,  68.90,  69.00,  69.10,  69.20,  69.30,  69.40,  69.50,  69.60,  69.70,
-     69.80,  69.90,  70.00,  70.10,  70.20,  70.30,  70.40,  70.50,  70.60,  70.70,  70.80,  70.90,
-     71.00,  71.10,  71.20,  71.30,  71.40,  71.50,  71.60,  71.70,  71.80,  71.90,  72.00,  72.10,
-     72.20,  72.30,  72.40,  72.50,  72.60,  72.70,  72.80,  72.90,  73.00,  73.10,  73.20,  73.30,
-     73.40,  73.50,  73.60,  73.70,  73.80,  73.90,  74.00,  74.10,  74.20,  74.30,  74.40,  74.50,
-     74.60,  74.70,  74.80,  74.90,  75.00,  75.10,  75.20,  75.30,  75.40,  75.50,  75.60,  75.70,
-     75.80,  75.90,  76.00,  76.10,  76.20,  76.30,  76.40,  76.50,  76.60,  76.70,  76.80,  76.90,
-     77.00,  77.10,  77.20,  77.30,  77.40,  77.50,  77.60,  77.70,  77.80,  77.90,  78.00,  78.10,
-     78.20,  78.30,  78.40,  78.50,  78.60,  78.70,  78.80,  78.90,  79.00,  79.10,  79.20,  79.30,
-     79.40,  79.50,  79.60,  79.70,  79.80,  79.90,  80.00,  80.10,  80.20,  80.30,  80.40,  80.50,
-     80.60,  80.70,  80.80,  80.90,  81.00,  81.10,  81.20,  81.30,  81.40,  81.50,  81.60,  81.70,
-     81.80,  81.90,  82.00,  82.10,  82.20,  82.30,  82.40,  82.50,  82.60,  82.70,  82.80,  82.90,
-     83.00,  83.10,  83.20,  83.30,  83.40,  83.50,  83.60,  83.70,  83.80,  83.90,  84.00,  84.10,
-     84.20,  84.30,  84.40,  84.50,  84.60,  84.70,  84.80,  84.90,  85.00,  85.10,  85.20,  85.30,
-     85.40,  85.50,  85.60,  85.70,  85.80,  85.90,  86.00,  86.10,  86.20,  86.30,  86.40,  86.50,
-     86.60,  86.70,  86.80,  86.90,  87.00,  87.10,  87.20,  87.30,  87.40,  87.50,  87.60,  87.70,
-     87.80,  87.90,  88.00,  88.10,  88.20,  88.30,  88.40,  88.50,  88.60,  88.70,  88.80,  88.90,
-     89.00,  89.10,  89.20,  89.30,  89.40,  89.50,  89.60,  89.70,  89.80,  89.90,  90.00,  90.10,
-     90.20,  90.30,  90.40,  90.50,  90.60,  90.70,  90.80,  90.90,  91.00,  91.10,  91.20,  91.30,
-     91.40,  91.50,  91.60,  91.70,  91.80,  91.90,  92.00,  92.10,  92.20,  92.30,  92.40,  92.50,
-     92.60,  92.70,  92.80,  92.90,  93.00,  93.10,  93.20,  93.30,  93.40,  93.50,  93.60,  93.70,
-     93.80,  93.90,  94.00,  94.10,  94.20,  94.30,  94.40,  94.50,  94.60,  94.70,  94.80,  94.90,
-     95.00,  95.10,  95.20,  95.30,  95.40,  95.50,  95.60,  95.70,  95.80,  95.90,  96.00,  96.10,
-     96.20,  96.30,  96.40,  96.50,  96.60,  96.70,  96.80,  96.90,  97.00,  97.10,  97.20,  97.30,
-     97.40,  97.50,  97.60,  97.70,  97.80,  97.90,  98.00,  98.10,  98.20,  98.30,  98.40,  98.50,
-     98.60,  98.70,  98.80,  98.90,  99.00,  99.10,  99.20,  99.30,  99.40,  99.50,  99.60,  99.70,
-     99.80,  99.90,  100.00, 100.10, 100.20, 100.30, 100.40, 100.50, 100.60, 100.70, 100.80, 100.90,
-     101.00, 101.10, 101.20, 101.30, 101.40, 101.50, 101.60, 101.70, 101.80, 101.90, 102.00, 102.10,
-     102.20, 102.30, 102.40, 102.50, 102.60, 102.70, 102.80, 102.90, 103.00, 103.10, 103.20, 103.30,
-     103.40, 103.50, 103.60, 103.70, 103.80, 103.90, 104.00, 104.10, 104.20, 104.30, 104.40, 104.50,
-     104.60, 104.70, 104.80, 104.90, 105.00, 105.10, 105.20, 105.30, 105.40, 105.50, 105.60, 105.70,
-     105.80, 105.90, 106.00, 106.10, 106.20, 106.30, 106.40, 106.50, 106.60, 106.70, 106.80, 106.90,
-     107.00, 107.10, 107.20, 107.30, 107.40, 107.50, 107.60, 107.70, 107.80, 107.90, 108.00, 108.10,
-     108.20, 108.30, 108.40, 108.50, 108.60, 108.70, 108.80, 108.90, 109.00, 109.10, 109.20, 109.30,
-     109.40, 109.50, 109.60, 109.70, 109.80, 109.90, 110.00, 110.10, 110.20, 110.30, 110.40, 110.50,
-     110.60, 110.70, 110.80, 110.90, 111.00, 111.10, 111.20, 111.30, 111.40, 111.50, 111.60, 111.70,
-     111.80, 111.90, 112.00, 112.10, 112.20, 112.30, 112.40, 112.50, 112.60, 112.70, 112.80, 112.90,
-     113.00, 113.10, 113.20, 113.30, 113.40, 113.50, 113.60, 113.70, 113.80, 113.90, 114.00, 114.10,
-     114.20, 114.30, 114.40, 114.50, 114.60, 114.70, 114.80, 114.90, 115.00, 115.10, 115.20, 115.30,
-     115.40, 115.50, 115.60, 115.70, 115.80, 115.90, 116.00, 116.10, 116.20, 116.30, 116.40, 116.50,
-     116.60, 116.70, 116.80, 116.90, 117.00, 117.10, 117.20, 117.30, 117.40, 117.50, 117.60, 117.70,
-     117.80, 117.90, 118.00, 118.10, 118.20, 118.30, 118.40, 118.50, 118.60, 118.70, 118.80, 118.90,
-     119.00, 119.10, 119.20, 119.30, 119.40, 119.50, 119.60, 119.70, 119.80, 119.90, 120.00, 120.10,
-     120.20, 120.30, 120.40, 120.50, 120.60, 120.70, 120.80, 120.90, 121.00, 121.10, 121.20, 121.30,
-     121.40, 121.50, 121.60, 121.70, 121.80, 121.90, 122.00, 122.10, 122.20, 122.30, 122.40, 122.50,
-     122.60, 122.70, 122.80, 122.90, 123.00, 124.00, 124.10, 124.20, 124.30, 124.40, 124.50, 124.60,
-     124.70, 124.80, 124.90, 125.00, 125.10, 125.20, 125.30, 125.40, 125.50, 125.60, 125.70},
-
-    {0.46118, 0.46267, 0.46260, 0.46062, 0.45988, 0.45750, 0.46021, 0.45820, 0.45774, 0.45697,
-     0.45678, 0.45633, 0.45606, 0.45543, 0.45327, 0.45136, 0.45307, 0.45066, 0.45022, 0.45080,
-     0.45273, 0.44948, 0.44888, 0.44860, 0.44675, 0.44709, 0.44582, 0.44565, 0.44609, 0.44360,
-     0.44545, 0.44266, 0.44093, 0.43993, 0.44263, 0.43984, 0.44125, 0.43735, 0.43871, 0.43871,
-     0.43657, 0.43548, 0.43303, 0.43389, 0.43231, 0.43082, 0.42820, 0.43007, 0.42968, 0.42675,
-     0.42627, 0.42764, 0.42337, 0.42284, 0.42278, 0.42405, 0.42300, 0.42091, 0.42366, 0.41906,
-     0.41808, 0.41793, 0.41369, 0.41378, 0.41458, 0.40974, 0.41490, 0.40885, 0.40906, 0.40843,
-     0.40971, 0.40465, 0.40670, 0.40583, 0.40500, 0.40214, 0.39765, 0.39891, 0.39995, 0.39777,
-     0.39554, 0.39643, 0.39355, 0.39314, 0.39298, 0.39014, 0.39016, 0.38465, 0.38676, 0.38720,
-     0.38353, 0.38203, 0.38124, 0.37889, 0.37913, 0.38090, 0.37601, 0.37684, 0.37213, 0.37500,
-     0.36958, 0.37097, 0.36830, 0.36682, 0.36694, 0.36576, 0.36606, 0.36664, 0.36577, 0.35699,
-     0.35730, 0.36052, 0.35415, 0.35786, 0.35534, 0.35470, 0.35333, 0.34656, 0.34505, 0.34741,
-     0.34548, 0.34278, 0.34095, 0.34258, 0.34055, 0.33822, 0.34134, 0.33565, 0.33245, 0.33118,
-     0.33255, 0.33021, 0.33177, 0.32911, 0.32361, 0.32331, 0.32341, 0.31790, 0.32211, 0.31771,
-     0.31716, 0.31626, 0.31212, 0.31109, 0.31258, 0.31131, 0.30939, 0.30945, 0.30670, 0.30392,
-     0.30476, 0.29625, 0.29820, 0.29838, 0.29118, 0.29760, 0.29542, 0.29289, 0.29306, 0.29124,
-     0.28701, 0.29202, 0.28291, 0.28125, 0.28487, 0.28201, 0.28330, 0.27724, 0.27599, 0.27545,
-     0.27225, 0.26982, 0.27139, 0.27038, 0.26739, 0.27304, 0.26271, 0.26461, 0.26286, 0.26207,
-     0.25751, 0.25496, 0.25117, 0.25785, 0.25969, 0.25750, 0.25104, 0.24651, 0.24727, 0.24331,
-     0.24747, 0.24436, 0.24197, 0.24228, 0.23812, 0.23746, 0.24105, 0.23958, 0.23261, 0.23509,
-     0.23063, 0.22904, 0.22771, 0.22589, 0.22494, 0.22919, 0.21779, 0.22510, 0.22190, 0.22851,
-     0.22021, 0.21828, 0.21555, 0.21002, 0.21568, 0.21790, 0.21169, 0.20729, 0.20910, 0.20595,
-     0.20535, 0.20659, 0.20241, 0.19891, 0.20217, 0.19881, 0.19875, 0.19408, 0.19711, 0.19132,
-     0.19490, 0.19370, 0.19445, 0.18866, 0.19095, 0.18546, 0.18449, 0.18135, 0.18628, 0.18052,
-     0.18081, 0.18175, 0.17860, 0.18217, 0.17379, 0.17589, 0.17549, 0.17115, 0.17109, 0.16823,
-     0.16760, 0.16847, 0.16650, 0.16673, 0.16417, 0.15719, 0.16389, 0.16475, 0.16396, 0.15941,
-     0.15694, 0.15821, 0.15311, 0.15547, 0.15958, 0.15608, 0.15193, 0.15027, 0.15130, 0.15188,
-     0.14897, 0.14370, 0.14713, 0.14235, 0.13992, 0.13778, 0.14128, 0.14296, 0.13726, 0.13844,
-     0.13587, 0.13568, 0.13714, 0.13412, 0.13302, 0.13634, 0.13058, 0.13133, 0.13256, 0.12865,
-     0.12876, 0.12829, 0.12406, 0.12533, 0.12706, 0.12624, 0.11936, 0.11965, 0.11939, 0.11757,
-     0.11776, 0.11811, 0.11718, 0.11292, 0.11913, 0.10995, 0.11550, 0.11022, 0.11052, 0.10881,
-     0.10867, 0.10698, 0.10993, 0.10747, 0.10380, 0.10409, 0.10705, 0.10460, 0.10166, 0.10276,
-     0.10485, 0.09890, 0.10002, 0.09657, 0.09693, 0.09508, 0.09633, 0.09700, 0.09512, 0.09168,
-     0.09455, 0.09765, 0.09106, 0.09576, 0.09068, 0.09121, 0.09251, 0.08922, 0.08709, 0.08406,
-     0.08608, 0.08811, 0.08714, 0.08411, 0.08723, 0.08366, 0.08314, 0.08139, 0.08106, 0.08273,
-     0.07820, 0.08163, 0.07717, 0.07587, 0.07916, 0.07616, 0.07180, 0.07727, 0.07398, 0.07423,
-     0.07447, 0.07200, 0.07306, 0.06731, 0.07200, 0.06953, 0.07260, 0.07068, 0.06838, 0.06614,
-     0.06788, 0.06488, 0.06502, 0.06604, 0.06503, 0.06189, 0.06450, 0.06353, 0.06871, 0.06509,
-     0.06091, 0.06271, 0.06141, 0.05912, 0.06207, 0.05918, 0.05966, 0.05936, 0.05913, 0.05385,
-     0.05791, 0.05680, 0.05699, 0.05690, 0.05578, 0.05569, 0.05763, 0.05589, 0.05162, 0.05217,
-     0.05249, 0.05286, 0.05150, 0.05125, 0.05162, 0.04853, 0.05216, 0.04819, 0.05178, 0.04746,
-     0.04974, 0.05071, 0.04636, 0.04751, 0.04621, 0.04922, 0.04485, 0.04282, 0.04456, 0.04577,
-     0.04733, 0.04461, 0.04297, 0.03982, 0.04220, 0.04204, 0.04470, 0.03948, 0.04224, 0.03938,
-     0.04113, 0.03856, 0.03958, 0.03687, 0.03819, 0.03968, 0.03604, 0.03745, 0.03770, 0.03881,
-     0.03740, 0.03711, 0.03711, 0.03750, 0.03827, 0.03633, 0.03664, 0.03596, 0.03561, 0.03440,
-     0.03416, 0.03353, 0.03344, 0.03290, 0.03280, 0.03212, 0.03479, 0.03208, 0.03169, 0.03309,
-     0.03087, 0.03068, 0.03111, 0.03014, 0.03140, 0.03072, 0.03159, 0.02948, 0.02990, 0.03048,
-     0.03073, 0.02976, 0.02836, 0.03049, 0.02816, 0.02985, 0.02744, 0.02492, 0.02753, 0.02632,
-     0.02492, 0.02622, 0.02767, 0.02521, 0.02632, 0.02540, 0.02395, 0.02473, 0.02274, 0.02603,
-     0.02361, 0.02216, 0.02414, 0.02342, 0.02327, 0.02178, 0.02352, 0.02192, 0.02400, 0.02081,
-     0.02298, 0.01936, 0.02235, 0.02110, 0.02090, 0.02042, 0.02318, 0.02076, 0.01984, 0.01979,
-     0.02071, 0.01921, 0.02177, 0.02046, 0.01824, 0.01985, 0.01935, 0.01999, 0.01950, 0.02037,
-     0.01824, 0.01713, 0.01912, 0.01771, 0.01959, 0.01809, 0.01877, 0.01690, 0.01863, 0.01684,
-     0.01844, 0.01568, 0.01858, 0.01810, 0.01786, 0.01757, 0.01451, 0.01602, 0.01583, 0.01534,
-     0.01389, 0.01630, 0.01461, 0.01572, 0.01592, 0.01519, 0.01655, 0.01476, 0.01345, 0.01369,
-     0.01722, 0.01485, 0.01427, 0.01345, 0.01456, 0.01480, 0.01374, 0.01747, 0.01403, 0.01456,
-     0.01442, 0.01209, 0.01239, 0.01311, 0.01268, 0.01253, 0.01195, 0.01306, 0.01249, 0.01355,
-     0.01229, 0.01413, 0.01359, 0.01127, 0.01166, 0.01045, 0.01079, 0.01041, 0.01350, 0.01326,
-     0.01060, 0.00977, 0.00905, 0.00856, 0.01248, 0.00943, 0.00992, 0.00987, 0.01074, 0.00943,
-     0.01185, 0.01118, 0.00890, 0.00986, 0.00929, 0.00822, 0.00939, 0.00827, 0.00818},
-
-    {0.95430, 0.95690, 0.95710, 0.95300, 0.95170, 0.94690, 0.95250, 0.94820, 0.94680, 0.94550,
-     0.94480, 0.94400, 0.94340, 0.94230, 0.93770, 0.93400, 0.93730, 0.93230, 0.93170, 0.93250,
-     0.93700, 0.93000, 0.92880, 0.92830, 0.92400, 0.92500, 0.92250, 0.92190, 0.92260, 0.91810,
-     0.92150, 0.91580, 0.91230, 0.91040, 0.91540, 0.91020, 0.91280, 0.90520, 0.90780, 0.90810,
-     0.90300, 0.90080, 0.89620, 0.89770, 0.89490, 0.89140, 0.88610, 0.88970, 0.88870, 0.88260,
-     0.88200, 0.88520, 0.87580, 0.87510, 0.87460, 0.87710, 0.87520, 0.87080, 0.87690, 0.86720,
-     0.86490, 0.86480, 0.85620, 0.85650, 0.85760, 0.84760, 0.85830, 0.84620, 0.84630, 0.84530,
-     0.84780, 0.83740, 0.84160, 0.83980, 0.83790, 0.83190, 0.82300, 0.82610, 0.82790, 0.82320,
-     0.81820, 0.82010, 0.81460, 0.81430, 0.81360, 0.80740, 0.80730, 0.79670, 0.80050, 0.80120,
-     0.79360, 0.79050, 0.78920, 0.78410, 0.78480, 0.78850, 0.77820, 0.78020, 0.77010, 0.77600,
-     0.76480, 0.76720, 0.76240, 0.75910, 0.75940, 0.75700, 0.75770, 0.75840, 0.75710, 0.73930,
-     0.73940, 0.74600, 0.73270, 0.74030, 0.73500, 0.73360, 0.73120, 0.71730, 0.71400, 0.71880,
-     0.71490, 0.70910, 0.70550, 0.70900, 0.70450, 0.70000, 0.70600, 0.69440, 0.68800, 0.68560,
-     0.68800, 0.68340, 0.68620, 0.68080, 0.66950, 0.66890, 0.66940, 0.65770, 0.66640, 0.65780,
-     0.65660, 0.65440, 0.64580, 0.64390, 0.64670, 0.64380, 0.64030, 0.64000, 0.63430, 0.62900,
-     0.63060, 0.61280, 0.61750, 0.61770, 0.60290, 0.61590, 0.61130, 0.60600, 0.60600, 0.60260,
-     0.59420, 0.60440, 0.58570, 0.58170, 0.58960, 0.58370, 0.58660, 0.57360, 0.57090, 0.56980,
-     0.56350, 0.55850, 0.56160, 0.55940, 0.55320, 0.56540, 0.54380, 0.54730, 0.54410, 0.54220,
-     0.53280, 0.52760, 0.51980, 0.53340, 0.53730, 0.53260, 0.51970, 0.50970, 0.51180, 0.50390,
-     0.51240, 0.50590, 0.50140, 0.50140, 0.49290, 0.49120, 0.49880, 0.49580, 0.48140, 0.48620,
-     0.47760, 0.47370, 0.47130, 0.46800, 0.46530, 0.47400, 0.45070, 0.46620, 0.45950, 0.47260,
-     0.45560, 0.45180, 0.44590, 0.43500, 0.44630, 0.45130, 0.43800, 0.42900, 0.43270, 0.42640,
-     0.42490, 0.42720, 0.41910, 0.41150, 0.41870, 0.41130, 0.41100, 0.40170, 0.40770, 0.39580,
-     0.40330, 0.40110, 0.40260, 0.39040, 0.39520, 0.38380, 0.38170, 0.37530, 0.38540, 0.37330,
-     0.37410, 0.37630, 0.36970, 0.37700, 0.35940, 0.36390, 0.36300, 0.35430, 0.35430, 0.34790,
-     0.34680, 0.34850, 0.34450, 0.34470, 0.33970, 0.32510, 0.33920, 0.34090, 0.33960, 0.33040,
-     0.32500, 0.32710, 0.31720, 0.32180, 0.33020, 0.32280, 0.31430, 0.31060, 0.31280, 0.31410,
-     0.30810, 0.29720, 0.30420, 0.29460, 0.28930, 0.28550, 0.29230, 0.29610, 0.28380, 0.28660,
-     0.28110, 0.28090, 0.28390, 0.27740, 0.27540, 0.28190, 0.27000, 0.27190, 0.27410, 0.26600,
-     0.26640, 0.26560, 0.25670, 0.25940, 0.26290, 0.26130, 0.24690, 0.24740, 0.24730, 0.24320,
-     0.24350, 0.24440, 0.24220, 0.23360, 0.24650, 0.22780, 0.23900, 0.22790, 0.22890, 0.22520,
-     0.22490, 0.22140, 0.22740, 0.22250, 0.21510, 0.21580, 0.22200, 0.21630, 0.21040, 0.21240,
-     0.21700, 0.20470, 0.20710, 0.19970, 0.20080, 0.19680, 0.19940, 0.20060, 0.19670, 0.18960,
-     0.19590, 0.20210, 0.18840, 0.19820, 0.18790, 0.18880, 0.19140, 0.18470, 0.18020, 0.17380,
-     0.17820, 0.18240, 0.18040, 0.17400, 0.18040, 0.17310, 0.17220, 0.16860, 0.16790, 0.17110,
-     0.16200, 0.16890, 0.15960, 0.15690, 0.16380, 0.15770, 0.14860, 0.15980, 0.15320, 0.15370,
-     0.15430, 0.14900, 0.15110, 0.13940, 0.14900, 0.14390, 0.15050, 0.14610, 0.14160, 0.13680,
-     0.14040, 0.13420, 0.13440, 0.13650, 0.13460, 0.12820, 0.13350, 0.13150, 0.14210, 0.13480,
-     0.12600, 0.12990, 0.12710, 0.12230, 0.12840, 0.12250, 0.12340, 0.12270, 0.12240, 0.11140,
-     0.11970, 0.11740, 0.11780, 0.11780, 0.11530, 0.11520, 0.11940, 0.11570, 0.10680, 0.10820,
-     0.10850, 0.10980, 0.10690, 0.10620, 0.10680, 0.10040, 0.10790, 0.09990, 0.10720, 0.09820,
-     0.10300, 0.10490, 0.09600, 0.09820, 0.09570, 0.10200, 0.09280, 0.08860, 0.09210, 0.09460,
-     0.09810, 0.09240, 0.08890, 0.08230, 0.08740, 0.08690, 0.09240, 0.08180, 0.08750, 0.08140,
-     0.08510, 0.07970, 0.08190, 0.07620, 0.07920, 0.08220, 0.07450, 0.07750, 0.07810, 0.08040,
-     0.07740, 0.07670, 0.07670, 0.07760, 0.07920, 0.07510, 0.07610, 0.07460, 0.07360, 0.07120,
-     0.07060, 0.06940, 0.06920, 0.06810, 0.06780, 0.06640, 0.07210, 0.06630, 0.06550, 0.06840,
-     0.06390, 0.06350, 0.06430, 0.06230, 0.06490, 0.06350, 0.06530, 0.06120, 0.06180, 0.06300,
-     0.06360, 0.06160, 0.05880, 0.06320, 0.05830, 0.06170, 0.05680, 0.05150, 0.05690, 0.05450,
-     0.05150, 0.05430, 0.05720, 0.05210, 0.05450, 0.05260, 0.04950, 0.05120, 0.04700, 0.05380,
-     0.04880, 0.04590, 0.05000, 0.04840, 0.04810, 0.04520, 0.04870, 0.04530, 0.04960, 0.04310,
-     0.04750, 0.04020, 0.04630, 0.04370, 0.04320, 0.04230, 0.04800, 0.04300, 0.04100, 0.04100,
-     0.04280, 0.03970, 0.04500, 0.04230, 0.03780, 0.04120, 0.04000, 0.04140, 0.04030, 0.04220,
-     0.03780, 0.03540, 0.03970, 0.03670, 0.04050, 0.03740, 0.03880, 0.03510, 0.03860, 0.03490,
-     0.03820, 0.03250, 0.03850, 0.03750, 0.03710, 0.03640, 0.03000, 0.03320, 0.03290, 0.03170,
-     0.02880, 0.03370, 0.03020, 0.03250, 0.03290, 0.03140, 0.03420, 0.03050, 0.02780, 0.02830,
-     0.03560, 0.03070, 0.02950, 0.02780, 0.03010, 0.03060, 0.02840, 0.03620, 0.02900, 0.03010,
-     0.02980, 0.02500, 0.02560, 0.02710, 0.02630, 0.02590, 0.02470, 0.02700, 0.02590, 0.02810,
-     0.02540, 0.02930, 0.02810, 0.02330, 0.02410, 0.02160, 0.02230, 0.02160, 0.02800, 0.02740,
-     0.02200, 0.02020, 0.01870, 0.01770, 0.02580, 0.01950, 0.02050, 0.02040, 0.02220, 0.01950,
-     0.02450, 0.02310, 0.01840, 0.02050, 0.01930, 0.01700, 0.01940, 0.01710, 0.01690},
-
-    {0.04361, 0.04124, 0.04106, 0.04479, 0.04597, 0.05028, 0.04524, 0.04912, 0.05037, 0.05153,
-     0.05215, 0.05286, 0.05340, 0.05437, 0.05842, 0.06164, 0.05877, 0.06312, 0.06363, 0.06294,
-     0.05903, 0.06510, 0.06613, 0.06656, 0.07022, 0.06938, 0.07149, 0.07200, 0.07141, 0.07519,
-     0.07234, 0.07711, 0.08001, 0.08157, 0.07744, 0.08174, 0.07960, 0.08581, 0.08370, 0.08345,
-     0.08759, 0.08936, 0.09303, 0.09183, 0.09405, 0.09681, 0.10093, 0.09813, 0.09891, 0.10362,
-     0.10408, 0.10162, 0.10877, 0.10930, 0.10967, 0.10780, 0.10923, 0.11251, 0.10795, 0.11516,
-     0.11685, 0.11692, 0.12312, 0.12291, 0.12212, 0.12917, 0.12162, 0.13015, 0.13008, 0.13077,
-     0.12904, 0.13616, 0.13331, 0.13454, 0.13582, 0.13984, 0.14567, 0.14366, 0.14248, 0.14554,
-     0.14875, 0.14754, 0.15103, 0.15122, 0.15166, 0.15551, 0.15557, 0.16197, 0.15970, 0.15928,
-     0.16380, 0.16561, 0.16636, 0.16929, 0.16889, 0.16677, 0.17261, 0.17149, 0.17705, 0.17382,
-     0.17988, 0.17860, 0.18115, 0.18287, 0.18271, 0.18395, 0.18359, 0.18323, 0.18390, 0.19274,
-     0.19269, 0.18948, 0.19585, 0.19226, 0.19478, 0.19543, 0.19655, 0.20278, 0.20420, 0.20213,
-     0.20382, 0.20628, 0.20777, 0.20632, 0.20818, 0.21000, 0.20756, 0.21221, 0.21466, 0.21555,
-     0.21466, 0.21636, 0.21533, 0.21731, 0.22127, 0.22147, 0.22130, 0.22513, 0.22231, 0.22510,
-     0.22548, 0.22616, 0.22874, 0.22929, 0.22848, 0.22932, 0.23032, 0.23040, 0.23196, 0.23336,
-     0.23294, 0.23728, 0.23619, 0.23615, 0.23941, 0.23657, 0.23761, 0.23876, 0.23876, 0.23947,
-     0.24113, 0.23910, 0.24266, 0.24333, 0.24197, 0.24299, 0.24250, 0.24458, 0.24497, 0.24513,
-     0.24597, 0.24658, 0.24621, 0.24647, 0.24717, 0.24572, 0.24808, 0.24776, 0.24805, 0.24822,
-     0.24892, 0.24924, 0.24961, 0.24888, 0.24861, 0.24894, 0.24961, 0.24991, 0.24986, 0.24999,
-     0.24985, 0.24996, 0.25000, 0.25000, 0.24995, 0.24992, 0.25000, 0.24998, 0.24965, 0.24981,
-     0.24950, 0.24931, 0.24918, 0.24898, 0.24880, 0.24932, 0.24757, 0.24886, 0.24836, 0.24925,
-     0.24803, 0.24768, 0.24707, 0.24577, 0.24712, 0.24763, 0.24616, 0.24496, 0.24547, 0.24458,
-     0.24436, 0.24470, 0.24346, 0.24217, 0.24339, 0.24213, 0.24208, 0.24034, 0.24148, 0.23914,
-     0.24065, 0.24022, 0.24051, 0.23799, 0.23902, 0.23650, 0.23600, 0.23445, 0.23687, 0.23395,
-     0.23415, 0.23470, 0.23302, 0.23487, 0.23023, 0.23148, 0.23123, 0.22877, 0.22877, 0.22687,
-     0.22653, 0.22705, 0.22582, 0.22588, 0.22430, 0.21941, 0.22414, 0.22469, 0.22427, 0.22124,
-     0.21937, 0.22011, 0.21658, 0.21824, 0.22117, 0.21860, 0.21552, 0.21413, 0.21496, 0.21544,
-     0.21317, 0.20887, 0.21166, 0.20781, 0.20561, 0.20399, 0.20686, 0.20842, 0.20326, 0.20446,
-     0.20208, 0.20200, 0.20330, 0.20045, 0.19956, 0.20243, 0.19710, 0.19797, 0.19897, 0.19524,
-     0.19543, 0.19506, 0.19081, 0.19211, 0.19378, 0.19302, 0.18594, 0.18619, 0.18614, 0.18405,
-     0.18421, 0.18467, 0.18354, 0.17903, 0.18574, 0.17591, 0.18188, 0.17596, 0.17650, 0.17449,
-     0.17432, 0.17238, 0.17569, 0.17299, 0.16883, 0.16923, 0.17272, 0.16951, 0.16613, 0.16729,
-     0.16991, 0.16280, 0.16421, 0.15982, 0.16048, 0.15807, 0.15964, 0.16036, 0.15801, 0.15365,
-     0.15752, 0.16126, 0.15291, 0.15892, 0.15259, 0.15316, 0.15477, 0.15059, 0.14773, 0.14359,
-     0.14644, 0.14913, 0.14786, 0.14372, 0.14786, 0.14314, 0.14255, 0.14017, 0.13971, 0.14183,
-     0.13576, 0.14037, 0.13413, 0.13228, 0.13697, 0.13283, 0.12652, 0.13426, 0.12973, 0.13008,
-     0.13049, 0.12680, 0.12827, 0.11997, 0.12680, 0.12319, 0.12785, 0.12476, 0.12155, 0.11809,
-     0.12069, 0.11619, 0.11634, 0.11787, 0.11648, 0.11177, 0.11568, 0.11421, 0.12191, 0.11663,
-     0.11012, 0.11303, 0.11095, 0.10734, 0.11191, 0.10749, 0.10817, 0.10765, 0.10742, 0.09899,
-     0.10537, 0.10362, 0.10392, 0.10392, 0.10201, 0.10193, 0.10514, 0.10231, 0.09539, 0.09649,
-     0.09673, 0.09774, 0.09547, 0.09492, 0.09539, 0.09032, 0.09626, 0.08992, 0.09571, 0.08856,
-     0.09239, 0.09390, 0.08678, 0.08856, 0.08654, 0.09160, 0.08419, 0.08075, 0.08362, 0.08565,
-     0.08848, 0.08386, 0.08100, 0.07553, 0.07976, 0.07935, 0.08386, 0.07511, 0.07984, 0.07477,
-     0.07786, 0.07335, 0.07519, 0.07039, 0.07293, 0.07544, 0.06895, 0.07149, 0.07200, 0.07394,
-     0.07141, 0.07082, 0.07082, 0.07158, 0.07293, 0.06946, 0.07031, 0.06903, 0.06818, 0.06613,
-     0.06562, 0.06458, 0.06441, 0.06346, 0.06320, 0.06199, 0.06690, 0.06190, 0.06121, 0.06372,
-     0.05982, 0.05947, 0.06017, 0.05842, 0.06069, 0.05947, 0.06104, 0.05745, 0.05798, 0.05903,
-     0.05955, 0.05781, 0.05534, 0.05921, 0.05490, 0.05789, 0.05357, 0.04885, 0.05366, 0.05153,
-     0.04885, 0.05135, 0.05393, 0.04939, 0.05153, 0.04983, 0.04705, 0.04858, 0.04479, 0.05091,
-     0.04642, 0.04379, 0.04750, 0.04606, 0.04579, 0.04316, 0.04633, 0.04325, 0.04714, 0.04124,
-     0.04524, 0.03858, 0.04416, 0.04179, 0.04133, 0.04051, 0.04570, 0.04115, 0.03932, 0.03932,
-     0.04097, 0.03812, 0.04297, 0.04051, 0.03637, 0.03950, 0.03840, 0.03969, 0.03868, 0.04042,
-     0.03637, 0.03415, 0.03812, 0.03535, 0.03886, 0.03600, 0.03730, 0.03387, 0.03711, 0.03368,
-     0.03674, 0.03144, 0.03702, 0.03609, 0.03572, 0.03508, 0.02910, 0.03210, 0.03182, 0.03070,
-     0.02797, 0.03256, 0.02929, 0.03144, 0.03182, 0.03041, 0.03303, 0.02957, 0.02703, 0.02750,
-     0.03433, 0.02976, 0.02863, 0.02703, 0.02919, 0.02966, 0.02759, 0.03489, 0.02816, 0.02919,
-     0.02891, 0.02438, 0.02494, 0.02637, 0.02561, 0.02523, 0.02409, 0.02627, 0.02523, 0.02731,
-     0.02475, 0.02844, 0.02731, 0.02276, 0.02352, 0.02113, 0.02180, 0.02113, 0.02722, 0.02665,
-     0.02152, 0.01979, 0.01835, 0.01739, 0.02513, 0.01912, 0.02008, 0.01998, 0.02171, 0.01912,
-     0.02390, 0.02257, 0.01806, 0.02008, 0.01893, 0.01671, 0.01902, 0.01681, 0.01661},
-
-    {0.95021, 0.95292, 0.95313, 0.94885, 0.94750, 0.94251, 0.94833, 0.94386, 0.94240, 0.94105,
-     0.94032, 0.93949, 0.93887, 0.93773, 0.93296, 0.92913, 0.93255, 0.92738, 0.92676, 0.92758,
-     0.93224, 0.92500, 0.92376, 0.92324, 0.91881, 0.91984, 0.91726, 0.91664, 0.91736, 0.91273,
-     0.91623, 0.91036, 0.90676, 0.90480, 0.90995, 0.90460, 0.90727, 0.89946, 0.90213, 0.90244,
-     0.89720, 0.89494, 0.89022, 0.89176, 0.88889, 0.88530, 0.87987, 0.88356, 0.88254, 0.87629,
-     0.87568, 0.87895, 0.86934, 0.86862, 0.86811, 0.87067, 0.86872, 0.86423, 0.87046, 0.86055,
-     0.85820, 0.85810, 0.84932, 0.84963, 0.85075, 0.84056, 0.85147, 0.83913, 0.83923, 0.83821,
-     0.84076, 0.83017, 0.83444, 0.83261, 0.83068, 0.82457, 0.81552, 0.81867, 0.82050, 0.81572,
-     0.81064, 0.81257, 0.80698, 0.80668, 0.80597, 0.79967, 0.79957, 0.78881, 0.79267, 0.79338,
-     0.78567, 0.78252, 0.78121, 0.77604, 0.77675, 0.78050, 0.77006, 0.77208, 0.76185, 0.76783,
-     0.75649, 0.75892, 0.75406, 0.75072, 0.75102, 0.74859, 0.74930, 0.75001, 0.74869, 0.73069,
-     0.73080, 0.73747, 0.72403, 0.73171, 0.72635, 0.72493, 0.72251, 0.70847, 0.70514, 0.70999,
-     0.70605, 0.70020, 0.69657, 0.70010, 0.69556, 0.69102, 0.69707, 0.68537, 0.67892, 0.67650,
-     0.67892, 0.67428, 0.67710, 0.67166, 0.66028, 0.65968, 0.66018, 0.64840, 0.65716, 0.64850,
-     0.64729, 0.64508, 0.63643, 0.63452, 0.63733, 0.63441, 0.63089, 0.63059, 0.62486, 0.61953,
-     0.62114, 0.60325, 0.60797, 0.60818, 0.59331, 0.60637, 0.60175, 0.59642, 0.59642, 0.59301,
-     0.58457, 0.59482, 0.57605, 0.57203, 0.57996, 0.57404, 0.57695, 0.56391, 0.56120, 0.56010,
-     0.55378, 0.54877, 0.55188, 0.54967, 0.54346, 0.55568, 0.53404, 0.53754, 0.53434, 0.53243,
-     0.52302, 0.51782, 0.51001, 0.52362, 0.52753, 0.52282, 0.50991, 0.49990, 0.50200, 0.49410,
-     0.50260, 0.49610, 0.49160, 0.49160, 0.48310, 0.48140, 0.48900, 0.48600, 0.47161, 0.47640,
-     0.46781, 0.46391, 0.46152, 0.45822, 0.45552, 0.46421, 0.44095, 0.45642, 0.44973, 0.46281,
-     0.44584, 0.44205, 0.43616, 0.42528, 0.43656, 0.44155, 0.42828, 0.41930, 0.42299, 0.41671,
-     0.41521, 0.41750, 0.40943, 0.40186, 0.40903, 0.40165, 0.40136, 0.39209, 0.39807, 0.38621,
-     0.39369, 0.39149, 0.39299, 0.38084, 0.38562, 0.37427, 0.37218, 0.36581, 0.37586, 0.36382,
-     0.36462, 0.36680, 0.36024, 0.36750, 0.35000, 0.35447, 0.35357, 0.34492, 0.34492, 0.33856,
-     0.33747, 0.33916, 0.33519, 0.33538, 0.33042, 0.31592, 0.32992, 0.33161, 0.33032, 0.32118,
-     0.31582, 0.31790, 0.30808, 0.31264, 0.32098, 0.31364, 0.30520, 0.30153, 0.30371, 0.30500,
-     0.29905, 0.28824, 0.29518, 0.28567, 0.28041, 0.27665, 0.28339, 0.28715, 0.27496, 0.27774,
-     0.27229, 0.27209, 0.27506, 0.26863, 0.26664, 0.27308, 0.26130, 0.26318, 0.26536, 0.25734,
-     0.25773, 0.25694, 0.24814, 0.25081, 0.25427, 0.25269, 0.23845, 0.23894, 0.23884, 0.23479,
-     0.23509, 0.23598, 0.23380, 0.22531, 0.23805, 0.21958, 0.23064, 0.21968, 0.22067, 0.21701,
-     0.21672, 0.21326, 0.21918, 0.21435, 0.20705, 0.20774, 0.21385, 0.20823, 0.20241, 0.20438,
-     0.20892, 0.19679, 0.19916, 0.19186, 0.19295, 0.18901, 0.19157, 0.19275, 0.18891, 0.18192,
-     0.18812, 0.19423, 0.18074, 0.19039, 0.18024, 0.18113, 0.18369, 0.17709, 0.17267, 0.16637,
-     0.17070, 0.17483, 0.17286, 0.16657, 0.17286, 0.16568, 0.16480, 0.16126, 0.16057, 0.16372,
-     0.15478, 0.16156, 0.15242, 0.14977, 0.15655, 0.15056, 0.14163, 0.15262, 0.14614, 0.14663,
-     0.14722, 0.14202, 0.14408, 0.13261, 0.14202, 0.13702, 0.14349, 0.13918, 0.13477, 0.13006,
-     0.13359, 0.12752, 0.12771, 0.12977, 0.12791, 0.12165, 0.12683, 0.12488, 0.13526, 0.12811,
-     0.11950, 0.12331, 0.12057, 0.11588, 0.12184, 0.11607, 0.11695, 0.11627, 0.11598, 0.10523,
-     0.11334, 0.11109, 0.11148, 0.11148, 0.10904, 0.10894, 0.11305, 0.10943, 0.10075, 0.10211,
-     0.10240, 0.10367, 0.10084, 0.10016, 0.10075, 0.09451, 0.10182, 0.09402, 0.10114, 0.09237,
-     0.09704, 0.09889, 0.09023, 0.09237, 0.08993, 0.09607, 0.08711, 0.08303, 0.08643, 0.08886,
-     0.09227, 0.08672, 0.08332, 0.07691, 0.08186, 0.08138, 0.08672, 0.07643, 0.08196, 0.07604,
-     0.07963, 0.07439, 0.07652, 0.07100, 0.07391, 0.07682, 0.06935, 0.07226, 0.07284, 0.07507,
-     0.07216, 0.07148, 0.07148, 0.07236, 0.07391, 0.06993, 0.07090, 0.06945, 0.06848, 0.06616,
-     0.06558, 0.06442, 0.06423, 0.06316, 0.06287, 0.06152, 0.06703, 0.06142, 0.06065, 0.06345,
-     0.05911, 0.05872, 0.05949, 0.05756, 0.06007, 0.05872, 0.06046, 0.05650, 0.05708, 0.05824,
-     0.05882, 0.05689, 0.05419, 0.05843, 0.05371, 0.05698, 0.05226, 0.04717, 0.05236, 0.05005,
-     0.04717, 0.04986, 0.05265, 0.04774, 0.05005, 0.04822, 0.04525, 0.04688, 0.04285, 0.04938,
-     0.04458, 0.04180, 0.04573, 0.04419, 0.04391, 0.04113, 0.04448, 0.04122, 0.04535, 0.03912,
-     0.04333, 0.03635, 0.04218, 0.03969, 0.03921, 0.03836, 0.04381, 0.03902, 0.03711, 0.03711,
-     0.03883, 0.03587, 0.04094, 0.03836, 0.03406, 0.03730, 0.03616, 0.03750, 0.03644, 0.03826,
-     0.03406, 0.03178, 0.03587, 0.03302, 0.03664, 0.03368, 0.03501, 0.03149, 0.03482, 0.03130,
-     0.03444, 0.02902, 0.03473, 0.03378, 0.03340, 0.03273, 0.02666, 0.02969, 0.02940, 0.02827,
-     0.02552, 0.03016, 0.02685, 0.02902, 0.02940, 0.02798, 0.03064, 0.02713, 0.02458, 0.02505,
-     0.03197, 0.02732, 0.02618, 0.02458, 0.02675, 0.02722, 0.02514, 0.03254, 0.02571, 0.02675,
-     0.02647, 0.02194, 0.02250, 0.02392, 0.02316, 0.02279, 0.02166, 0.02382, 0.02279, 0.02486,
-     0.02232, 0.02600, 0.02486, 0.02034, 0.02109, 0.01875, 0.01941, 0.01875, 0.02477, 0.02420,
-     0.01912, 0.01744, 0.01605, 0.01512, 0.02269, 0.01679, 0.01772, 0.01763, 0.01931, 0.01679,
-     0.02147, 0.02016, 0.01577, 0.01772, 0.01660, 0.01447, 0.01670, 0.01456, 0.01437},
-
-    {0.95839, 0.96088, 0.96107, 0.95715, 0.95590, 0.95130, 0.95667, 0.95254, 0.95120, 0.94995,
-     0.94928, 0.94851, 0.94793, 0.94687, 0.94244, 0.93887, 0.94205, 0.93722, 0.93664, 0.93742,
-     0.94176, 0.93500, 0.93384, 0.93336, 0.92919, 0.93016, 0.92774, 0.92716, 0.92784, 0.92348,
-     0.92677, 0.92124, 0.91784, 0.91600, 0.92085, 0.91580, 0.91833, 0.91094, 0.91347, 0.91376,
-     0.90880, 0.90666, 0.90218, 0.90364, 0.90091, 0.89750, 0.89233, 0.89584, 0.89486, 0.88891,
-     0.88832, 0.89145, 0.88226, 0.88158, 0.88109, 0.88353, 0.88168, 0.87737, 0.88334, 0.87385,
-     0.87160, 0.87150, 0.86308, 0.86337, 0.86445, 0.85464, 0.86513, 0.85327, 0.85337, 0.85239,
-     0.85484, 0.84463, 0.84876, 0.84699, 0.84512, 0.83923, 0.83048, 0.83353, 0.83530, 0.83068,
-     0.82576, 0.82763, 0.82222, 0.82192, 0.82123, 0.81513, 0.81503, 0.80459, 0.80833, 0.80902,
-     0.80153, 0.79848, 0.79719, 0.79216, 0.79285, 0.79650, 0.78634, 0.78832, 0.77835, 0.78417,
-     0.77311, 0.77548, 0.77074, 0.76748, 0.76778, 0.76541, 0.76610, 0.76679, 0.76550, 0.74791,
-     0.74800, 0.75453, 0.74137, 0.74889, 0.74365, 0.74226, 0.73989, 0.72613, 0.72286, 0.72761,
-     0.72375, 0.71800, 0.71443, 0.71790, 0.71344, 0.70898, 0.71493, 0.70343, 0.69708, 0.69470,
-     0.69708, 0.69252, 0.69529, 0.68994, 0.67872, 0.67812, 0.67862, 0.66700, 0.67564, 0.66710,
-     0.66591, 0.66372, 0.65517, 0.65329, 0.65607, 0.65319, 0.64971, 0.64941, 0.64374, 0.63847,
-     0.64006, 0.62235, 0.62703, 0.62723, 0.61249, 0.62543, 0.62085, 0.61558, 0.61558, 0.61219,
-     0.60382, 0.61398, 0.59535, 0.59137, 0.59924, 0.59336, 0.59625, 0.58329, 0.58060, 0.57950,
-     0.57322, 0.56823, 0.57132, 0.56913, 0.56294, 0.57512, 0.55356, 0.55706, 0.55386, 0.55197,
-     0.54258, 0.53739, 0.52959, 0.54318, 0.54707, 0.54238, 0.52949, 0.51950, 0.52160, 0.51370,
-     0.52220, 0.51570, 0.51120, 0.51120, 0.50270, 0.50100, 0.50860, 0.50560, 0.49119, 0.49600,
-     0.48739, 0.48349, 0.48108, 0.47778, 0.47508, 0.48379, 0.46045, 0.47598, 0.46927, 0.48239,
-     0.46536, 0.46155, 0.45564, 0.44472, 0.45604, 0.46105, 0.44772, 0.43870, 0.44241, 0.43609,
-     0.43459, 0.43690, 0.42877, 0.42114, 0.42837, 0.42095, 0.42064, 0.41131, 0.41733, 0.40538,
-     0.41291, 0.41071, 0.41221, 0.39996, 0.40478, 0.39333, 0.39122, 0.38479, 0.39494, 0.38278,
-     0.38358, 0.38579, 0.37916, 0.38650, 0.36880, 0.37333, 0.37243, 0.36368, 0.36368, 0.35724,
-     0.35613, 0.35784, 0.35381, 0.35402, 0.34898, 0.33428, 0.34848, 0.35019, 0.34888, 0.33962,
-     0.33418, 0.33630, 0.32632, 0.33096, 0.33942, 0.33196, 0.32340, 0.31967, 0.32189, 0.32320,
-     0.31715, 0.30616, 0.31322, 0.30353, 0.29819, 0.29435, 0.30121, 0.30505, 0.29264, 0.29546,
-     0.28991, 0.28971, 0.29274, 0.28618, 0.28416, 0.29072, 0.27870, 0.28062, 0.28284, 0.27466,
-     0.27507, 0.27426, 0.26526, 0.26799, 0.27153, 0.26991, 0.25535, 0.25586, 0.25576, 0.25161,
-     0.25191, 0.25282, 0.25060, 0.24189, 0.25495, 0.23602, 0.24736, 0.23612, 0.23713, 0.23339,
-     0.23308, 0.22954, 0.23561, 0.23065, 0.22315, 0.22386, 0.23015, 0.22437, 0.21839, 0.22042,
-     0.22508, 0.21261, 0.21504, 0.20754, 0.20865, 0.20459, 0.20723, 0.20845, 0.20449, 0.19728,
-     0.20368, 0.20997, 0.19606, 0.20601, 0.19556, 0.19647, 0.19911, 0.19231, 0.18773, 0.18123,
-     0.18570, 0.18997, 0.18794, 0.18143, 0.18794, 0.18052, 0.17960, 0.17594, 0.17523, 0.17848,
-     0.16922, 0.17624, 0.16678, 0.16403, 0.17105, 0.16484, 0.15557, 0.16698, 0.16026, 0.16077,
-     0.16138, 0.15598, 0.15812, 0.14619, 0.15598, 0.15078, 0.15751, 0.15302, 0.14843, 0.14353,
-     0.14721, 0.14088, 0.14108, 0.14323, 0.14129, 0.13475, 0.14017, 0.13812, 0.14894, 0.14149,
-     0.13250, 0.13649, 0.13363, 0.12872, 0.13496, 0.12893, 0.12985, 0.12913, 0.12882, 0.11757,
-     0.12606, 0.12371, 0.12412, 0.12412, 0.12156, 0.12146, 0.12576, 0.12197, 0.11285, 0.11429,
-     0.11460, 0.11593, 0.11296, 0.11224, 0.11285, 0.10629, 0.11398, 0.10578, 0.11326, 0.10403,
-     0.10896, 0.11091, 0.10177, 0.10403, 0.10147, 0.10793, 0.09849, 0.09417, 0.09777, 0.10034,
-     0.10393, 0.09808, 0.09448, 0.08769, 0.09294, 0.09242, 0.09808, 0.08717, 0.09304, 0.08676,
-     0.09057, 0.08501, 0.08728, 0.08140, 0.08449, 0.08758, 0.07965, 0.08274, 0.08336, 0.08573,
-     0.08264, 0.08192, 0.08192, 0.08284, 0.08449, 0.08027, 0.08130, 0.07975, 0.07872, 0.07624,
-     0.07562, 0.07438, 0.07417, 0.07304, 0.07273, 0.07128, 0.07717, 0.07118, 0.07035, 0.07335,
-     0.06869, 0.06828, 0.06911, 0.06704, 0.06973, 0.06828, 0.07014, 0.06590, 0.06652, 0.06776,
-     0.06838, 0.06631, 0.06341, 0.06797, 0.06289, 0.06642, 0.06134, 0.05583, 0.06144, 0.05895,
-     0.05583, 0.05874, 0.06175, 0.05646, 0.05895, 0.05697, 0.05375, 0.05552, 0.05115, 0.05822,
-     0.05302, 0.05000, 0.05427, 0.05261, 0.05229, 0.04927, 0.05292, 0.04938, 0.05386, 0.04708,
-     0.05167, 0.04405, 0.05042, 0.04771, 0.04718, 0.04625, 0.05219, 0.04698, 0.04489, 0.04489,
-     0.04677, 0.04353, 0.04906, 0.04625, 0.04154, 0.04510, 0.04384, 0.04530, 0.04415, 0.04614,
-     0.04154, 0.03902, 0.04353, 0.04038, 0.04436, 0.04112, 0.04258, 0.03871, 0.04238, 0.03850,
-     0.04196, 0.03598, 0.04227, 0.04122, 0.04081, 0.04007, 0.03334, 0.03671, 0.03640, 0.03513,
-     0.03208, 0.03724, 0.03355, 0.03598, 0.03640, 0.03482, 0.03776, 0.03387, 0.03102, 0.03155,
-     0.03923, 0.03408, 0.03282, 0.03102, 0.03345, 0.03398, 0.03166, 0.03986, 0.03229, 0.03345,
-     0.03313, 0.02806, 0.02870, 0.03028, 0.02944, 0.02901, 0.02774, 0.03018, 0.02901, 0.03134,
-     0.02848, 0.03261, 0.03134, 0.02626, 0.02711, 0.02445, 0.02519, 0.02445, 0.03123, 0.03060,
-     0.02488, 0.02296, 0.02135, 0.02028, 0.02891, 0.02221, 0.02328, 0.02317, 0.02509, 0.02221,
-     0.02753, 0.02604, 0.02103, 0.02328, 0.02200, 0.01953, 0.02210, 0.01964, 0.01943},
-};
-
-/** @}*/
-} // namespace ns3
-
-#endif /* WIMAX_DEFAULT_TRACES_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/dl-mac-messages.cc ns-3.46/src/wimax/model/dl-mac-messages.cc
--- ns-3.45/src/wimax/model/dl-mac-messages.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/dl-mac-messages.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,657 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "dl-mac-messages.h"
-
-#include "ns3/address-utils.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-DcdChannelEncodings::DcdChannelEncodings()
-    : m_bsEirp(0),
-      m_eirXPIrMax(0),
-      m_frequency(0)
-{
-}
-
-DcdChannelEncodings::~DcdChannelEncodings()
-{
-}
-
-void
-DcdChannelEncodings::SetBsEirp(uint16_t bs_eirp)
-{
-    m_bsEirp = bs_eirp;
-}
-
-void
-DcdChannelEncodings::SetEirxPIrMax(uint16_t eir_x_p_ir_max)
-{
-    m_eirXPIrMax = eir_x_p_ir_max;
-}
-
-void
-DcdChannelEncodings::SetFrequency(uint32_t frequency)
-{
-    m_frequency = frequency;
-}
-
-uint16_t
-DcdChannelEncodings::GetBsEirp() const
-{
-    return m_bsEirp;
-}
-
-uint16_t
-DcdChannelEncodings::GetEirxPIrMax() const
-{
-    return m_eirXPIrMax;
-}
-
-uint32_t
-DcdChannelEncodings::GetFrequency() const
-{
-    return m_frequency;
-}
-
-uint16_t
-DcdChannelEncodings::GetSize() const
-{
-    return 2 + 2 + 4;
-}
-
-Buffer::Iterator
-DcdChannelEncodings::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU16(m_bsEirp);
-    i.WriteU16(m_eirXPIrMax);
-    i.WriteU32(m_frequency);
-    return DoWrite(i);
-}
-
-Buffer::Iterator
-DcdChannelEncodings::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_bsEirp = i.ReadU16();
-    m_eirXPIrMax = i.ReadU16();
-    m_frequency = i.ReadU32();
-    return DoRead(i);
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-OfdmDcdChannelEncodings::OfdmDcdChannelEncodings()
-    : m_channelNr(0),
-      m_ttg(0),
-      m_rtg(0),
-      m_baseStationId(Mac48Address("00:00:00:00:00:00")),
-      m_frameDurationCode(0),
-      m_frameNumber(0)
-{
-}
-
-OfdmDcdChannelEncodings::~OfdmDcdChannelEncodings()
-{
-}
-
-void
-OfdmDcdChannelEncodings::SetChannelNr(uint8_t channelNr)
-{
-    m_channelNr = channelNr;
-}
-
-void
-OfdmDcdChannelEncodings::SetTtg(uint8_t ttg)
-{
-    m_ttg = ttg;
-}
-
-void
-OfdmDcdChannelEncodings::SetRtg(uint8_t rtg)
-{
-    m_rtg = rtg;
-}
-
-void
-OfdmDcdChannelEncodings::SetBaseStationId(Mac48Address baseStationId)
-{
-    m_baseStationId = baseStationId;
-}
-
-void
-OfdmDcdChannelEncodings::SetFrameDurationCode(uint8_t frameDurationCode)
-{
-    m_frameDurationCode = frameDurationCode;
-}
-
-void
-OfdmDcdChannelEncodings::SetFrameNumber(uint32_t frameNumber)
-{
-    m_frameNumber = frameNumber;
-}
-
-uint8_t
-OfdmDcdChannelEncodings::GetChannelNr() const
-{
-    return m_channelNr;
-}
-
-uint8_t
-OfdmDcdChannelEncodings::GetTtg() const
-{
-    return m_ttg;
-}
-
-uint8_t
-OfdmDcdChannelEncodings::GetRtg() const
-{
-    return m_rtg;
-}
-
-Mac48Address
-OfdmDcdChannelEncodings::GetBaseStationId() const
-{
-    return m_baseStationId;
-}
-
-uint8_t
-OfdmDcdChannelEncodings::GetFrameDurationCode() const
-{
-    return m_frameDurationCode;
-}
-
-uint32_t
-OfdmDcdChannelEncodings::GetFrameNumber() const
-{
-    return m_frameNumber;
-}
-
-uint16_t
-OfdmDcdChannelEncodings::GetSize() const
-{
-    return DcdChannelEncodings::GetSize() + 1 + 1 + 1 + 6 + 1 + 4;
-}
-
-Buffer::Iterator
-OfdmDcdChannelEncodings::DoWrite(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_channelNr);
-    i.WriteU8(m_ttg);
-    i.WriteU8(m_rtg);
-    WriteTo(i, m_baseStationId);
-    i.WriteU8(m_frameDurationCode);
-    i.WriteU32(m_frameNumber);
-    return i;
-}
-
-Buffer::Iterator
-OfdmDcdChannelEncodings::DoRead(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_channelNr = i.ReadU8();
-    m_ttg = i.ReadU8();
-    m_rtg = i.ReadU8();
-    ReadFrom(i, m_baseStationId); // length (6) shall also be written in packet instead of hard
-                                  // coded, see ARP example
-    m_frameDurationCode = i.ReadU8();
-    m_frameNumber = i.ReadU32();
-    return i;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-OfdmDlBurstProfile::OfdmDlBurstProfile()
-    : m_type(0),
-      m_length(0),
-      m_diuc(0),
-      m_fecCodeType(0)
-{
-}
-
-OfdmDlBurstProfile::~OfdmDlBurstProfile()
-{
-}
-
-void
-OfdmDlBurstProfile::SetType(uint8_t type)
-{
-    m_type = type;
-}
-
-void
-OfdmDlBurstProfile::SetLength(uint8_t length)
-{
-    m_length = length;
-}
-
-void
-OfdmDlBurstProfile::SetDiuc(uint8_t diuc)
-{
-    m_diuc = diuc;
-}
-
-void
-OfdmDlBurstProfile::SetFecCodeType(uint8_t fecCodeType)
-{
-    m_fecCodeType = fecCodeType;
-}
-
-uint8_t
-OfdmDlBurstProfile::GetType() const
-{
-    return m_type;
-}
-
-uint8_t
-OfdmDlBurstProfile::GetLength() const
-{
-    return m_length;
-}
-
-uint8_t
-OfdmDlBurstProfile::GetDiuc() const
-{
-    return m_diuc;
-}
-
-uint8_t
-OfdmDlBurstProfile::GetFecCodeType() const
-{
-    return m_fecCodeType;
-}
-
-uint16_t
-OfdmDlBurstProfile::GetSize() const
-{
-    return 1 + 1 + 1 + 1;
-}
-
-Buffer::Iterator
-OfdmDlBurstProfile::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_type);
-    i.WriteU8(m_length);
-    i.WriteU8(m_diuc);
-    i.WriteU8(m_fecCodeType);
-    return i;
-}
-
-Buffer::Iterator
-OfdmDlBurstProfile::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_type = i.ReadU8();
-    m_length = i.ReadU8();
-    m_diuc = i.ReadU8();
-    m_fecCodeType = i.ReadU8();
-    return i;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(Dcd);
-
-Dcd::Dcd()
-    : m_reserved(0),
-      m_configurationChangeCount(0),
-      m_nrDlBurstProfiles(0)
-{
-}
-
-Dcd::~Dcd()
-{
-}
-
-void
-Dcd::SetConfigurationChangeCount(uint8_t configurationChangeCount)
-{
-    m_configurationChangeCount = configurationChangeCount;
-}
-
-void
-Dcd::SetChannelEncodings(OfdmDcdChannelEncodings channelEncodings)
-{
-    m_channelEncodings = channelEncodings;
-}
-
-void
-Dcd::SetNrDlBurstProfiles(uint8_t nrDlBurstProfiles)
-{
-    m_nrDlBurstProfiles = nrDlBurstProfiles;
-}
-
-void
-Dcd::AddDlBurstProfile(OfdmDlBurstProfile dlBurstProfile)
-{
-    m_dlBurstProfiles.push_back(dlBurstProfile);
-}
-
-uint8_t
-Dcd::GetConfigurationChangeCount() const
-{
-    return m_configurationChangeCount;
-}
-
-OfdmDcdChannelEncodings
-Dcd::GetChannelEncodings() const
-{
-    return m_channelEncodings;
-}
-
-std::vector<OfdmDlBurstProfile>
-Dcd::GetDlBurstProfiles() const
-{
-    return m_dlBurstProfiles;
-}
-
-uint8_t
-Dcd::GetNrDlBurstProfiles() const
-{
-    return m_nrDlBurstProfiles;
-}
-
-std::string
-Dcd::GetName() const
-{
-    return "DCD";
-}
-
-TypeId
-Dcd::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::Dcd").SetParent<Header>().SetGroupName("Wimax").AddConstructor<Dcd>();
-    return tid;
-}
-
-TypeId
-Dcd::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-Dcd::Print(std::ostream& os) const
-{
-    os << " configuration change count = " << (uint32_t)m_configurationChangeCount
-       << ", number of dl burst profiles = " << m_dlBurstProfiles.size();
-}
-
-uint32_t
-Dcd::GetSerializedSize() const
-{
-    uint32_t dlBurstProfilesSize = 0;
-
-    for (const auto& burstProfile : m_dlBurstProfiles)
-    {
-        dlBurstProfilesSize += burstProfile.GetSize();
-    }
-
-    return 1 + 1 + m_channelEncodings.GetSize() + dlBurstProfilesSize;
-}
-
-void
-Dcd::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_reserved);
-    i.WriteU8(m_configurationChangeCount);
-    i = m_channelEncodings.Write(i);
-
-    for (const auto& burstProfile : m_dlBurstProfiles)
-    {
-        i = burstProfile.Write(i);
-    }
-}
-
-uint32_t
-Dcd::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_reserved = i.ReadU8();
-    m_configurationChangeCount = i.ReadU8();
-    i = m_channelEncodings.Read(i);
-
-    for (uint8_t j = 0; j < m_nrDlBurstProfiles; j++)
-    {
-        OfdmDlBurstProfile burstProfile;
-        i = burstProfile.Read(i);
-        AddDlBurstProfile(burstProfile);
-    }
-
-    return i.GetDistanceFrom(start);
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-OfdmDlMapIe::OfdmDlMapIe()
-    : m_cid(),
-      m_diuc(0),
-      m_preamblePresent(0),
-      m_startTime(0)
-{
-}
-
-OfdmDlMapIe::~OfdmDlMapIe()
-{
-}
-
-void
-OfdmDlMapIe::SetCid(Cid cid)
-{
-    m_cid = cid;
-}
-
-void
-OfdmDlMapIe::SetDiuc(uint8_t diuc)
-{
-    m_diuc = diuc;
-}
-
-void
-OfdmDlMapIe::SetPreamblePresent(uint8_t preamblePresent)
-{
-    m_preamblePresent = preamblePresent;
-}
-
-void
-OfdmDlMapIe::SetStartTime(uint16_t startTime)
-{
-    m_startTime = startTime;
-}
-
-Cid
-OfdmDlMapIe::GetCid() const
-{
-    return m_cid;
-}
-
-uint8_t
-OfdmDlMapIe::GetDiuc() const
-{
-    return m_diuc;
-}
-
-uint8_t
-OfdmDlMapIe::GetPreamblePresent() const
-{
-    return m_preamblePresent;
-}
-
-uint16_t
-OfdmDlMapIe::GetStartTime() const
-{
-    return m_startTime;
-}
-
-uint16_t
-OfdmDlMapIe::GetSize() const
-{
-    return 2 + 1 + 1 + 2;
-}
-
-Buffer::Iterator
-OfdmDlMapIe::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU16(m_cid.GetIdentifier());
-    i.WriteU8(m_diuc);
-    i.WriteU8(m_preamblePresent);
-    i.WriteU16(m_startTime);
-    return i;
-}
-
-Buffer::Iterator
-OfdmDlMapIe::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_cid = i.ReadU16();
-    m_diuc = i.ReadU8();
-    m_preamblePresent = i.ReadU8();
-    m_startTime = i.ReadU16();
-    return i;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(DlMap);
-
-DlMap::DlMap()
-    : m_dcdCount(0),
-      m_baseStationId(Mac48Address("00:00:00:00:00:00"))
-{
-}
-
-DlMap::~DlMap()
-{
-}
-
-void
-DlMap::SetDcdCount(uint8_t dcdCount)
-{
-    m_dcdCount = dcdCount;
-}
-
-void
-DlMap::SetBaseStationId(Mac48Address baseStationId)
-{
-    m_baseStationId = baseStationId;
-}
-
-void
-DlMap::AddDlMapElement(OfdmDlMapIe dlMapElement)
-{
-    m_dlMapElements.push_back(dlMapElement);
-}
-
-uint8_t
-DlMap::GetDcdCount() const
-{
-    return m_dcdCount;
-}
-
-Mac48Address
-DlMap::GetBaseStationId() const
-{
-    return m_baseStationId;
-}
-
-std::list<OfdmDlMapIe>
-DlMap::GetDlMapElements() const
-{
-    return m_dlMapElements;
-}
-
-std::string
-DlMap::GetName() const
-{
-    return "DL-MAP";
-}
-
-TypeId
-DlMap::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::DlMap").SetParent<Header>().SetGroupName("Wimax").AddConstructor<DlMap>();
-    return tid;
-}
-
-TypeId
-DlMap::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-DlMap::Print(std::ostream& os) const
-{
-    os << " dcd count = " << (uint32_t)m_dcdCount << ", base station id = " << m_baseStationId
-       << ", number of dl-map elements = " << m_dlMapElements.size();
-}
-
-uint32_t
-DlMap::GetSerializedSize() const
-{
-    uint32_t dlMapElementsSize = 0;
-
-    for (const auto& dlMapIe : m_dlMapElements)
-    {
-        dlMapElementsSize += dlMapIe.GetSize();
-    }
-
-    return 1 + 6 + dlMapElementsSize;
-}
-
-void
-DlMap::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_dcdCount);
-    WriteTo(i, m_baseStationId);
-
-    for (const auto& dlMapIe : m_dlMapElements)
-    {
-        i = dlMapIe.Write(i);
-    }
-}
-
-uint32_t
-DlMap::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_dcdCount = i.ReadU8();
-    ReadFrom(i, m_baseStationId); // length (6) shall also be written in packet instead of hard
-                                  // coded, see ARP example
-
-    m_dlMapElements.clear(); // only for printing, otherwise it shows wrong number of elements
-
-    while (true)
-    {
-        OfdmDlMapIe dlMapIe;
-        i = dlMapIe.Read(i);
-
-        AddDlMapElement(dlMapIe);
-
-        if (dlMapIe.GetDiuc() == 14) // End of Map IE
-        {
-            break;
-        }
-    }
-    return i.GetDistanceFrom(start);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/dl-mac-messages.h ns-3.46/src/wimax/model/dl-mac-messages.h
--- ns-3.45/src/wimax/model/dl-mac-messages.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/dl-mac-messages.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,608 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef DCD_CHANNEL_ENCODINGS_H
-#define DCD_CHANNEL_ENCODINGS_H
-
-#include "ns3/buffer.h"
-
-#include <list>
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the DCD channel encodings as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 11.4.1 DCD channel encodings, page 659
- */
-class DcdChannelEncodings
-{
-  public:
-    DcdChannelEncodings();
-    virtual ~DcdChannelEncodings();
-
-    /**
-     * Set BS EIRP field
-     * @param bs_eirp the BS EIRP
-     */
-    void SetBsEirp(uint16_t bs_eirp);
-    /**
-     * Set EIRX IR MAX field
-     * @param rss_ir_max the EIRRX IR MAX
-     */
-    void SetEirxPIrMax(uint16_t rss_ir_max);
-    /**
-     * Set frequency field
-     * @param frequency the frequency
-     */
-    void SetFrequency(uint32_t frequency);
-
-    /**
-     * Get BS EIRP field
-     * @returns the BS EIRP
-     */
-    uint16_t GetBsEirp() const;
-    /**
-     * Get EIRX IR MAX field
-     * @returns the EIRX IR MAX
-     */
-    uint16_t GetEirxPIrMax() const;
-    /**
-     * Get frequency function
-     * @returns the frequency
-     */
-    uint32_t GetFrequency() const;
-
-    /**
-     * Get size field
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    /**
-     * Write item
-     * @param start iterator
-     * @returns the updated iterator
-     */
-    virtual Buffer::Iterator DoWrite(Buffer::Iterator start) const = 0;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    virtual Buffer::Iterator DoRead(Buffer::Iterator start) = 0;
-
-    uint16_t m_bsEirp;     ///< BS EIRP
-    uint16_t m_eirXPIrMax; ///< EIRX IR MAX
-    uint32_t m_frequency;  ///< frequency
-};
-
-} // namespace ns3
-
-#endif /* DCD_CHANNEL_ENCODINGS_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef OFDM_DCD_CHANNEL_ENCODINGS_H
-#define OFDM_DCD_CHANNEL_ENCODINGS_H
-
-#include "ns3/mac48-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * This class implements the OFDM DCD channel encodings as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems"
- */
-class OfdmDcdChannelEncodings : public DcdChannelEncodings
-{
-  public:
-    OfdmDcdChannelEncodings();
-    ~OfdmDcdChannelEncodings() override;
-
-    /**
-     * Set channel number field
-     * @param channelNr the channel number
-     */
-    void SetChannelNr(uint8_t channelNr);
-    /**
-     * Set TTG field
-     * @param ttg the TTG
-     */
-    void SetTtg(uint8_t ttg);
-    /**
-     * Set RTG field
-     * @param rtg the RTG
-     */
-    void SetRtg(uint8_t rtg);
-
-    /**
-     * Set base station ID field
-     * @param baseStationId the base station ID
-     */
-    void SetBaseStationId(Mac48Address baseStationId);
-    /**
-     * Set frame duration code field
-     * @param frameDurationCode the frame duration code
-     */
-    void SetFrameDurationCode(uint8_t frameDurationCode);
-    /**
-     * Set frame number field
-     * @param frameNumber the frame number
-     */
-    void SetFrameNumber(uint32_t frameNumber);
-
-    /**
-     * Get channel number field
-     * @returns the channel number
-     */
-    uint8_t GetChannelNr() const;
-    /**
-     * Get TTG field
-     * @returns the TTG
-     */
-    uint8_t GetTtg() const;
-    /**
-     * Get RTG field
-     * @returns the RTG
-     */
-    uint8_t GetRtg() const;
-
-    /**
-     * Get base station ID field
-     * @returns the base station MAC address
-     */
-    Mac48Address GetBaseStationId() const;
-    /**
-     * Get frame duration code field
-     * @returns the frame duration code
-     */
-    uint8_t GetFrameDurationCode() const;
-    /**
-     * Get frame number field
-     * @returns the frame number
-     */
-    uint32_t GetFrameNumber() const;
-
-    /**
-     * Get size field
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-  private:
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator DoWrite(Buffer::Iterator start) const override;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator DoRead(Buffer::Iterator start) override;
-
-    uint8_t m_channelNr; ///< channel number
-    uint8_t m_ttg;       ///< TTG
-    uint8_t m_rtg;       ///< RTG
-
-    Mac48Address m_baseStationId; ///< base station ID
-    uint8_t m_frameDurationCode;  ///< frame duration code
-    uint32_t m_frameNumber;       ///< frame number
-};
-
-} // namespace ns3
-
-#endif /* OFDM_DCD_CHANNEL_ENCODINGS_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef OFDM_DL_BURST_PROFILE_H
-#define OFDM_DL_BURST_PROFILE_H
-
-#include "ns3/buffer.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * This class implements the OFDM Downlink burst profile descriptor as described by "IEEE Standard
- * for Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless
- * Access Systems" 8.2.1.10 Burst profile formats page 416
- *
- */
-class OfdmDlBurstProfile
-{
-  public:
-    /// DIUC enumeration
-    enum Diuc
-    {
-        DIUC_STC_ZONE = 0,
-        DIUC_BURST_PROFILE_1,
-        DIUC_BURST_PROFILE_2,
-        DIUC_BURST_PROFILE_3,
-        DIUC_BURST_PROFILE_4,
-        DIUC_BURST_PROFILE_5,
-        DIUC_BURST_PROFILE_6,
-        DIUC_BURST_PROFILE_7,
-        DIUC_BURST_PROFILE_8,
-        DIUC_BURST_PROFILE_9,
-        DIUC_BURST_PROFILE_10,
-        DIUC_BURST_PROFILE_11,
-        // 12 is reserved
-        DIUC_GAP = 13,
-        DIUC_END_OF_MAP
-    };
-
-    OfdmDlBurstProfile();
-    ~OfdmDlBurstProfile();
-
-    /**
-     * Set type field
-     * @param type the type to set
-     */
-    void SetType(uint8_t type);
-    /**
-     * Set length field
-     * @param length the length to set
-     */
-    void SetLength(uint8_t length);
-    /**
-     * Set DIUC field
-     * @param diuc the DIUC
-     */
-    void SetDiuc(uint8_t diuc);
-
-    /**
-     * Set FEC code type
-     * @param fecCodeType the FEC code type
-     */
-    void SetFecCodeType(uint8_t fecCodeType);
-
-    /**
-     * Get type function
-     * @returns the type
-     */
-    uint8_t GetType() const;
-    /** @returns the length field */
-    uint8_t GetLength() const;
-    /** @returns the DIUC field */
-    uint8_t GetDiuc() const;
-
-    /** @returns the FEC code type */
-    uint8_t GetFecCodeType() const;
-
-    /** @returns the size */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item
-     * @param start the starting item iterator
-     * @returns the iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item
-     * @param start the starting item iterator
-     * @returns the iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    uint8_t m_type;   ///< type
-    uint8_t m_length; ///< length
-    uint8_t m_diuc;   ///< diuc
-
-    // TLV Encoded information
-    uint8_t m_fecCodeType; ///< FEC code type
-};
-
-} // namespace ns3
-
-#endif /* OFDM_DL_BURST_PROFILE_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef DCD_H
-#define DCD_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-#include <vector>
-
-namespace ns3
-{
-
-/**
- * This class implements Downlink channel descriptor as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.1 Downlink Channel Descriptor (DCD) message, page 45
- */
-class Dcd : public Header
-{
-  public:
-    Dcd();
-    ~Dcd() override;
-
-    /**
-     * Set configuration change count field
-     * @param configurationChangeCount the configuration change count
-     */
-    void SetConfigurationChangeCount(uint8_t configurationChangeCount);
-    /**
-     * Set channel encodings field
-     * @param channelEncodings the channel encodings
-     */
-    void SetChannelEncodings(OfdmDcdChannelEncodings channelEncodings);
-    /**
-     * Add DL burst profile field
-     * @param dlBurstProfile the DL burst profile
-     */
-    void AddDlBurstProfile(OfdmDlBurstProfile dlBurstProfile);
-    /**
-     * Set number DL burst profile field
-     * @param nrDlBurstProfiles the number of DL burst profiles
-     */
-    void SetNrDlBurstProfiles(uint8_t nrDlBurstProfiles);
-
-    /**
-     * Get configuration change count field
-     * @returns the configuration change count
-     */
-    uint8_t GetConfigurationChangeCount() const;
-    /**
-     * Get channel encodings field
-     * @returns the channel encodings
-     */
-    OfdmDcdChannelEncodings GetChannelEncodings() const;
-    /**
-     * Get DL burst profile field
-     * @returns the DL burst profiles
-     */
-    std::vector<OfdmDlBurstProfile> GetDlBurstProfiles() const;
-    /**
-     * Get number DL burst profiles field
-     * @returns the number of DL burst profiles
-     */
-    uint8_t GetNrDlBurstProfiles() const;
-
-    /**
-     * Get name field
-     * @returns the name string
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_reserved;                         ///< changed as per the amendment 802.16e-2005
-    uint8_t m_configurationChangeCount;         ///< configuration change count
-    OfdmDcdChannelEncodings m_channelEncodings; ///< TLV Encoded information for the overall channel
-    std::vector<OfdmDlBurstProfile> m_dlBurstProfiles; ///< vector of download burst profiles
-
-    uint8_t m_nrDlBurstProfiles; ///< number DL purst profiles
-};
-
-} // namespace ns3
-
-#endif /* DCD_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef OFDM_DL_MAP_IE_H
-#define OFDM_DL_MAP_IE_H
-
-#include "cid.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * This class implements the OFDM DL-MAP information element as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.43.6 Compact DL-MAP IE page 109
- */
-class OfdmDlMapIe
-{
-  public:
-    OfdmDlMapIe();
-    ~OfdmDlMapIe();
-
-    /**
-     * Set CID function
-     * @param cid the CID
-     */
-    void SetCid(Cid cid);
-    /**
-     * Set DIUC field
-     * @param diuc the DIUC
-     */
-    void SetDiuc(uint8_t diuc);
-    /**
-     * Set preamble present field
-     * @param preamblePresent the preamble present
-     */
-    void SetPreamblePresent(uint8_t preamblePresent);
-    /**
-     * Set start time field
-     * @param startTime the start time value
-     */
-    void SetStartTime(uint16_t startTime);
-
-    /**
-     * Set CID field
-     * @returns the CID
-     */
-    Cid GetCid() const;
-    /**
-     * Get DIUC field
-     * @returns the DIUC
-     */
-    uint8_t GetDiuc() const;
-    /**
-     * Get preamble present field
-     * @returns the preamble present indicator
-     */
-    uint8_t GetPreamblePresent() const;
-    /**
-     * Get start time field
-     * @returns the start time
-     */
-    uint16_t GetStartTime() const;
-
-    /**
-     * Get size
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    Cid m_cid;                 ///< CID
-    uint8_t m_diuc;            ///< DIUC
-    uint8_t m_preamblePresent; ///< preamble present
-    uint16_t m_startTime;      ///< start time
-};
-
-} // namespace ns3
-
-#endif /* OFDM_DL_MAP_IE_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef DL_MAP_H
-#define DL_MAP_H
-
-#include "ns3/header.h"
-#include "ns3/mac48-address.h"
-
-#include <stdint.h>
-#include <vector>
-
-namespace ns3
-{
-
-/**
- * This class implements DL-MAP as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 8.2.1.8.1 Compressed DL-MAP, page 402
- */
-class DlMap : public Header
-{
-  public:
-    DlMap();
-    ~DlMap() override;
-
-    /**
-     * Set DCD count field
-     * @param dcdCount the DCD count
-     */
-    void SetDcdCount(uint8_t dcdCount);
-    /**
-     * Set base station ID field
-     * @param baseStationID the base station ID
-     */
-    void SetBaseStationId(Mac48Address baseStationID);
-    /**
-     * Add DL Map element field
-     * @param dlMapElement the DL map element
-     */
-    void AddDlMapElement(OfdmDlMapIe dlMapElement);
-
-    /**
-     * Get DCD count field
-     * @returns the DCD count
-     */
-    uint8_t GetDcdCount() const;
-    /**
-     * Get base station ID field
-     * @returns the MAC address
-     */
-    Mac48Address GetBaseStationId() const;
-    /**
-     * Get DL Map elements field
-     * @returns the DL map elements
-     */
-    std::list<OfdmDlMapIe> GetDlMapElements() const;
-
-    /**
-     * Get name field
-     * @returns the name string
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_dcdCount;                     ///< DCD count
-    Mac48Address m_baseStationId;           ///< base station ID
-    std::list<OfdmDlMapIe> m_dlMapElements; ///< DL Map elements
-                                            // m_paddingNibble; //fields to be implemented later on:
-};
-
-} // namespace ns3
-
-#endif /* DL_MAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ipcs-classifier.cc ns-3.46/src/wimax/model/ipcs-classifier.cc
--- ns-3.45/src/wimax/model/ipcs-classifier.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ipcs-classifier.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,91 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-
-#include "ipcs-classifier.h"
-
-#include "service-flow.h"
-
-#include "ns3/ipv4-header.h"
-#include "ns3/llc-snap-header.h"
-#include "ns3/log.h"
-#include "ns3/packet.h"
-#include "ns3/tcp-header.h"
-#include "ns3/tcp-l4-protocol.h"
-#include "ns3/udp-header.h"
-#include "ns3/udp-l4-protocol.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("IpcsClassifier");
-
-NS_OBJECT_ENSURE_REGISTERED(IpcsClassifier);
-
-TypeId
-IpcsClassifier::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::IpcsClassifier").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-IpcsClassifier::IpcsClassifier()
-{
-}
-
-IpcsClassifier::~IpcsClassifier()
-{
-}
-
-ServiceFlow*
-IpcsClassifier::Classify(Ptr<const Packet> packet,
-                         Ptr<ServiceFlowManager> sfm,
-                         ServiceFlow::Direction dir)
-{
-    Ptr<Packet> C_Packet = packet->Copy();
-
-    LlcSnapHeader llc;
-    C_Packet->RemoveHeader(llc);
-
-    Ipv4Header ipv4Header;
-    C_Packet->RemoveHeader(ipv4Header);
-    Ipv4Address source_address = ipv4Header.GetSource();
-    Ipv4Address dest_address = ipv4Header.GetDestination();
-    uint8_t protocol = ipv4Header.GetProtocol();
-
-    uint16_t sourcePort = 0;
-    uint16_t destPort = 0;
-    if (protocol == UdpL4Protocol::PROT_NUMBER)
-    {
-        UdpHeader udpHeader;
-        C_Packet->RemoveHeader(udpHeader);
-        sourcePort = udpHeader.GetSourcePort();
-        destPort = udpHeader.GetDestinationPort();
-    }
-    else if (protocol == TcpL4Protocol::PROT_NUMBER)
-    {
-        TcpHeader tcpHeader;
-        C_Packet->RemoveHeader(tcpHeader);
-        sourcePort = tcpHeader.GetSourcePort();
-        destPort = tcpHeader.GetDestinationPort();
-    }
-    else
-    {
-        NS_LOG_INFO("\t\t\tUnknown protocol: " << protocol);
-        return nullptr;
-    }
-
-    NS_LOG_INFO("Classifing packet: src_addr=" << source_address << " dst_addr=" << dest_address
-                                               << " src_port=" << sourcePort << " dst_port="
-                                               << destPort << " proto=" << (uint16_t)protocol);
-    return (sfm->DoClassify(source_address, dest_address, sourcePort, destPort, protocol, dir));
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ipcs-classifier.h ns-3.46/src/wimax/model/ipcs-classifier.h
--- ns-3.45/src/wimax/model/ipcs-classifier.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ipcs-classifier.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,53 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-
-#ifndef IPCS_CLASSIFIER_H
-#define IPCS_CLASSIFIER_H
-
-#include "ss-service-flow-manager.h"
-
-#include "ns3/packet.h"
-#include "ns3/ptr.h"
-
-#include <stdint.h>
-#include <vector>
-
-namespace ns3
-{
-class SsServiceFlowManager;
-
-/**
- * @ingroup wimax
- *
- * IPCS classifier
- */
-class IpcsClassifier : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    IpcsClassifier();
-    ~IpcsClassifier() override;
-    /**
-     * @brief classify a packet in a service flow
-     * @param packet the packet to classify
-     * @param sfm the service flow manager to be used to classify packets
-     * @param dir The direction on which the packet should be sent (UP or DOWN)
-     * @return The service flow that should be used to send this packet
-     */
-    ServiceFlow* Classify(Ptr<const Packet> packet,
-                          Ptr<ServiceFlowManager> sfm,
-                          ServiceFlow::Direction dir);
-};
-} // namespace ns3
-
-#endif /* IPCS_CLASSIFIER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ipcs-classifier-record.cc ns-3.46/src/wimax/model/ipcs-classifier-record.cc
--- ns-3.45/src/wimax/model/ipcs-classifier-record.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ipcs-classifier-record.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,364 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-#include "ipcs-classifier-record.h"
-
-#include "wimax-tlv.h"
-
-#include "ns3/ipv4-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("IpcsClassifierRecord");
-
-IpcsClassifierRecord::IpcsClassifierRecord()
-{
-    m_priority = 255;
-    m_priority = 0;
-    m_index = 0;
-    m_tosLow = 0;
-    m_tosHigh = 0;
-    m_tosMask = 0;
-    m_cid = 0;
-    m_protocol.push_back(6);  // tcp
-    m_protocol.push_back(17); // udp
-    AddSrcAddr(Ipv4Address("0.0.0.0"), Ipv4Mask("0.0.0.0"));
-    AddDstAddr(Ipv4Address("0.0.0.0"), Ipv4Mask("0.0.0.0"));
-    AddSrcPortRange(0, 65535);
-    AddDstPortRange(0, 65535);
-}
-
-IpcsClassifierRecord::~IpcsClassifierRecord()
-{
-}
-
-IpcsClassifierRecord::IpcsClassifierRecord(Tlv tlv)
-{
-    NS_ASSERT_MSG(tlv.GetType() == CsParamVectorTlvValue::Packet_Classification_Rule,
-                  "Invalid TLV");
-    ClassificationRuleVectorTlvValue* rules =
-        ((ClassificationRuleVectorTlvValue*)(tlv.PeekValue()));
-    m_priority = 0;
-    m_index = 0;
-    m_tosLow = 0;
-    m_tosHigh = 0;
-    m_tosMask = 0;
-    m_cid = 0;
-    for (auto iter = rules->Begin(); iter != rules->End(); ++iter)
-    {
-        switch ((*iter)->GetType())
-        {
-        case ClassificationRuleVectorTlvValue::Priority: {
-            m_priority = ((U8TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::ToS: {
-            NS_FATAL_ERROR("ToS Not implemented-- please implement and contribute a patch");
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::Protocol: {
-            auto list = (ProtocolTlvValue*)(*iter)->PeekValue();
-            for (auto iter2 = list->Begin(); iter2 != list->End(); ++iter2)
-            {
-                AddProtocol(*iter2);
-            }
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::IP_src: {
-            auto list = (Ipv4AddressTlvValue*)(*iter)->PeekValue();
-            for (auto iter2 = list->Begin(); iter2 != list->End(); ++iter2)
-            {
-                AddSrcAddr((*iter2).Address, (*iter2).Mask);
-            }
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::IP_dst: {
-            auto list = (Ipv4AddressTlvValue*)(*iter)->PeekValue();
-            for (auto iter2 = list->Begin(); iter2 != list->End(); ++iter2)
-            {
-                AddDstAddr((*iter2).Address, (*iter2).Mask);
-            }
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::Port_src: {
-            auto list = (PortRangeTlvValue*)(*iter)->PeekValue();
-            for (auto iter2 = list->Begin(); iter2 != list->End(); ++iter2)
-            {
-                AddSrcPortRange((*iter2).PortLow, (*iter2).PortHigh);
-            }
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::Port_dst: {
-            auto list = (PortRangeTlvValue*)(*iter)->PeekValue();
-            for (auto iter2 = list->Begin(); iter2 != list->End(); ++iter2)
-            {
-                AddDstPortRange((*iter2).PortLow, (*iter2).PortHigh);
-            }
-            break;
-        }
-        case ClassificationRuleVectorTlvValue::Index: {
-            m_index = ((U16TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        }
-    }
-}
-
-IpcsClassifierRecord::IpcsClassifierRecord(Ipv4Address SrcAddress,
-                                           Ipv4Mask SrcMask,
-                                           Ipv4Address DstAddress,
-                                           Ipv4Mask DstMask,
-                                           uint16_t SrcPortLow,
-                                           uint16_t SrcPortHigh,
-                                           uint16_t DstPortLow,
-                                           uint16_t DstPortHigh,
-                                           uint8_t protocol,
-                                           uint8_t priority)
-{
-    m_priority = priority;
-    m_protocol.push_back(protocol);
-    AddSrcAddr(SrcAddress, SrcMask);
-    AddDstAddr(DstAddress, DstMask);
-    AddSrcPortRange(SrcPortLow, SrcPortHigh);
-    AddDstPortRange(DstPortLow, DstPortHigh);
-    m_index = 0;
-    m_tosLow = 0;
-    m_tosHigh = 0;
-    m_tosMask = 0;
-    m_cid = 0;
-}
-
-void
-IpcsClassifierRecord::AddSrcAddr(Ipv4Address srcAddress, Ipv4Mask srcMask)
-{
-    Ipv4Addr tmp;
-    tmp.Address = srcAddress;
-    tmp.Mask = srcMask;
-    m_srcAddr.push_back(tmp);
-}
-
-void
-IpcsClassifierRecord::AddDstAddr(Ipv4Address dstAddress, Ipv4Mask dstMask)
-{
-    Ipv4Addr tmp;
-    tmp.Address = dstAddress;
-    tmp.Mask = dstMask;
-    m_dstAddr.push_back(tmp);
-}
-
-void
-IpcsClassifierRecord::AddSrcPortRange(uint16_t srcPortLow, uint16_t srcPortHigh)
-{
-    PortRange tmp;
-    tmp.PortLow = srcPortLow;
-    tmp.PortHigh = srcPortHigh;
-    m_srcPortRange.push_back(tmp);
-}
-
-void
-IpcsClassifierRecord::AddDstPortRange(uint16_t dstPortLow, uint16_t dstPortHigh)
-{
-    PortRange tmp;
-    tmp.PortLow = dstPortLow;
-    tmp.PortHigh = dstPortHigh;
-    m_dstPortRange.push_back(tmp);
-}
-
-void
-IpcsClassifierRecord::AddProtocol(uint8_t proto)
-{
-    m_protocol.push_back(proto);
-}
-
-void
-IpcsClassifierRecord::SetPriority(uint8_t prio)
-{
-    m_priority = prio;
-}
-
-void
-IpcsClassifierRecord::SetCid(uint16_t cid)
-{
-    m_cid = cid;
-}
-
-void
-IpcsClassifierRecord::SetIndex(uint16_t index)
-{
-    m_index = index;
-}
-
-uint16_t
-IpcsClassifierRecord::GetIndex() const
-{
-    return m_index;
-}
-
-uint16_t
-IpcsClassifierRecord::GetCid() const
-{
-    return m_cid;
-}
-
-uint8_t
-IpcsClassifierRecord::GetPriority() const
-{
-    return m_priority;
-}
-
-bool
-IpcsClassifierRecord::CheckMatchSrcAddr(Ipv4Address srcAddress) const
-{
-    for (auto iter = m_srcAddr.begin(); iter != m_srcAddr.end(); ++iter)
-    {
-        NS_LOG_INFO("src addr check match: pkt=" << srcAddress << " cls=" << (*iter).Address << "/"
-                                                 << (*iter).Mask);
-        if (srcAddress.CombineMask((*iter).Mask) == (*iter).Address)
-        {
-            return true;
-        }
-    }
-    NS_LOG_INFO("NOT OK!");
-    return false;
-}
-
-bool
-IpcsClassifierRecord::CheckMatchDstAddr(Ipv4Address dstAddress) const
-{
-    for (auto iter = m_dstAddr.begin(); iter != m_dstAddr.end(); ++iter)
-    {
-        NS_LOG_INFO("dst addr check match: pkt=" << dstAddress << " cls=" << (*iter).Address << "/"
-                                                 << (*iter).Mask);
-        if (dstAddress.CombineMask((*iter).Mask) == (*iter).Address)
-        {
-            return true;
-        }
-    }
-    NS_LOG_INFO("NOT OK!");
-    return false;
-}
-
-bool
-IpcsClassifierRecord::CheckMatchSrcPort(uint16_t port) const
-{
-    for (auto iter = m_srcPortRange.begin(); iter != m_srcPortRange.end(); ++iter)
-    {
-        NS_LOG_INFO("src port check match: pkt=" << port << " cls= [" << (*iter).PortLow << " TO "
-                                                 << (*iter).PortHigh << "]");
-        if (port >= (*iter).PortLow && port <= (*iter).PortHigh)
-        {
-            return true;
-        }
-    }
-    NS_LOG_INFO("NOT OK!");
-    return false;
-}
-
-bool
-IpcsClassifierRecord::CheckMatchDstPort(uint16_t port) const
-{
-    for (auto iter = m_dstPortRange.begin(); iter != m_dstPortRange.end(); ++iter)
-    {
-        NS_LOG_INFO("dst port check match: pkt=" << port << " cls= [" << (*iter).PortLow << " TO "
-                                                 << (*iter).PortHigh << "]");
-        if (port >= (*iter).PortLow && port <= (*iter).PortHigh)
-        {
-            return true;
-        }
-    }
-    NS_LOG_INFO("NOT OK!");
-    return false;
-}
-
-bool
-IpcsClassifierRecord::CheckMatchProtocol(uint8_t proto) const
-{
-    for (auto iter = m_protocol.begin(); iter != m_protocol.end(); ++iter)
-    {
-        NS_LOG_INFO("proto check match: pkt=" << (uint16_t)proto << " cls=" << (uint16_t)proto);
-        if (proto == (*iter))
-        {
-            return true;
-        }
-    }
-    NS_LOG_INFO("NOT OK!");
-    return false;
-}
-
-bool
-IpcsClassifierRecord::CheckMatch(Ipv4Address srcAddress,
-                                 Ipv4Address dstAddress,
-                                 uint16_t srcPort,
-                                 uint16_t dstPort,
-                                 uint8_t proto) const
-{
-    return (CheckMatchProtocol(proto) && CheckMatchDstPort(dstPort) && CheckMatchSrcPort(srcPort) &&
-            CheckMatchDstAddr(dstAddress) && CheckMatchSrcAddr(srcAddress));
-}
-
-Tlv
-IpcsClassifierRecord::ToTlv() const
-{
-    Ipv4AddressTlvValue ipv4AddrValSrc;
-    for (auto iter = m_srcAddr.begin(); iter != m_srcAddr.end(); ++iter)
-    {
-        ipv4AddrValSrc.Add((*iter).Address, (*iter).Mask);
-    }
-
-    Ipv4AddressTlvValue ipv4AddrValDst;
-    for (auto iter = m_dstAddr.begin(); iter != m_dstAddr.end(); ++iter)
-    {
-        ipv4AddrValDst.Add((*iter).Address, (*iter).Mask);
-    }
-
-    ProtocolTlvValue protoVal;
-    for (auto iter = m_protocol.begin(); iter != m_protocol.end(); ++iter)
-    {
-        protoVal.Add(*iter);
-    }
-
-    PortRangeTlvValue portValueSrc;
-    for (auto iter = m_srcPortRange.begin(); iter != m_srcPortRange.end(); ++iter)
-    {
-        portValueSrc.Add((*iter).PortLow, (*iter).PortHigh);
-    }
-
-    PortRangeTlvValue portValueDst;
-    for (auto iter = m_dstPortRange.begin(); iter != m_dstPortRange.end(); ++iter)
-    {
-        portValueDst.Add((*iter).PortLow, (*iter).PortHigh);
-    }
-
-    ClassificationRuleVectorTlvValue ClassVectVal;
-    ClassVectVal.Add(Tlv(ClassificationRuleVectorTlvValue::Priority, 1, U8TlvValue(m_priority)));
-    ClassVectVal.Add(
-        Tlv(ClassificationRuleVectorTlvValue::Protocol, protoVal.GetSerializedSize(), protoVal));
-    ClassVectVal.Add(Tlv(ClassificationRuleVectorTlvValue::IP_src,
-                         ipv4AddrValSrc.GetSerializedSize(),
-                         ipv4AddrValSrc));
-    ClassVectVal.Add(Tlv(ClassificationRuleVectorTlvValue::IP_dst,
-                         ipv4AddrValDst.GetSerializedSize(),
-                         ipv4AddrValDst));
-    ClassVectVal.Add(Tlv(ClassificationRuleVectorTlvValue::Port_src,
-                         portValueSrc.GetSerializedSize(),
-                         portValueSrc));
-    ClassVectVal.Add(Tlv(ClassificationRuleVectorTlvValue::Port_dst,
-                         portValueDst.GetSerializedSize(),
-                         portValueDst));
-    ClassVectVal.Add(Tlv(ClassificationRuleVectorTlvValue::Index, 2, U16TlvValue(1)));
-
-    Tlv tmp_tlv(CsParamVectorTlvValue::Packet_Classification_Rule,
-                ClassVectVal.GetSerializedSize(),
-                ClassVectVal);
-
-    return tmp_tlv;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ipcs-classifier-record.h ns-3.46/src/wimax/model/ipcs-classifier-record.h
--- ns-3.45/src/wimax/model/ipcs-classifier-record.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ipcs-classifier-record.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,197 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-
-#ifndef IPCS_CLASSIFIER_RECORD_H
-#define IPCS_CLASSIFIER_RECORD_H
-
-#include "wimax-tlv.h"
-
-#include "ns3/ipv4-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief IpcsClassifierRecord class
- */
-class IpcsClassifierRecord
-{
-  public:
-    IpcsClassifierRecord();
-    ~IpcsClassifierRecord();
-    /**
-     * @brief creates a classifier records and sets all its parameters
-     * @param srcAddress the source ip address
-     * @param srcMask the mask to apply on the source ip address
-     * @param dstAddress the destination ip address
-     * @param dstMask the mask to apply on the destination ip address
-     * @param srcPortLow the lower boundary of the source port range
-     * @param srcPortHigh the higher boundary of the source port range
-     * @param dstPortLow the lower boundary of the destination port range
-     * @param dstPortHigh the higher boundary of the destination port range
-     * @param protocol the L4 protocol
-     * @param priority the priority of this classifier
-     *
-     */
-    IpcsClassifierRecord(Ipv4Address srcAddress,
-                         Ipv4Mask srcMask,
-                         Ipv4Address dstAddress,
-                         Ipv4Mask dstMask,
-                         uint16_t srcPortLow,
-                         uint16_t srcPortHigh,
-                         uint16_t dstPortLow,
-                         uint16_t dstPortHigh,
-                         uint8_t protocol,
-                         uint8_t priority);
-    /**
-     * @brief Decodes a TLV and creates a classifier
-     * @param tlv the TLV to decode and from which the classifier parameters will be extracted
-     */
-    IpcsClassifierRecord(Tlv tlv);
-    /**
-     * @brief Creates a TLV from this classifier
-     * @return the created TLV
-     */
-    Tlv ToTlv() const;
-    /**
-     * @brief add a new source ip address to the classifier
-     * @param srcAddress the source ip address
-     * @param srcMask the mask to apply on the source ip address
-     */
-    void AddSrcAddr(Ipv4Address srcAddress, Ipv4Mask srcMask);
-    /**
-     * @brief add a new destination ip address to the classifier
-     * @param dstAddress the destination ip address
-     * @param dstMask the mask to apply on the destination ip address
-     */
-    void AddDstAddr(Ipv4Address dstAddress, Ipv4Mask dstMask);
-    /**
-     * @brief add a range of source port to the classifier
-     * @param srcPortLow the lower boundary of the source port range
-     * @param srcPortHigh the higher boundary of the source port range
-     */
-    void AddSrcPortRange(uint16_t srcPortLow, uint16_t srcPortHigh);
-    /**
-     * @brief add a range of destination port to the classifier
-     * @param dstPortLow the lower boundary of the destination port range
-     * @param dstPortHigh the higher boundary of the destination port range
-     */
-    void AddDstPortRange(uint16_t dstPortLow, uint16_t dstPortHigh);
-    /**
-     * @brief add a protocol to the classifier
-     * @param proto the L4 protocol to add
-     */
-    void AddProtocol(uint8_t proto);
-    /**
-     * @brief Set the priority of this classifier
-     * @param prio the priority of the classifier
-     */
-    void SetPriority(uint8_t prio);
-    /**
-     * @brief Set the index of the classifier
-     * @param index the index of the classifier
-     */
-    void SetIndex(uint16_t index);
-    /**
-     * @brief check if a packets can be used with this classifier
-     * @param srcAddress the source ip address of the packet
-     * @param dstAddress the destination ip address of the packet
-     * @param srcPort the source port of the packet
-     * @param dstPort the destination port of the packet
-     * @param proto The L4 protocol of the packet
-     * @return true if there is a match
-     */
-    bool CheckMatch(Ipv4Address srcAddress,
-                    Ipv4Address dstAddress,
-                    uint16_t srcPort,
-                    uint16_t dstPort,
-                    uint8_t proto) const;
-    /**
-     * @return the cid associated with this classifier
-     */
-    uint16_t GetCid() const;
-    /**
-     * @return the priority of this classifier
-     */
-    uint8_t GetPriority() const;
-    /**
-     * @return the index of this classifier
-     */
-    uint16_t GetIndex() const;
-    /**
-     * @brief Set the cid associated to this classifier
-     * @param cid the connection identifier
-     */
-    void SetCid(uint16_t cid);
-
-  private:
-    /**
-     * Check match source address function
-     * @param srcAddress source IP address to check
-     * @returns true if a match
-     */
-    bool CheckMatchSrcAddr(Ipv4Address srcAddress) const;
-    /**
-     * Check match destination address function
-     * @param dstAddress destination IP address to check
-     * @returns true if a match
-     */
-    bool CheckMatchDstAddr(Ipv4Address dstAddress) const;
-    /**
-     * Check match source port function
-     * @param srcPort source port to check
-     * @returns true if a match
-     */
-    bool CheckMatchSrcPort(uint16_t srcPort) const;
-    /**
-     * Check match destination port function
-     * @param dstPort destination port to check
-     * @returns true if a match
-     */
-    bool CheckMatchDstPort(uint16_t dstPort) const;
-    /**
-     * Check match protocol function
-     * @param proto protocol number to check
-     * @returns true if a match
-     */
-    bool CheckMatchProtocol(uint8_t proto) const;
-
-    /// PortRange structure
-    struct PortRange
-    {
-        uint16_t PortLow;  ///< port low
-        uint16_t PortHigh; ///< port high
-    };
-
-    /// Ipv4Addr structure
-    struct Ipv4Addr
-    {
-        Ipv4Address Address; ///< IP address
-        Ipv4Mask Mask;       ///< net mask
-    };
-
-    uint8_t m_priority;                    ///< priority
-    uint16_t m_index;                      ///< index
-    uint8_t m_tosLow;                      ///< TOS low
-    uint8_t m_tosHigh;                     ///< TOS high
-    uint8_t m_tosMask;                     ///< TOS mask
-    std::vector<uint8_t> m_protocol;       ///< protocol
-    std::vector<Ipv4Addr> m_srcAddr;       ///< source address
-    std::vector<Ipv4Addr> m_dstAddr;       ///< destination address
-    std::vector<PortRange> m_srcPortRange; ///< source port range
-    std::vector<PortRange> m_dstPortRange; ///< destination port range
-
-    uint16_t m_cid; ///< the CID
-};
-} // namespace ns3
-
-#endif /* IPCS_CLASSIFIER_RECORD_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/mac-messages.cc ns-3.46/src/wimax/model/mac-messages.cc
--- ns-3.45/src/wimax/model/mac-messages.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/mac-messages.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,848 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "mac-messages.h"
-
-#include "wimax-tlv.h"
-
-#include "ns3/address-utils.h"
-#include "ns3/log.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("MACMESSAGES");
-
-NS_OBJECT_ENSURE_REGISTERED(ManagementMessageType);
-
-ManagementMessageType::ManagementMessageType()
-    : m_type(~0)
-{
-}
-
-ManagementMessageType::ManagementMessageType(uint8_t type)
-    : m_type(type)
-{
-}
-
-ManagementMessageType::~ManagementMessageType()
-{
-}
-
-void
-ManagementMessageType::SetType(uint8_t type)
-{
-    m_type = type;
-}
-
-uint8_t
-ManagementMessageType::GetType() const
-{
-    return m_type;
-}
-
-std::string
-ManagementMessageType::GetName() const
-{
-    return "Management Message Type";
-}
-
-TypeId
-ManagementMessageType::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::ManagementMessageType")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<ManagementMessageType>();
-    return tid;
-}
-
-TypeId
-ManagementMessageType::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-ManagementMessageType::Print(std::ostream& os) const
-{
-    os << " management message type = " << (uint32_t)m_type;
-}
-
-uint32_t
-ManagementMessageType::GetSerializedSize() const
-{
-    return 1;
-}
-
-void
-ManagementMessageType::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_type);
-}
-
-uint32_t
-ManagementMessageType::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_type = i.ReadU8();
-    return i.GetDistanceFrom(start);
-}
-
-// ---------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(RngReq);
-
-RngReq::RngReq()
-    : m_reserved(0),
-      m_reqDlBurstProfile(0),
-      m_macAddress(Mac48Address("00:00:00:00:00:00")),
-      m_rangingAnomalies(0)
-{
-}
-
-RngReq::~RngReq()
-{
-}
-
-void
-RngReq::SetReqDlBurstProfile(uint8_t reqDlBurstProfile)
-{
-    m_reqDlBurstProfile = reqDlBurstProfile;
-}
-
-void
-RngReq::SetMacAddress(Mac48Address macAddress)
-{
-    m_macAddress = macAddress;
-}
-
-void
-RngReq::SetRangingAnomalies(uint8_t rangingAnomalies)
-{
-    m_rangingAnomalies = rangingAnomalies;
-}
-
-uint8_t
-RngReq::GetReqDlBurstProfile() const
-{
-    return m_reqDlBurstProfile;
-}
-
-Mac48Address
-RngReq::GetMacAddress() const
-{
-    return m_macAddress;
-}
-
-uint8_t
-RngReq::GetRangingAnomalies() const
-{
-    return m_rangingAnomalies;
-}
-
-std::string
-RngReq::GetName() const
-{
-    return "RNG-REQ";
-}
-
-TypeId
-RngReq::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::RngReq").SetParent<Header>().SetGroupName("Wimax").AddConstructor<RngReq>();
-    return tid;
-}
-
-TypeId
-RngReq::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-RngReq::Print(std::ostream& os) const
-{
-    os << " requested dl burst profile = " << (uint32_t)m_reqDlBurstProfile
-       << ", mac address = " << m_macAddress
-       << ", ranging anomalies = " << (uint32_t)m_rangingAnomalies;
-}
-
-void
-RngReq::PrintDebug() const
-{
-    NS_LOG_DEBUG(" requested dl burst profile = "
-                 << (uint32_t)m_reqDlBurstProfile << ", mac address = " << m_macAddress
-                 << ", ranging anomalies = " << (uint32_t)m_rangingAnomalies);
-}
-
-uint32_t
-RngReq::GetSerializedSize() const
-{
-    return 1 + 1 + 6 + 1;
-}
-
-void
-RngReq::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_reserved);
-    i.WriteU8(m_reqDlBurstProfile);
-    WriteTo(i, m_macAddress);
-    i.WriteU8(m_rangingAnomalies);
-}
-
-uint32_t
-RngReq::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_reserved = i.ReadU8();
-    m_reqDlBurstProfile = i.ReadU8();
-    ReadFrom(i, m_macAddress);
-    m_rangingAnomalies = i.ReadU8();
-
-    return i.GetDistanceFrom(start);
-}
-
-// ---------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(RngRsp);
-
-RngRsp::RngRsp()
-    : m_reserved(0),
-      m_timingAdjust(0),
-      m_powerLevelAdjust(0),
-      m_offsetFreqAdjust(0),
-      m_rangStatus(0),
-      m_dlFreqOverride(0),
-      m_ulChnlIdOverride(0),
-      m_dlOperBurstProfile(0),
-      m_macAddress(Mac48Address("00:00:00:00:00:00")),
-      m_basicCid(),
-      m_primaryCid(),
-      m_aasBdcastPermission(0),
-      m_frameNumber(0),
-      m_initRangOppNumber(0),
-      m_rangSubchnl(0)
-{
-}
-
-RngRsp::~RngRsp()
-{
-}
-
-void
-RngRsp::SetTimingAdjust(uint32_t timingAdjust)
-{
-    m_timingAdjust = timingAdjust;
-}
-
-void
-RngRsp::SetPowerLevelAdjust(uint8_t powerLevelAdjust)
-{
-    m_powerLevelAdjust = powerLevelAdjust;
-}
-
-void
-RngRsp::SetOffsetFreqAdjust(uint32_t offsetFreqAdjust)
-{
-    m_offsetFreqAdjust = offsetFreqAdjust;
-}
-
-void
-RngRsp::SetRangStatus(uint8_t rangStatus)
-{
-    m_rangStatus = rangStatus;
-}
-
-void
-RngRsp::SetDlFreqOverride(uint32_t dlFreqOverride)
-{
-    m_dlFreqOverride = dlFreqOverride;
-}
-
-void
-RngRsp::SetUlChnlIdOverride(uint8_t ulChnlIdOverride)
-{
-    m_ulChnlIdOverride = ulChnlIdOverride;
-}
-
-void
-RngRsp::SetDlOperBurstProfile(uint16_t dlOperBurstProfile)
-{
-    m_dlOperBurstProfile = dlOperBurstProfile;
-}
-
-void
-RngRsp::SetMacAddress(Mac48Address macAddress)
-{
-    m_macAddress = macAddress;
-}
-
-void
-RngRsp::SetBasicCid(Cid basicCid)
-{
-    m_basicCid = basicCid;
-}
-
-void
-RngRsp::SetPrimaryCid(Cid primaryCid)
-{
-    m_primaryCid = primaryCid;
-}
-
-void
-RngRsp::SetAasBdcastPermission(uint8_t aasBdcastPermission)
-{
-    m_aasBdcastPermission = aasBdcastPermission;
-}
-
-void
-RngRsp::SetFrameNumber(uint32_t frameNumber)
-{
-    m_frameNumber = frameNumber;
-}
-
-void
-RngRsp::SetInitRangOppNumber(uint8_t initRangOppNumber)
-{
-    m_initRangOppNumber = initRangOppNumber;
-}
-
-void
-RngRsp::SetRangSubchnl(uint8_t rangSubchnl)
-{
-    m_rangSubchnl = rangSubchnl;
-}
-
-uint32_t
-RngRsp::GetTimingAdjust() const
-{
-    return m_timingAdjust;
-}
-
-uint8_t
-RngRsp::GetPowerLevelAdjust() const
-{
-    return m_powerLevelAdjust;
-}
-
-uint32_t
-RngRsp::GetOffsetFreqAdjust() const
-{
-    return m_offsetFreqAdjust;
-}
-
-uint8_t
-RngRsp::GetRangStatus() const
-{
-    return m_rangStatus;
-}
-
-uint32_t
-RngRsp::GetDlFreqOverride() const
-{
-    return m_dlFreqOverride;
-}
-
-uint8_t
-RngRsp::GetUlChnlIdOverride() const
-{
-    return m_ulChnlIdOverride;
-}
-
-uint16_t
-RngRsp::GetDlOperBurstProfile() const
-{
-    return m_dlOperBurstProfile;
-}
-
-Mac48Address
-RngRsp::GetMacAddress() const
-{
-    return m_macAddress;
-}
-
-Cid
-RngRsp::GetBasicCid() const
-{
-    return m_basicCid;
-}
-
-Cid
-RngRsp::GetPrimaryCid() const
-{
-    return m_primaryCid;
-}
-
-uint8_t
-RngRsp::GetAasBdcastPermission() const
-{
-    return m_aasBdcastPermission;
-}
-
-uint32_t
-RngRsp::GetFrameNumber() const
-{
-    return m_frameNumber;
-}
-
-uint8_t
-RngRsp::GetInitRangOppNumber() const
-{
-    return m_initRangOppNumber;
-}
-
-uint8_t
-RngRsp::GetRangSubchnl() const
-{
-    return m_rangSubchnl;
-}
-
-std::string
-RngRsp::GetName() const
-{
-    return "RNG-RSP";
-}
-
-TypeId
-RngRsp::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::RngRsp").SetParent<Header>().SetGroupName("Wimax").AddConstructor<RngRsp>();
-    return tid;
-}
-
-TypeId
-RngRsp::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-RngRsp::Print(std::ostream& os) const
-{
-    os << " timing adjust = " << m_timingAdjust
-       << ", power level adjust = " << (uint32_t)m_powerLevelAdjust
-       << ", offset freq adjust = " << m_offsetFreqAdjust
-       << ", ranging status = " << (uint32_t)m_rangStatus
-       << ", dl freq override = " << m_dlFreqOverride
-       << ", ul channel id override = " << (uint32_t)m_ulChnlIdOverride
-       << ", dl operational burst profile = " << (uint32_t)m_dlOperBurstProfile
-       << ", mac address = " << m_macAddress << ", basic cid = " << m_basicCid
-       << ", primary management cid = " << m_primaryCid
-       << ", aas broadcast permission = " << (uint32_t)m_aasBdcastPermission
-       << ", frame number = " << m_frameNumber
-       << ", initial ranging opportunity number = " << (uint32_t)m_initRangOppNumber
-       << ", ranging subchannel = " << (uint32_t)m_rangSubchnl;
-}
-
-uint32_t
-RngRsp::GetSerializedSize() const
-{
-    return 1 + 4 + 1 + 4 + 1 + 4 + 1 + 2 + 6 + 2 + 2 + 1 + 4 + 1 + 1;
-}
-
-void
-RngRsp::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_reserved);
-    i.WriteU32(m_timingAdjust);
-    i.WriteU8(m_powerLevelAdjust);
-    i.WriteU32(m_offsetFreqAdjust);
-    i.WriteU8(m_rangStatus);
-    i.WriteU32(m_dlFreqOverride);
-    i.WriteU8(m_ulChnlIdOverride);
-    i.WriteU16(m_dlOperBurstProfile);
-    WriteTo(i, m_macAddress);
-    i.WriteU16(m_basicCid.GetIdentifier());
-    i.WriteU16(m_primaryCid.GetIdentifier());
-    i.WriteU8(m_aasBdcastPermission);
-    i.WriteU32(m_frameNumber);
-    i.WriteU8(m_initRangOppNumber);
-    i.WriteU8(m_rangSubchnl);
-}
-
-uint32_t
-RngRsp::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_reserved = i.ReadU8();
-    m_timingAdjust = i.ReadU32();
-    m_powerLevelAdjust = i.ReadU8();
-    m_offsetFreqAdjust = i.ReadU32();
-    m_rangStatus = i.ReadU8();
-    m_dlFreqOverride = i.ReadU32();
-    m_ulChnlIdOverride = i.ReadU8();
-    m_dlOperBurstProfile = i.ReadU16();
-    ReadFrom(i, m_macAddress); // length (6) shall also be written in packet instead of hard coded,
-                               // see ARP example
-    m_basicCid = i.ReadU16();
-    m_primaryCid = i.ReadU16();
-    m_aasBdcastPermission = i.ReadU8();
-    m_frameNumber = i.ReadU32();
-    m_initRangOppNumber = i.ReadU8();
-    m_rangSubchnl = i.ReadU8();
-
-    return i.GetDistanceFrom(start);
-}
-
-// ---------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(DsaReq);
-
-DsaReq::DsaReq()
-    : m_transactionId(0),
-      m_sfid(0),
-      m_cid(),
-      m_serviceFlow(ServiceFlow::SF_DIRECTION_DOWN)
-{
-}
-
-DsaReq::DsaReq(ServiceFlow sf)
-{
-    m_transactionId = 0;
-    m_serviceFlow = sf;
-}
-
-DsaReq::~DsaReq()
-{
-}
-
-void
-DsaReq::SetTransactionId(uint16_t transactionId)
-{
-    m_transactionId = transactionId;
-}
-
-uint16_t
-DsaReq::GetTransactionId() const
-{
-    return m_transactionId;
-}
-
-void
-DsaReq::SetSfid(uint32_t sfid)
-{
-    m_sfid = sfid;
-}
-
-uint32_t
-DsaReq::GetSfid() const
-{
-    return m_sfid;
-}
-
-void
-DsaReq::SetCid(Cid cid)
-{
-    m_cid = cid;
-}
-
-Cid
-DsaReq::GetCid() const
-{
-    return m_cid;
-}
-
-std::string
-DsaReq::GetName() const
-{
-    return "DSA-REQ";
-}
-
-TypeId
-DsaReq::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::DsaReq").SetParent<Header>().SetGroupName("Wimax").AddConstructor<DsaReq>();
-    return tid;
-}
-
-TypeId
-DsaReq::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-DsaReq::Print(std::ostream& os) const
-{
-    os << " transaction id = " << (uint32_t)m_transactionId << ", m_sfid = " << m_sfid
-       << ", cid = " << m_cid;
-}
-
-uint32_t
-DsaReq::GetSerializedSize() const
-{
-    Tlv t = m_serviceFlow.ToTlv();
-    uint32_t size = 2 + t.GetSerializedSize();
-    return size;
-}
-
-void
-DsaReq::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU16(m_transactionId);
-    Tlv t = m_serviceFlow.ToTlv();
-    t.Serialize(i);
-}
-
-uint32_t
-DsaReq::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_transactionId = i.ReadU16();
-    Tlv tlv;
-    uint32_t size = tlv.Deserialize(i);
-    m_serviceFlow = ServiceFlow(tlv);
-    return size + 2;
-}
-
-ServiceFlow
-DsaReq::GetServiceFlow() const
-{
-    return m_serviceFlow;
-}
-
-void
-DsaReq::SetServiceFlow(ServiceFlow sf)
-{
-    m_serviceFlow = sf;
-}
-
-// ---------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(DsaRsp);
-
-DsaRsp::DsaRsp()
-    : m_transactionId(0),
-      m_confirmationCode(0),
-      m_sfid(0),
-      m_cid()
-{
-}
-
-DsaRsp::~DsaRsp()
-{
-}
-
-void
-DsaRsp::SetTransactionId(uint16_t transactionId)
-{
-    m_transactionId = transactionId;
-}
-
-uint16_t
-DsaRsp::GetTransactionId() const
-{
-    return m_transactionId;
-}
-
-ServiceFlow
-DsaRsp::GetServiceFlow() const
-{
-    return m_serviceFlow;
-}
-
-void
-DsaRsp::SetServiceFlow(ServiceFlow sf)
-{
-    m_serviceFlow = sf;
-}
-
-void
-DsaRsp::SetConfirmationCode(uint16_t confirmationCode)
-{
-    m_confirmationCode = confirmationCode;
-}
-
-uint16_t
-DsaRsp::GetConfirmationCode() const
-{
-    return m_confirmationCode;
-}
-
-void
-DsaRsp::SetSfid(uint32_t sfid)
-{
-    m_sfid = sfid;
-}
-
-uint32_t
-DsaRsp::GetSfid() const
-{
-    return m_sfid;
-}
-
-void
-DsaRsp::SetCid(Cid cid)
-{
-    m_cid = cid;
-}
-
-Cid
-DsaRsp::GetCid() const
-{
-    return m_cid;
-}
-
-std::string
-DsaRsp::GetName() const
-{
-    return "DSA-RSP";
-}
-
-TypeId
-DsaRsp::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::DsaRsp").SetParent<Header>().SetGroupName("Wimax").AddConstructor<DsaRsp>();
-    return tid;
-}
-
-TypeId
-DsaRsp::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-DsaRsp::Print(std::ostream& os) const
-{
-    os << " transaction id = " << (uint32_t)m_transactionId
-       << ", confirmation code = " << (uint32_t)m_confirmationCode << ", m_sfid = " << m_sfid
-       << ", cid = " << m_cid;
-}
-
-uint32_t
-DsaRsp::GetSerializedSize() const
-{
-    return 2 + 1 + m_serviceFlow.ToTlv().GetSerializedSize();
-}
-
-void
-DsaRsp::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-
-    i.WriteU16(m_transactionId);
-    i.WriteU8(m_confirmationCode);
-    m_serviceFlow.ToTlv().Serialize(i);
-}
-
-uint32_t
-DsaRsp::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-
-    m_transactionId = i.ReadU16();
-    m_confirmationCode = i.ReadU8();
-    Tlv tlv;
-    uint32_t size = tlv.Deserialize(i);
-    m_serviceFlow = ServiceFlow(tlv);
-    return size + 3;
-}
-
-// ---------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(DsaAck);
-
-DsaAck::DsaAck()
-    : m_transactionId(0),
-      m_confirmationCode(0)
-{
-}
-
-DsaAck::~DsaAck()
-{
-}
-
-void
-DsaAck::SetTransactionId(uint16_t transactionId)
-{
-    m_transactionId = transactionId;
-}
-
-uint16_t
-DsaAck::GetTransactionId() const
-{
-    return m_transactionId;
-}
-
-void
-DsaAck::SetConfirmationCode(uint16_t confirmationCode)
-{
-    m_confirmationCode = confirmationCode;
-}
-
-uint16_t
-DsaAck::GetConfirmationCode() const
-{
-    return m_confirmationCode;
-}
-
-std::string
-DsaAck::GetName() const
-{
-    return "DSA-ACK";
-}
-
-TypeId
-DsaAck::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::DsaAck").SetParent<Header>().SetGroupName("Wimax").AddConstructor<DsaAck>();
-    return tid;
-}
-
-TypeId
-DsaAck::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-DsaAck::Print(std::ostream& os) const
-{
-    os << " transaction id = " << (uint32_t)m_transactionId
-       << ", confirmation code = " << (uint32_t)m_confirmationCode;
-}
-
-uint32_t
-DsaAck::GetSerializedSize() const
-{
-    return 2 + 1;
-}
-
-void
-DsaAck::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU16(m_transactionId);
-    i.WriteU8(m_confirmationCode);
-}
-
-uint32_t
-DsaAck::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_transactionId = i.ReadU16();
-    m_confirmationCode = i.ReadU8();
-
-    return i.GetDistanceFrom(start);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/mac-messages.h ns-3.46/src/wimax/model/mac-messages.h
--- ns-3.45/src/wimax/model/mac-messages.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/mac-messages.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,718 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-/*
- *This file does not contain all MAC messages, the rest of MAC messages have
- *This been categorized as DL and UL messages and are placed in
- *This dl-mac-messages.h and ul-mac-messages.h files.
- */
-
-#ifndef MANAGEMENT_MESSAGE_TYPE_H
-#define MANAGEMENT_MESSAGE_TYPE_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * Mac Management messages
- * Section 6.3.2.3 MAC Management messages page 42, Table 14 page 43
- */
-class ManagementMessageType : public Header
-{
-  public:
-    /// Message type enumeration
-    enum MessageType
-    {
-        MESSAGE_TYPE_UCD = 0,
-        MESSAGE_TYPE_DCD = 1,
-        MESSAGE_TYPE_DL_MAP = 2,
-        MESSAGE_TYPE_UL_MAP = 3,
-        MESSAGE_TYPE_RNG_REQ = 4,
-        MESSAGE_TYPE_RNG_RSP = 5,
-        MESSAGE_TYPE_REG_REQ = 6,
-        MESSAGE_TYPE_REG_RSP = 7,
-        MESSAGE_TYPE_DSA_REQ = 11,
-        MESSAGE_TYPE_DSA_RSP = 12,
-        MESSAGE_TYPE_DSA_ACK = 13
-    };
-
-    ManagementMessageType();
-    /**
-     * Constructor
-     *
-     * @param type message type
-     */
-    ManagementMessageType(uint8_t type);
-    ~ManagementMessageType() override;
-    /**
-     * Set type field
-     * @param type the type
-     */
-    void SetType(uint8_t type);
-    /**
-     * Get type field
-     * @returns the type value
-     */
-    uint8_t GetType() const;
-
-    /** @returns the name field */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_type; ///< type
-};
-
-} // namespace ns3
-
-#endif /* MANAGEMENT_MESSAGE_TYPE_H */
-
-// ---------------------------------------------------------------------
-
-#ifndef RNG_RSP_H
-#define RNG_RSP_H
-
-#include "cid.h"
-#include "service-flow.h"
-
-#include "ns3/header.h"
-#include "ns3/mac48-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the ranging response message described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.6 Ranging response (RNG-RSP) message, page 50
- */
-class RngRsp : public Header
-{
-  public:
-    RngRsp();
-    ~RngRsp() override;
-    /**
-     * @brief set the  Tx timing offset adjustment (signed 32-bit).
-     * @param timingAdjust The time required to advance SS transmission so frames
-     * arrive at the expected time instance at the BS.
-     */
-    void SetTimingAdjust(uint32_t timingAdjust);
-    /**
-     * @brief set the relative change in transmission power level that the SS should make in order
-     * that transmissions arrive at the BS at the desired power. When subchannelization is employed,
-     * the subscriber shall interpret the power offset adjustment as a required change to the
-     * transmitted power density.
-     * @param powerLevelAdjust the relative change in transmission power level
-     */
-    void SetPowerLevelAdjust(uint8_t powerLevelAdjust);
-    /**
-     * @brief set the relative change in transmission frequency that the SS should take in order to
-     * better match the BS. This is fine-frequency adjustment within a channel, not reassignment to
-     * a different channel
-     * @param offsetFreqAdjust Offset frequency adjustment
-     */
-    void SetOffsetFreqAdjust(uint32_t offsetFreqAdjust);
-    /**
-     * @brief set the range status.
-     * @param rangStatus Range status
-     */
-    void SetRangStatus(uint8_t rangStatus);
-    /**
-     * @brief set the Center frequency, in kHz, of new downlink channel where the SS should redo
-     * initial ranging.
-     * @param dlFreqOverride the Center frequency in kHz
-     */
-    void SetDlFreqOverride(uint32_t dlFreqOverride);
-    /**
-     * @brief set the identifier of the uplink channel with which the SS is to redo initial ranging
-     * @param ulChnlIdOverride the uplink channel index
-     */
-    void SetUlChnlIdOverride(uint8_t ulChnlIdOverride);
-    /**
-     * @brief set the DL oper burst profile
-     * @param dlOperBurstProfile the oper burt profile
-     */
-    void SetDlOperBurstProfile(uint16_t dlOperBurstProfile);
-    /**
-     * @brief set the MAC address
-     * @param macAddress the MAC address
-     */
-    void SetMacAddress(Mac48Address macAddress);
-
-    /**
-     * @brief set basic CID.
-     * @param basicCid Basic CID
-     */
-    void SetBasicCid(Cid basicCid);
-    /**
-     * @brief set primary CID.
-     * @param primaryCid Primary CID
-     */
-    void SetPrimaryCid(Cid primaryCid);
-
-    /**
-     * @brief set AAS broadcast permission.
-     * @param aasBdcastPermission AAS broadcast permission
-     */
-    void SetAasBdcastPermission(uint8_t aasBdcastPermission);
-    /**
-     * @brief set frame number.
-     * @param frameNumber Frame number
-     */
-    void SetFrameNumber(uint32_t frameNumber);
-    /**
-     * @brief set initial range opp number.
-     * @param initRangOppNumber Initial range opp number
-     */
-    void SetInitRangOppNumber(uint8_t initRangOppNumber);
-    /**
-     * @brief set range sub channel.
-     * @param rangSubchnl Range subchannel
-     */
-    void SetRangSubchnl(uint8_t rangSubchnl);
-    /**
-     * @return Tx timing offset adjustment (signed 32-bit). The time required to advance SS
-     * transmission so frames arrive at the expected time instance at the BS.
-     */
-    uint32_t GetTimingAdjust() const;
-    /**
-     * @return the relative change in transmission power level that the SS should take in order
-     * that transmissions arrive at the BS at the desired power. When subchannelization is employed,
-     * the subscriber shall interpret the power offset adjustment as a required change to the
-     * transmitted power density.
-     */
-    uint8_t GetPowerLevelAdjust() const;
-    /**
-     * @return the relative change in transmission frequency that the SS should take in order to
-     * better match the BS. This is fine-frequency adjustment within a channel, not reassignment to
-     * a different channel.
-     */
-    uint32_t GetOffsetFreqAdjust() const;
-    /**
-     * @return the range status.
-     */
-    uint8_t GetRangStatus() const;
-    /**
-     * @return Center frequency, in kHz, of new downlink channel where the SS should redo initial
-     * ranging.
-     */
-    uint32_t GetDlFreqOverride() const;
-    /**
-     * @return The identifier of the uplink channel with which the SS is to redo initial ranging
-     */
-    uint8_t GetUlChnlIdOverride() const;
-    /**
-     * @return DlOperBurstProfile: This parameter is sent in response to the RNG-REQ Requested
-     * Downlink Burst Profile parameter
-     */
-    uint16_t GetDlOperBurstProfile() const;
-    /**
-     * @return MAC address
-     */
-    Mac48Address GetMacAddress() const;
-    /**
-     * @return basic CID
-     */
-    Cid GetBasicCid() const;
-    /**
-     * @return primary CID
-     */
-    Cid GetPrimaryCid() const;
-    /**
-     * @return AAS broadcast permission
-     */
-    uint8_t GetAasBdcastPermission() const;
-    /**
-     * @return frame number
-     */
-    uint32_t GetFrameNumber() const;
-    /**
-     * @return initial range opp number
-     */
-    uint8_t GetInitRangOppNumber() const;
-    /**
-     * @return range sub channel
-     */
-    uint8_t GetRangSubchnl() const;
-
-    /**
-     * @return name string
-     */
-    std::string GetName() const;
-    /**
-     * Register this type.
-     * @return The TypeId.
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_reserved; ///< changed as per the amendment 802.16e-2005
-
-    // TLV Encoded Information
-
-    /**
-     * Tx timing offset adjustment (signed 32-bit). The time required to advance SS transmission so
-     * frames arrive at the expected time instance at the BS.
-     */
-    uint32_t m_timingAdjust;
-
-    /**
-     * Specifies the relative change in transmission power level that the SS is to make in order
-     * that transmissions arrive at the BS at the desired power. When subchannelization is employed,
-     * the subscriber shall interpret the power offset adjustment as a required change to the
-     * transmitted power density.
-     */
-    uint8_t m_powerLevelAdjust;
-
-    /**
-     * Specifies the relative change in transmission frequency that the SS is to make in order to
-     * better match the BS. This is fine-frequency adjustment within a channel, not reassignment to
-     * a different channel.
-     */
-    uint32_t m_offsetFreqAdjust;
-
-    /**
-     * range status.
-     */
-    uint8_t m_rangStatus;
-
-    /// Center frequency, in kHz, of new downlink channel where the SS should redo initial ranging.
-    uint32_t m_dlFreqOverride;
-
-    /**
-     * Licensed bands: The identifier of the uplink channel with which the SS is to redo initial
-     * ranging (not used with PHYs without channelized uplinks).
-     */
-    uint8_t m_ulChnlIdOverride;
-
-    /**
-     * This parameter is sent in response to the RNG-REQ Requested Downlink Burst Profile parameter.
-     * Byte 0: Specifies the least robust DIUC that may be used by the BS for transmissions to the
-     * SS. Byte 1: Configuration Change Count value of DCD defining the burst profile associated
-     * with DIUC.
-     */
-    uint16_t m_dlOperBurstProfile;
-
-    Mac48Address m_macAddress;     ///< MAC address
-    Cid m_basicCid;                ///< basic CID
-    Cid m_primaryCid;              ///< primary CID
-    uint8_t m_aasBdcastPermission; ///< AAS broadcast permission
-
-    /**
-     * Frame number where the associated RNG_REQ message was detected by the BS. Usage is mutually
-     * exclusive with SS MAC Address
-     */
-    uint32_t m_frameNumber;
-
-    /**
-     * Initial Ranging opportunity (1–255) in which the associated RNG_REQ message was detected by
-     * the BS. Usage is mutually exclusive with SS MAC Address
-     */
-    uint8_t m_initRangOppNumber;
-
-    /**
-     * Used to indicate the OFDM subchannel reference that was used to transmit the initial ranging
-     * message (OFDM with subchannelization).
-     */
-    uint8_t m_rangSubchnl;
-};
-
-} // namespace ns3
-
-#endif /* RNG_RSP_H */
-
-// ---------------------------------------------------------------------
-
-#ifndef DSA_REQ_H
-#define DSA_REQ_H
-
-#include "cid.h"
-#include "service-flow.h"
-
-#include "ns3/buffer.h"
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-/**
- * @ingroup wimax
- * This class implements the DSA-REQ message described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.10 DSA-REQ message, page 62
- */
-class DsaReq : public Header
-{
-  public:
-    DsaReq();
-    ~DsaReq() override;
-    /**
-     * Constructor
-     *
-     * @param sf service flow
-     */
-    DsaReq(ServiceFlow sf);
-    /**
-     * @brief set the transaction ID
-     * @param transactionId
-     */
-    void SetTransactionId(uint16_t transactionId);
-    /**
-     * @brief set the service flow identifier
-     * @param sfid the service flow identifier
-     */
-    void SetSfid(uint32_t sfid);
-    /**
-     * @brief set the connection identifier
-     * @param cid the connection identifier
-     */
-    void SetCid(Cid cid);
-    /**
-     * @brief specify a service flow to be requested by this message
-     * @param sf the service flow
-     */
-    void SetServiceFlow(ServiceFlow sf);
-    /**
-     * @return the service flow requested by this message
-     */
-    ServiceFlow GetServiceFlow() const;
-    /**
-     * @return the transaction ID
-     */
-    uint16_t GetTransactionId() const;
-    /**
-     * @return the service flow identifier
-     */
-    uint32_t GetSfid() const;
-    /**
-     * @return the connection identifier
-     */
-    Cid GetCid() const;
-    /**
-     * @return the service name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint16_t m_transactionId; ///< transaction ID
-    // TLV Encoded Information
-    uint32_t m_sfid;           ///< SFID
-    Cid m_cid;                 ///< CID
-    ServiceFlow m_serviceFlow; ///< service flow
-};
-
-} // namespace ns3
-
-#endif /* DSA_REQ_H */
-
-// ---------------------------------------------------------------------
-
-#ifndef DSA_RSP_H
-#define DSA_RSP_H
-
-#include "cid.h"
-
-#include "ns3/buffer.h"
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the DSA-RSP message described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.11 DSA-RSP message, page 63
- * @verbatim
-   0             7             15            23
-   +-------------+-------------+-------------+
-   |Mngt msg type|       Transaction ID      |
-   +-------------+-------------+-------------+
-   | Conf Code   | Service Flow TLV          |
-   +~~~~~~~~~~~~~+~~~~~~~~~~~~~+~~~~~~~~~~~~~+
-   \endverbatim
- */
-class DsaRsp : public Header
-{
-  public:
-    DsaRsp();
-    ~DsaRsp() override;
-
-    /**
-     * @brief set the transaction ID
-     * @param transactionId
-     */
-    void SetTransactionId(uint16_t transactionId);
-    /**
-     * @return the transaction ID
-     */
-    uint16_t GetTransactionId() const;
-
-    /**
-     * @brief set the confirmation code
-     * @param confirmationCode
-     */
-    void SetConfirmationCode(uint16_t confirmationCode);
-    /**
-     * @return the confirmation code
-     */
-    uint16_t GetConfirmationCode() const;
-    /**
-     * @brief set the service flow identifier
-     * @param sfid the service flow identifier
-     */
-    void SetSfid(uint32_t sfid);
-    /**
-     * @return the service flow identifier
-     */
-    uint32_t GetSfid() const;
-    /**
-     * @brief set the connection identifier
-     * @param cid the connection identifier
-     */
-    void SetCid(Cid cid);
-    /**
-     * @return the connection identifier
-     */
-    Cid GetCid() const;
-    /**
-     * @brief specify a service flow to be requested by this message
-     * @param sf the service flow
-     */
-    void SetServiceFlow(ServiceFlow sf);
-    /**
-     * @return the service flow requested by this message
-     */
-    ServiceFlow GetServiceFlow() const;
-
-    /**
-     * @return the service name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint16_t m_transactionId;   ///< transaction ID
-    uint8_t m_confirmationCode; ///< confirmation code
-    // TLV Encoded Information
-    ServiceFlow m_serviceFlow; ///< service flow
-    uint32_t m_sfid;           ///< SFID
-    Cid m_cid;                 ///< CID
-};
-
-} // namespace ns3
-
-#endif /* DSA_RSP_H */
-
-// ---------------------------------------------------------------------
-
-#ifndef DSA_ACK_H
-#define DSA_ACK_H
-
-#include "ns3/buffer.h"
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the DSA-ACK message described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.12 DSA-ACK message, page 64
- */
-class DsaAck : public Header
-{
-  public:
-    DsaAck();
-    ~DsaAck() override;
-
-    /**
-     * Set transaction ID field
-     * @param transactionId the transaction ID
-     */
-    void SetTransactionId(uint16_t transactionId);
-    /**
-     * Get transaction ID field
-     * @returns the transaction ID
-     */
-    uint16_t GetTransactionId() const;
-
-    /**
-     * Set confirmation code field
-     * @param confirmationCode the confirmation code
-     */
-    void SetConfirmationCode(uint16_t confirmationCode);
-    /**
-     * Get confirmation code field
-     * @returns the confirmation code
-     */
-    uint16_t GetConfirmationCode() const;
-
-    /**
-     * Get name field
-     * @return the name string
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint16_t m_transactionId;   ///< transaction ID
-    uint8_t m_confirmationCode; ///< confirmation code
-};
-
-} // namespace ns3
-
-#endif /* DSA_ACK_H */
-
-// ---------------------------------------------------------------------
-
-#ifndef RNG_REQ_H
-#define RNG_REQ_H
-
-#include "service-flow.h"
-
-#include "ns3/header.h"
-#include "ns3/mac48-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the ranging request message described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems"
- */
-class RngReq : public Header
-{
-  public:
-    RngReq();
-    ~RngReq() override;
-
-    /**
-     * Set request DL burst profile field
-     * @param reqDlBurstProfile the request DL burst profile
-     */
-    void SetReqDlBurstProfile(uint8_t reqDlBurstProfile);
-    /**
-     * Set MAC address field
-     * @param macAddress the MAC address
-     */
-    void SetMacAddress(Mac48Address macAddress);
-    /**
-     * Set ranging anomalies field
-     * @param rangingAnomalies the rnaging anomalies
-     */
-    void SetRangingAnomalies(uint8_t rangingAnomalies);
-
-    /**
-     * Get request DL burst profile field
-     * @returns the request DL burst profile
-     */
-    uint8_t GetReqDlBurstProfile() const;
-    /**
-     * Get MAC address field
-     * @returns the MAC address
-     */
-    Mac48Address GetMacAddress() const;
-    /**
-     * Get ranging anomalies field
-     * @returns the ranging anomalies
-     */
-    uint8_t GetRangingAnomalies() const;
-
-    /**
-     * @brief Get name field
-     * @returns the name string
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    /// Print debug function
-    void PrintDebug() const;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_reserved; ///< changed as per the amendment 802.16e-2005
-
-    // TLV Encoded Information
-    uint8_t m_reqDlBurstProfile; ///< request DL burst profile
-    Mac48Address m_macAddress;   ///< MAC address
-    uint8_t m_rangingAnomalies;  ///< ranging anomalies
-};
-
-} // namespace ns3
-
-#endif /* RNG_REQ_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ofdm-downlink-frame-prefix.cc ns-3.46/src/wimax/model/ofdm-downlink-frame-prefix.cc
--- ns-3.45/src/wimax/model/ofdm-downlink-frame-prefix.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ofdm-downlink-frame-prefix.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "ofdm-downlink-frame-prefix.h"
-
-#include "ns3/address-utils.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-DlFramePrefixIe::DlFramePrefixIe()
-    : m_rateId(0),
-      m_diuc(0),
-      m_preamblePresent(0),
-      m_length(0),
-      m_startTime(0)
-{
-}
-
-DlFramePrefixIe::~DlFramePrefixIe()
-{
-}
-
-void
-DlFramePrefixIe::SetRateId(uint8_t rateId)
-{
-    m_rateId = rateId;
-}
-
-void
-DlFramePrefixIe::SetDiuc(uint8_t diuc)
-{
-    m_diuc = diuc;
-}
-
-void
-DlFramePrefixIe::SetPreamblePresent(uint8_t preamblePresent)
-{
-    m_preamblePresent = preamblePresent;
-}
-
-void
-DlFramePrefixIe::SetLength(uint16_t length)
-{
-    m_length = length;
-}
-
-void
-DlFramePrefixIe::SetStartTime(uint16_t startTime)
-{
-    m_startTime = startTime;
-}
-
-uint8_t
-DlFramePrefixIe::GetRateId() const
-{
-    return m_rateId;
-}
-
-uint8_t
-DlFramePrefixIe::GetDiuc() const
-{
-    return m_diuc;
-}
-
-uint8_t
-DlFramePrefixIe::GetPreamblePresent() const
-{
-    return m_preamblePresent;
-}
-
-uint16_t
-DlFramePrefixIe::GetLength() const
-{
-    return m_length;
-}
-
-uint16_t
-DlFramePrefixIe::GetStartTime() const
-{
-    return m_startTime;
-}
-
-uint16_t
-DlFramePrefixIe::GetSize() const
-{
-    return 1 + 1 + 1 + 2 + 2;
-}
-
-Buffer::Iterator
-DlFramePrefixIe::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_rateId);
-    i.WriteU8(m_diuc);
-    i.WriteU8(m_preamblePresent);
-    i.WriteU16(m_length);
-    i.WriteU16(m_startTime);
-    return i;
-}
-
-Buffer::Iterator
-DlFramePrefixIe::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_rateId = i.ReadU8();
-    m_diuc = i.ReadU8();
-    m_preamblePresent = i.ReadU8();
-    m_length = i.ReadU16();
-    m_startTime = i.ReadU16();
-    return i;
-}
-
-OfdmDownlinkFramePrefix::OfdmDownlinkFramePrefix()
-    : m_baseStationId(Mac48Address("00:00:00:00:00:00")),
-      m_frameNumber(0),
-      m_configurationChangeCount(0),
-      m_hcs(0)
-{
-}
-
-OfdmDownlinkFramePrefix::~OfdmDownlinkFramePrefix()
-{
-}
-
-/* static */
-TypeId
-OfdmDownlinkFramePrefix::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::OfdmDownlinkFramePrefix").SetParent<Header>().SetGroupName("Wimax")
-        // No AddConstructor because this is an abstract class.
-        ;
-    return tid;
-}
-
-void
-OfdmDownlinkFramePrefix::SetBaseStationId(Mac48Address baseStationId)
-{
-    m_baseStationId = baseStationId;
-}
-
-void
-OfdmDownlinkFramePrefix::SetFrameNumber(uint32_t frameNumber)
-{
-    m_frameNumber = frameNumber;
-}
-
-void
-OfdmDownlinkFramePrefix::SetConfigurationChangeCount(uint8_t configurationChangeCount)
-{
-    m_configurationChangeCount = configurationChangeCount;
-}
-
-void
-OfdmDownlinkFramePrefix::AddDlFramePrefixElement(DlFramePrefixIe dlFramePrefixElement)
-{
-    m_dlFramePrefixElements.push_back(dlFramePrefixElement);
-}
-
-void
-OfdmDownlinkFramePrefix::SetHcs(uint8_t hcs)
-{
-    m_hcs = hcs;
-}
-
-Mac48Address
-OfdmDownlinkFramePrefix::GetBaseStationId() const
-{
-    return m_baseStationId;
-}
-
-uint32_t
-OfdmDownlinkFramePrefix::GetFrameNumber() const
-{
-    return m_frameNumber;
-}
-
-uint8_t
-OfdmDownlinkFramePrefix::GetConfigurationChangeCount() const
-{
-    return m_configurationChangeCount;
-}
-
-std::vector<DlFramePrefixIe>
-OfdmDownlinkFramePrefix::GetDlFramePrefixElements() const
-{
-    return m_dlFramePrefixElements;
-}
-
-uint8_t
-OfdmDownlinkFramePrefix::GetHcs() const
-{
-    return m_hcs;
-}
-
-std::string
-OfdmDownlinkFramePrefix::GetName() const
-{
-    return "OFDM Downlink Frame Prefix";
-}
-
-void
-OfdmDownlinkFramePrefix::Print(std::ostream& os) const
-{
-    os << " base station id = " << m_baseStationId << ", frame number = " << m_frameNumber
-       << ", configuration change count = " << (uint32_t)m_configurationChangeCount
-       << ", number of dl frame prefix elements = " << m_dlFramePrefixElements.size()
-       << ", hcs = " << (uint32_t)m_hcs;
-}
-
-uint32_t
-OfdmDownlinkFramePrefix::GetSerializedSize() const
-{
-    int dlFramePrefixElementsSize = 0;
-
-    for (const auto& dlFramePrefixElement : m_dlFramePrefixElements)
-    {
-        dlFramePrefixElementsSize += dlFramePrefixElement.GetSize();
-    }
-
-    return 6 + 4 + 1 + dlFramePrefixElementsSize + 1;
-}
-
-void
-OfdmDownlinkFramePrefix::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    WriteTo(i, m_baseStationId);
-    i.WriteU32(m_frameNumber);
-    i.WriteU8(m_configurationChangeCount);
-
-    for (const auto& dlFramePrefixElement : m_dlFramePrefixElements)
-    {
-        i = dlFramePrefixElement.Write(i);
-    }
-
-    i.WriteU8(m_hcs);
-}
-
-uint32_t
-OfdmDownlinkFramePrefix::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    ReadFrom(i, m_baseStationId);
-    m_frameNumber = i.ReadU32();
-    m_configurationChangeCount = i.ReadU8();
-
-    bool end = false;
-
-    while (!end)
-    {
-        DlFramePrefixIe dlFramePrefixElement;
-        i = dlFramePrefixElement.Read(i);
-
-        AddDlFramePrefixElement(dlFramePrefixElement);
-
-        if (dlFramePrefixElement.GetDiuc() == 14)
-        {
-            end = true;
-        }
-    }
-
-    m_hcs = i.ReadU8();
-
-    return GetSerializedSize();
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ofdm-downlink-frame-prefix.h ns-3.46/src/wimax/model/ofdm-downlink-frame-prefix.h
--- ns-3.45/src/wimax/model/ofdm-downlink-frame-prefix.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ofdm-downlink-frame-prefix.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef DL_FRAME_PREFIX_IE_H
-#define DL_FRAME_PREFIX_IE_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief This class implements  the DL Frame Prefix IE as described by IEEE-802.16 standard
- * @brief The DL Frame Prefix IE is contained in DLFP (Downlink Frame Prefix) in OFDM PHY
- */
-class DlFramePrefixIe
-{
-  public:
-    DlFramePrefixIe();
-    ~DlFramePrefixIe();
-
-    /**
-     * Set rate ID field
-     * @param rateId the rate ID
-     */
-    void SetRateId(uint8_t rateId);
-    /**
-     * Set DIUC field
-     * @param diuc the DIUC
-     */
-    void SetDiuc(uint8_t diuc);
-    /**
-     * Set preamble present field
-     * @param preamblePresent the preambel present
-     */
-    void SetPreamblePresent(uint8_t preamblePresent);
-    /**
-     * Set length field
-     * @param length the length
-     */
-    void SetLength(uint16_t length);
-    /**
-     * Set start time field
-     * @param startTime the start time
-     */
-    void SetStartTime(uint16_t startTime);
-
-    /**
-     * Get rate ID field
-     * @returns the rate ID
-     */
-    uint8_t GetRateId() const;
-    /**
-     * Get DIUC field
-     * @returns the DIUC
-     */
-    uint8_t GetDiuc() const;
-    /**
-     * Get preamble present field
-     * @returns the preamble present
-     */
-    uint8_t GetPreamblePresent() const;
-    /**
-     * Get length field
-     * @returns the length
-     */
-    uint16_t GetLength() const;
-    /**
-     * Get start time field
-     * @returns the start time
-     */
-    uint16_t GetStartTime() const;
-
-    /**
-     * Get size field
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item function
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item function
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    uint8_t m_rateId;          ///< rate ID
-    uint8_t m_diuc;            ///< DIUC
-    uint8_t m_preamblePresent; ///< preamble present
-    uint16_t m_length;         ///< length
-    uint16_t m_startTime;      ///< start time
-
-    // shall actually contain m_startTime if DIUC is 0. see Table 225, page 452
-};
-
-} // namespace ns3
-
-#endif /* DL_FRAME_PREFIX_IE_H */
-
-#ifndef OFDM_DOWNLINK_FRAME_PREFIX_H
-#define OFDM_DOWNLINK_FRAME_PREFIX_H
-
-#include "ns3/header.h"
-#include "ns3/mac48-address.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * OfdmDownlinkFramePrefix
- */
-class OfdmDownlinkFramePrefix : public Header
-{
-  public:
-    OfdmDownlinkFramePrefix();
-    ~OfdmDownlinkFramePrefix() override;
-
-    /**
-     * Register this type.
-     * @return The TypeId.
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * Set base station ID field
-     * @param baseStationId the base station ID
-     */
-    void SetBaseStationId(Mac48Address baseStationId);
-    /**
-     * Set frame number field
-     * @param frameNumber the frame number
-     */
-    void SetFrameNumber(uint32_t frameNumber);
-    /**
-     * Set configuration change count field
-     * @param configurationChangeCount the configuration change count
-     */
-    void SetConfigurationChangeCount(uint8_t configurationChangeCount);
-    /**
-     * Add DL frame prefix element field
-     * @param dlFramePrefixElement the DL frame prefix element
-     */
-    void AddDlFramePrefixElement(DlFramePrefixIe dlFramePrefixElement);
-    /**
-     * Set HCS field
-     * @param hcs the HCS
-     */
-    void SetHcs(uint8_t hcs);
-
-    /**
-     * Get base station ID field
-     * @returns the base station ID
-     */
-    Mac48Address GetBaseStationId() const;
-    /**
-     * Get frame number field
-     * @returns the frame number
-     */
-    uint32_t GetFrameNumber() const;
-    /**
-     * Get configuration change count field
-     * @returns the configuration change count
-     */
-    uint8_t GetConfigurationChangeCount() const;
-    /**
-     * Get DL frame prefix elements
-     * @returns the DL frame prefix elements
-     */
-    std::vector<DlFramePrefixIe> GetDlFramePrefixElements() const;
-    /**
-     * Get HCS field
-     * @returns the HCS
-     */
-    uint8_t GetHcs() const;
-
-    /**
-     * Get name field
-     * @returns the name
-     */
-    std::string GetName() const;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    Mac48Address m_baseStationId; ///< base station ID
-    uint32_t m_frameNumber; ///< shall actually be only 4 LSB of the same field in OFDM DCD Channel
-                            ///< Encodings
-    uint8_t m_configurationChangeCount; ///< shall actually be only 4 LSB of the same field in DCD
-    std::vector<DlFramePrefixIe> m_dlFramePrefixElements; ///< vector of dl frame prefix elements
-    uint8_t m_hcs;                                        ///< Header Check Sequence
-};
-
-} // namespace ns3
-
-#endif /* OFDM_DOWNLINK_FRAME_PREFIX_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/send-params.cc ns-3.46/src/wimax/model/send-params.cc
--- ns-3.45/src/wimax/model/send-params.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/send-params.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "send-params.h"
-
-#include "ns3/packet.h"
-
-namespace ns3
-{
-
-SendParams::SendParams()
-{
-}
-
-SendParams::~SendParams()
-{
-}
-
-// -----------------------------------------
-
-OfdmSendParams::OfdmSendParams(Ptr<PacketBurst> burst, uint8_t modulationType, uint8_t direction)
-    : SendParams(),
-      m_burst(burst),
-      m_modulationType(modulationType),
-      m_direction(direction)
-{
-}
-
-OfdmSendParams::~OfdmSendParams()
-{
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/send-params.h ns-3.46/src/wimax/model/send-params.h
--- ns-3.45/src/wimax/model/send-params.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/send-params.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef SEND_PARAMS_H
-#define SEND_PARAMS_H
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class WimaxPhy;
-
-/**
- * @ingroup wimax
- * @brief The SendParams class defines the parameters with which Send() function of
- *  a particular PHY is called. The sole purpose of this class is to allow
- *  defining the pure virtual Send() function in the PHY base-class (WimaxPhy).
- *  This class shall be sub-classed every time a new PHY is integrated (i.e.,
- *  a new sub-class of WimaxPhy is created) which requires different or
- *  additional parameters to call its Send() function. For example as it is
- *  seen here, it has been sub-classed for the OFDM PHY layer since its Send()
- *  function requires two additional parameters.
- */
-class SendParams
-{
-  public:
-    SendParams();
-    virtual ~SendParams();
-
-  private:
-};
-
-} // namespace ns3
-
-#endif /* SEND_PARAMS_H */
-
-#ifndef OFDM_SEND_PARAMS_H
-#define OFDM_SEND_PARAMS_H
-
-#include "ns3/packet-burst.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * OfdmSendParams class
- */
-class OfdmSendParams : public SendParams
-{
-  public:
-    /**
-     * Constructor
-     *
-     * @param burst packet burst object
-     * @param modulationType modulation type
-     * @param direction the direction
-     */
-    OfdmSendParams(Ptr<PacketBurst> burst, uint8_t modulationType, uint8_t direction);
-    ~OfdmSendParams() override;
-
-    /**
-     * @return the packet burst
-     */
-    Ptr<PacketBurst> GetBurst() const
-    {
-        return m_burst;
-    }
-
-    /**
-     * @return the modulation type
-     */
-    uint8_t GetModulationType() const
-    {
-        return m_modulationType;
-    }
-
-    /**
-     * @return the direction
-     */
-    uint8_t GetDirection() const
-    {
-        return m_direction;
-    }
-
-  private:
-    Ptr<PacketBurst> m_burst; ///< packet burst
-    uint8_t m_modulationType; ///< modulation type
-    uint8_t m_direction;      ///< direction
-};
-
-} // namespace ns3
-
-#endif /* OFDM_SEND_PARAMS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/service-flow.cc ns-3.46/src/wimax/model/service-flow.cc
--- ns-3.45/src/wimax/model/service-flow.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/service-flow.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,888 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "service-flow.h"
-
-#include "service-flow-record.h"
-#include "wimax-tlv.h"
-
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-ServiceFlow::ServiceFlow(Direction direction)
-{
-    InitValues();
-    m_direction = direction;
-    m_type = SF_TYPE_PROVISIONED;
-    m_record = new ServiceFlowRecord();
-    m_sfid = 0;
-    m_connection = nullptr;
-    m_isEnabled = false;
-    m_isMulticast = false;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_QPSK_12;
-}
-
-ServiceFlow::ServiceFlow()
-    : m_sfid(0),
-      m_direction(SF_DIRECTION_DOWN),
-      m_type(SF_TYPE_PROVISIONED),
-      m_connection(nullptr),
-      m_isEnabled(false),
-      m_record(new ServiceFlowRecord())
-{
-    InitValues();
-    m_isMulticast = false;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_QPSK_12;
-}
-
-ServiceFlow::ServiceFlow(uint32_t sfid, Direction direction, Ptr<WimaxConnection> connection)
-{
-    InitValues();
-    m_record = new ServiceFlowRecord();
-    m_isEnabled = false;
-    m_connection = connection;
-    m_connection->SetServiceFlow(this);
-    m_type = SF_TYPE_PROVISIONED;
-    m_direction = direction;
-    m_sfid = sfid;
-    m_isMulticast = false;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_QPSK_12;
-}
-
-ServiceFlow::ServiceFlow(Tlv tlv)
-{
-    InitValues();
-    m_connection = nullptr;
-    m_isEnabled = false;
-    m_record = new ServiceFlowRecord();
-    NS_ASSERT_MSG(tlv.GetType() == Tlv::UPLINK_SERVICE_FLOW ||
-                      tlv.GetType() == Tlv::DOWNLINK_SERVICE_FLOW,
-                  "Invalid TLV");
-
-    SfVectorTlvValue* param;
-    param = (SfVectorTlvValue*)(tlv.PeekValue());
-
-    if (tlv.GetType() == Tlv::UPLINK_SERVICE_FLOW)
-    {
-        m_direction = SF_DIRECTION_UP;
-    }
-    else
-    {
-        m_direction = SF_DIRECTION_DOWN;
-    }
-
-    for (auto iter = param->Begin(); iter != param->End(); ++iter)
-    {
-        switch ((*iter)->GetType())
-        {
-        case SfVectorTlvValue::SFID: {
-            m_sfid = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::CID: {
-            uint16_t cid = ((U16TlvValue*)((*iter)->PeekValue()))->GetValue();
-            m_connection = CreateObject<WimaxConnection>(cid, Cid::TRANSPORT);
-            break;
-        }
-        case SfVectorTlvValue::QoS_Parameter_Set_Type: {
-            m_qosParamSetType = ((U8TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Traffic_Priority: {
-            m_trafficPriority = ((U8TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Maximum_Sustained_Traffic_Rate: {
-            m_maxSustainedTrafficRate = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Maximum_Traffic_Burst: {
-            m_maxTrafficBurst = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Minimum_Reserved_Traffic_Rate: {
-            m_minReservedTrafficRate = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Minimum_Tolerable_Traffic_Rate: {
-            m_minTolerableTrafficRate = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Service_Flow_Scheduling_Type: {
-            m_schedulingType =
-                (ServiceFlow::SchedulingType)((U8TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Request_Transmission_Policy: {
-            m_requestTransmissionPolicy = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Tolerated_Jitter: {
-            m_toleratedJitter = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Maximum_Latency: {
-            m_maximumLatency = ((U32TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::Fixed_length_versus_Variable_length_SDU_Indicator: {
-            m_fixedversusVariableSduIndicator = ((U8TlvValue*)((*iter)->PeekValue()))->GetValue();
-            break;
-        }
-        case SfVectorTlvValue::CS_Specification: {
-            m_csSpecification =
-                (CsSpecification)(((U8TlvValue*)((*iter)->PeekValue()))->GetValue());
-            break;
-        }
-
-        case SfVectorTlvValue::IPV4_CS_Parameters: {
-            m_convergenceSublayerParam = CsParameters(*(*iter));
-            break;
-        }
-        }
-    }
-    m_isMulticast = false;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_QPSK_12;
-}
-
-ServiceFlow::~ServiceFlow()
-{
-    if (m_record != nullptr)
-    {
-        delete m_record;
-        m_record = nullptr;
-    }
-    m_connection = nullptr;
-}
-
-void
-ServiceFlow::SetDirection(Direction direction)
-{
-    m_direction = direction;
-}
-
-ServiceFlow::Direction
-ServiceFlow::GetDirection() const
-{
-    return m_direction;
-}
-
-void
-ServiceFlow::SetType(Type type)
-{
-    m_type = type;
-}
-
-ServiceFlow::Type
-ServiceFlow::GetType() const
-{
-    return m_type;
-}
-
-void
-ServiceFlow::SetConnection(Ptr<WimaxConnection> connection)
-{
-    m_connection = connection;
-    m_connection->SetServiceFlow(this);
-}
-
-Ptr<WimaxConnection>
-ServiceFlow::GetConnection() const
-{
-    return m_connection;
-}
-
-void
-ServiceFlow::SetIsEnabled(bool isEnabled)
-{
-    m_isEnabled = isEnabled;
-}
-
-bool
-ServiceFlow::GetIsEnabled() const
-{
-    return m_isEnabled;
-}
-
-void
-ServiceFlow::SetRecord(ServiceFlowRecord* record)
-{
-    m_record = record;
-}
-
-ServiceFlowRecord*
-ServiceFlow::GetRecord() const
-{
-    return m_record;
-}
-
-Ptr<WimaxMacQueue>
-ServiceFlow::GetQueue() const
-{
-    if (!m_connection)
-    {
-        return nullptr;
-    }
-    return m_connection->GetQueue();
-}
-
-ServiceFlow::SchedulingType
-ServiceFlow::GetSchedulingType() const
-{
-    return m_schedulingType;
-}
-
-bool
-ServiceFlow::HasPackets() const
-{
-    if (!m_connection)
-    {
-        return false;
-    }
-    return m_connection->HasPackets();
-}
-
-bool
-ServiceFlow::HasPackets(MacHeaderType::HeaderType packetType) const
-{
-    if (!m_connection)
-    {
-        return false;
-    }
-    return m_connection->HasPackets(packetType);
-}
-
-void
-ServiceFlow::CleanUpQueue()
-{
-    GenericMacHeader hdr;
-    Time timeStamp;
-    Ptr<Packet> packet;
-    Time currentTime = Simulator::Now();
-    if (m_connection)
-    {
-        while (m_connection->HasPackets())
-        {
-            packet = m_connection->GetQueue()->Peek(hdr, timeStamp);
-
-            if (currentTime - timeStamp > MilliSeconds(GetMaximumLatency()))
-            {
-                m_connection->Dequeue();
-            }
-            else
-            {
-                break;
-            }
-        }
-    }
-}
-
-void
-ServiceFlow::PrintQoSParameters() const
-{
-}
-
-// ==============================================================================
-
-uint32_t
-ServiceFlow::GetSfid() const
-{
-    return m_sfid;
-}
-
-uint16_t
-ServiceFlow::GetCid() const
-{
-    if (!m_connection)
-    {
-        return 0;
-    }
-    return m_connection->GetCid().GetIdentifier();
-}
-
-std::string
-ServiceFlow::GetServiceClassName() const
-{
-    return m_serviceClassName;
-}
-
-uint8_t
-ServiceFlow::GetQosParamSetType() const
-{
-    return m_qosParamSetType;
-}
-
-uint8_t
-ServiceFlow::GetTrafficPriority() const
-{
-    return m_trafficPriority;
-}
-
-uint32_t
-ServiceFlow::GetMaxSustainedTrafficRate() const
-{
-    return m_maxSustainedTrafficRate;
-}
-
-uint32_t
-ServiceFlow::GetMaxTrafficBurst() const
-{
-    return m_maxTrafficBurst;
-}
-
-uint32_t
-ServiceFlow::GetMinReservedTrafficRate() const
-{
-    return m_minReservedTrafficRate;
-}
-
-uint32_t
-ServiceFlow::GetMinTolerableTrafficRate() const
-{
-    return m_minTolerableTrafficRate;
-}
-
-ServiceFlow::SchedulingType
-ServiceFlow::GetServiceSchedulingType() const
-{
-    return m_schedulingType;
-}
-
-uint32_t
-ServiceFlow::GetRequestTransmissionPolicy() const
-{
-    return m_requestTransmissionPolicy;
-}
-
-uint32_t
-ServiceFlow::GetToleratedJitter() const
-{
-    return m_toleratedJitter;
-}
-
-uint32_t
-ServiceFlow::GetMaximumLatency() const
-{
-    return m_maximumLatency;
-}
-
-uint8_t
-ServiceFlow::GetFixedversusVariableSduIndicator() const
-{
-    return m_fixedversusVariableSduIndicator;
-}
-
-uint8_t
-ServiceFlow::GetSduSize() const
-{
-    return m_sduSize;
-}
-
-uint16_t
-ServiceFlow::GetTargetSAID() const
-{
-    return m_targetSAID;
-}
-
-uint8_t
-ServiceFlow::GetArqEnable() const
-{
-    return m_arqEnable;
-}
-
-uint16_t
-ServiceFlow::GetArqWindowSize() const
-{
-    return m_arqWindowSize;
-}
-
-uint16_t
-ServiceFlow::GetArqRetryTimeoutTx() const
-{
-    return m_arqRetryTimeoutTx;
-}
-
-uint16_t
-ServiceFlow::GetArqRetryTimeoutRx() const
-{
-    return m_arqRetryTimeoutRx;
-}
-
-uint16_t
-ServiceFlow::GetArqBlockLifeTime() const
-{
-    return m_arqBlockLifeTime;
-}
-
-uint16_t
-ServiceFlow::GetArqSyncLoss() const
-{
-    return m_arqSyncLoss;
-}
-
-uint8_t
-ServiceFlow::GetArqDeliverInOrder() const
-{
-    return m_arqDeliverInOrder;
-}
-
-uint16_t
-ServiceFlow::GetArqPurgeTimeout() const
-{
-    return m_arqPurgeTimeout;
-}
-
-uint16_t
-ServiceFlow::GetArqBlockSize() const
-{
-    return m_arqBlockSize;
-}
-
-ServiceFlow::CsSpecification
-ServiceFlow::GetCsSpecification() const
-{
-    return m_csSpecification;
-}
-
-CsParameters
-ServiceFlow::GetConvergenceSublayerParam() const
-{
-    return m_convergenceSublayerParam;
-}
-
-uint16_t
-ServiceFlow::GetUnsolicitedGrantInterval() const
-{
-    return m_unsolicitedGrantInterval;
-}
-
-uint16_t
-ServiceFlow::GetUnsolicitedPollingInterval() const
-{
-    return m_unsolicitedPollingInterval;
-}
-
-bool
-ServiceFlow::GetIsMulticast() const
-{
-    return m_isMulticast;
-}
-
-WimaxPhy::ModulationType
-ServiceFlow::GetModulation() const
-{
-    return m_modulationType;
-}
-
-// ==============================================================================
-
-void
-ServiceFlow::SetSfid(uint32_t sfid)
-{
-    m_sfid = sfid;
-}
-
-void
-ServiceFlow::SetServiceClassName(std::string name)
-{
-    m_serviceClassName = name;
-}
-
-void
-ServiceFlow::SetQosParamSetType(uint8_t type)
-{
-    m_qosParamSetType = type;
-}
-
-void
-ServiceFlow::SetTrafficPriority(uint8_t priority)
-{
-    m_trafficPriority = priority;
-}
-
-void
-ServiceFlow::SetMaxSustainedTrafficRate(uint32_t maxSustainedRate)
-{
-    m_maxSustainedTrafficRate = maxSustainedRate;
-}
-
-void
-ServiceFlow::SetMaxTrafficBurst(uint32_t maxTrafficBurst)
-{
-    m_maxTrafficBurst = maxTrafficBurst;
-}
-
-void
-ServiceFlow::SetMinReservedTrafficRate(uint32_t minResvRate)
-{
-    m_minReservedTrafficRate = minResvRate;
-}
-
-void
-ServiceFlow::SetMinTolerableTrafficRate(uint32_t minJitter)
-{
-    m_minTolerableTrafficRate = minJitter;
-}
-
-void
-ServiceFlow::SetServiceSchedulingType(ServiceFlow::SchedulingType schedType)
-{
-    m_schedulingType = schedType;
-}
-
-void
-ServiceFlow::SetRequestTransmissionPolicy(uint32_t policy)
-{
-    m_requestTransmissionPolicy = policy;
-}
-
-void
-ServiceFlow::SetToleratedJitter(uint32_t jitter)
-{
-    m_toleratedJitter = jitter;
-}
-
-void
-ServiceFlow::SetMaximumLatency(uint32_t MaximumLatency)
-{
-    m_maximumLatency = MaximumLatency;
-}
-
-void
-ServiceFlow::SetFixedversusVariableSduIndicator(uint8_t sduIndicator)
-{
-    m_fixedversusVariableSduIndicator = sduIndicator;
-}
-
-void
-ServiceFlow::SetSduSize(uint8_t sduSize)
-{
-    m_sduSize = sduSize;
-}
-
-void
-ServiceFlow::SetTargetSAID(uint16_t targetSaid)
-{
-    m_targetSAID = targetSaid;
-}
-
-void
-ServiceFlow::SetArqEnable(uint8_t arqEnable)
-{
-    m_arqEnable = arqEnable;
-}
-
-void
-ServiceFlow::SetArqWindowSize(uint16_t arqWindowSize)
-{
-    m_arqWindowSize = arqWindowSize;
-}
-
-void
-ServiceFlow::SetArqRetryTimeoutTx(uint16_t timeout)
-{
-    m_arqRetryTimeoutTx = timeout;
-}
-
-void
-ServiceFlow::SetArqRetryTimeoutRx(uint16_t timeout)
-{
-    m_arqRetryTimeoutRx = timeout;
-}
-
-void
-ServiceFlow::SetArqBlockLifeTime(uint16_t lifeTime)
-{
-    m_arqBlockLifeTime = lifeTime;
-}
-
-void
-ServiceFlow::SetArqSyncLoss(uint16_t syncLoss)
-{
-    m_arqSyncLoss = syncLoss;
-}
-
-void
-ServiceFlow::SetArqDeliverInOrder(uint8_t inOrder)
-{
-    m_arqDeliverInOrder = inOrder;
-}
-
-void
-ServiceFlow::SetArqPurgeTimeout(uint16_t timeout)
-{
-    m_arqPurgeTimeout = timeout;
-}
-
-void
-ServiceFlow::SetArqBlockSize(uint16_t size)
-{
-    m_arqBlockSize = size;
-}
-
-void
-ServiceFlow::SetCsSpecification(ServiceFlow::CsSpecification spec)
-{
-    m_csSpecification = spec;
-}
-
-void
-ServiceFlow::SetConvergenceSublayerParam(CsParameters csparam)
-{
-    m_convergenceSublayerParam = csparam;
-}
-
-void
-ServiceFlow::SetUnsolicitedGrantInterval(uint16_t unsolicitedGrantInterval)
-{
-    m_unsolicitedGrantInterval = unsolicitedGrantInterval;
-}
-
-void
-ServiceFlow::SetUnsolicitedPollingInterval(uint16_t unsolicitedPollingInterval)
-{
-    m_unsolicitedPollingInterval = unsolicitedPollingInterval;
-}
-
-void
-ServiceFlow::SetIsMulticast(bool isMulticast)
-{
-    m_isMulticast = isMulticast;
-}
-
-void
-ServiceFlow::SetModulation(WimaxPhy::ModulationType modulationType)
-{
-    m_modulationType = modulationType;
-}
-
-void
-ServiceFlow::InitValues()
-{
-    m_sfid = 0;
-    m_serviceClassName = "";
-    m_qosParamSetType = 0;
-    m_trafficPriority = 0;
-    m_maxSustainedTrafficRate = 0;
-    m_maxTrafficBurst = 0;
-    m_minReservedTrafficRate = 0;
-    m_minTolerableTrafficRate = 0;
-    m_schedulingType = ServiceFlow::SF_TYPE_NONE;
-    m_requestTransmissionPolicy = 0;
-    m_toleratedJitter = 0;
-    m_maximumLatency = 0;
-    m_fixedversusVariableSduIndicator = 0;
-    m_sduSize = 0;
-    m_targetSAID = 0;
-    m_arqEnable = 0;
-    m_arqWindowSize = 0;
-    m_arqRetryTimeoutTx = 0;
-    m_arqRetryTimeoutRx = 0;
-    m_csSpecification = ServiceFlow::IPV4;
-    m_unsolicitedGrantInterval = 0;
-    m_unsolicitedPollingInterval = 0;
-    m_arqBlockLifeTime = 0;
-    m_arqSyncLoss = 0;
-    m_arqDeliverInOrder = 0;
-    m_arqPurgeTimeout = 0;
-    m_arqBlockSize = 0;
-    m_direction = ServiceFlow::SF_DIRECTION_DOWN;
-    m_type = ServiceFlow::SF_TYPE_ACTIVE;
-    m_isMulticast = false;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_QPSK_12;
-}
-
-void
-ServiceFlow::CopyParametersFrom(ServiceFlow sf)
-{
-    m_serviceClassName = sf.GetServiceClassName();
-    m_qosParamSetType = sf.GetQosParamSetType();
-    m_trafficPriority = sf.GetTrafficPriority();
-    m_maxSustainedTrafficRate = sf.GetMaxSustainedTrafficRate();
-    m_maxTrafficBurst = sf.GetMaxTrafficBurst();
-    m_minReservedTrafficRate = sf.GetMinReservedTrafficRate();
-    m_minTolerableTrafficRate = sf.GetMinTolerableTrafficRate();
-    m_schedulingType = sf.GetServiceSchedulingType();
-    m_requestTransmissionPolicy = sf.GetRequestTransmissionPolicy();
-    m_toleratedJitter = sf.GetToleratedJitter();
-    m_maximumLatency = sf.GetMaximumLatency();
-    m_fixedversusVariableSduIndicator = sf.GetFixedversusVariableSduIndicator();
-    m_sduSize = sf.GetSduSize();
-    m_targetSAID = sf.GetTargetSAID();
-    m_arqEnable = sf.GetArqEnable();
-    m_arqWindowSize = sf.GetArqWindowSize();
-    m_arqRetryTimeoutTx = sf.GetArqRetryTimeoutTx();
-    m_arqRetryTimeoutRx = sf.GetArqRetryTimeoutRx();
-    m_csSpecification = sf.GetCsSpecification();
-    m_convergenceSublayerParam = sf.GetConvergenceSublayerParam();
-    m_unsolicitedGrantInterval = sf.GetUnsolicitedGrantInterval();
-    m_unsolicitedPollingInterval = sf.GetUnsolicitedPollingInterval();
-    m_direction = sf.GetDirection();
-    m_isMulticast = sf.GetIsMulticast();
-    m_modulationType = sf.GetModulation();
-}
-
-ServiceFlow::ServiceFlow(const ServiceFlow& sf)
-{
-    m_sfid = sf.GetSfid();
-    m_serviceClassName = sf.GetServiceClassName();
-    m_qosParamSetType = sf.GetQosParamSetType();
-    m_trafficPriority = sf.GetTrafficPriority();
-    m_maxSustainedTrafficRate = sf.GetMaxSustainedTrafficRate();
-    m_maxTrafficBurst = sf.GetMaxTrafficBurst();
-    m_minReservedTrafficRate = sf.GetMinReservedTrafficRate();
-    m_minTolerableTrafficRate = sf.GetMinTolerableTrafficRate();
-    m_schedulingType = sf.GetServiceSchedulingType();
-    m_requestTransmissionPolicy = sf.GetRequestTransmissionPolicy();
-    m_toleratedJitter = sf.GetToleratedJitter();
-    m_maximumLatency = sf.GetMaximumLatency();
-    m_fixedversusVariableSduIndicator = sf.GetFixedversusVariableSduIndicator();
-    m_sduSize = sf.GetSduSize();
-    m_targetSAID = sf.GetTargetSAID();
-    m_arqEnable = sf.GetArqEnable();
-    m_arqWindowSize = sf.GetArqWindowSize();
-    m_arqRetryTimeoutTx = sf.GetArqRetryTimeoutTx();
-    m_arqRetryTimeoutRx = sf.GetArqRetryTimeoutRx();
-    m_csSpecification = sf.GetCsSpecification();
-    m_convergenceSublayerParam = sf.GetConvergenceSublayerParam();
-    m_unsolicitedGrantInterval = sf.GetUnsolicitedGrantInterval();
-    m_unsolicitedPollingInterval = sf.GetUnsolicitedPollingInterval();
-    m_direction = sf.GetDirection();
-    m_type = sf.GetType();
-    m_connection = sf.GetConnection();
-    m_isEnabled = sf.GetIsEnabled();
-    m_record = new ServiceFlowRecord();
-    (*m_record) = (*sf.GetRecord());
-    m_isMulticast = sf.GetIsMulticast();
-    m_modulationType = sf.GetModulation();
-}
-
-ServiceFlow&
-ServiceFlow::operator=(const ServiceFlow& o)
-{
-    m_sfid = o.GetSfid();
-    m_serviceClassName = o.GetServiceClassName();
-    m_qosParamSetType = o.GetQosParamSetType();
-    m_trafficPriority = o.GetTrafficPriority();
-    m_maxSustainedTrafficRate = o.GetMaxSustainedTrafficRate();
-    m_maxTrafficBurst = o.GetMaxTrafficBurst();
-    m_minReservedTrafficRate = o.GetMinReservedTrafficRate();
-    m_minTolerableTrafficRate = o.GetMinTolerableTrafficRate();
-    m_schedulingType = o.GetServiceSchedulingType();
-    m_requestTransmissionPolicy = o.GetRequestTransmissionPolicy();
-    m_toleratedJitter = o.GetToleratedJitter();
-    m_maximumLatency = o.GetMaximumLatency();
-    m_fixedversusVariableSduIndicator = o.GetFixedversusVariableSduIndicator();
-    m_sduSize = o.GetSduSize();
-    m_targetSAID = o.GetTargetSAID();
-    m_arqEnable = o.GetArqEnable();
-    m_arqWindowSize = o.GetArqWindowSize();
-    m_arqRetryTimeoutTx = o.GetArqRetryTimeoutTx();
-    m_arqRetryTimeoutRx = o.GetArqRetryTimeoutRx();
-    m_csSpecification = o.GetCsSpecification();
-    m_convergenceSublayerParam = o.GetConvergenceSublayerParam();
-    m_unsolicitedGrantInterval = o.GetUnsolicitedGrantInterval();
-    m_unsolicitedPollingInterval = o.GetUnsolicitedPollingInterval();
-    m_direction = o.GetDirection();
-    m_type = o.GetType();
-    m_connection = o.GetConnection();
-    m_isEnabled = o.GetIsEnabled();
-    m_isMulticast = o.GetIsMulticast();
-    m_modulationType = o.GetModulation();
-    if (m_record != nullptr)
-    {
-        delete m_record;
-    }
-
-    m_record = new ServiceFlowRecord();
-
-    (*m_record) = (*o.GetRecord());
-    return *this;
-}
-
-char*
-ServiceFlow::GetSchedulingTypeStr() const
-{
-    switch (m_schedulingType)
-    {
-    case SF_TYPE_UGS:
-        return (char*)"UGS";
-    case SF_TYPE_RTPS:
-        return (char*)"rtPS";
-    case SF_TYPE_NRTPS:
-        return (char*)"nrtPS";
-    case SF_TYPE_BE:
-        return (char*)"BE";
-    default:
-        NS_FATAL_ERROR("Invalid scheduling type");
-    }
-    return nullptr;
-}
-
-Tlv
-ServiceFlow::ToTlv() const
-{
-    SfVectorTlvValue tmpSfVector;
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::SFID, 4, U32TlvValue(m_sfid)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::CID, 2, U16TlvValue(GetCid())));
-    tmpSfVector.Add(
-        Tlv(SfVectorTlvValue::QoS_Parameter_Set_Type, 1, U8TlvValue(m_qosParamSetType)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Traffic_Priority, 1, U8TlvValue(m_trafficPriority)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Maximum_Sustained_Traffic_Rate,
-                        4,
-                        U32TlvValue(m_maxSustainedTrafficRate)));
-    tmpSfVector.Add(
-        Tlv(SfVectorTlvValue::Maximum_Traffic_Burst, 4, U32TlvValue(m_maxTrafficBurst)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Minimum_Reserved_Traffic_Rate,
-                        4,
-                        U32TlvValue(m_minReservedTrafficRate)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Minimum_Tolerable_Traffic_Rate,
-                        4,
-                        U32TlvValue(m_minTolerableTrafficRate)));
-    tmpSfVector.Add(
-        Tlv(SfVectorTlvValue::Service_Flow_Scheduling_Type, 1, U8TlvValue(m_schedulingType)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Request_Transmission_Policy,
-                        4,
-                        U32TlvValue(m_requestTransmissionPolicy)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Tolerated_Jitter, 4, U32TlvValue(m_toleratedJitter)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Maximum_Latency, 4, U32TlvValue(m_maximumLatency)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Fixed_length_versus_Variable_length_SDU_Indicator,
-                        1,
-                        U8TlvValue(m_fixedversusVariableSduIndicator)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::SDU_Size, 1, U8TlvValue(m_sduSize)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::Target_SAID, 2, U16TlvValue(m_targetSAID)));
-    tmpSfVector.Add(Tlv(SfVectorTlvValue::CS_Specification, 1, U8TlvValue(m_csSpecification)));
-    tmpSfVector.Add(m_convergenceSublayerParam.ToTlv());
-    if (m_direction == SF_DIRECTION_UP)
-    {
-        return Tlv(Tlv::UPLINK_SERVICE_FLOW, tmpSfVector.GetSerializedSize(), tmpSfVector);
-    }
-    else
-    {
-        return Tlv(Tlv::DOWNLINK_SERVICE_FLOW, tmpSfVector.GetSerializedSize(), tmpSfVector);
-    }
-}
-
-bool
-ServiceFlow::CheckClassifierMatch(Ipv4Address srcAddress,
-                                  Ipv4Address dstAddress,
-                                  uint16_t srcPort,
-                                  uint16_t dstPort,
-                                  uint8_t proto) const
-{
-    return m_convergenceSublayerParam.GetPacketClassifierRule().CheckMatch(srcAddress,
-                                                                           dstAddress,
-                                                                           srcPort,
-                                                                           dstPort,
-                                                                           proto);
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/service-flow.h ns-3.46/src/wimax/model/service-flow.h
--- ns-3.45/src/wimax/model/service-flow.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/service-flow.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef SERVICE_FLOW_H
-#define SERVICE_FLOW_H
-
-#include "cs-parameters.h"
-#include "wimax-connection.h"
-#include "wimax-mac-header.h"
-#include "wimax-phy.h"
-
-#include <cstdint>
-
-namespace ns3
-{
-
-class ServiceFlowRecord;
-class WimaxConnection;
-class WimaxMacQueue;
-
-/**
- * @ingroup wimax
- * This class implements service flows as described by the IEEE-802.16 standard
- */
-class ServiceFlow
-{
-  public:
-    /// Direction enumeration
-    enum Direction
-    {
-        SF_DIRECTION_DOWN,
-        SF_DIRECTION_UP
-    };
-
-    /// Type enumeration
-    enum Type
-    {
-        SF_TYPE_PROVISIONED,
-        SF_TYPE_ADMITTED,
-        SF_TYPE_ACTIVE
-    };
-
-    /// section 11.13.11 Service flow scheduling type, page 701
-    enum SchedulingType
-    {
-        SF_TYPE_NONE = 0,
-        SF_TYPE_UNDEF = 1,
-        SF_TYPE_BE = 2,
-        SF_TYPE_NRTPS = 3,
-        SF_TYPE_RTPS = 4,
-        SF_TYPE_UGS = 6,
-        SF_TYPE_ALL = 255
-    };
-
-    /// section 11.13.19.2 CS parameter encoding rules, page 707
-    enum CsSpecification
-    {
-        ATM = 99,
-        IPV4 = 100,
-        IPV6 = 101,
-        ETHERNET = 102,
-        VLAN = 103,
-        IPV4_OVER_ETHERNET = 104,
-        IPV6_OVER_ETHERNET = 105,
-        IPV4_OVER_VLAN = 106,
-        IPV6_OVER_VLAN = 107
-    };
-
-    /// Modulation type enumeration, Table 356 and 362
-    enum ModulationType
-    {
-        MODULATION_TYPE_BPSK_12,
-        MODULATION_TYPE_QPSK_12,
-        MODULATION_TYPE_QPSK_34,
-        MODULATION_TYPE_QAM16_12,
-        MODULATION_TYPE_QAM16_34,
-        MODULATION_TYPE_QAM64_23,
-        MODULATION_TYPE_QAM64_34
-    };
-
-    /**
-     * @brief creates a TLV from this service flow
-     * @return the created tlv
-     */
-    Tlv ToTlv() const;
-    /**
-     * @brief creates a service flow from a TLV
-     * @param tlv the tlv from which the service flow will be created
-     */
-    ServiceFlow(Tlv tlv);
-    /**
-     * @brief check classifier match.
-     * @param srcAddress the source ip address
-     * @param dstAddress the destination ip address
-     * @param srcPort the source port
-     * @param dstPort the destination port
-     * @param proto the layer 4 protocol
-     * @return true if the passed parameters match the classifier of the service flow, false
-     * otherwise
-     */
-    bool CheckClassifierMatch(Ipv4Address srcAddress,
-                              Ipv4Address dstAddress,
-                              uint16_t srcPort,
-                              uint16_t dstPort,
-                              uint8_t proto) const;
-    /**
-     * Default constructor.
-     */
-    ServiceFlow();
-    /**
-     * Constructor
-     *
-     * @param direction the direction
-     */
-    ServiceFlow(Direction direction);
-    /**
-     * Constructor
-     *
-     * @param sf service flow
-     */
-    ServiceFlow(const ServiceFlow& sf);
-    /**
-     * Constructor
-     *
-     * @param sfid the SFID
-     * @param direction the direction
-     * @param connection the connection object
-     */
-    ServiceFlow(uint32_t sfid, Direction direction, Ptr<WimaxConnection> connection);
-    /**
-     * Destructor.
-     */
-    ~ServiceFlow();
-    /**
-     * assignment operator
-     * @param o the service flow to assign
-     * @returns the service flow
-     */
-    ServiceFlow& operator=(const ServiceFlow& o);
-
-    /**
-     * Initialize values.
-     */
-    void InitValues();
-    /**
-     * Set direction
-     * @param direction the direction value
-     */
-    void SetDirection(Direction direction);
-    /**
-     * Get direction
-     * @returns the direction
-     */
-    Direction GetDirection() const;
-    /**
-     * Copy parameters from another service flow
-     * @param sf the service flow
-     */
-    void CopyParametersFrom(ServiceFlow sf);
-
-    /**
-     * Set type of service flow
-     * @param type the type value
-     */
-    void SetType(Type type);
-    /**
-     * Get type of service flow
-     * @returns the type
-     */
-    Type GetType() const;
-    /**
-     * Set connection
-     * @param connection the connection
-     */
-    void SetConnection(Ptr<WimaxConnection> connection);
-    /**
-     * Can return a null connection is this service flow has not
-     * been associated yet to a connection.
-     * @returns pointer to the WimaxConnection
-     */
-    Ptr<WimaxConnection> GetConnection() const;
-
-    /**
-     * Set is enabled flag
-     * @param isEnabled is enabled flag
-     */
-    void SetIsEnabled(bool isEnabled);
-    /**
-     * Get is enabled flag
-     * @returns is enabled
-     */
-    bool GetIsEnabled() const;
-
-    /**
-     * Set service flow record
-     * @param record pointer to the service flow record
-     */
-    void SetRecord(ServiceFlowRecord* record);
-    /**
-     * Get service flow record
-     * @returns pointer to the service flow record
-     */
-    ServiceFlowRecord* GetRecord() const;
-
-    // wrapper functions
-    /**
-     * Get pointer to queue
-     * @returns pointer to the wimax mac queue
-     */
-    Ptr<WimaxMacQueue> GetQueue() const;
-    /**
-     * Get scheduling type
-     * @returns the scheduling type
-     */
-    ServiceFlow::SchedulingType GetSchedulingType() const;
-    /**
-     * Check if packets are present
-     * @returns true if there are packets
-     */
-    bool HasPackets() const;
-    /**
-     * Check if packets of particular type are present
-     * @param packetType the packet type to select
-     * @returns true if there are packets of the packet type
-     */
-    bool HasPackets(MacHeaderType::HeaderType packetType) const;
-
-    /**
-     * Shall be called only by BS.
-     */
-    void CleanUpQueue();
-
-    /**
-     * Print QoS parameters.
-     */
-    void PrintQoSParameters() const;
-
-    /**
-     * Get scheduling type string
-     * @returns the name of the scheduling type
-     */
-    char* GetSchedulingTypeStr() const;
-
-    /**
-     * Get SFID
-     * @returns the SFID
-     */
-    uint32_t GetSfid() const;
-    /**
-     * Get CID
-     * @returns the CID
-     */
-    uint16_t GetCid() const;
-    /**
-     * Get service class name
-     * @returns the service class name
-     */
-    std::string GetServiceClassName() const;
-    /**
-     * Get QOS parameter set type
-     * @returns the QOS parameter set type
-     */
-    uint8_t GetQosParamSetType() const;
-    /**
-     * Get traffic priority
-     * @returns the traffic priority
-     */
-    uint8_t GetTrafficPriority() const;
-    /**
-     * Get max sustained traffic rate
-     * @returns the maximum sustained traffic rate
-     */
-    uint32_t GetMaxSustainedTrafficRate() const;
-    /**
-     * Get max traffic burst
-     * @returns the maximum traffic burst
-     */
-    uint32_t GetMaxTrafficBurst() const;
-    /**
-     * Get minimum reserved traffic rate
-     * @returns the minimum reserved traffic rate
-     */
-    uint32_t GetMinReservedTrafficRate() const;
-    /**
-     * Get minimum tolerable traffic rate
-     * @returns the minimum tolerable traffic rate
-     */
-    uint32_t GetMinTolerableTrafficRate() const;
-    /**
-     * Get service scheduling type
-     * @returns the scheduling type
-     */
-    ServiceFlow::SchedulingType GetServiceSchedulingType() const;
-    /**
-     * Get request transmission policy
-     * @returns the request transmission policy
-     */
-    uint32_t GetRequestTransmissionPolicy() const;
-    /**
-     * Get tolerated jitter
-     * @returns the tolerated jitter
-     */
-    uint32_t GetToleratedJitter() const;
-    /**
-     * Get maximum latency
-     * @returns the maximum latency
-     */
-    uint32_t GetMaximumLatency() const;
-    /**
-     * Get fixed versus variable SDU indicator
-     * @returns the fixed vs variable SDU indicator
-     */
-    uint8_t GetFixedversusVariableSduIndicator() const;
-    /**
-     * Get SDU size
-     * @returns the SDU size
-     */
-    uint8_t GetSduSize() const;
-    /**
-     * Get target SAID
-     * @returns the target SAID
-     */
-    uint16_t GetTargetSAID() const;
-    /**
-     * Get ARQ enable
-     * @returns the ARQ enable
-     */
-    uint8_t GetArqEnable() const;
-    /**
-     * Get ARQ retry timeout transmit
-     * @returns the ARQ retry timeout
-     */
-    uint16_t GetArqWindowSize() const;
-    /**
-     * Get ARQ retry timeout transmit
-     * @returns the ARQ retry timeout transmit
-     */
-    uint16_t GetArqRetryTimeoutTx() const;
-    /**
-     * Get ARQ retry timeout receive
-     * @returns the ARQ retry timeout receive
-     */
-    uint16_t GetArqRetryTimeoutRx() const;
-    /**
-     * Get ARQ block lifetime
-     * @returns the ARQ block lifetime
-     */
-    uint16_t GetArqBlockLifeTime() const;
-    /**
-     * Get ARQ sync loss
-     * @returns the ARQ sync loss value
-     */
-    uint16_t GetArqSyncLoss() const;
-    /**
-     * Get ARQ deliver in order
-     * @returns the ARQ deliver in order
-     */
-    uint8_t GetArqDeliverInOrder() const;
-    /**
-     * Get ARQ purge timeout
-     * @returns the ARQ purge timeout value
-     */
-    uint16_t GetArqPurgeTimeout() const;
-    /**
-     * Get ARQ block size
-     * @returns the ARQ block size
-     */
-    uint16_t GetArqBlockSize() const;
-    /**
-     * Get CS specification
-     * @returns the CS specification
-     */
-    CsSpecification GetCsSpecification() const;
-    /**
-     * Get convergence sublayer
-     * @returns the convergence sublayer
-     */
-    CsParameters GetConvergenceSublayerParam() const;
-    /**
-     * Get unsolicited grant interval
-     * @returns the unsolicited grant interval
-     */
-    uint16_t GetUnsolicitedGrantInterval() const;
-    /**
-     * Get unsolicited polling interval
-     * @returns the unsolicited polling interval
-     */
-    uint16_t GetUnsolicitedPollingInterval() const;
-    /**
-     * Get is multicast
-     * @returns the is multicast flag
-     */
-    bool GetIsMulticast() const;
-    /**
-     * Get modulation
-     * @returns the modulation
-     */
-    WimaxPhy::ModulationType GetModulation() const;
-
-    /**
-     * Set SFID
-     * @param sfid the SFID
-     */
-    void SetSfid(uint32_t sfid);
-    /**
-     * Set service class name
-     * @param name the service class name
-     */
-    void SetServiceClassName(std::string name);
-    /**
-     * Set QOS parameter set type
-     * @param type the QOS parameter set type
-     */
-    void SetQosParamSetType(uint8_t type);
-    /**
-     * Set traffic priority
-     * @param priority the traffic priority
-     */
-    void SetTrafficPriority(uint8_t priority);
-    /**
-     * Set max sustained traffic rate
-     * @param maxSustainedRate the maximum sustained traffic rate
-     */
-    void SetMaxSustainedTrafficRate(uint32_t maxSustainedRate);
-    /**
-     * Set maximum traffic burst
-     * @param maxTrafficBurst the maximum traffic burst
-     */
-    void SetMaxTrafficBurst(uint32_t maxTrafficBurst);
-    /**
-     * Set minimum reserved traffic rate
-     * @param minResvRate the minimum reserved traffic rate
-     */
-    void SetMinReservedTrafficRate(uint32_t minResvRate);
-    /**
-     * Set minimum tolerable traffic rate
-     * @param minJitter the minimum tolerable traffic rate
-     */
-    void SetMinTolerableTrafficRate(uint32_t minJitter);
-    /**
-     * Set service scheduling type
-     * @param schedType the service scheduling type
-     */
-    void SetServiceSchedulingType(ServiceFlow::SchedulingType schedType);
-    /**
-     * Set request transmission policy
-     * @param policy the request transmission policy
-     */
-    void SetRequestTransmissionPolicy(uint32_t policy);
-    /**
-     * Set tolerated jitter
-     * @param jitter the tolerated jitter
-     */
-    void SetToleratedJitter(uint32_t jitter);
-    /**
-     * Set maximum latency
-     * @param MaximumLatency the maximum latency
-     */
-    void SetMaximumLatency(uint32_t MaximumLatency);
-    /**
-     * Set fixed versus variable SDU indicator
-     * @param sduIndicator fixed vs variable SDU indicator
-     */
-    void SetFixedversusVariableSduIndicator(uint8_t sduIndicator);
-    /**
-     * Set SDU size
-     * @param sduSize the SDU size
-     */
-    void SetSduSize(uint8_t sduSize);
-    /**
-     * Set target SAID
-     * @param targetSaid the target SAID value
-     */
-    void SetTargetSAID(uint16_t targetSaid);
-    /**
-     * Set ARQ enable
-     * @param arqEnable the ARQ enable setting
-     */
-    void SetArqEnable(uint8_t arqEnable);
-    /**
-     * Set ARQ retry timeout transmit
-     * @param arqWindowSize the ARQ retry timeout transmit
-     */
-    void SetArqWindowSize(uint16_t arqWindowSize);
-    /**
-     * Set ARQ retry timeout transmit
-     * @param timeout the ARQ retry timeout transmit
-     */
-    void SetArqRetryTimeoutTx(uint16_t timeout);
-    /**
-     * Set ARQ retry timeout receive
-     * @param timeout the timeout
-     */
-    void SetArqRetryTimeoutRx(uint16_t timeout);
-    /**
-     * Set ARQ block lifetime
-     * @param lifeTime the ARQ block life time
-     */
-    void SetArqBlockLifeTime(uint16_t lifeTime);
-    /**
-     * Set ARQ sync loss
-     * @param syncLoss the ARQ sync loss
-     */
-    void SetArqSyncLoss(uint16_t syncLoss);
-    /**
-     * Set ARQ deliver in order
-     * @param inOrder the deliver in order setting
-     */
-    void SetArqDeliverInOrder(uint8_t inOrder);
-    /**
-     * Set ARQ purge timeout
-     * @param timeout the timeout value
-     */
-    void SetArqPurgeTimeout(uint16_t timeout);
-    /**
-     * Set ARQ block size
-     * @param size the size
-     */
-    void SetArqBlockSize(uint16_t size);
-    /**
-     * Set CS specification
-     * @param spec the CS specification
-     */
-    void SetCsSpecification(CsSpecification spec);
-    /**
-     * Set convergence sublayer parameters
-     * @param csparam the convergence sublayer parameters
-     */
-    void SetConvergenceSublayerParam(CsParameters csparam);
-
-    /**
-     * Set unsolicited grant interval
-     * @param unsolicitedGrantInterval the unsolicited grant interval
-     */
-    void SetUnsolicitedGrantInterval(uint16_t unsolicitedGrantInterval);
-    /**
-     * Set unsolicited polling interval
-     * @param unsolicitedPollingInterval the unsolicited polling interval
-     */
-    void SetUnsolicitedPollingInterval(uint16_t unsolicitedPollingInterval);
-    /**
-     * Set is multicast
-     * @param isMulticast the is multicast flag
-     */
-    void SetIsMulticast(bool isMulticast);
-    /**
-     * Set modulation
-     * @param modulationType the modulation type
-     */
-    void SetModulation(WimaxPhy::ModulationType modulationType);
-
-  private:
-    uint32_t m_sfid;                              ///< SFID
-    std::string m_serviceClassName;               ///< service class name
-    uint8_t m_qosParamSetType;                    ///< QOS parameter type
-    uint8_t m_trafficPriority;                    ///< traffic priority
-    uint32_t m_maxSustainedTrafficRate;           ///< maximum sustained traffic rate
-    uint32_t m_maxTrafficBurst;                   ///< maximum traffic burst
-    uint32_t m_minReservedTrafficRate;            ///< minimum reserved traffic rate
-    uint32_t m_minTolerableTrafficRate;           ///< minimum tolerable traffic rate
-    ServiceFlow::SchedulingType m_schedulingType; ///< scheduling type
-    uint32_t m_requestTransmissionPolicy;         ///< request transmission policy
-    uint32_t m_toleratedJitter;                   ///< tolerated jitter
-    uint32_t m_maximumLatency;                    ///< maximum latency
-    uint8_t m_fixedversusVariableSduIndicator;    ///< fixed versus variable SDI indicator
-    uint8_t m_sduSize;                            ///< SDU size
-    uint16_t m_targetSAID;                        ///< target SAID
-    uint8_t m_arqEnable;                          ///< ARQ enable
-    uint16_t m_arqWindowSize;                     ///< ARQ window size
-    uint16_t m_arqRetryTimeoutTx;                 ///< ARQ retry timeout transmit
-    uint16_t m_arqRetryTimeoutRx;                 ///< ARQ retry timeout receive
-    uint16_t m_arqBlockLifeTime;                  ///< ARQ block life time
-    uint16_t m_arqSyncLoss;                       ///< ARQ sync loss
-    uint8_t m_arqDeliverInOrder;                  ///< ARQ deliver in order
-    uint16_t m_arqPurgeTimeout;                   ///< ARQ purge timeout
-    uint16_t m_arqBlockSize;                      ///< ARQ block size
-    CsSpecification m_csSpecification;            ///< CS specification
-    CsParameters m_convergenceSublayerParam;      ///< convergence sublayer parameters
-    uint16_t m_unsolicitedGrantInterval;          ///< unsolicited grant interval
-    uint16_t m_unsolicitedPollingInterval;        ///< unsolicited polling interval
-    Direction m_direction;                        ///< direction
-    Type m_type;                                  ///< type
-    Ptr<WimaxConnection> m_connection;            ///< connection
-    bool m_isEnabled;                             ///< is enabled?
-    bool m_isMulticast;                           ///< is multicast?
-    WimaxPhy::ModulationType m_modulationType;    ///< modulation type
-    // will be used by the BS
-    ServiceFlowRecord* m_record; ///< service flow record
-};
-
-} // namespace ns3
-
-#endif /* SERVICE_FLOW_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/service-flow-manager.cc ns-3.46/src/wimax/model/service-flow-manager.cc
--- ns-3.45/src/wimax/model/service-flow-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/service-flow-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#include "service-flow-manager.h"
-
-#include "bs-net-device.h"
-#include "bs-uplink-scheduler.h"
-#include "connection-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-net-device.h"
-#include "ss-record.h"
-#include "ss-scheduler.h"
-#include "wimax-connection.h"
-#include "wimax-net-device.h"
-
-#include "ns3/buffer.h"
-#include "ns3/enum.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("ServiceFlowManager");
-
-NS_OBJECT_ENSURE_REGISTERED(ServiceFlowManager);
-
-TypeId
-ServiceFlowManager::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::ServiceFlowManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-ServiceFlowManager::ServiceFlowManager()
-{
-    m_serviceFlows = new std::vector<ServiceFlow*>;
-}
-
-ServiceFlowManager::~ServiceFlowManager()
-{
-}
-
-void
-ServiceFlowManager::DoDispose()
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        delete (*iter);
-    }
-    m_serviceFlows->clear();
-    delete m_serviceFlows;
-}
-
-void
-ServiceFlowManager::AddServiceFlow(ServiceFlow* serviceFlow)
-{
-    m_serviceFlows->push_back(serviceFlow);
-}
-
-ServiceFlow*
-ServiceFlowManager::DoClassify(Ipv4Address srcAddress,
-                               Ipv4Address dstAddress,
-                               uint16_t srcPort,
-                               uint16_t dstPort,
-                               uint8_t proto,
-                               ServiceFlow::Direction dir) const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetDirection() == dir)
-        {
-            if ((*iter)->CheckClassifierMatch(srcAddress, dstAddress, srcPort, dstPort, proto))
-            {
-                return *iter;
-            }
-        }
-    }
-    return nullptr;
-}
-
-ServiceFlow*
-ServiceFlowManager::GetServiceFlow(uint32_t sfid) const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetSfid() == sfid)
-        {
-            return *iter;
-        }
-    }
-
-    NS_LOG_DEBUG("GetServiceFlow: service flow not found!");
-    return nullptr;
-}
-
-ServiceFlow*
-ServiceFlowManager::GetServiceFlow(Cid cid) const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetCid() == cid.GetIdentifier())
-        {
-            return *iter;
-        }
-    }
-
-    NS_LOG_DEBUG("GetServiceFlow: service flow not found!");
-    return nullptr;
-}
-
-std::vector<ServiceFlow*>
-ServiceFlowManager::GetServiceFlows(ServiceFlow::SchedulingType schedulingType) const
-{
-    std::vector<ServiceFlow*> tmpServiceFlows;
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if (((*iter)->GetSchedulingType() == schedulingType) ||
-            (schedulingType == ServiceFlow::SF_TYPE_ALL))
-        {
-            tmpServiceFlows.push_back(*iter);
-        }
-    }
-    return tmpServiceFlows;
-}
-
-bool
-ServiceFlowManager::AreServiceFlowsAllocated()
-{
-    return AreServiceFlowsAllocated(m_serviceFlows);
-}
-
-bool
-ServiceFlowManager::AreServiceFlowsAllocated(std::vector<ServiceFlow*>* serviceFlowVector)
-{
-    return AreServiceFlowsAllocated(*serviceFlowVector);
-}
-
-bool
-ServiceFlowManager::AreServiceFlowsAllocated(std::vector<ServiceFlow*> serviceFlowVector)
-{
-    for (auto iter = serviceFlowVector.begin(); iter != serviceFlowVector.end(); ++iter)
-    {
-        if (!(*iter)->GetIsEnabled())
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-ServiceFlow*
-ServiceFlowManager::GetNextServiceFlowToAllocate()
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if (!(*iter)->GetIsEnabled())
-        {
-            return *iter;
-        }
-    }
-    return nullptr;
-}
-
-uint32_t
-ServiceFlowManager::GetNrServiceFlows() const
-{
-    return m_serviceFlows->size();
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/service-flow-manager.h ns-3.46/src/wimax/model/service-flow-manager.h
--- ns-3.45/src/wimax/model/service-flow-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/service-flow-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef SERVICE_FLOW_MANAGER_H
-#define SERVICE_FLOW_MANAGER_H
-
-#include "mac-messages.h"
-
-#include "ns3/buffer.h"
-#include "ns3/event-id.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class Packet;
-class ServiceFlow;
-class WimaxNetDevice;
-class SSRecord;
-class WimaxConnection;
-
-/**
- * @ingroup wimax
- * The same service flow manager class serves both for BS and SS though some functions are exclusive
- * to only one of them.
- */
-class ServiceFlowManager : public Object
-{
-  public:
-    /// confirmation code enumeration as per Table 384 (not all codes implemented)
-    enum ConfirmationCode
-    {
-        CONFIRMATION_CODE_SUCCESS,
-        CONFIRMATION_CODE_REJECT
-    };
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    ServiceFlowManager();
-    ~ServiceFlowManager() override;
-    void DoDispose() override;
-
-    /**
-     * Add service flow function
-     * @param serviceFlow the service flow
-     */
-    void AddServiceFlow(ServiceFlow* serviceFlow);
-    /**
-     * Get service flow by flow id
-     * @param sfid the service flow id
-     * @returns pointer to the service flow object corresponding to the flow id
-     */
-    ServiceFlow* GetServiceFlow(uint32_t sfid) const;
-    /**
-     * Get service flow by CID
-     * @param cid the CID
-     * @returns pointer to the service flow object corresponding to the CID
-     */
-    ServiceFlow* GetServiceFlow(Cid cid) const;
-    /**
-     * Get service flows function
-     * @param schedulingType the scheduling type
-     * @returns vector of pointers to service flows corresponding to the scheduling type
-     */
-    std::vector<ServiceFlow*> GetServiceFlows(ServiceFlow::SchedulingType schedulingType) const;
-
-    /**
-     * @return true if all service flows are allocated, false otherwise
-     */
-    bool AreServiceFlowsAllocated();
-    /**
-     * @param  serviceFlows vector of pointers to service flows to be checked
-     * @return true if all service flows are allocated, false otherwise
-     */
-    bool AreServiceFlowsAllocated(std::vector<ServiceFlow*>* serviceFlows);
-    /**
-     * @param  serviceFlows vector of pointers to service flows to be checked
-     * @return true if all service flows are allocated, false otherwise
-     */
-    bool AreServiceFlowsAllocated(std::vector<ServiceFlow*> serviceFlows);
-    /**
-     * @return pointer to the next service flow to be allocated
-     */
-    ServiceFlow* GetNextServiceFlowToAllocate();
-
-    /**
-     * @return the number of all service flows
-     */
-    uint32_t GetNrServiceFlows() const;
-
-    /**
-     * @param SrcAddress the source ip address
-     * @param DstAddress the destination ip address
-     * @param SrcPort the source port
-     * @param DstPort the destination port
-     * @param Proto the protocol
-     * @param dir the direction of the service flow
-     * @return the service flow to which this ip flow is associated
-     */
-    ServiceFlow* DoClassify(Ipv4Address SrcAddress,
-                            Ipv4Address DstAddress,
-                            uint16_t SrcPort,
-                            uint16_t DstPort,
-                            uint8_t Proto,
-                            ServiceFlow::Direction dir) const;
-
-  private:
-    std::vector<ServiceFlow*>* m_serviceFlows; ///< the service flows
-};
-
-} // namespace ns3
-
-#endif /* SERVICE_FLOW_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/service-flow-record.cc ns-3.46/src/wimax/model/service-flow-record.cc
--- ns-3.45/src/wimax/model/service-flow-record.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/service-flow-record.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "service-flow-record.h"
-
-namespace ns3
-{
-
-ServiceFlowRecord::ServiceFlowRecord()
-    : m_grantSize(0),
-      m_grantTimeStamp(),
-      m_dlTimeStamp(),
-      m_pktsSent(0),
-      m_pktsRcvd(0),
-      m_bytesSent(0),
-      m_bytesRcvd(0),
-      m_requestedBandwidth(0),
-      m_grantedBandwidth(0),
-      m_bwSinceLastExpiry(0)
-{
-    m_lastGrantTime = Seconds(0);
-    m_backlogged = 0;
-    m_backloggedTemp = 0;
-    m_grantedBandwidthTemp = 0;
-}
-
-ServiceFlowRecord::~ServiceFlowRecord()
-{
-}
-
-void
-ServiceFlowRecord::SetGrantSize(uint32_t grantSize)
-{
-    m_grantSize = grantSize;
-}
-
-uint32_t
-ServiceFlowRecord::GetGrantSize() const
-{
-    return m_grantSize;
-}
-
-void
-ServiceFlowRecord::SetGrantTimeStamp(Time grantTimeStamp)
-{
-    m_grantTimeStamp = grantTimeStamp;
-}
-
-Time
-ServiceFlowRecord::GetGrantTimeStamp() const
-{
-    return m_grantTimeStamp;
-}
-
-void
-ServiceFlowRecord::SetDlTimeStamp(Time dlTimeStamp)
-{
-    m_dlTimeStamp = dlTimeStamp;
-}
-
-Time
-ServiceFlowRecord::GetDlTimeStamp() const
-{
-    return m_dlTimeStamp;
-}
-
-void
-ServiceFlowRecord::SetPktsSent(uint32_t pktsSent)
-{
-    m_pktsSent = pktsSent;
-}
-
-void
-ServiceFlowRecord::UpdatePktsSent(uint32_t pktsSent)
-{
-    m_pktsSent += pktsSent;
-}
-
-uint32_t
-ServiceFlowRecord::GetPktsSent() const
-{
-    return m_pktsSent;
-}
-
-void
-ServiceFlowRecord::SetPktsRcvd(uint32_t pktsRcvd)
-{
-    m_pktsRcvd = pktsRcvd;
-}
-
-void
-ServiceFlowRecord::UpdatePktsRcvd(uint32_t pktsRcvd)
-{
-    m_pktsRcvd += pktsRcvd;
-}
-
-uint32_t
-ServiceFlowRecord::GetPktsRcvd() const
-{
-    return m_pktsRcvd;
-}
-
-void
-ServiceFlowRecord::SetBytesSent(uint32_t bytesSent)
-{
-    m_bytesSent = bytesSent;
-}
-
-void
-ServiceFlowRecord::UpdateBytesSent(uint32_t bytesSent)
-{
-    m_bytesSent += bytesSent;
-}
-
-uint32_t
-ServiceFlowRecord::GetBytesSent() const
-{
-    return m_bytesSent;
-}
-
-void
-ServiceFlowRecord::SetBytesRcvd(uint32_t bytesRcvd)
-{
-    m_bytesRcvd = bytesRcvd;
-}
-
-void
-ServiceFlowRecord::UpdateBytesRcvd(uint32_t bytesRcvd)
-{
-    m_bytesRcvd += bytesRcvd;
-}
-
-uint32_t
-ServiceFlowRecord::GetBytesRcvd() const
-{
-    return m_bytesRcvd;
-}
-
-void
-ServiceFlowRecord::SetRequestedBandwidth(uint32_t requestedBandwidth)
-{
-    m_requestedBandwidth = requestedBandwidth;
-}
-
-void
-ServiceFlowRecord::UpdateRequestedBandwidth(uint32_t requestedBandwidth)
-{
-    m_requestedBandwidth += requestedBandwidth;
-}
-
-uint32_t
-ServiceFlowRecord::GetRequestedBandwidth() const
-{
-    return m_requestedBandwidth;
-}
-
-void
-ServiceFlowRecord::SetGrantedBandwidth(uint32_t grantedBandwidth)
-{
-    m_grantedBandwidth = grantedBandwidth;
-}
-
-void
-ServiceFlowRecord::UpdateGrantedBandwidth(uint32_t grantedBandwidth)
-{
-    m_grantedBandwidth += grantedBandwidth;
-}
-
-uint32_t
-ServiceFlowRecord::GetGrantedBandwidth() const
-{
-    return m_grantedBandwidth;
-}
-
-void
-ServiceFlowRecord::SetGrantedBandwidthTemp(uint32_t grantedBandwidthTemp)
-{
-    m_grantedBandwidthTemp = grantedBandwidthTemp;
-}
-
-void
-ServiceFlowRecord::UpdateGrantedBandwidthTemp(uint32_t grantedBandwidthTemp)
-{
-    m_grantedBandwidthTemp += grantedBandwidthTemp;
-}
-
-uint32_t
-ServiceFlowRecord::GetGrantedBandwidthTemp() const
-{
-    return m_grantedBandwidthTemp;
-}
-
-void
-ServiceFlowRecord::SetLastGrantTime(Time grantTime)
-{
-    m_lastGrantTime = grantTime;
-}
-
-Time
-ServiceFlowRecord::GetLastGrantTime() const
-{
-    return m_lastGrantTime;
-}
-
-void
-ServiceFlowRecord::SetBacklogged(uint32_t backlogged)
-{
-    m_backlogged = backlogged;
-}
-
-void
-ServiceFlowRecord::IncreaseBacklogged(uint32_t backlogged)
-{
-    m_backlogged += backlogged;
-}
-
-uint32_t
-ServiceFlowRecord::GetBacklogged() const
-{
-    return m_backlogged;
-}
-
-void
-ServiceFlowRecord::SetBackloggedTemp(uint32_t backloggedTemp)
-{
-    m_backloggedTemp = backloggedTemp;
-}
-
-void
-ServiceFlowRecord::IncreaseBackloggedTemp(uint32_t backloggedTemp)
-{
-    m_backloggedTemp += backloggedTemp;
-}
-
-uint32_t
-ServiceFlowRecord::GetBackloggedTemp() const
-{
-    return m_backloggedTemp;
-}
-
-void
-ServiceFlowRecord::SetBwSinceLastExpiry(uint32_t bwSinceLastExpiry)
-{
-    m_bwSinceLastExpiry = bwSinceLastExpiry;
-}
-
-void
-ServiceFlowRecord::UpdateBwSinceLastExpiry(uint32_t bwSinceLastExpiry)
-{
-    m_bwSinceLastExpiry += bwSinceLastExpiry;
-}
-
-uint32_t
-ServiceFlowRecord::GetBwSinceLastExpiry() const
-{
-    return m_bwSinceLastExpiry;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/service-flow-record.h ns-3.46/src/wimax/model/service-flow-record.h
--- ns-3.45/src/wimax/model/service-flow-record.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/service-flow-record.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef SERVICE_FLOW_RECORD_H
-#define SERVICE_FLOW_RECORD_H
-
-#include "bs-net-device.h"
-#include "bs-uplink-scheduler.h"
-
-#include "ns3/nstime.h"
-#include "ns3/ptr.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief this class implements a structure to manage some parameters and statistics related to a
- * service flow
- */
-class ServiceFlowRecord
-{
-  public:
-    ServiceFlowRecord();
-    ~ServiceFlowRecord();
-
-    /**
-     * @brief Set the grant size (only for UGS service flows)
-     * @param grantSize the grant size to set
-     */
-    void SetGrantSize(uint32_t grantSize);
-    /**
-     * @return the grant size (only for ugs service flows)
-     */
-    uint32_t GetGrantSize() const;
-    /**
-     * @brief Set the grant time stamp. Used for data allocation for ugs flows, and unicast poll
-     * (bw request) for non-UGS flows
-     * @param grantTimeStamp the grant time stamp to set
-     */
-    void SetGrantTimeStamp(Time grantTimeStamp);
-    /**
-     * @return the grant time stamp. Used for data allocation for ugs flows, and unicast poll (bw
-     * request) for non-UGS flows
-     */
-    Time GetGrantTimeStamp() const;
-    /**
-     * @brief Set the DlTimeStamp.
-     * @param dlTimeStamp time when this service flow's traffic was last sent.
-     */
-    void SetDlTimeStamp(Time dlTimeStamp);
-    /**
-     * @return the DlTimeStamp: time when this service flow's traffic was last sent
-     */
-    Time GetDlTimeStamp() const;
-    /**
-     * @brief set the number of sent packets in this service flow
-     * @param pktsSent the number of sent packets
-     */
-    void SetPktsSent(uint32_t pktsSent);
-    /**
-     * @brief update the number of sent packets by adding pktsSent
-     * @param pktsSent the number of sent packets to add
-     */
-    void UpdatePktsSent(uint32_t pktsSent);
-    /**
-     * @return the number of sent packet in this service flow
-     */
-    uint32_t GetPktsSent() const;
-    /**
-     * @brief Set the number of received packets
-     * @param pktsRcvd The number of received packets
-     */
-    void SetPktsRcvd(uint32_t pktsRcvd);
-    /**
-     * @brief update the number of received packets by adding pktsRcvd
-     * @param pktsRcvd the number of received packets to add
-     */
-    void UpdatePktsRcvd(uint32_t pktsRcvd);
-    /**
-     * @return the number of received packet
-     */
-    uint32_t GetPktsRcvd() const;
-    /**
-     * @brief Set the number of sent bytes
-     * @param bytesSent the number of sent bytes
-     */
-    void SetBytesSent(uint32_t bytesSent);
-    /**
-     * @brief update the number of sent bytes by adding bytesSent
-     * @param bytesSent the number of bytes to add
-     */
-    void UpdateBytesSent(uint32_t bytesSent);
-    /**
-     * @return The number of sent bytes
-     */
-    uint32_t GetBytesSent() const;
-    /**
-     * @brief Set the number of received bytes
-     * @param bytesRcvd the number of received bytes
-     */
-    void SetBytesRcvd(uint32_t bytesRcvd);
-    /**
-     * @brief update the number of received bytes by adding bytesRcvd
-     * @param bytesRcvd the number of bytes to add
-     */
-    void UpdateBytesRcvd(uint32_t bytesRcvd);
-    /**
-     * @return The number of received bytes
-     */
-    uint32_t GetBytesRcvd() const;
-
-    /**
-     * @brief set the requested bandwidth
-     * @param requestedBandwidth the requested bandwidth
-     */
-    void SetRequestedBandwidth(uint32_t requestedBandwidth);
-    /**
-     * @brief update the requested bandwidth
-     * @param requestedBandwidth the requested bandwidth update
-     */
-    void UpdateRequestedBandwidth(uint32_t requestedBandwidth);
-    /**
-     * @return The requested bandwidth
-     */
-    uint32_t GetRequestedBandwidth() const;
-
-    /**
-     * @brief set the granted bandwidth
-     * @param grantedBandwidth the granted bandwidth
-     */
-    void SetGrantedBandwidth(uint32_t grantedBandwidth);
-    /**
-     * @brief update the granted bandwidth
-     * @param grantedBandwidth the granted bandwidth update
-     */
-    void UpdateGrantedBandwidth(uint32_t grantedBandwidth);
-    /**
-     * @return The granted bandwidth
-     */
-    uint32_t GetGrantedBandwidth() const;
-
-    /**
-     * @brief set the temporary granted bandwidth
-     * @param grantedBandwidthTemp the temporary granted bandwidth
-     */
-    void SetGrantedBandwidthTemp(uint32_t grantedBandwidthTemp);
-    /**
-     * @brief update the temporary granted bandwidth
-     * @param grantedBandwidthTemp the temporary granted bandwidth
-     */
-    void UpdateGrantedBandwidthTemp(uint32_t grantedBandwidthTemp);
-    /**
-     * @return The temporary granted bandwidth
-     */
-    uint32_t GetGrantedBandwidthTemp() const;
-
-    /**
-     * @brief set BW since last expiry
-     * @param bwSinceLastExpiry bandwidth since last expiry
-     */
-    void SetBwSinceLastExpiry(uint32_t bwSinceLastExpiry);
-    /**
-     * @brief update BW since last expiry
-     * @param bwSinceLastExpiry bandwidth since last expiry
-     */
-    void UpdateBwSinceLastExpiry(uint32_t bwSinceLastExpiry);
-    /**
-     * @return The bandwidth since last expiry
-     */
-    uint32_t GetBwSinceLastExpiry() const;
-
-    /**
-     * @brief set last grant time
-     * @param grantTime  grant time to set
-     */
-    void SetLastGrantTime(Time grantTime);
-    /**
-     * @return The last grant time
-     */
-    Time GetLastGrantTime() const;
-
-    /**
-     * @brief set backlogged
-     * @param backlogged number of backlogged
-     */
-    void SetBacklogged(uint32_t backlogged);
-    /**
-     * @brief increase backlogged
-     * @param backlogged the number of backlogged to update
-     */
-    void IncreaseBacklogged(uint32_t backlogged);
-    /**
-     * @return The number of backlogged
-     */
-    uint32_t GetBacklogged() const;
-
-    /**
-     * @brief set temporary back logged
-     * @param backloggedTemp the temporary backlogged value
-     */
-    void SetBackloggedTemp(uint32_t backloggedTemp);
-    /**
-     * @brief increase temporary back logged
-     * @param backloggedTemp the temporary backlogged value
-     */
-    void IncreaseBackloggedTemp(uint32_t backloggedTemp);
-    /**
-     * @return The value of temporary backlogged
-     */
-    uint32_t GetBackloggedTemp() const;
-
-  private:
-    uint32_t m_grantSize;  ///< only used for UGS flow
-    Time m_grantTimeStamp; ///< allocation (for data) for UGS flows and unicast poll (for bandwidth
-                           ///< requests) for non-UGS flows
-    Time m_dlTimeStamp;    ///< time when this service flow's traffic was last sent
-
-    // stats members
-    uint32_t m_pktsSent; ///< packets sent
-    uint32_t m_pktsRcvd; ///< packets received
-
-    uint32_t m_bytesSent; ///< bytes sent
-    uint32_t m_bytesRcvd; ///< bytes received
-
-    uint32_t m_requestedBandwidth;   ///< requested bandwidth
-    uint32_t m_grantedBandwidth;     ///< granted badnwidth
-    uint32_t m_grantedBandwidthTemp; ///< Temporary variable used to sort list. Necessary to keep
-                                     ///< original order
-
-    /** bandwidth granted since last expiry of minimum reserved traffic rate interval,
-     * only for nrtPS, to make sure minimum reserved traffic rate is maintained */
-    uint32_t m_bwSinceLastExpiry;
-    Time m_lastGrantTime;     ///< last grant time
-    int32_t m_backlogged;     ///< back logged
-    int32_t m_backloggedTemp; ///< back logged temp
-};
-
-} // namespace ns3
-
-#endif /* SERVICE_FLOW_RECORD_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/simple-ofdm-send-param.cc ns-3.46/src/wimax/model/simple-ofdm-send-param.cc
--- ns-3.45/src/wimax/model/simple-ofdm-send-param.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/simple-ofdm-send-param.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,156 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#include "simple-ofdm-send-param.h"
-
-#include "simple-ofdm-wimax-channel.h"
-#include "simple-ofdm-wimax-phy.h"
-
-namespace ns3
-{
-SimpleOfdmSendParam::SimpleOfdmSendParam()
-{
-    // m_fecBlock = 0;
-    m_burstSize = 0;
-    m_isFirstBlock = false;
-    m_frequency = 0;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_QPSK_12;
-    m_direction = 0;
-    m_rxPowerDbm = 0;
-}
-
-SimpleOfdmSendParam::SimpleOfdmSendParam(const Bvec& fecBlock,
-                                         uint32_t burstSize,
-                                         bool isFirstBlock,
-                                         uint64_t Frequency,
-                                         WimaxPhy::ModulationType modulationType,
-                                         uint8_t direction,
-                                         double rxPowerDbm)
-{
-    m_fecBlock = fecBlock;
-    m_burstSize = burstSize;
-    m_isFirstBlock = isFirstBlock;
-    m_frequency = Frequency;
-    m_modulationType = modulationType;
-    m_direction = direction;
-    m_rxPowerDbm = rxPowerDbm;
-}
-
-SimpleOfdmSendParam::SimpleOfdmSendParam(uint32_t burstSize,
-                                         bool isFirstBlock,
-                                         uint64_t Frequency,
-                                         WimaxPhy::ModulationType modulationType,
-                                         uint8_t direction,
-                                         double rxPowerDbm,
-                                         Ptr<PacketBurst> burst)
-{
-    m_burstSize = burstSize;
-    m_isFirstBlock = isFirstBlock;
-    m_frequency = Frequency;
-    m_modulationType = modulationType;
-    m_direction = direction;
-    m_rxPowerDbm = rxPowerDbm;
-    m_burst = burst;
-}
-
-SimpleOfdmSendParam::~SimpleOfdmSendParam()
-{
-}
-
-void
-SimpleOfdmSendParam::SetFecBlock(const Bvec& fecBlock)
-{
-    m_fecBlock = fecBlock;
-}
-
-void
-SimpleOfdmSendParam::SetBurstSize(uint32_t burstSize)
-{
-    m_burstSize = burstSize;
-}
-
-void
-SimpleOfdmSendParam::SetIsFirstBlock(bool isFirstBlock)
-{
-    m_isFirstBlock = isFirstBlock;
-}
-
-void
-SimpleOfdmSendParam::SetFrequency(uint64_t Frequency)
-{
-    m_frequency = Frequency;
-}
-
-void
-SimpleOfdmSendParam::SetModulationType(WimaxPhy::ModulationType modulationType)
-{
-    m_modulationType = modulationType;
-}
-
-void
-SimpleOfdmSendParam::SetDirection(uint8_t direction)
-{
-    m_direction = direction;
-}
-
-void
-SimpleOfdmSendParam::SetRxPowerDbm(double rxPowerDbm)
-{
-    m_rxPowerDbm = rxPowerDbm;
-}
-
-Bvec
-SimpleOfdmSendParam::GetFecBlock()
-{
-    return m_fecBlock;
-}
-
-uint32_t
-SimpleOfdmSendParam::GetBurstSize() const
-{
-    return m_burstSize;
-}
-
-bool
-SimpleOfdmSendParam::GetIsFirstBlock() const
-{
-    return m_isFirstBlock;
-}
-
-uint64_t
-SimpleOfdmSendParam::GetFrequency() const
-{
-    return m_frequency;
-}
-
-WimaxPhy::ModulationType
-SimpleOfdmSendParam::GetModulationType()
-{
-    return m_modulationType;
-}
-
-uint8_t
-SimpleOfdmSendParam::GetDirection() const
-{
-    return m_direction;
-}
-
-double
-SimpleOfdmSendParam::GetRxPowerDbm() const
-{
-    return m_rxPowerDbm;
-}
-
-Ptr<PacketBurst>
-SimpleOfdmSendParam::GetBurst()
-{
-    return m_burst;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/simple-ofdm-send-param.h ns-3.46/src/wimax/model/simple-ofdm-send-param.h
--- ns-3.45/src/wimax/model/simple-ofdm-send-param.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/simple-ofdm-send-param.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,145 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef SIMPLE_OFDM_SEND_PARAM_H
-#define SIMPLE_OFDM_SEND_PARAM_H
-
-#include "bvec.h"
-#include "wimax-channel.h"
-#include "wimax-phy.h"
-
-#include "ns3/propagation-loss-model.h"
-
-#include <list>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * SimpleOfdmSendParam class
- */
-class SimpleOfdmSendParam
-{
-  public:
-    SimpleOfdmSendParam();
-    /**
-     * Constructor
-     *
-     * @param fecBlock FEC block
-     * @param burstSize burst size
-     * @param isFirstBlock is the first block
-     * @param Frequency frequency
-     * @param modulationType modulation type
-     * @param direction the direction
-     * @param rxPowerDbm receive power
-     */
-    SimpleOfdmSendParam(const Bvec& fecBlock,
-                        uint32_t burstSize,
-                        bool isFirstBlock,
-                        uint64_t Frequency,
-                        WimaxPhy::ModulationType modulationType,
-                        uint8_t direction,
-                        double rxPowerDbm);
-    /**
-     * Constructor
-     *
-     * @param burstSize burst size
-     * @param isFirstBlock is the first block
-     * @param Frequency frequency
-     * @param modulationType modulation type
-     * @param direction the direction
-     * @param rxPowerDbm receive power
-     * @param burst packet burst object
-     */
-    SimpleOfdmSendParam(uint32_t burstSize,
-                        bool isFirstBlock,
-                        uint64_t Frequency,
-                        WimaxPhy::ModulationType modulationType,
-                        uint8_t direction,
-                        double rxPowerDbm,
-                        Ptr<PacketBurst> burst);
-    ~SimpleOfdmSendParam();
-    /**
-     * @brief sent the fec block to send
-     * @param fecBlock the fec block to send
-     */
-    void SetFecBlock(const Bvec& fecBlock);
-    /**
-     * @brief set the burst size
-     * @param burstSize the burst size in bytes
-     */
-    void SetBurstSize(uint32_t burstSize);
-    /**
-     * @param isFirstBlock Set to true if this fec block is the first one in the burst, set to false
-     * otherwise
-     */
-    void SetIsFirstBlock(bool isFirstBlock);
-    /**
-     * @param Frequency set the frequency of the channel in which this fec block will be sent
-     */
-    void SetFrequency(uint64_t Frequency);
-    /**
-     * @param modulationType the modulation type used to send this fec block
-     */
-    void SetModulationType(WimaxPhy::ModulationType modulationType);
-    /**
-     * @param direction the direction on which this fec block will be sent
-     */
-    void SetDirection(uint8_t direction);
-    /**
-     * @param rxPowerDbm the received power
-     */
-    void SetRxPowerDbm(double rxPowerDbm);
-    /**
-     * @return the fec block
-     */
-    Bvec GetFecBlock();
-    /**
-     * @return the burst size
-     */
-    uint32_t GetBurstSize() const;
-    /**
-     * @return true if this fec block is the first one in the burst, false otherwise
-     */
-    bool GetIsFirstBlock() const;
-    /**
-     * @return the frequency on which the fec block is sent/received
-     */
-    uint64_t GetFrequency() const;
-    /**
-     * @return the modulation type used to send this fec block
-     */
-    WimaxPhy::ModulationType GetModulationType();
-    /**
-     * @return the direction on which this fec block was sent. UP or DOWN
-     */
-    uint8_t GetDirection() const;
-    /**
-     * @return the Received power
-     */
-    double GetRxPowerDbm() const;
-    /**
-     * @return the received burst
-     */
-    Ptr<PacketBurst> GetBurst();
-
-  private:
-    Bvec m_fecBlock;                           ///< FEC block
-    uint32_t m_burstSize;                      ///< burst size
-    bool m_isFirstBlock;                       ///< is first block
-    uint64_t m_frequency;                      ///< frequency
-    WimaxPhy::ModulationType m_modulationType; ///< modulation type
-    uint8_t m_direction;                       ///< direction
-    double m_rxPowerDbm;                       ///< receive power dbM
-    Ptr<PacketBurst> m_burst;                  ///< burst
-};
-} // namespace ns3
-
-#endif /* SIMPLE_OFDM_SEND_PARAM_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/simple-ofdm-wimax-channel.cc ns-3.46/src/wimax/model/simple-ofdm-wimax-channel.cc
--- ns-3.45/src/wimax/model/simple-ofdm-wimax-channel.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/simple-ofdm-wimax-channel.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,218 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#include "simple-ofdm-wimax-channel.h"
-
-#include "simple-ofdm-send-param.h"
-#include "simple-ofdm-wimax-phy.h"
-#include "wimax-phy.h"
-
-#include "ns3/assert.h"
-#include "ns3/callback.h"
-#include "ns3/cost231-propagation-loss-model.h"
-#include "ns3/event-id.h"
-#include "ns3/mobility-model.h"
-#include "ns3/net-device.h"
-#include "ns3/node.h"
-#include "ns3/nstime.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("simpleOfdmWimaxChannel");
-
-// NS_OBJECT_ENSURE_REGISTERED (simpleOfdmWimaxChannel);
-
-SimpleOfdmWimaxChannel::SimpleOfdmWimaxChannel()
-{
-    m_loss = nullptr;
-}
-
-SimpleOfdmWimaxChannel::~SimpleOfdmWimaxChannel()
-{
-    m_phyList.clear();
-}
-
-/* static */
-TypeId
-SimpleOfdmWimaxChannel::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::SimpleOfdmWimaxChannel")
-                            .SetParent<WimaxChannel>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<SimpleOfdmWimaxChannel>();
-    return tid;
-}
-
-SimpleOfdmWimaxChannel::SimpleOfdmWimaxChannel(PropModel propModel)
-{
-    switch (propModel)
-    {
-    case RANDOM_PROPAGATION:
-        m_loss = CreateObject<RandomPropagationLossModel>();
-        break;
-
-    case FRIIS_PROPAGATION:
-        m_loss = CreateObject<FriisPropagationLossModel>();
-        break;
-    case LOG_DISTANCE_PROPAGATION:
-        m_loss = CreateObject<LogDistancePropagationLossModel>();
-        break;
-
-    case COST231_PROPAGATION:
-        m_loss = CreateObject<Cost231PropagationLossModel>();
-        break;
-
-    default:
-        m_loss = nullptr;
-    }
-}
-
-void
-SimpleOfdmWimaxChannel::SetPropagationModel(PropModel propModel)
-{
-    switch (propModel)
-    {
-    case RANDOM_PROPAGATION:
-        m_loss = CreateObject<RandomPropagationLossModel>();
-        break;
-
-    case FRIIS_PROPAGATION:
-        m_loss = CreateObject<FriisPropagationLossModel>();
-        break;
-    case LOG_DISTANCE_PROPAGATION:
-        m_loss = CreateObject<LogDistancePropagationLossModel>();
-        break;
-
-    case COST231_PROPAGATION:
-        m_loss = CreateObject<Cost231PropagationLossModel>();
-        break;
-
-    default:
-        m_loss = nullptr;
-    }
-}
-
-void
-SimpleOfdmWimaxChannel::DoAttach(Ptr<WimaxPhy> phy)
-{
-    Ptr<SimpleOfdmWimaxPhy> o_phy = phy->GetObject<SimpleOfdmWimaxPhy>();
-    m_phyList.push_back(o_phy);
-}
-
-std::size_t
-SimpleOfdmWimaxChannel::DoGetNDevices() const
-{
-    return m_phyList.size();
-}
-
-Ptr<NetDevice>
-SimpleOfdmWimaxChannel::DoGetDevice(std::size_t index) const
-{
-    std::size_t j = 0;
-    for (auto iter = m_phyList.begin(); iter != m_phyList.end(); ++iter)
-    {
-        if (j == index)
-        {
-            return (*iter)->GetDevice();
-        }
-        j++;
-    }
-
-    NS_FATAL_ERROR("Unable to get device");
-    return nullptr;
-}
-
-void
-SimpleOfdmWimaxChannel::Send(Time BlockTime,
-                             uint32_t burstSize,
-                             Ptr<WimaxPhy> phy,
-                             bool isFirstBlock,
-                             bool isLastBlock,
-                             uint64_t frequency,
-                             WimaxPhy::ModulationType modulationType,
-                             uint8_t direction,
-                             double txPowerDbm,
-                             Ptr<PacketBurst> burst)
-{
-    double rxPowerDbm = 0;
-    Ptr<MobilityModel> senderMobility = nullptr;
-    Ptr<MobilityModel> receiverMobility = nullptr;
-    senderMobility = phy->GetDevice()->GetNode()->GetObject<MobilityModel>();
-    SimpleOfdmSendParam* param;
-    for (auto iter = m_phyList.begin(); iter != m_phyList.end(); ++iter)
-    {
-        Time delay;
-        if (phy != *iter)
-        {
-            double distance = 0;
-            receiverMobility = (*iter)->GetDevice()->GetNode()->GetObject<MobilityModel>();
-            if (receiverMobility && senderMobility && m_loss)
-            {
-                distance = senderMobility->GetDistanceFrom(receiverMobility);
-                delay = Seconds(distance / 300000000.0);
-                rxPowerDbm = m_loss->CalcRxPower(txPowerDbm, senderMobility, receiverMobility);
-            }
-
-            param = new SimpleOfdmSendParam(burstSize,
-                                            isFirstBlock,
-                                            frequency,
-                                            modulationType,
-                                            direction,
-                                            rxPowerDbm,
-                                            burst);
-            Ptr<Object> dstNetDevice = (*iter)->GetDevice();
-            uint32_t dstNode;
-            if (!dstNetDevice)
-            {
-                dstNode = 0xffffffff;
-            }
-            else
-            {
-                dstNode = dstNetDevice->GetObject<NetDevice>()->GetNode()->GetId();
-            }
-            Simulator::ScheduleWithContext(dstNode,
-                                           delay,
-                                           &SimpleOfdmWimaxChannel::EndSendDummyBlock,
-                                           this,
-                                           *iter,
-                                           param);
-        }
-    }
-}
-
-void
-SimpleOfdmWimaxChannel::EndSendDummyBlock(Ptr<SimpleOfdmWimaxPhy> rxphy, SimpleOfdmSendParam* param)
-{
-    rxphy->StartReceive(param->GetBurstSize(),
-                        param->GetIsFirstBlock(),
-                        param->GetFrequency(),
-                        param->GetModulationType(),
-                        param->GetDirection(),
-                        param->GetRxPowerDbm(),
-                        param->GetBurst());
-    delete param;
-}
-
-int64_t
-SimpleOfdmWimaxChannel::AssignStreams(int64_t stream)
-{
-    int64_t currentStream = stream;
-    for (auto i = m_phyList.begin(); i != m_phyList.end(); i++)
-    {
-        Ptr<SimpleOfdmWimaxPhy> simpleOfdm = (*i);
-        currentStream += simpleOfdm->AssignStreams(currentStream);
-    }
-    return (currentStream - stream);
-}
-
-} // namespace ns3
-
-// namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/simple-ofdm-wimax-channel.h ns-3.46/src/wimax/model/simple-ofdm-wimax-channel.h
--- ns-3.45/src/wimax/model/simple-ofdm-wimax-channel.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/simple-ofdm-wimax-channel.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,128 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef SIMPLE_OFDM_WIMAX_CHANNEL_H
-#define SIMPLE_OFDM_WIMAX_CHANNEL_H
-
-#include "bvec.h"
-#include "simple-ofdm-send-param.h"
-#include "wimax-channel.h"
-#include "wimax-phy.h"
-
-#include "ns3/propagation-loss-model.h"
-
-#include <list>
-
-namespace ns3
-{
-
-class Packet;
-class PacketBurst;
-class SimpleOfdmWimaxPhy;
-
-/**
- * @ingroup wimax
- * @brief SimpleOfdmWimaxChannel class
- */
-class SimpleOfdmWimaxChannel : public WimaxChannel
-{
-  public:
-    SimpleOfdmWimaxChannel();
-    ~SimpleOfdmWimaxChannel() override;
-
-    /// PropModel enumeration
-    enum PropModel
-    {
-        RANDOM_PROPAGATION,
-        FRIIS_PROPAGATION,
-        LOG_DISTANCE_PROPAGATION,
-        COST231_PROPAGATION
-    };
-
-    /**
-     * Register this type.
-     * @return The TypeId.
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief Creates a channel and sets the propagation model
-     * @param propModel the propagation model to use
-     */
-    SimpleOfdmWimaxChannel(PropModel propModel);
-
-    /**
-     * @brief Sends a dummy fec block to all connected physical devices
-     * @param BlockTime the time needed to send the block
-     * @param burstSize the size of the burst
-     * @param phy the sender device
-     * @param isFirstBlock true if this block is the first one, false otherwise
-     * @param isLastBlock true if this block is the last one, false otherwise
-     * @param frequency the frequency on which the block is sent
-     * @param modulationType the modulation used to send the fec block
-     * @param direction uplink or downlink
-     * @param txPowerDbm the transmission power
-     * @param burst the packet burst to send
-     */
-    void Send(Time BlockTime,
-              uint32_t burstSize,
-              Ptr<WimaxPhy> phy,
-              bool isFirstBlock,
-              bool isLastBlock,
-              uint64_t frequency,
-              WimaxPhy::ModulationType modulationType,
-              uint8_t direction,
-              double txPowerDbm,
-              Ptr<PacketBurst> burst);
-    /**
-     * @brief sets the propagation model
-     * @param propModel the propagation model to used
-     */
-    void SetPropagationModel(PropModel propModel);
-
-    /**
-     * Assign a fixed random variable stream number to the random variables
-     * used by this model.  Return the number of streams (possibly zero) that
-     * have been assigned.
-     *
-     * @param stream first stream index to use
-     * @return the number of stream indices assigned by this model
-     */
-    int64_t AssignStreams(int64_t stream) override;
-
-  private:
-    /**
-     * Attach function
-     * @param phy the phy layer
-     */
-    void DoAttach(Ptr<WimaxPhy> phy) override;
-    std::list<Ptr<SimpleOfdmWimaxPhy>> m_phyList; ///< phy list
-    /**
-     * Get number of devices function
-     * @returns the number of devices
-     */
-    std::size_t DoGetNDevices() const override;
-    /**
-     * End send dummy block function
-     * @param rxphy the Ptr<SimpleOfdmWimaxPhy>
-     * @param param the SimpleOfdmSendParam *
-     */
-    void EndSendDummyBlock(Ptr<SimpleOfdmWimaxPhy> rxphy, SimpleOfdmSendParam* param);
-    /**
-     * Get device function
-     * @param i the device index
-     * @returns the device
-     */
-    Ptr<NetDevice> DoGetDevice(std::size_t i) const override;
-    Ptr<PropagationLossModel> m_loss; ///< loss
-};
-
-} // namespace ns3
-
-#endif /* SIMPLE_OFDM_WIMAX_CHANNEL_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/simple-ofdm-wimax-phy.cc ns-3.46/src/wimax/model/simple-ofdm-wimax-phy.cc
--- ns-3.45/src/wimax/model/simple-ofdm-wimax-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/simple-ofdm-wimax-phy.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,1088 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#include "simple-ofdm-wimax-phy.h"
-
-#include "simple-ofdm-wimax-channel.h"
-#include "wimax-channel.h"
-#include "wimax-mac-header.h"
-#include "wimax-net-device.h"
-
-#include "ns3/double.h"
-#include "ns3/node.h"
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-#include "ns3/simulator.h"
-#include "ns3/string.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-
-#include <cmath>
-#include <string>
-#include <vector>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SimpleOfdmWimaxPhy");
-
-NS_OBJECT_ENSURE_REGISTERED(SimpleOfdmWimaxPhy);
-
-TypeId
-SimpleOfdmWimaxPhy::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::SimpleOfdmWimaxPhy")
-            .SetParent<WimaxPhy>()
-            .SetGroupName("Wimax")
-
-            .AddConstructor<SimpleOfdmWimaxPhy>()
-
-            .AddAttribute(
-                "NoiseFigure",
-                "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver.",
-                DoubleValue(5),
-                MakeDoubleAccessor(&SimpleOfdmWimaxPhy::SetNoiseFigure,
-                                   &SimpleOfdmWimaxPhy::GetNoiseFigure),
-                MakeDoubleChecker<double>())
-
-            .AddAttribute("TxPower",
-                          "Transmission power (dB).",
-                          DoubleValue(30),
-                          MakeDoubleAccessor(&SimpleOfdmWimaxPhy::SetTxPower,
-                                             &SimpleOfdmWimaxPhy::GetTxPower),
-                          MakeDoubleChecker<double>())
-
-            .AddAttribute("G",
-                          "This is the ratio of CP time to useful time.",
-                          DoubleValue(0.25),
-                          MakeDoubleAccessor(&SimpleOfdmWimaxPhy::DoSetGValue,
-                                             &SimpleOfdmWimaxPhy::DoGetGValue),
-                          MakeDoubleChecker<double>())
-
-            .AddAttribute(
-                "TxGain",
-                "Transmission gain (dB).",
-                DoubleValue(0),
-                MakeDoubleAccessor(&SimpleOfdmWimaxPhy::SetTxGain, &SimpleOfdmWimaxPhy::GetTxGain),
-                MakeDoubleChecker<double>())
-
-            .AddAttribute(
-                "RxGain",
-                "Reception gain (dB).",
-                DoubleValue(0),
-                MakeDoubleAccessor(&SimpleOfdmWimaxPhy::SetRxGain, &SimpleOfdmWimaxPhy::GetRxGain),
-                MakeDoubleChecker<double>())
-
-            .AddAttribute("Nfft",
-                          "FFT size",
-                          UintegerValue(256),
-                          MakeUintegerAccessor(&SimpleOfdmWimaxPhy::DoSetNfft,
-                                               &SimpleOfdmWimaxPhy::DoGetNfft),
-                          MakeUintegerChecker<uint16_t>(256, 1024))
-
-            .AddAttribute("TraceFilePath",
-                          "Path to the directory containing SNR to block error rate files",
-                          StringValue(""),
-                          MakeStringAccessor(&SimpleOfdmWimaxPhy::GetTraceFilePath,
-                                             &SimpleOfdmWimaxPhy::SetTraceFilePath),
-                          MakeStringChecker())
-
-            .AddTraceSource("Rx",
-                            "Receive trace",
-                            MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_traceRx),
-                            "ns3::PacketBurst::TracedCallback")
-            .AddTraceSource("Tx",
-                            "Transmit trace",
-                            MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_traceTx),
-                            "ns3::PacketBurst::TracedCallback")
-
-            .AddTraceSource(
-                "PhyTxBegin",
-                "Trace source indicating a packet has begun transmitting over the channel medium",
-                MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_phyTxBeginTrace),
-                "ns3::PacketBurst::TracedCallback")
-
-            .AddTraceSource(
-                "PhyTxEnd",
-                "Trace source indicating a packet has been completely transmitted over the channel",
-                MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_phyTxEndTrace),
-                "ns3::PacketBurst::TracedCallback")
-
-            .AddTraceSource("PhyTxDrop",
-                            "Trace source indicating a packet has been dropped by the device "
-                            "during transmission",
-                            MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_phyTxDropTrace),
-                            "ns3::PacketBurst::TracedCallback")
-
-            .AddTraceSource("PhyRxBegin",
-                            "Trace source indicating a packet has begun being received from the "
-                            "channel medium by the device",
-                            MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_phyRxBeginTrace),
-                            "ns3::PacketBurst::TracedCallback")
-
-            .AddTraceSource("PhyRxEnd",
-                            "Trace source indicating a packet has been completely received from "
-                            "the channel medium by the device",
-                            MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_phyRxEndTrace),
-                            "ns3::PacketBurst::TracedCallback")
-
-            .AddTraceSource(
-                "PhyRxDrop",
-                "Trace source indicating a packet has been dropped by the device during reception",
-                MakeTraceSourceAccessor(&SimpleOfdmWimaxPhy::m_phyRxDropTrace),
-                "ns3::PacketBurst::TracedCallback");
-    return tid;
-}
-
-void
-SimpleOfdmWimaxPhy::InitSimpleOfdmWimaxPhy()
-{
-    m_fecBlockSize = 0;
-    m_nrFecBlocksSent = 0;
-    m_dataRateBpsk12 = 0;
-    m_dataRateQpsk12 = 0;
-    m_dataRateQpsk34 = 0;
-    m_dataRateQam16_12 = 0;
-
-    m_dataRateQam16_34 = 0;
-    m_dataRateQam64_23 = 0;
-    m_dataRateQam64_34 = 0;
-
-    m_nrBlocks = 0;
-    m_blockSize = 0;
-    m_paddingBits = 0;
-    m_rxGain = 0;
-    m_txGain = 0;
-    m_nfft = 256;
-    m_g = 1.0 / 4;
-    SetNrCarriers(192);
-    m_fecBlocks = new std::list<Bvec>;
-    m_receivedFecBlocks = new std::list<Bvec>;
-    m_currentBurstSize = 0;
-    m_noiseFigure = 5;      // dB
-    m_txPower = 30;         // dBm
-    SetBandwidth(10000000); // 10Mhz
-    m_nbErroneousBlock = 0;
-    m_nrReceivedFecBlocks = 0;
-    m_snrToBlockErrorRateManager = new SNRToBlockErrorRateManager();
-}
-
-SimpleOfdmWimaxPhy::SimpleOfdmWimaxPhy()
-{
-    m_URNG = CreateObject<UniformRandomVariable>();
-
-    InitSimpleOfdmWimaxPhy();
-    m_snrToBlockErrorRateManager->SetTraceFilePath((char*)"");
-    m_snrToBlockErrorRateManager->LoadTraces();
-}
-
-SimpleOfdmWimaxPhy::SimpleOfdmWimaxPhy(char* tracesPath)
-{
-    InitSimpleOfdmWimaxPhy();
-    m_snrToBlockErrorRateManager->SetTraceFilePath(tracesPath);
-    m_snrToBlockErrorRateManager->LoadTraces();
-}
-
-SimpleOfdmWimaxPhy::~SimpleOfdmWimaxPhy()
-{
-}
-
-void
-SimpleOfdmWimaxPhy::ActivateLoss(bool loss)
-{
-    m_snrToBlockErrorRateManager->ActivateLoss(loss);
-}
-
-void
-SimpleOfdmWimaxPhy::SetSNRToBlockErrorRateTracesPath(char* tracesPath)
-{
-    m_snrToBlockErrorRateManager->SetTraceFilePath(tracesPath);
-    m_snrToBlockErrorRateManager->ReLoadTraces();
-}
-
-uint32_t
-SimpleOfdmWimaxPhy::GetBandwidth() const
-{
-    return WimaxPhy::GetChannelBandwidth();
-}
-
-void
-SimpleOfdmWimaxPhy::SetBandwidth(uint32_t BW)
-{
-    WimaxPhy::SetChannelBandwidth(BW);
-}
-
-double
-SimpleOfdmWimaxPhy::GetTxPower() const
-{
-    return m_txPower;
-}
-
-void
-SimpleOfdmWimaxPhy::SetTxPower(double txPower)
-{
-    m_txPower = txPower;
-}
-
-double
-SimpleOfdmWimaxPhy::GetNoiseFigure() const
-{
-    return m_noiseFigure;
-}
-
-void
-SimpleOfdmWimaxPhy::SetNoiseFigure(double noiseFigure)
-{
-    m_noiseFigure = noiseFigure;
-}
-
-void
-SimpleOfdmWimaxPhy::DoDispose()
-{
-    delete m_receivedFecBlocks;
-    delete m_fecBlocks;
-    m_receivedFecBlocks = nullptr;
-    m_fecBlocks = nullptr;
-    delete m_snrToBlockErrorRateManager;
-    WimaxPhy::DoDispose();
-}
-
-void
-SimpleOfdmWimaxPhy::DoAttach(Ptr<WimaxChannel> channel)
-{
-    GetChannel()->Attach(this);
-}
-
-void
-SimpleOfdmWimaxPhy::Send(SendParams* params)
-{
-    auto o_params = dynamic_cast<OfdmSendParams*>(params);
-    NS_ASSERT(o_params != nullptr);
-    Send(o_params->GetBurst(),
-         (WimaxPhy::ModulationType)o_params->GetModulationType(),
-         o_params->GetDirection());
-}
-
-WimaxPhy::PhyType
-SimpleOfdmWimaxPhy::GetPhyType() const
-{
-    return WimaxPhy::simpleOfdmWimaxPhy;
-}
-
-void
-SimpleOfdmWimaxPhy::Send(Ptr<PacketBurst> burst,
-                         WimaxPhy::ModulationType modulationType,
-                         uint8_t direction)
-{
-    if (GetState() != PHY_STATE_TX)
-    {
-        m_currentBurstSize = burst->GetSize();
-        m_nrFecBlocksSent = 0;
-        m_currentBurst = burst;
-        SetBlockParameters(burst->GetSize(), modulationType);
-        NotifyTxBegin(m_currentBurst);
-        StartSendDummyFecBlock(true, modulationType, direction);
-        m_traceTx(burst);
-    }
-}
-
-void
-SimpleOfdmWimaxPhy::StartSendDummyFecBlock(bool isFirstBlock,
-                                           WimaxPhy::ModulationType modulationType,
-                                           uint8_t direction)
-{
-    SetState(PHY_STATE_TX);
-    bool isLastFecBlock = false;
-    if (isFirstBlock)
-    {
-        m_blockTime = GetBlockTransmissionTime(modulationType);
-    }
-
-    SimpleOfdmWimaxChannel* channel =
-        dynamic_cast<SimpleOfdmWimaxChannel*>(PeekPointer(GetChannel()));
-    NS_ASSERT(channel != nullptr);
-
-    isLastFecBlock = (m_nrRemainingBlocksToSend == 1);
-    channel->Send(m_blockTime,
-                  m_currentBurstSize,
-                  this,
-                  isFirstBlock,
-                  isLastFecBlock,
-                  GetTxFrequency(),
-                  modulationType,
-                  direction,
-                  m_txPower,
-                  m_currentBurst);
-
-    m_nrRemainingBlocksToSend--;
-    Simulator::Schedule(m_blockTime,
-                        &SimpleOfdmWimaxPhy::EndSendFecBlock,
-                        this,
-                        modulationType,
-                        direction);
-}
-
-void
-SimpleOfdmWimaxPhy::EndSendFecBlock(WimaxPhy::ModulationType modulationType, uint8_t direction)
-{
-    m_nrFecBlocksSent++;
-    SetState(PHY_STATE_IDLE);
-
-    if (m_nrFecBlocksSent * m_blockSize == m_currentBurstSize * 8 + m_paddingBits)
-    {
-        // this is the last FEC block of the burst
-        NS_ASSERT_MSG(m_nrRemainingBlocksToSend == 0, "Error while sending a burst");
-        NotifyTxEnd(m_currentBurst);
-    }
-    else
-    {
-        StartSendDummyFecBlock(false, modulationType, direction);
-    }
-}
-
-void
-SimpleOfdmWimaxPhy::EndSend()
-{
-    SetState(PHY_STATE_IDLE);
-}
-
-void
-SimpleOfdmWimaxPhy::StartReceive(uint32_t burstSize,
-                                 bool isFirstBlock,
-                                 uint64_t frequency,
-                                 WimaxPhy::ModulationType modulationType,
-                                 uint8_t direction,
-                                 double rxPower,
-                                 Ptr<PacketBurst> burst)
-{
-    bool drop = false;
-    double Nwb = -114 + m_noiseFigure + 10 * std::log(GetBandwidth() / 1000000000.0) / 2.303;
-    double SNR = rxPower - Nwb;
-
-    SNRToBlockErrorRateRecord* record =
-        m_snrToBlockErrorRateManager->GetSNRToBlockErrorRateRecord(SNR, modulationType);
-    double I1 = record->GetI1();
-    double I2 = record->GetI2();
-
-    double blockErrorRate = m_URNG->GetValue(I1, I2);
-
-    double rand = m_URNG->GetValue(0.0, 1.0);
-
-    if (rand < blockErrorRate)
-    {
-        drop = true;
-    }
-    if (rand > blockErrorRate)
-    {
-        drop = false;
-    }
-
-    if (blockErrorRate == 1.0)
-    {
-        drop = true;
-    }
-    if (blockErrorRate == 0.0)
-    {
-        drop = false;
-    }
-    delete record;
-
-    NS_LOG_INFO("PHY: Receive rxPower=" << rxPower << ", Nwb=" << Nwb << ", SNR=" << SNR
-                                        << ", Modulation=" << modulationType << ", BlockErrorRate="
-                                        << blockErrorRate << ", drop=" << std::boolalpha << drop);
-
-    switch (GetState())
-    {
-    case PHY_STATE_SCANNING:
-        if (frequency == GetScanningFrequency())
-        {
-            Simulator::Cancel(GetChnlSrchTimeoutEvent());
-            SetScanningCallback();
-            SetSimplex(frequency);
-            SetState(PHY_STATE_IDLE);
-        }
-        break;
-    case PHY_STATE_IDLE:
-        if (frequency == GetRxFrequency())
-        {
-            if (isFirstBlock)
-            {
-                NotifyRxBegin(burst);
-                m_receivedFecBlocks->clear();
-                m_nrReceivedFecBlocks = 0;
-                SetBlockParameters(burstSize, modulationType);
-                m_blockTime = GetBlockTransmissionTime(modulationType);
-            }
-
-            Simulator::Schedule(m_blockTime,
-                                &SimpleOfdmWimaxPhy::EndReceiveFecBlock,
-                                this,
-                                burstSize,
-                                modulationType,
-                                direction,
-                                drop,
-                                burst);
-
-            SetState(PHY_STATE_RX);
-        }
-        break;
-    case PHY_STATE_RX:
-        // drop
-        break;
-    case PHY_STATE_TX:
-        if (IsDuplex() && frequency == GetRxFrequency())
-        {
-        }
-        break;
-    }
-}
-
-void
-SimpleOfdmWimaxPhy::EndReceiveFecBlock(uint32_t burstSize,
-                                       WimaxPhy::ModulationType modulationType,
-                                       uint8_t direction,
-                                       bool drop,
-                                       Ptr<PacketBurst> burst)
-{
-    SetState(PHY_STATE_IDLE);
-    m_nrReceivedFecBlocks++;
-
-    if (drop)
-    {
-        m_nbErroneousBlock++;
-    }
-
-    if ((uint32_t)m_nrReceivedFecBlocks * m_blockSize == burstSize * 8 + m_paddingBits)
-    {
-        NotifyRxEnd(burst);
-        if (m_nbErroneousBlock == 0)
-        {
-            Simulator::Schedule(Seconds(0), &SimpleOfdmWimaxPhy::EndReceive, this, burst);
-        }
-        else
-        {
-            NotifyRxDrop(burst);
-        }
-        m_nbErroneousBlock = 0;
-        m_nrReceivedFecBlocks = 0;
-    }
-}
-
-void
-SimpleOfdmWimaxPhy::EndReceive(Ptr<const PacketBurst> burst)
-{
-    Ptr<PacketBurst> b = burst->Copy();
-    GetReceiveCallback()(b);
-    m_traceRx(burst);
-}
-
-Bvec
-SimpleOfdmWimaxPhy::ConvertBurstToBits(Ptr<const PacketBurst> burst)
-{
-    Bvec buffer(burst->GetSize() * 8, false);
-
-    std::list<Ptr<Packet>> packets = burst->GetPackets();
-
-    uint32_t j = 0;
-    for (auto iter = packets.begin(); iter != packets.end(); ++iter)
-    {
-        Ptr<Packet> packet = *iter;
-        auto pstart = (uint8_t*)std::malloc(packet->GetSize());
-        std::memset(pstart, 0, packet->GetSize());
-        packet->CopyData(pstart, packet->GetSize());
-        Bvec temp(8);
-        temp.resize(0, false);
-        temp.resize(8, false);
-        for (uint32_t i = 0; i < packet->GetSize(); i++)
-        {
-            for (uint8_t l = 0; l < 8; l++)
-            {
-                temp[l] = (bool)((((uint8_t)pstart[i]) >> (7 - l)) & 0x01);
-                buffer.at(j * 8 + l) = temp[l];
-            }
-            j++;
-        }
-        std::free(pstart);
-    }
-
-    return buffer;
-}
-
-/*
- Converts back the bit buffer (Bvec) to the actual burst.
- Actually creates byte buffer from the Bvec and resets the buffer
- of each packet in the copy of the original burst stored before transmitting.
- By doing this it preserves the metadata and tags in the packet.
- Function could also be named DeserializeBurst because actually it
- copying to the burst's byte buffer.
- */
-Ptr<PacketBurst>
-SimpleOfdmWimaxPhy::ConvertBitsToBurst(Bvec buffer)
-{
-    const auto bufferSize = buffer.size() / 8;
-    std::vector<uint8_t> bytes(bufferSize, 0);
-    int32_t j = 0;
-    // recreating byte buffer from bit buffer (Bvec)
-    for (std::size_t i = 0; i < buffer.size(); i += 8)
-    {
-        uint8_t temp = 0;
-        for (std::size_t l = 0; l < 8; l++)
-        {
-            bool bin = buffer.at(i + l);
-            temp |= (bin << (7 - l));
-        }
-
-        bytes[j] = temp;
-        j++;
-    }
-    uint16_t pos = 0;
-    Ptr<PacketBurst> RecvBurst = Create<PacketBurst>();
-    while (pos < bufferSize)
-    {
-        uint16_t packetSize = 0;
-        // Get the header type: first bit
-        uint8_t ht = (bytes[pos] >> 7) & 0x01;
-        if (ht == 1)
-        {
-            // BW request header. Size is always 8 bytes
-            packetSize = 6;
-        }
-        else
-        {
-            // Read the size
-            uint8_t Len_MSB = bytes[pos + 1] & 0x07;
-            packetSize = (uint16_t)((uint16_t)(Len_MSB << 8) | (uint16_t)(bytes[pos + 2]));
-            if (packetSize == 0)
-            {
-                break; // padding
-            }
-        }
-
-        Ptr<Packet> p = Create<Packet>(&bytes[pos], packetSize);
-        RecvBurst->AddPacket(p);
-        pos += packetSize;
-    }
-    return RecvBurst;
-}
-
-void
-SimpleOfdmWimaxPhy::CreateFecBlocks(const Bvec& buffer, WimaxPhy::ModulationType modulationType)
-{
-    Bvec fecBlock(m_blockSize);
-    for (uint32_t i = 0, j = m_nrBlocks; j > 0; i += m_blockSize, j--)
-    {
-        if (j == 1 && m_paddingBits > 0) // last block can be smaller than block size
-        {
-            fecBlock = Bvec(buffer.begin() + i, buffer.end());
-            fecBlock.resize(m_blockSize, false);
-        }
-        else
-        {
-            fecBlock = Bvec(buffer.begin() + i, buffer.begin() + i + m_blockSize);
-        }
-
-        m_fecBlocks->push_back(fecBlock);
-    }
-}
-
-Bvec
-SimpleOfdmWimaxPhy::RecreateBuffer()
-{
-    Bvec buffer(m_blockSize * (unsigned long)m_nrBlocks);
-    Bvec block(m_blockSize);
-    uint32_t i = 0;
-    for (uint32_t j = 0; j < m_nrBlocks; j++)
-    {
-        Bvec tmpRecFecBlock = m_receivedFecBlocks->front();
-        buffer.insert(buffer.begin() + i, tmpRecFecBlock.begin(), tmpRecFecBlock.end());
-        m_receivedFecBlocks->pop_front();
-        i += m_blockSize;
-    }
-    return buffer;
-}
-
-void
-SimpleOfdmWimaxPhy::DoSetDataRates()
-{
-    m_dataRateBpsk12 = CalculateDataRate(MODULATION_TYPE_BPSK_12);    // 6912000 bps
-    m_dataRateQpsk12 = CalculateDataRate(MODULATION_TYPE_QPSK_12);    // 13824000
-    m_dataRateQpsk34 = CalculateDataRate(MODULATION_TYPE_QPSK_34);    // 20736000
-    m_dataRateQam16_12 = CalculateDataRate(MODULATION_TYPE_QAM16_12); // 27648000
-    m_dataRateQam16_34 = CalculateDataRate(MODULATION_TYPE_QAM16_34); // 41472000
-    m_dataRateQam64_23 = CalculateDataRate(MODULATION_TYPE_QAM64_23); // 55224000
-    m_dataRateQam64_34 = CalculateDataRate(MODULATION_TYPE_QAM64_34); // 62208000
-}
-
-void
-SimpleOfdmWimaxPhy::GetModulationFecParams(WimaxPhy::ModulationType modulationType,
-                                           uint8_t& bitsPerSymbol,
-                                           double& fecCode) const
-{
-    switch (modulationType)
-    {
-    case MODULATION_TYPE_BPSK_12:
-        bitsPerSymbol = 1;
-        fecCode = 1.0 / 2;
-        break;
-    case MODULATION_TYPE_QPSK_12:
-        bitsPerSymbol = 2;
-        fecCode = 1.0 / 2;
-        break;
-    case MODULATION_TYPE_QPSK_34:
-        bitsPerSymbol = 2;
-        fecCode = 3.0 / 4;
-        break;
-    case MODULATION_TYPE_QAM16_12:
-        bitsPerSymbol = 4;
-        fecCode = 1.0 / 2;
-        break;
-    case MODULATION_TYPE_QAM16_34:
-        bitsPerSymbol = 4;
-        fecCode = 3.0 / 4;
-        break;
-    case MODULATION_TYPE_QAM64_23:
-        bitsPerSymbol = 6;
-        fecCode = 2.0 / 3;
-        break;
-    case MODULATION_TYPE_QAM64_34:
-        bitsPerSymbol = 6;
-        fecCode = 0.75;
-        break;
-    }
-}
-
-uint32_t
-SimpleOfdmWimaxPhy::CalculateDataRate(WimaxPhy::ModulationType modulationType) const
-{
-    uint8_t bitsPerSymbol = 0;
-    double fecCode = 0;
-    GetModulationFecParams(modulationType, bitsPerSymbol, fecCode);
-    double symbolsPerSecond = 1 / GetSymbolDuration().GetSeconds();
-    auto bitsTransmittedPerSymbol = (uint16_t)(bitsPerSymbol * GetNrCarriers() * fecCode);
-    // 96, 192, 288, 384, 576, 767 and 864 bits per symbol for the seven modulations, respectively
-
-    return (uint32_t)symbolsPerSecond * bitsTransmittedPerSymbol;
-}
-
-uint32_t
-SimpleOfdmWimaxPhy::DoGetDataRate(WimaxPhy::ModulationType modulationType) const
-{
-    switch (modulationType)
-    {
-    case MODULATION_TYPE_BPSK_12:
-        return m_dataRateBpsk12;
-    case MODULATION_TYPE_QPSK_12:
-        return m_dataRateQpsk12;
-    case MODULATION_TYPE_QPSK_34:
-        return m_dataRateQpsk34;
-    case MODULATION_TYPE_QAM16_12:
-        return m_dataRateQam16_12;
-    case MODULATION_TYPE_QAM16_34:
-        return m_dataRateQam16_34;
-    case MODULATION_TYPE_QAM64_23:
-        return m_dataRateQam64_23;
-    case MODULATION_TYPE_QAM64_34:
-        return m_dataRateQam64_34;
-    }
-    NS_FATAL_ERROR("Invalid modulation type");
-    return 0;
-}
-
-Time
-SimpleOfdmWimaxPhy::GetBlockTransmissionTime(WimaxPhy::ModulationType modulationType) const
-{
-    return Seconds((double)GetFecBlockSize(modulationType) / DoGetDataRate(modulationType));
-}
-
-Time
-SimpleOfdmWimaxPhy::DoGetTransmissionTime(uint32_t size,
-                                          WimaxPhy::ModulationType modulationType) const
-{
-    /*adding 3 extra nano second to cope with the loss of precision problem.
-     the time is internally stored in a 64 bit hence a floating-point time would loss
-     precision, e.g., 0.00001388888888888889 seconds will become 13888888888 femtoseconds.*/
-    return Seconds(DoGetNrSymbols(size, modulationType) * GetSymbolDuration().GetSeconds()) +
-           NanoSeconds(3);
-}
-
-uint64_t
-SimpleOfdmWimaxPhy::DoGetNrSymbols(uint32_t size, WimaxPhy::ModulationType modulationType) const
-{
-    Time transmissionTime =
-        Seconds((double)(GetNrBlocks(size, modulationType) * GetFecBlockSize(modulationType)) /
-                DoGetDataRate(modulationType));
-    return (uint64_t)std::ceil(transmissionTime.GetSeconds() / GetSymbolDuration().GetSeconds());
-}
-
-uint64_t
-SimpleOfdmWimaxPhy::DoGetNrBytes(uint32_t symbols, WimaxPhy::ModulationType modulationType) const
-{
-    Time transmissionTime = Seconds(symbols * GetSymbolDuration().GetSeconds());
-    return (uint64_t)std::floor((transmissionTime.GetSeconds() * DoGetDataRate(modulationType)) /
-                                8);
-}
-
-uint32_t
-SimpleOfdmWimaxPhy::GetFecBlockSize(WimaxPhy::ModulationType modulationType) const
-{
-    uint32_t blockSize = 0;
-    switch (modulationType)
-    {
-    case MODULATION_TYPE_BPSK_12:
-        blockSize = 12;
-        break;
-    case MODULATION_TYPE_QPSK_12:
-        blockSize = 24;
-        break;
-    case MODULATION_TYPE_QPSK_34:
-        blockSize = 36;
-        break;
-    case MODULATION_TYPE_QAM16_12:
-        blockSize = 48;
-        break;
-    case MODULATION_TYPE_QAM16_34:
-        blockSize = 72;
-        break;
-    case MODULATION_TYPE_QAM64_23:
-        blockSize = 96;
-        break;
-    case MODULATION_TYPE_QAM64_34:
-        blockSize = 108;
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid modulation type");
-        break;
-    }
-    return blockSize * 8; // in bits
-}
-
-// Channel coding block size, Table 215, page 434
-uint32_t
-SimpleOfdmWimaxPhy::GetCodedFecBlockSize(WimaxPhy::ModulationType modulationType) const
-{
-    uint32_t blockSize = 0;
-    switch (modulationType)
-    {
-    case MODULATION_TYPE_BPSK_12:
-        blockSize = 24;
-        break;
-    case MODULATION_TYPE_QPSK_12:
-    case MODULATION_TYPE_QPSK_34:
-        blockSize = 48;
-        break;
-    case MODULATION_TYPE_QAM16_12:
-    case MODULATION_TYPE_QAM16_34:
-        blockSize = 96;
-        break;
-    case MODULATION_TYPE_QAM64_23:
-    case MODULATION_TYPE_QAM64_34:
-        blockSize = 144;
-        break;
-    default:
-        NS_FATAL_ERROR("Invalid modulation type");
-        break;
-    }
-    return blockSize * 8; // in bits
-}
-
-void
-SimpleOfdmWimaxPhy::SetBlockParameters(uint32_t burstSize, WimaxPhy::ModulationType modulationType)
-{
-    m_blockSize = GetFecBlockSize(modulationType);
-    m_nrBlocks = GetNrBlocks(burstSize, modulationType);
-    m_paddingBits = (m_nrBlocks * m_blockSize) - (burstSize * 8);
-    m_nrRemainingBlocksToSend = m_nrBlocks;
-    NS_ASSERT_MSG(static_cast<uint32_t>(m_nrBlocks * m_blockSize) >= (burstSize * 8),
-                  "Size of padding bytes < 0");
-}
-
-uint16_t
-SimpleOfdmWimaxPhy::DoGetTtg() const
-{
-    // assumed equal to 2 symbols
-    return 2 * GetPsPerSymbol();
-}
-
-uint16_t
-SimpleOfdmWimaxPhy::DoGetRtg() const
-{
-    // assumed equal to 2 symbols
-    return 2 * GetPsPerSymbol();
-}
-
-uint8_t
-SimpleOfdmWimaxPhy::DoGetFrameDurationCode() const
-{
-    uint16_t duration = 0;
-    duration = (uint16_t)(GetFrameDuration().GetSeconds() * 10000);
-    uint8_t retval = 0;
-    switch (duration)
-    {
-    case 25: {
-        retval = FRAME_DURATION_2_POINT_5_MS;
-        break;
-    }
-    case 40: {
-        retval = FRAME_DURATION_4_MS;
-        break;
-    }
-    case 50: {
-        retval = FRAME_DURATION_5_MS;
-        break;
-    }
-    case 80: {
-        retval = FRAME_DURATION_8_MS;
-        break;
-    }
-    case 100: {
-        retval = FRAME_DURATION_10_MS;
-        break;
-    }
-    case 125: {
-        retval = FRAME_DURATION_12_POINT_5_MS;
-        break;
-    }
-    case 200: {
-        retval = FRAME_DURATION_20_MS;
-        break;
-    }
-    default: {
-        NS_FATAL_ERROR("Invalid frame duration = " << duration);
-        retval = 0;
-    }
-    }
-    return retval;
-}
-
-Time
-SimpleOfdmWimaxPhy::DoGetFrameDuration(uint8_t frameDurationCode) const
-{
-    switch (frameDurationCode)
-    {
-    case FRAME_DURATION_2_POINT_5_MS:
-        return Seconds(2.5);
-    case FRAME_DURATION_4_MS:
-        return Seconds(4);
-    case FRAME_DURATION_5_MS:
-        return Seconds(5);
-    case FRAME_DURATION_8_MS:
-        return Seconds(8);
-    case FRAME_DURATION_10_MS:
-        return Seconds(10);
-    case FRAME_DURATION_12_POINT_5_MS:
-        return Seconds(12.5);
-    case FRAME_DURATION_20_MS:
-        return Seconds(20);
-    default:
-        NS_FATAL_ERROR("Invalid modulation type");
-    }
-    return Seconds(0);
-}
-
-/*
- Returns number of blocks (FEC blocks) the burst will be split in.
- The size of the block is specific for each modulation type.
- */
-uint16_t
-SimpleOfdmWimaxPhy::GetNrBlocks(uint32_t burstSize, WimaxPhy::ModulationType modulationType) const
-{
-    uint32_t blockSize = GetFecBlockSize(modulationType);
-    uint16_t nrBlocks = (burstSize * 8) / blockSize;
-
-    if ((burstSize * 8) % blockSize > 0)
-    {
-        nrBlocks += 1;
-    }
-
-    return nrBlocks;
-}
-
-/*---------------------PHY parameters functions-----------------------*/
-
-void
-SimpleOfdmWimaxPhy::DoSetPhyParameters()
-{
-    /*Calculations as per section 8.3.2.
-     Currently assuming license-exempt 5 GHz band. For channel bandwidth 20 MHz (Table B.28, page
-     812) and frame duration 10 ms (Table 232, page 460) i.e, 100 frames per second, sampling
-     frequency is 23040000, symbol (OFDM symbol) duration is 1.388888888888889e-05 seconds, PS
-     duration is 1.7361111111111112e-07 seconds. Hence PSs per frame is 57600, symbols per frame is
-     720 and PSs per symbol is 80. Note that defining these parameters (symbol and PS duration) as
-     Time may not result in exactly these values therefore lrint has been used (otherwise should be
-     defined as double). For licensed bands set channel bandwidth according to Table B.26, page
-     810.*/
-
-    double samplingFrequency = DoGetSamplingFrequency();
-    Time psDuration = Seconds(4.0 / samplingFrequency);
-
-    SetPsDuration(psDuration);
-    uint16_t psPerFrame = (uint16_t)(GetFrameDuration().GetSeconds() / psDuration.GetSeconds());
-    SetPsPerFrame(psPerFrame);
-    double subcarrierSpacing = samplingFrequency / DoGetNfft();
-    double tb = 1.0 / subcarrierSpacing;    // Tb (useful symbol time)
-    double tg = DoGetGValue() * tb;         // Tg (cyclic prefix time)
-    Time symbolDuration = Seconds(tb + tg); // OFDM Symbol Time
-    SetSymbolDuration(symbolDuration);
-    uint16_t psPerSymbol = lrint(symbolDuration.GetSeconds() / psDuration.GetSeconds());
-    SetPsPerSymbol(psPerSymbol);
-    uint32_t symbolsPerFrame = lrint(GetFrameDuration().GetSeconds() / symbolDuration.GetSeconds());
-    SetSymbolsPerFrame(symbolsPerFrame);
-}
-
-void
-SimpleOfdmWimaxPhy::DoSetNfft(uint16_t nfft)
-{
-    m_nfft = nfft;
-}
-
-uint16_t
-SimpleOfdmWimaxPhy::DoGetNfft() const
-{
-    return m_nfft;
-}
-
-double
-SimpleOfdmWimaxPhy::DoGetSamplingFactor() const
-{
-    // sampling factor (n), see Table 213, page 429
-
-    uint32_t channelBandwidth = GetChannelBandwidth();
-
-    if (channelBandwidth % 1750000 == 0)
-    {
-        return 8.0 / 7;
-    }
-    else if (channelBandwidth % 1500000 == 0)
-    {
-        return 86.0 / 75;
-    }
-    else if (channelBandwidth % 1250000 == 0)
-    {
-        return 144.0 / 125;
-    }
-    else if (channelBandwidth % 2750000 == 0)
-    {
-        return 316.0 / 275;
-    }
-    else if (channelBandwidth % 2000000 == 0)
-    {
-        return 57.0 / 50;
-    }
-    else
-    {
-        NS_LOG_DEBUG("Oops may be wrong channel bandwidth for OFDM PHY!");
-        NS_FATAL_ERROR("wrong channel bandwidth for OFDM PHY");
-    }
-
-    return 8.0 / 7;
-}
-
-double
-SimpleOfdmWimaxPhy::DoGetSamplingFrequency() const
-{
-    // sampling frequency (Fs), see 8.3.2.2
-
-    return (DoGetSamplingFactor() * GetChannelBandwidth() / 8000) * 8000;
-}
-
-double
-SimpleOfdmWimaxPhy::DoGetGValue() const
-{
-    return m_g;
-}
-
-void
-SimpleOfdmWimaxPhy::DoSetGValue(double g)
-{
-    m_g = g;
-}
-
-void
-SimpleOfdmWimaxPhy::SetTxGain(double txGain)
-{
-    m_txGain = txGain;
-}
-
-void
-SimpleOfdmWimaxPhy::SetRxGain(double txRain)
-{
-    m_rxGain = txRain;
-}
-
-double
-SimpleOfdmWimaxPhy::GetTxGain() const
-{
-    return m_txGain;
-}
-
-double
-SimpleOfdmWimaxPhy::GetRxGain() const
-{
-    return m_rxGain;
-}
-
-std::string
-SimpleOfdmWimaxPhy::GetTraceFilePath() const
-{
-    return (m_snrToBlockErrorRateManager->GetTraceFilePath());
-}
-
-void
-SimpleOfdmWimaxPhy::SetTraceFilePath(std::string path)
-{
-    m_snrToBlockErrorRateManager->SetTraceFilePath((char*)path.c_str());
-    m_snrToBlockErrorRateManager->LoadTraces();
-}
-
-void
-SimpleOfdmWimaxPhy::NotifyTxBegin(Ptr<PacketBurst> burst)
-{
-    m_phyTxBeginTrace(burst);
-}
-
-void
-SimpleOfdmWimaxPhy::NotifyTxEnd(Ptr<PacketBurst> burst)
-{
-    m_phyTxEndTrace(burst);
-}
-
-void
-SimpleOfdmWimaxPhy::NotifyTxDrop(Ptr<PacketBurst> burst)
-{
-    m_phyTxDropTrace(burst);
-}
-
-void
-SimpleOfdmWimaxPhy::NotifyRxBegin(Ptr<PacketBurst> burst)
-{
-    m_phyRxBeginTrace(burst);
-}
-
-void
-SimpleOfdmWimaxPhy::NotifyRxEnd(Ptr<PacketBurst> burst)
-{
-    m_phyRxEndTrace(burst);
-}
-
-void
-SimpleOfdmWimaxPhy::NotifyRxDrop(Ptr<PacketBurst> burst)
-{
-    m_phyRxDropTrace(burst);
-}
-
-int64_t
-SimpleOfdmWimaxPhy::AssignStreams(int64_t stream)
-{
-    NS_LOG_FUNCTION(this << stream);
-    m_URNG->SetStream(stream);
-    return 1;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/simple-ofdm-wimax-phy.h ns-3.46/src/wimax/model/simple-ofdm-wimax-phy.h
--- ns-3.45/src/wimax/model/simple-ofdm-wimax-phy.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/simple-ofdm-wimax-phy.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,540 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef SIMPLE_OFDM_WIMAX_PHY_H
-#define SIMPLE_OFDM_WIMAX_PHY_H
-
-#include "bvec.h"
-#include "snr-to-block-error-rate-manager.h"
-#include "wimax-connection.h"
-#include "wimax-phy.h"
-
-#include "ns3/callback.h"
-#include "ns3/event-id.h"
-#include "ns3/nstime.h"
-#include "ns3/random-variable-stream.h"
-
-#include <list>
-#include <stdint.h>
-
-namespace ns3
-{
-
-class WimaxChannel;
-class WimaxNetDevice;
-class NetDevice;
-class Packet;
-class SimpleOfdmWimaxChannel;
-
-/**
- * @ingroup wimax
- * @brief SimpleOfdmWimaxPhy class
- */
-class SimpleOfdmWimaxPhy : public WimaxPhy
-{
-  public:
-    /// Frame duration code enumeration
-    enum FrameDurationCode
-    {
-        FRAME_DURATION_2_POINT_5_MS,
-        FRAME_DURATION_4_MS,
-        FRAME_DURATION_5_MS,
-        FRAME_DURATION_8_MS,
-        FRAME_DURATION_10_MS,
-        FRAME_DURATION_12_POINT_5_MS,
-        FRAME_DURATION_20_MS
-    };
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    SimpleOfdmWimaxPhy();
-    /**
-     * Constructor
-     *
-     * @param tracesPath trace path
-     */
-    SimpleOfdmWimaxPhy(char* tracesPath);
-    ~SimpleOfdmWimaxPhy() override;
-    /**
-     * @brief if called with true it will enable the loss model
-     * @param loss set to true to enable the loss model
-     */
-    void ActivateLoss(bool loss);
-    /**
-     * @brief Set the path of the repository containing the traces
-     * @param tracesPath the path to the repository.
-     *  see snr-to-block-error-rate-manager.h for more details.
-     */
-    void SetSNRToBlockErrorRateTracesPath(char* tracesPath);
-    /**
-     * Attach the physical layer to a channel.
-     * @param channel the channel to which the physical layer will be attached
-     */
-    void DoAttach(Ptr<WimaxChannel> channel) override;
-    /**
-     * @brief set the callback function to call when a burst is received
-     * @param callback the receive callback function
-     */
-    void SetReceiveCallback(Callback<void, Ptr<PacketBurst>, Ptr<WimaxConnection>> callback);
-    /**
-     * @brief Sends a burst on the channel
-     * @param burst the burst to send
-     * @param modulationType the modulation that will be used to send this burst
-     * @param direction set to uplink or downlink
-     */
-    void Send(Ptr<PacketBurst> burst, WimaxPhy::ModulationType modulationType, uint8_t direction);
-    /**
-     * @brief Sends a burst on the channel
-     * @param params parameters
-     * @see SendParams
-     */
-    void Send(SendParams* params) override;
-    /**
-     * @brief returns the type this physical layer
-     * @return always  WimaxPhy::simpleOfdmWimaxPhy;
-     */
-    WimaxPhy::PhyType GetPhyType() const override;
-    /**
-     * @brief start the reception of a fec block
-     * @param burstSize the burst size
-     * @param isFirstBlock true if this block is the first one, false otherwise
-     * @param frequency the frequency in which the fec block is being received
-     * @param modulationType the modulation used to transmit this fec Block
-     * @param direction set to uplink and downlink
-     * @param rxPower the received power.
-     * @param burst the burst to be sent
-     */
-
-    void StartReceive(uint32_t burstSize,
-                      bool isFirstBlock,
-                      uint64_t frequency,
-                      WimaxPhy::ModulationType modulationType,
-                      uint8_t direction,
-                      double rxPower,
-                      Ptr<PacketBurst> burst);
-
-    /**
-     * @return the bandwidth
-     */
-    uint32_t GetBandwidth() const;
-    /**
-     * @brief Set the bandwidth
-     * @param BW the bandwidth
-     */
-    void SetBandwidth(uint32_t BW);
-    /**
-     * @return the transmission power
-     */
-    double GetTxPower() const;
-    /**
-     * @brief set the transmission power
-     * @param txPower the transmission power
-     */
-    void SetTxPower(double txPower);
-    /**
-     * @return the noise figure
-     */
-    double GetNoiseFigure() const;
-    /**
-     * @brief set the noise figure of the device
-     * @param nf the noise figure
-     */
-    void SetNoiseFigure(double nf);
-
-    /**
-     * Public method used to fire a PhyTxBegin trace.  Implemented for encapsulation
-     * purposes.
-     * @param burst the packet burst
-     */
-    void NotifyTxBegin(Ptr<PacketBurst> burst);
-
-    /**
-     * Public method used to fire a PhyTxEnd trace.  Implemented for encapsulation
-     * purposes.
-     * @param burst the packet burst
-     */
-    void NotifyTxEnd(Ptr<PacketBurst> burst);
-
-    /**
-     * Public method used to fire a PhyTxDrop trace.  Implemented for encapsulation
-     * purposes.
-     * @param burst the packet burst
-     */
-    void NotifyTxDrop(Ptr<PacketBurst> burst);
-
-    /**
-     * Public method used to fire a PhyRxBegin trace.  Implemented for encapsulation
-     * purposes.
-     * @param burst the packet burst
-     */
-    void NotifyRxBegin(Ptr<PacketBurst> burst);
-
-    /**
-     * Public method used to fire a PhyRxEnd trace.  Implemented for encapsulation
-     * purposes.
-     * @param burst the packet burst
-     */
-    void NotifyRxEnd(Ptr<PacketBurst> burst);
-
-    /**
-     * Public method used to fire a PhyRxDrop trace.  Implemented for encapsulation
-     * purposes.
-     * @param burst the packet burst
-     */
-    void NotifyRxDrop(Ptr<PacketBurst> burst);
-
-    /**
-     * Assign a fixed random variable stream number to the random variables
-     * used by this model.  Return the number of streams (possibly zero) that
-     * have been assigned.
-     *
-     * @param stream first stream index to use
-     * @return the number of stream indices assigned by this model
-     */
-    int64_t AssignStreams(int64_t stream) override;
-
-  private:
-    /**
-     * Get transmission time
-     * @param size the size
-     * @param modulationType the modulation type
-     * @returns the transmission time
-     */
-    Time DoGetTransmissionTime(uint32_t size,
-                               WimaxPhy::ModulationType modulationType) const override;
-    /**
-     * Get number of symbols
-     * @param size the size
-     * @param modulationType the modulation type
-     * @returns the number of symbols
-     */
-    uint64_t DoGetNrSymbols(uint32_t size, WimaxPhy::ModulationType modulationType) const override;
-    /**
-     * Get number of bytes
-     * @param symbols the symbols
-     * @param modulationType the modulation type
-     * @returns the number of bytes
-     */
-    uint64_t DoGetNrBytes(uint32_t symbols, WimaxPhy::ModulationType modulationType) const override;
-    /**
-     * Convert burst to bits
-     * @param burst the packet burst
-     * @returns the BVEC
-     */
-    Bvec ConvertBurstToBits(Ptr<const PacketBurst> burst);
-    /**
-     * Convert bits to burst
-     * @param buffer the BVEC
-     * @returns the packet burst
-     */
-    Ptr<PacketBurst> ConvertBitsToBurst(Bvec buffer);
-    /**
-     * Create FEC blocks
-     * @param buffer the BVEC
-     * @param modulationType the modulation type
-     */
-    void CreateFecBlocks(const Bvec& buffer, WimaxPhy::ModulationType modulationType);
-    /**
-     * Recreate buffer
-     * @returns BVEC
-     */
-    Bvec RecreateBuffer();
-    /**
-     * Get FEC block size
-     * @param type the modulation type
-     * @returns the FEC block size
-     */
-    uint32_t GetFecBlockSize(WimaxPhy::ModulationType type) const;
-    /**
-     * Get coded FEC block size
-     * @param modulationType the modulation type
-     * @returns the coded FEC block size
-     */
-    uint32_t GetCodedFecBlockSize(WimaxPhy::ModulationType modulationType) const;
-    /**
-     * Set block parameters
-     * @param burstSize the burst size
-     * @param modulationType the modulation type
-     */
-    void SetBlockParameters(uint32_t burstSize, WimaxPhy::ModulationType modulationType);
-    /**
-     * Get number of blocks
-     * @param burstSize the burst size
-     * @param modulationType the modulation type
-     * @returns the number of blocks
-     */
-    uint16_t GetNrBlocks(uint32_t burstSize, WimaxPhy::ModulationType modulationType) const;
-    void DoDispose() override;
-    /// End send
-    void EndSend();
-    /**
-     * End send FEC block
-     * @param modulationType the modulation type
-     * @param direction the direction
-     */
-    void EndSendFecBlock(WimaxPhy::ModulationType modulationType, uint8_t direction);
-    /**
-     * End receive
-     * @param burst
-     */
-    void EndReceive(Ptr<const PacketBurst> burst);
-    /**
-     * End receive FEC block
-     * @param burstSize the burst size
-     * @param modulationType the modulation type
-     * @param direction the direction
-     * @param drop whether to drop
-     * @param burst the burst
-     */
-    void EndReceiveFecBlock(uint32_t burstSize,
-                            WimaxPhy::ModulationType modulationType,
-                            uint8_t direction,
-                            bool drop,
-                            Ptr<PacketBurst> burst);
-    /**
-     * Start end dummy FEC block
-     * @param isFirstBlock is the first block?
-     * @param modulationType the modulation type
-     * @param direction the direction
-     */
-    void StartSendDummyFecBlock(bool isFirstBlock,
-                                WimaxPhy::ModulationType modulationType,
-                                uint8_t direction);
-    /**
-     * Get block transmission time
-     * @param modulationType the modulation type
-     * @returns the block transmission time
-     */
-    Time GetBlockTransmissionTime(WimaxPhy::ModulationType modulationType) const;
-    /// Set data rates
-    void DoSetDataRates() override;
-    /// Initialize simple OFDM WIMAX Phy
-    void InitSimpleOfdmWimaxPhy();
-
-    /**
-     * Get moduleation FEC parameters
-     * @param modulationType the modulation type
-     * @param bitsPerSymbol the number of bits per symbol
-     * @param fecCode the FEC code
-     */
-    void GetModulationFecParams(WimaxPhy::ModulationType modulationType,
-                                uint8_t& bitsPerSymbol,
-                                double& fecCode) const;
-    /**
-     * Calculate data rate
-     * @param modulationType the modulation type
-     * @returns the data rate
-     */
-    uint32_t CalculateDataRate(WimaxPhy::ModulationType modulationType) const;
-    /**
-     * Get data rate
-     * @param modulationType the modulation type
-     * @returns the data rate
-     */
-    uint32_t DoGetDataRate(WimaxPhy::ModulationType modulationType) const override;
-    /**
-     * Get TTG
-     * @returns the TTG
-     */
-    uint16_t DoGetTtg() const override;
-    /**
-     * Get RTG
-     * @returns the RTG
-     */
-    uint16_t DoGetRtg() const override;
-    /**
-     * Get frame duration code
-     * @returns the frame duration code
-     */
-    uint8_t DoGetFrameDurationCode() const override;
-    /**
-     * Get frame duration
-     * @param frameDurationCode the frame duration code
-     * @returns the frame duration
-     */
-    Time DoGetFrameDuration(uint8_t frameDurationCode) const override;
-    /// Set Phy parameters
-    void DoSetPhyParameters() override;
-    /**
-     * Get NFFT
-     * @returns the NFFT
-     */
-    uint16_t DoGetNfft() const override;
-    /**
-     * Set NFFT
-     * @param nfft the NFFT
-     */
-    void DoSetNfft(uint16_t nfft);
-    /**
-     * Get sampling factor
-     * @returns the sampling factor
-     */
-    double DoGetSamplingFactor() const override;
-    /**
-     * Get sampling frequency
-     * @returns the sampling frequency
-     */
-    double DoGetSamplingFrequency() const override;
-    /**
-     * Get G value
-     * @returns the G value
-     */
-    double DoGetGValue() const override;
-    /**
-     * Set G value
-     * @param g the G value
-     */
-    void DoSetGValue(double g);
-
-    /**
-     * Get receive gain
-     * @returns the receive gain
-     */
-    double GetRxGain() const;
-    /**
-     * Set receive gsain
-     * @param rxgain the receive gain
-     */
-    void SetRxGain(double rxgain);
-
-    /**
-     * Get transmit gain
-     * @returns the transmit gain
-     */
-    double GetTxGain() const;
-    /**
-     * Set transmit gain
-     * @param txgain the transmit gain
-     */
-    void SetTxGain(double txgain);
-
-    /**
-     * Get trace file path
-     * @returns the trace file path name
-     */
-    std::string GetTraceFilePath() const;
-    /**
-     * Set trace file path
-     * @param path the trace file path
-     */
-    void SetTraceFilePath(std::string path);
-
-    uint16_t m_fecBlockSize;     ///< in bits, size of FEC block transmitted after PHY operations
-    uint32_t m_currentBurstSize; ///< current burst size
-
-    std::list<Bvec>* m_receivedFecBlocks; ///< a list of received FEC blocks until they are combined
-                                          ///< to recreate the full burst buffer
-    uint32_t m_nrFecBlocksSent;   ///< counting the number of FEC blocks sent (within a burst)
-    std::list<Bvec>* m_fecBlocks; ///< the FEC blocks
-    Time m_blockTime;             ///< block time
-
-    TracedCallback<Ptr<const PacketBurst>> m_traceRx; ///< trace receive callback
-    TracedCallback<Ptr<const PacketBurst>> m_traceTx; ///< trace transmit callback
-
-    // data rates for this Phy
-    uint32_t m_dataRateBpsk12;   ///< data rate
-    uint32_t m_dataRateQpsk12;   ///< data rate
-    uint32_t m_dataRateQpsk34;   ///< data rate
-    uint32_t m_dataRateQam16_12; ///< data rate
-    uint32_t m_dataRateQam16_34; ///< data rate
-    uint32_t m_dataRateQam64_23; ///< data rate
-    uint32_t m_dataRateQam64_34; ///< data rate
-
-    // parameters to store for a per burst life-time
-    uint16_t m_nrBlocks;                ///< number of blocks
-    uint16_t m_nrRemainingBlocksToSend; ///< number of remaining blocks to send
-    Ptr<PacketBurst> m_currentBurst;    ///< current burst
-    uint16_t m_blockSize;               ///< block size
-    uint32_t m_paddingBits;             ///< padding bits
-    uint16_t m_nbErroneousBlock;        ///< erroneous blocks
-    uint16_t m_nrReceivedFecBlocks;     ///< number received FEC blocks
-    uint16_t m_nfft;                    ///< NFFT
-    double m_g;                         ///< G value
-    double m_bandWidth;                 ///< bandwidth
-    double m_txPower;                   ///< transmit power
-    double m_noiseFigure;               ///< noise figure
-    double m_txGain;                    ///< transmit gain
-    double m_rxGain;                    ///< receive gain
-    /**
-     * The trace source fired when a packet begins the transmission process on
-     * the medium.
-     *
-     * @see class CallBackTraceSource
-     * @deprecated The non-const \c Ptr<PacketBurst> argument is deprecated
-     * and will be changed to \c Ptrc<PacketBurst> in a future release.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<PacketBurst>> m_phyTxBeginTrace;
-
-    /**
-     * The trace source fired when a packet ends the transmission process on
-     * the medium.
-     *
-     * @see class CallBackTraceSource
-     * @deprecated The non-const \c Ptr<PacketBurst> argument is deprecated
-     * and will be changed to \c Ptrc<PacketBurst> in a future release.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<PacketBurst>> m_phyTxEndTrace;
-
-    /**
-     * The trace source fired when the phy layer drops a packet as it tries
-     * to transmit it.
-     *
-     * @see class CallBackTraceSource
-     * @deprecated The non-const \c Ptr<PacketBurst> argument is deprecated
-     * and will be changed to \c Ptrc<PacketBurst> in a future release.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<PacketBurst>> m_phyTxDropTrace;
-
-    /**
-     * The trace source fired when a packet begins the reception process from
-     * the medium.
-     *
-     * @see class CallBackTraceSource
-     * @deprecated The non-const \c Ptr<PacketBurst> argument is deprecated
-     * and will be changed to \c Ptrc<PacketBurst> in a future release.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<PacketBurst>> m_phyRxBeginTrace;
-
-    /**
-     * The trace source fired when a packet ends the reception process from
-     * the medium.
-     *
-     * @see class CallBackTraceSource
-     * @deprecated The non-const \c Ptr<PacketBurst> argument is deprecated
-     * and will be changed to \c Ptrc<PacketBurst> in a future release.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<PacketBurst>> m_phyRxEndTrace;
-
-    /**
-     * The trace source fired when the phy layer drops a packet it has received.
-     *
-     * @see class CallBackTraceSource
-     * @deprecated The non-const \c Ptr<PacketBurst> argument is deprecated
-     * and will be changed to \c Ptrc<PacketBurst> in a future release.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<PacketBurst>> m_phyRxDropTrace;
-
-    SNRToBlockErrorRateManager* m_snrToBlockErrorRateManager; ///< SNR to block error rate manager
-
-    /// Provides uniform random variables.
-    Ptr<UniformRandomVariable> m_URNG; ///< URNG
-};
-
-} // namespace ns3
-
-#endif /* OFDM_WIMAX_PHY_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/snr-to-block-error-rate-manager.cc ns-3.46/src/wimax/model/snr-to-block-error-rate-manager.cc
--- ns-3.45/src/wimax/model/snr-to-block-error-rate-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/snr-to-block-error-rate-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,343 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#include "snr-to-block-error-rate-manager.h"
-
-#include "default-traces.h"
-#include "snr-to-block-error-rate-record.h"
-
-#include "ns3/assert.h"
-#include "ns3/log.h"
-
-#include <cstring>
-#include <fstream>
-#include <sstream>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SNRToBlockErrorRateManager");
-
-SNRToBlockErrorRateManager::SNRToBlockErrorRateManager()
-{
-    for (int i = 0; i < 7; i++)
-    {
-        m_recordModulation[i] = new std::vector<SNRToBlockErrorRateRecord*>();
-    }
-    m_activateLoss = false;
-    m_traceFilePath = "DefaultTraces";
-}
-
-SNRToBlockErrorRateManager::~SNRToBlockErrorRateManager()
-{
-    ClearRecords();
-    for (int i = 0; i < 7; i++)
-    {
-        delete m_recordModulation[i];
-    }
-}
-
-void
-SNRToBlockErrorRateManager::ClearRecords()
-{
-    for (int i = 0; i < 7; i++)
-    {
-        for (auto iter = m_recordModulation[i]->begin(); iter != m_recordModulation[i]->end();
-             ++iter)
-        {
-            if (*iter)
-            {
-                delete (*iter);
-                (*iter) = 0;
-            }
-        }
-        m_recordModulation[i]->clear();
-    }
-}
-
-void
-SNRToBlockErrorRateManager::ActivateLoss(bool loss)
-{
-    m_activateLoss = loss;
-}
-
-void
-SNRToBlockErrorRateManager::LoadTraces()
-{
-    std::ifstream traceFile;
-    ClearRecords();
-    double snrValue;
-    double bitErrorRate;
-    double burstErrorRate;
-    double sigma2;
-    double I1;
-    double I2;
-
-    for (int i = 0; i < 7; i++)
-    {
-        std::stringstream traceFilePath;
-        traceFilePath << m_traceFilePath << "/modulation" << i << ".txt";
-
-        traceFile.open(traceFilePath.str(), std::ifstream::in);
-        if (!traceFile.good())
-        {
-            NS_LOG_INFO("Unable to load " << traceFilePath.str() << "!! Loading default traces...");
-            LoadDefaultTraces();
-            return;
-        }
-        while (traceFile.good())
-        {
-            traceFile >> snrValue >> bitErrorRate >> burstErrorRate >> sigma2 >> I1 >> I2;
-            auto record = new SNRToBlockErrorRateRecord(snrValue,
-                                                        bitErrorRate,
-                                                        burstErrorRate,
-                                                        sigma2,
-                                                        I1,
-                                                        I2);
-            m_recordModulation[i]->push_back(record);
-        }
-        traceFile.close();
-    }
-    m_activateLoss = true;
-}
-
-void
-SNRToBlockErrorRateManager::LoadDefaultTraces()
-{
-    double snrValue;
-    double bitErrorRate;
-    double burstErrorRate;
-    double sigma2;
-    double I1;
-    double I2;
-    ClearRecords();
-    for (unsigned int j = 0; j < sizeof(modulation0[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation0[0][j];
-        bitErrorRate = modulation0[1][j];
-        burstErrorRate = modulation0[2][j];
-        sigma2 = modulation0[3][j];
-        I1 = modulation0[4][j];
-        I2 = modulation0[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[0]->push_back(record);
-    }
-    for (unsigned int j = 0; j < sizeof(modulation1[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation1[0][j];
-        bitErrorRate = modulation1[1][j];
-        burstErrorRate = modulation1[2][j];
-        sigma2 = modulation1[3][j];
-        I1 = modulation1[4][j];
-        I2 = modulation1[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[1]->push_back(record);
-    }
-    for (unsigned int j = 0; j < sizeof(modulation2[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation2[0][j];
-        bitErrorRate = modulation2[1][j];
-        burstErrorRate = modulation2[2][j];
-        sigma2 = modulation2[3][j];
-        I1 = modulation2[4][j];
-        I2 = modulation2[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[2]->push_back(record);
-    }
-    for (unsigned int j = 0; j < sizeof(modulation3[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation3[0][j];
-        bitErrorRate = modulation3[1][j];
-        burstErrorRate = modulation3[2][j];
-        sigma2 = modulation3[3][j];
-        I1 = modulation3[4][j];
-        I2 = modulation3[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[3]->push_back(record);
-    }
-    for (unsigned int j = 0; j < sizeof(modulation4[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation4[0][j];
-        bitErrorRate = modulation4[1][j];
-        burstErrorRate = modulation4[2][j];
-        sigma2 = modulation4[3][j];
-        I1 = modulation4[4][j];
-        I2 = modulation4[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[4]->push_back(record);
-    }
-    for (unsigned int j = 0; j < sizeof(modulation5[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation5[0][j];
-        bitErrorRate = modulation5[1][j];
-        burstErrorRate = modulation5[2][j];
-        sigma2 = modulation5[3][j];
-        I1 = modulation5[4][j];
-        I2 = modulation5[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[5]->push_back(record);
-    }
-    for (unsigned int j = 0; j < sizeof(modulation6[0]) / sizeof(double); j++)
-    {
-        snrValue = modulation6[0][j];
-        bitErrorRate = modulation6[1][j];
-        burstErrorRate = modulation6[2][j];
-        sigma2 = modulation6[3][j];
-        I1 = modulation6[4][j];
-        I2 = modulation6[5][j];
-        auto record =
-            new SNRToBlockErrorRateRecord(snrValue, bitErrorRate, burstErrorRate, sigma2, I1, I2);
-        m_recordModulation[6]->push_back(record);
-    }
-    m_activateLoss = true;
-}
-
-void
-SNRToBlockErrorRateManager::ReLoadTraces()
-{
-    double snrValue;
-    double bitErrorRate;
-    double burstErrorRate;
-    double sigma2;
-    double I1;
-    double I2;
-
-    ClearRecords();
-
-    std::ifstream traceFile;
-
-    for (int i = 0; i < 7; i++)
-    {
-        std::stringstream traceFilePath;
-        traceFilePath << m_traceFilePath << "/Modulation" << i << ".txt";
-
-        traceFile.open(traceFilePath.str(), std::ifstream::in);
-        if (!traceFile.good())
-        {
-            NS_LOG_INFO("Unable to load " << traceFilePath.str() << "!!Loading default traces...");
-            LoadDefaultTraces();
-            return;
-        }
-        while (traceFile.good())
-        {
-            traceFile >> snrValue >> bitErrorRate >> burstErrorRate >> sigma2 >> I1 >> I2;
-            auto record = new SNRToBlockErrorRateRecord(snrValue,
-                                                        bitErrorRate,
-                                                        burstErrorRate,
-                                                        sigma2,
-                                                        I1,
-                                                        I2);
-
-            m_recordModulation[i]->push_back(record);
-        }
-        traceFile.close();
-    }
-    m_activateLoss = true;
-}
-
-void
-SNRToBlockErrorRateManager::SetTraceFilePath(char* traceFilePath)
-{
-    m_traceFilePath = traceFilePath;
-}
-
-std::string
-SNRToBlockErrorRateManager::GetTraceFilePath()
-{
-    return m_traceFilePath;
-}
-
-double
-SNRToBlockErrorRateManager::GetBlockErrorRate(double SNR, uint8_t modulation)
-{
-    if (!m_activateLoss)
-    {
-        return 0;
-    }
-
-    std::vector<SNRToBlockErrorRateRecord*>* record = nullptr;
-
-    record = m_recordModulation[modulation];
-
-    if (SNR <= (record->at(0)->GetSNRValue()))
-    {
-        return 1;
-    }
-    if (SNR >= (record->at(record->size() - 1)->GetSNRValue()))
-    {
-        return 0;
-    }
-
-    unsigned int i;
-    for (i = 0; i < record->size(); i++)
-    {
-        if (SNR < record->at(i)->GetSNRValue())
-        {
-            break;
-        }
-    }
-    double intervalSize = (record->at(i)->GetSNRValue() - record->at(i - 1)->GetSNRValue());
-    double coeff1 = (SNR - record->at(i - 1)->GetSNRValue()) / intervalSize;
-    double coeff2 = -1 * (SNR - record->at(i)->GetSNRValue()) / intervalSize;
-    double BlockErrorRate = coeff2 * (record->at(i - 1)->GetBlockErrorRate()) +
-                            coeff1 * (record->at(i)->GetBlockErrorRate());
-    return BlockErrorRate;
-}
-
-SNRToBlockErrorRateRecord*
-SNRToBlockErrorRateManager::GetSNRToBlockErrorRateRecord(double SNR, uint8_t modulation)
-{
-    if (!m_activateLoss)
-    {
-        return new SNRToBlockErrorRateRecord(SNR, 0, 0, 0, 0, 0);
-    }
-
-    std::vector<SNRToBlockErrorRateRecord*>* record = nullptr;
-    record = m_recordModulation[modulation];
-
-    if (SNR <= (record->at(0)->GetSNRValue()))
-    {
-        return record->at(0)->Copy();
-    }
-    if (SNR >= (record->at(record->size() - 1)->GetSNRValue()))
-    {
-        return record->at(record->size() - 1)->Copy();
-    }
-
-    unsigned int i;
-    for (i = 0; i < record->size(); i++)
-    {
-        if (SNR < record->at(i)->GetSNRValue())
-        {
-            break;
-        }
-    }
-    double intervalSize = (record->at(i)->GetSNRValue() - record->at(i - 1)->GetSNRValue());
-    double coeff1 = (SNR - record->at(i - 1)->GetSNRValue()) / intervalSize;
-    double coeff2 = -1 * (SNR - record->at(i)->GetSNRValue()) / intervalSize;
-    double BER = coeff2 * (record->at(i - 1)->GetBitErrorRate()) +
-                 coeff1 * (record->at(i)->GetBitErrorRate());
-    double BlcER = coeff2 * (record->at(i - 1)->GetBlockErrorRate()) +
-                   coeff1 * (record->at(i)->GetBlockErrorRate());
-    double sigma2 =
-        coeff2 * (record->at(i - 1)->GetSigma2()) + coeff1 * (record->at(i)->GetSigma2());
-    double I1 = coeff2 * (record->at(i - 1)->GetI1()) + coeff1 * (record->at(i)->GetI1());
-    double I2 = coeff2 * (record->at(i - 1)->GetI2()) + coeff1 * (record->at(i)->GetI2());
-
-    auto SNRToBlockErrorRate = new SNRToBlockErrorRateRecord(SNR, BER, BlcER, sigma2, I1, I2);
-    return SNRToBlockErrorRate;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/snr-to-block-error-rate-manager.h ns-3.46/src/wimax/model/snr-to-block-error-rate-manager.h
--- ns-3.45/src/wimax/model/snr-to-block-error-rate-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/snr-to-block-error-rate-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,106 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef SNR_TO_BLOCK_ERROR_RATE_MANAGER_H
-#define SNR_TO_BLOCK_ERROR_RATE_MANAGER_H
-
-#include "snr-to-block-error-rate-record.h"
-
-#include "ns3/ptr.h"
-
-#include <vector>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief This class handles the  SNR to BlcER traces.
- *
- * A path to a repository containing trace files should be provided.
- * If no repository is provided the traces from default-traces.h will be loaded.
- * A valid repository should contain 7 files, one for each modulation
- * and coding scheme.
- *
- * The names of the files should respect the following format:
- * \c modulation<modulation-and-conding-index>.txt, _e.g._
- * \c modulation0.txt, \c modulation1.txt, _etc._ for
- * modulation 0, modulation 1, and so on...
- *
- * The file format is ASCII with six columns as follows:
- *
- * -#  The SNR value,
- * -#  The bit error rate BER,
- * -#  The block error rate BlcERm,
- * -#  The standard deviation on block error rate,
- * -#  The lower bound confidence interval for a given modulation, and
- * -#  The upper bound confidence interval for a given modulation.
- */
-class SNRToBlockErrorRateManager
-{
-  public:
-    SNRToBlockErrorRateManager();
-    ~SNRToBlockErrorRateManager();
-    /**
-     * @brief Set the path of the repository containing the traces
-     * @param traceFilePath the path to the repository.
-     */
-    void SetTraceFilePath(char* traceFilePath);
-    /**
-     * @return the path to the repository containing the traces.
-     */
-    std::string GetTraceFilePath();
-    /**
-     * @brief returns the Block Error Rate for a given modulation and SNR value
-     * @param SNR the SNR value
-     * @param modulation one of the seven MCS
-     * @return the Block Error Rate
-     */
-    double GetBlockErrorRate(double SNR, uint8_t modulation);
-    SNRToBlockErrorRateRecord*
-    /**
-     * @brief returns a record of type SNRToBlockErrorRateRecord corresponding to a given modulation
-     * and SNR value
-     * @param SNR the SNR value
-     * @param modulation one of the seven MCS
-     * @return the Block Error Rate
-     */
-    GetSNRToBlockErrorRateRecord(double SNR, uint8_t modulation);
-    /**
-     * @brief Loads the traces form the repository specified in the constructor or set by
-     * SetTraceFilePath function. If no repository is provided, default traces will be loaded from
-     * default-traces.h file
-     */
-
-    void LoadTraces();
-    /**
-     * @brief Loads the default traces from default-traces.h file
-     */
-    void LoadDefaultTraces();
-    /**
-     * @brief Reloads the trace
-     */
-    void ReLoadTraces();
-    /**
-     * @brief If activate loss is called with false, all the returned BlcER will be 0 (no losses)
-     * @param loss true to activates losses
-     */
-    void ActivateLoss(bool loss);
-
-  private:
-    /// Clear records function
-    void ClearRecords();
-    bool m_activateLoss;         ///< activate loss
-    std::string m_traceFilePath; ///< trace file path
-
-    std::vector<SNRToBlockErrorRateRecord*>* m_recordModulation[7]; ///< record modulation
-};
-} // namespace ns3
-
-#endif /* SNR_TO_BLOCK_ERROR_RATE_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/snr-to-block-error-rate-record.cc ns-3.46/src/wimax/model/snr-to-block-error-rate-record.cc
--- ns-3.45/src/wimax/model/snr-to-block-error-rate-record.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/snr-to-block-error-rate-record.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,120 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#include "snr-to-block-error-rate-record.h"
-
-#include "ns3/assert.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-SNRToBlockErrorRateRecord::SNRToBlockErrorRateRecord(double snrValue,
-                                                     double bitErrorRate,
-                                                     double blockErrorRate,
-                                                     double sigma2,
-                                                     double I1,
-                                                     double I2)
-{
-    m_snrValue = snrValue;
-    m_bitErrorRate = bitErrorRate;
-    m_blockErrorRate = blockErrorRate;
-    m_sigma2 = sigma2;
-    m_i1 = I1;
-    m_i2 = I2;
-}
-
-SNRToBlockErrorRateRecord*
-SNRToBlockErrorRateRecord::Copy() const
-{
-    return (new SNRToBlockErrorRateRecord(m_snrValue,
-                                          m_bitErrorRate,
-                                          m_blockErrorRate,
-                                          m_sigma2,
-                                          m_i1,
-                                          m_i2));
-}
-
-double
-SNRToBlockErrorRateRecord::GetSNRValue() const
-{
-    return m_snrValue;
-}
-
-SNRToBlockErrorRateRecord::~SNRToBlockErrorRateRecord()
-{
-    m_snrValue = 0;
-    m_bitErrorRate = 0;
-    m_blockErrorRate = 0;
-    m_sigma2 = 0;
-    m_i1 = 0;
-    m_i2 = 0;
-}
-
-double
-SNRToBlockErrorRateRecord::GetBitErrorRate() const
-{
-    return m_bitErrorRate;
-}
-
-double
-SNRToBlockErrorRateRecord::GetBlockErrorRate() const
-{
-    return m_blockErrorRate;
-}
-
-double
-SNRToBlockErrorRateRecord::GetSigma2() const
-{
-    return m_sigma2;
-}
-
-double
-SNRToBlockErrorRateRecord::GetI1() const
-{
-    return m_i1;
-}
-
-double
-SNRToBlockErrorRateRecord::GetI2() const
-{
-    return m_i2;
-}
-
-void
-SNRToBlockErrorRateRecord::SetSNRValue(double snrValue)
-{
-    m_snrValue = snrValue;
-}
-
-void
-SNRToBlockErrorRateRecord::SetBitErrorRate(double bitErrorRate)
-{
-    m_bitErrorRate = bitErrorRate;
-}
-
-void
-SNRToBlockErrorRateRecord::SetBlockErrorRate(double blockErrorRate)
-{
-    m_blockErrorRate = blockErrorRate;
-}
-
-void
-SNRToBlockErrorRateRecord::SetI1(double i1)
-{
-    m_i1 = i1;
-}
-
-void
-SNRToBlockErrorRateRecord::SetI2(double i2)
-{
-    m_i2 = i2;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/snr-to-block-error-rate-record.h ns-3.46/src/wimax/model/snr-to-block-error-rate-record.h
--- ns-3.45/src/wimax/model/snr-to-block-error-rate-record.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/snr-to-block-error-rate-record.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,110 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#ifndef SNR_TO_BLOCK_ERROR_RATE_RECORD_H
-#define SNR_TO_BLOCK_ERROR_RATE_RECORD_H
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief This class represents a record (handled by SnrToBlockErrorRate manager) that keeps a
- * mapping between an SNR value and its corresponding (1) Bit Error Rate, (2) Block Error Rate, (3)
- * Standard deviation, (4 and 5) confidence interval.
- *
- */
-class SNRToBlockErrorRateRecord
-{
-  public:
-    /**
-     * @brief creates a record and sets its values
-     * @param snrValue The SNR value
-     * @param bitErrorRate the BER
-     * @param BlockErrorRate the BlcER
-     * @param sigma2 the standard deviation
-     * @param I1 the lower boundary of the confidence interval
-     * @param I2 the upper boundary of the confidence interval
-     */
-    SNRToBlockErrorRateRecord(double snrValue,
-                              double bitErrorRate,
-                              double BlockErrorRate,
-                              double sigma2,
-                              double I1,
-                              double I2);
-    ~SNRToBlockErrorRateRecord();
-
-    /**
-     * @return the SNR value
-     */
-    double GetSNRValue() const;
-    /**
-     * @return the BER value
-     */
-    double GetBitErrorRate() const;
-    /**
-     * @return the BlcER value
-     */
-    double GetBlockErrorRate() const;
-    /**
-     * @return the standard deviation
-     */
-    double GetSigma2() const;
-    /**
-     * @return the lower boundary of the confidence interval
-     */
-    double GetI1() const;
-    /**
-     * @return the upper boundary of the confidence interval
-     */
-    double GetI2() const;
-    /**
-     * @brief copy a record
-     * @return a copy of this record
-     */
-    SNRToBlockErrorRateRecord* Copy() const;
-
-    /**
-     * @brief set the snr value
-     * @param snrValue the SNR value
-     */
-    void SetSNRValue(double snrValue);
-    /**
-     * @brief set the BER value
-     * @param bitErrorRate the bit error rate value
-     */
-    void SetBitErrorRate(double bitErrorRate);
-    /**
-     * @brief set the BlcER value
-     * @param blockErrorRate the block error rate value
-     */
-    void SetBlockErrorRate(double blockErrorRate);
-    /**
-     * @brief set the lower boundary of the confidence interval
-     * @param i1 the lower boundary of the confidence interval
-     */
-    void SetI1(double i1);
-    /**
-     * @brief set the upper boundary of the confidence interval
-     * @param i2 the upper boundary of the confidence interval
-     */
-    void SetI2(double i2);
-
-  private:
-    double m_snrValue;       ///< SNR value
-    double m_bitErrorRate;   ///< bit error rate
-    double m_blockErrorRate; ///< block error rate
-    double m_sigma2;         ///< sigma2
-    double m_i1;             ///< The lower boundary of the confidence interval
-    double m_i2;             ///< The upper boundary of the confidence interval
-};
-
-} // namespace ns3
-
-#endif /* SNR_TO_BLOCK_ERROR_RATE_RECORD_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-link-manager.cc ns-3.46/src/wimax/model/ss-link-manager.cc
--- ns-3.45/src/wimax/model/ss-link-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-link-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,493 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "ss-link-manager.h"
-
-#include "burst-profile-manager.h"
-#include "service-flow-manager.h"
-
-#include "ns3/enum.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SSLinkManager");
-
-NS_OBJECT_ENSURE_REGISTERED(SSLinkManager);
-
-TypeId
-SSLinkManager::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::SSLinkManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-SSLinkManager::SSLinkManager(Ptr<SubscriberStationNetDevice> ss)
-    : m_ss(ss),
-      m_rangingStatus(WimaxNetDevice::RANGING_STATUS_EXPIRED),
-      m_bsEirp(65535),
-      m_eirXPIrMax(65535),
-      m_pTxIrMax(0),
-      m_initRangOppNumber(0),
-      m_contentionRangingRetries(0),
-      m_rngReqFrameNumber(0),
-      m_dlChnlNr(0),
-      m_frequency(0),
-      m_rangingIntervalFound(false),
-      m_nrRngReqsSent(0),
-      m_nrRngRspsRecvd(0),
-      m_nrInvitedPollsRecvd(0),
-      m_rangingCW(0),
-      m_rangingBO(0),
-      m_nrRangingTransOpps(0),
-      m_isBackoffSet(false),
-      m_rangingAnomalies(0)
-{
-}
-
-SSLinkManager::~SSLinkManager()
-{
-    m_ss = nullptr;
-}
-
-void
-SSLinkManager::DoDispose()
-{
-    m_ss = nullptr;
-}
-
-void
-SSLinkManager::SetBsEirp(uint16_t bs_eirp)
-{
-    m_bsEirp = bs_eirp;
-}
-
-void
-SSLinkManager::SetEirXPIrMax(uint16_t eir_x_p_ir_max)
-{
-    m_eirXPIrMax = eir_x_p_ir_max;
-}
-
-void
-SSLinkManager::SetRangingIntervalFound(bool rangingIntervalFound)
-{
-    m_rangingIntervalFound = rangingIntervalFound;
-}
-
-bool
-SSLinkManager::GetRangingIntervalFound() const
-{
-    return m_rangingIntervalFound;
-}
-
-void
-SSLinkManager::SetNrRangingTransOpps(uint8_t nrRangingTransOpps)
-{
-    m_nrRangingTransOpps = nrRangingTransOpps;
-}
-
-void
-SSLinkManager::SetRangingCW(uint8_t rangingCW)
-{
-    m_rangingCW = rangingCW;
-}
-
-void
-SSLinkManager::IncrementNrInvitedPollsRecvd()
-{
-    m_nrInvitedPollsRecvd++;
-}
-
-EventId
-SSLinkManager::GetDlMapSyncTimeoutEvent()
-{
-    return m_dlMapSyncTimeoutEvent;
-}
-
-void
-SSLinkManager::StartScanning(SubscriberStationNetDevice::EventType type, bool deleteParameters)
-{
-    // temp parameter "type" just to check on expiry of which event the function was called
-
-    if (deleteParameters)
-    {
-        DeleteUplinkParameters();
-    }
-
-    NS_ASSERT_MSG(!m_ss->IsRegistered(),
-                  "Subscriber Station: Error while scanning: Already registered with a BS");
-
-    if (m_ss->GetState() != SubscriberStationNetDevice::SS_STATE_IDLE)
-    {
-        m_dlChnlNr++;
-    }
-
-    // using max number of channel according to according to Section 8.5.1 of IEEE 802.16-2004
-    // standard.
-    if (m_dlChnlNr >= 200)
-    {
-        m_dlChnlNr = 0;
-    }
-
-    uint64_t dlChannel = m_ss->GetChannel(m_dlChnlNr);
-
-    m_ss->SetState(SubscriberStationNetDevice::SS_STATE_SCANNING);
-    m_ss->GetPhy()->StartScanning(dlChannel,
-                                  m_ss->GetIntervalT20(),
-                                  MakeCallback(&SSLinkManager::EndScanning, this));
-}
-
-void
-SSLinkManager::EndScanning(bool status, uint64_t frequency)
-{
-    if (status)
-    {
-        StartSynchronizing();
-        m_frequency = frequency;
-    }
-    else
-    {
-        StartScanning(SubscriberStationNetDevice::EVENT_NONE, false);
-    }
-}
-
-void
-SSLinkManager::StartSynchronizing()
-{
-    m_ss->SetState(SubscriberStationNetDevice::SS_STATE_SYNCHRONIZING);
-    m_ss->SetTimer(Simulator::Schedule(m_ss->GetIntervalT21(),
-                                       &SSLinkManager::StartScanning,
-                                       this,
-                                       SubscriberStationNetDevice::EVENT_DL_MAP_SYNC_TIMEOUT,
-                                       false),
-                   m_dlMapSyncTimeoutEvent);
-}
-
-void
-SSLinkManager::SendRangingRequest(uint8_t uiuc, uint16_t allocationSize)
-{
-    NS_ASSERT_MSG(
-        m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL ||
-            m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_INV_RANG_INTRVL,
-        "SS: Error while sending a ranging request: the ss state should be "
-        "SS_STATE_WAITING_REG_RANG_INTRVL or SS_STATE_WAITING_INV_RANG_INTRVL");
-
-    if (m_nrRngReqsSent == 0) // sending the first time
-    {
-        m_pTxIrMax = CalculateMaxIRSignalStrength();
-        m_rngreq.SetReqDlBurstProfile(m_ss->GetBurstProfileManager()->GetBurstProfileToRequest());
-        m_rngreq.SetMacAddress(m_ss->GetMacAddress());
-    }
-    else
-    {
-        m_pTxIrMax++;
-        if (m_nrRngRspsRecvd > 0)
-        {
-            m_rngreq.SetRangingAnomalies(m_rangingAnomalies);
-        }
-    }
-
-    Ptr<Packet> packet = Create<Packet>();
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-
-    packet->AddHeader(m_rngreq);
-    packet->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_RNG_REQ));
-
-    Ptr<WimaxConnection> connection;
-
-    if (m_rangingStatus == WimaxNetDevice::RANGING_STATUS_CONTINUE)
-    {
-        connection = m_ss->GetBasicConnection();
-    }
-    else // have been assigned BCID, means currently adjusting parameters
-    {
-        connection = m_ss->GetInitialRangingConnection();
-    }
-
-    m_ss->Enqueue(packet, MacHeaderType(), connection);
-
-    m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_RNG_RSP);
-    m_ss->SetTimer(
-        Simulator::Schedule(m_ss->GetIntervalT3(), &SSLinkManager::StartContentionResolution, this),
-        m_waitForRngRspEvent);
-    m_nrRngReqsSent++;
-
-    NS_ASSERT_MSG(allocationSize ==
-                      m_ss->GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize() /
-                          m_ss->GetPhy()->GetPsPerSymbol(),
-                  "SS: Error while sending a ranging request: the allocation size is not correct");
-
-    // will work even if connection is not passed (i.e. null is passed) as scheduler will
-    // automatically select the same connection
-    m_ss->SendBurst(uiuc, allocationSize, connection);
-}
-
-void
-SSLinkManager::StartContentionResolution()
-{
-    NS_ASSERT_MSG(
-        m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_RNG_RSP ||
-            m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL ||
-            m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_ADJUSTING_PARAMETERS,
-        "SS: Can not start connection resolution: The SS state should be SS_STATE_WAITING_RNG_RSP "
-        "or SS_STATE_WAITING_REG_RANG_INTRVL or SS_STATE_ADJUSTING_PARAMETERS");
-
-    if (m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_RNG_RSP)
-    {
-        m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL);
-        IncreaseRangingRequestCW();
-        m_contentionRangingRetries++;
-    }
-    else if (m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_ADJUSTING_PARAMETERS)
-    {
-        m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL);
-    }
-
-    if (m_contentionRangingRetries == m_ss->GetMaxContentionRangingRetries())
-    {
-        StartScanning(SubscriberStationNetDevice::EVENT_NONE, false);
-    }
-    else
-    {
-        if (!m_isBackoffSet)
-        {
-            SelectRandomBackoff();
-        }
-    }
-}
-
-void
-SSLinkManager::PerformBackoff()
-{
-    Time deferTime;
-    Time timeToAllocation;
-    uint16_t nrPsPerRangOpp = m_ss->GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize();
-    uint16_t oppSize = m_ss->GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize() /
-                       m_ss->GetPhy()->GetPsPerSymbol();
-
-    for (uint8_t deferTOs = 0; deferTOs < m_nrRangingTransOpps; deferTOs++)
-    {
-        if (m_rangingBO == 0)
-        {
-            deferTime =
-                Seconds(deferTOs * nrPsPerRangOpp * m_ss->GetPhy()->GetPsDuration().GetSeconds());
-            timeToAllocation = m_ss->GetTimeToAllocation(deferTime);
-
-            Simulator::Schedule(timeToAllocation,
-                                &SSLinkManager::SendRangingRequest,
-                                this,
-                                OfdmUlBurstProfile::UIUC_INITIAL_RANGING,
-                                oppSize);
-
-            m_rngReqFrameNumber = m_ss->GetNrFrames();
-            m_initRangOppNumber = deferTOs + 1;
-
-            m_isBackoffSet = false;
-            break;
-        }
-        m_rangingBO--;
-    }
-}
-
-void
-SSLinkManager::SelectRandomBackoff()
-{
-    NS_ASSERT_MSG(
-        m_rangingCW != 0 && m_rangingBO == 0,
-        "be sure that CW has been set and BO is not already set"); // ensuring CW has been set and
-                                                                   // BO is not already set
-
-    m_rangingBO = (rand() % m_rangingCW);
-    m_isBackoffSet = true;
-}
-
-void
-SSLinkManager::IncreaseRangingRequestCW()
-{
-    m_rangingCW =
-        std::min(uint8_t((m_rangingCW * 2 + 1) - 1), m_ss->GetCurrentUcd().GetRangingBackoffEnd());
-}
-
-void
-SSLinkManager::ResetRangingRequestCW()
-{
-    m_rangingCW =
-        (uint8_t)std::pow(2.0, (double)m_ss->GetCurrentUcd().GetRangingBackoffStart()) - 1;
-}
-
-void
-SSLinkManager::PerformRanging(Cid cid, RngRsp rngrsp)
-{
-    // need to distinguish initial ranging or periodic ranging
-
-    if (cid == m_ss->GetInitialRangingConnection()->GetCid())
-    {
-        if (rngrsp.GetFrameNumber() == m_rngReqFrameNumber &&
-            rngrsp.GetInitRangOppNumber() == m_initRangOppNumber)
-        {
-            Simulator::Cancel(m_waitForRngRspEvent);
-            m_nrRngRspsRecvd++;
-
-            // RNG-REQ was undecodable
-            ResetRangingRequestCW();
-            AdjustRangingParameters(rngrsp);
-            m_ss->SetState(SubscriberStationNetDevice::SS_STATE_ADJUSTING_PARAMETERS);
-            return;
-        }
-
-        if (m_ss->GetAddress() != rngrsp.GetMacAddress())
-        {
-            return;
-        }
-
-        m_ss->SetBasicConnection(CreateObject<WimaxConnection>(rngrsp.GetBasicCid(), Cid::BASIC));
-
-        m_ss->SetPrimaryConnection(
-            CreateObject<WimaxConnection>(rngrsp.GetPrimaryCid(), Cid::PRIMARY));
-        m_ss->SetAreManagementConnectionsAllocated(true);
-    }
-    else
-    {
-        // either periodic ranging or an additional RNG-RSP during initial ranging
-    }
-
-    m_nrRngRspsRecvd++;
-    if (m_waitForRngRspEvent.IsPending())
-    {
-        Simulator::Cancel(m_waitForRngRspEvent);
-    }
-
-    m_rangingStatus = (WimaxNetDevice::RangingStatus)rngrsp.GetRangStatus();
-
-    NS_ASSERT_MSG(m_rangingStatus == WimaxNetDevice::RANGING_STATUS_CONTINUE ||
-                      m_rangingStatus == WimaxNetDevice::RANGING_STATUS_ABORT ||
-                      m_rangingStatus == WimaxNetDevice::RANGING_STATUS_SUCCESS,
-                  "SS: Can not perform ranging: the ranging status should be "
-                  "RANGING_STATUS_CONTINUE or RANGING_STATUS_ABORT or RANGING_STATUS_SUCCESS");
-
-    if (m_rangingStatus == WimaxNetDevice::RANGING_STATUS_ABORT)
-    {
-        if (rngrsp.GetDlFreqOverride())
-        {
-            // code to move to new channel/frequency goes here
-        }
-        // deassigning basic and primary CIDs
-        m_ss->SetBasicConnection(nullptr);
-        m_ss->SetPrimaryConnection(nullptr);
-        m_ss->SetAreManagementConnectionsAllocated(false);
-    }
-    else
-    {
-        AdjustRangingParameters(rngrsp);
-
-        if (m_rangingStatus == WimaxNetDevice::RANGING_STATUS_SUCCESS)
-        {
-            m_ss->SetState(SubscriberStationNetDevice::SS_STATE_REGISTERED);
-            // initiate service flows
-            if (m_ss->HasServiceFlows() && !m_ss->GetAreServiceFlowsAllocated())
-            {
-                m_ss->GetServiceFlowManager()->InitiateServiceFlows();
-            }
-
-            NegotiateBasicCapabilities();
-        }
-        else
-        {
-            m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_INV_RANG_INTRVL);
-            // wait for invited ranging interval assigned to its Basic CID
-        }
-    }
-}
-
-void
-SSLinkManager::DeleteUplinkParameters()
-{
-    m_ss->SetCurrentUcd(Ucd());
-}
-
-bool
-SSLinkManager::IsUlChannelUsable()
-{
-    // don't know how to check if usable, see Figure 58.
-    return true; // temporarily assuming usable
-}
-
-void
-SSLinkManager::AdjustRangingParameters(const RngRsp& rngrsp)
-{
-#if 0 /* a template for future implementation following */
-  bool successful = true;
-  uint8_t temp = rngrsp.GetTimingAdjust ();
-  temp = rngrsp.GetPowerLevelAdjust ();
-  temp = rngrsp.GetOffsetFreqAdjust ();
-
-  // code for adjusting parameters goes here
-
-  if (!successful)
-    {
-      // code for setting ranging anomalies goes here
-    }
-#endif
-}
-
-void
-SSLinkManager::NegotiateBasicCapabilities()
-{
-    // code to nagotiate basic capabilities goes here, ignored until very advanced stages
-}
-
-uint16_t
-SSLinkManager::CalculateMaxIRSignalStrength()
-{
-    // SS obtains RSSI measurement from the OFDM downlink preambles using a complex formula, page
-    // 486
-    uint16_t rss = 1;
-
-    if (m_bsEirp == 65535 || m_eirXPIrMax == 65535)
-    {
-        return GetMinTransmitPowerLevel();
-    }
-    else
-    {
-        return m_eirXPIrMax + m_bsEirp - rss;
-    }
-
-    return 0;
-}
-
-uint16_t
-SSLinkManager::GetMinTransmitPowerLevel()
-{
-    // code to calculate minimum transmit power level of the SS, see page 189 of amendment
-    return 10; // temp
-}
-
-void
-SSLinkManager::ScheduleScanningRestart(Time interval,
-                                       SubscriberStationNetDevice::EventType eventType,
-                                       bool deleteUlParameters,
-                                       EventId& eventId)
-{
-    m_ss->SetTimer(Simulator::Schedule(interval,
-                                       &SSLinkManager::StartScanning,
-                                       this,
-                                       eventType,
-                                       deleteUlParameters),
-                   eventId);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-link-manager.h ns-3.46/src/wimax/model/ss-link-manager.h
--- ns-3.45/src/wimax/model/ss-link-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-link-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef LINK_MANAGER_H
-#define LINK_MANAGER_H
-
-#include "cid.h"
-#include "mac-messages.h"
-#include "ss-net-device.h"
-#include "wimax-net-device.h"
-
-#include "ns3/event-id.h"
-#include "ns3/nstime.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief this class implements the link manager of subscriber station net device. An ss link
- * manager is responsible for link scanning and ranging
- */
-class SSLinkManager : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    /**
-     * Constructor
-     *
-     * @param ss subscriber station device
-     */
-    SSLinkManager(Ptr<SubscriberStationNetDevice> ss);
-    ~SSLinkManager() override;
-    void DoDispose() override;
-
-    /**
-     * Set BS EIRP
-     * @param bs_eirp the BS EIRP
-     */
-    void SetBsEirp(uint16_t bs_eirp);
-    /**
-     * Set EIRX IR maximum
-     * @param eir_x_p_ir_max the EIRX IR maximum
-     */
-    void SetEirXPIrMax(uint16_t eir_x_p_ir_max);
-    /**
-     * Set ranging interval found
-     * @param rangingIntervalFound the ranging interval found
-     */
-    void SetRangingIntervalFound(bool rangingIntervalFound);
-    /**
-     * Get ranging interval found
-     * @returns the ranging interval found
-     */
-    bool GetRangingIntervalFound() const;
-    /**
-     * Set NR ranging trans opps
-     * @param nrRangingTransOpps the NR ranging trans opps
-     */
-    void SetNrRangingTransOpps(uint8_t nrRangingTransOpps);
-    /**
-     * Set ranging CW
-     * @param rangingCW the ranging CW
-     */
-    void SetRangingCW(uint8_t rangingCW);
-    /// Increment NR invited polls received
-    void IncrementNrInvitedPollsRecvd();
-    /**
-     * Get DL map sync timeout event
-     * @returns the event ID
-     */
-    EventId GetDlMapSyncTimeoutEvent();
-
-    /**
-     * Perform ranging
-     * @param cid the CID
-     * @param rngrsp the ranging response
-     */
-    void PerformRanging(Cid cid, RngRsp rngrsp);
-    /**
-     * Start scanning
-     * @param type the event type
-     * @param deleteParameters the delete parameters
-     */
-    void StartScanning(SubscriberStationNetDevice::EventType type, bool deleteParameters);
-    /**
-     * Send ranging request
-     * @param uiuc the UIUC
-     * @param allocationSize the allocation size
-     */
-    void SendRangingRequest(uint8_t uiuc, uint16_t allocationSize);
-    /// Start contention resolution
-    void StartContentionResolution();
-    /// Perform backoff
-    void PerformBackoff();
-    /**
-     * Is UL channel usable
-     * @returns the UL channel usable flag
-     */
-    bool IsUlChannelUsable();
-    /**
-     * Schedule scanning request
-     * @param interval the scanning request interval
-     * @param eventType event type
-     * @param deleteUlParameters the delete UL parameters
-     * @param eventId the event ID
-     */
-    void ScheduleScanningRestart(Time interval,
-                                 SubscriberStationNetDevice::EventType eventType,
-                                 bool deleteUlParameters,
-                                 EventId& eventId);
-
-  private:
-    /// type conversion operator
-    SSLinkManager(const SSLinkManager&);
-    /**
-     * assignment operator
-     * @returns SS link manager
-     */
-    SSLinkManager& operator=(const SSLinkManager&);
-
-    /**
-     * End scanning
-     * @param status the end status
-     * @param frequency the frequency
-     */
-    void EndScanning(bool status, uint64_t frequency);
-    /// Start synchronizing
-    void StartSynchronizing();
-    /**
-     * Search for DL channel
-     * @param channel the DL channel
-     * @returns true if found
-     */
-    bool SearchForDlChannel(uint8_t channel);
-    /// Select random backoff
-    void SelectRandomBackoff();
-    /// Increase rnaging request CW
-    void IncreaseRangingRequestCW();
-    /// Reset ranging request CW
-    void ResetRangingRequestCW();
-    /// Delete uplink parameters
-    void DeleteUplinkParameters();
-    /**
-     * Adjust ranging parameters
-     * @param rngrsp the ranging response
-     */
-    void AdjustRangingParameters(const RngRsp& rngrsp);
-    /// Negotiate basic capabilities
-    void NegotiateBasicCapabilities();
-    /**
-     * Calculate maximum IR signal strength
-     * @returns the maximum IR signal strength
-     */
-    uint16_t CalculateMaxIRSignalStrength();
-    /**
-     * Get minimum transmit power level
-     * @returns the minimum transmit power level
-     */
-    uint16_t GetMinTransmitPowerLevel();
-
-    Ptr<SubscriberStationNetDevice> m_ss; ///< subscriber station device
-
-    WimaxNetDevice::RangingStatus m_rangingStatus; ///< ranging status
-    // initial ranging parameters obtained from DCD (in channel encodings)
-    uint16_t m_bsEirp;     ///< BS EIRP
-    uint16_t m_eirXPIrMax; ///< initial ranging maximum equivalent isotropic received power at BS
-    uint16_t m_pTxIrMax; ///< maximum transmit signal strength for initial ranging calculated by SS
-
-    uint8_t m_initRangOppNumber; ///< Initial Ranging opportunity (1–255) in which SS transmitted
-                                 ///< the RNG_REQ
-    uint8_t m_contentionRangingRetries; ///< contention ranging retries
-    uint32_t m_rngReqFrameNumber;       ///< frame number in which SS sent RNG_REQ message
-    RngReq m_rngreq;                    ///< rng request
-
-    uint8_t m_dlChnlNr;   ///< indicates the channel/frequency currently the SS is scanning
-    uint64_t m_frequency; ///< frequency on which it is currently operating, i.e., where scanning
-                          ///< was successful
-    bool m_rangingIntervalFound; ///< ranging interval found
-
-    // stats members
-    uint16_t m_nrRngReqsSent;       ///< number rang requests sent
-    uint16_t m_nrRngRspsRecvd;      ///< number rang responses received
-    uint16_t m_nrInvitedPollsRecvd; ///< number invited polls received
-
-    uint8_t m_rangingCW;          ///< ranging CW
-    uint8_t m_rangingBO;          ///< ranging BO
-    uint8_t m_nrRangingTransOpps; ///< number ranging trans opps
-    bool m_isBackoffSet;          ///< is backoff set
-    uint8_t m_rangingAnomalies;   ///< ranging anomalies
-
-    EventId m_waitForRngRspEvent;    ///< wait for rang response event
-    EventId m_dlMapSyncTimeoutEvent; ///< DL map sync timeout event
-};
-
-} // namespace ns3
-
-#endif /* LINK_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-manager.cc ns-3.46/src/wimax/model/ss-manager.cc
--- ns-3.45/src/wimax/model/ss-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "ss-manager.h"
-
-#include "service-flow.h"
-
-#include "ns3/log.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SSManager");
-
-NS_OBJECT_ENSURE_REGISTERED(SSManager);
-
-TypeId
-SSManager::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::SSManager").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-SSManager::SSManager()
-{
-    m_ssRecords = new std::vector<SSRecord*>();
-}
-
-SSManager::~SSManager()
-{
-    for (auto iter = m_ssRecords->begin(); iter != m_ssRecords->end(); ++iter)
-    {
-        delete *iter;
-    }
-    delete m_ssRecords;
-    m_ssRecords = nullptr;
-}
-
-SSRecord*
-SSManager::CreateSSRecord(const Mac48Address& macAddress)
-{
-    auto ssRecord = new SSRecord(macAddress);
-    m_ssRecords->push_back(ssRecord);
-    return ssRecord;
-}
-
-SSRecord*
-SSManager::GetSSRecord(const Mac48Address& macAddress) const
-{
-    for (auto iter = m_ssRecords->begin(); iter != m_ssRecords->end(); ++iter)
-    {
-        if ((*iter)->GetMacAddress() == macAddress)
-        {
-            return *iter;
-        }
-    }
-
-    NS_LOG_DEBUG("GetSSRecord: SSRecord not found!");
-    return nullptr;
-}
-
-SSRecord*
-SSManager::GetSSRecord(Cid cid) const
-{
-    for (auto iter1 = m_ssRecords->begin(); iter1 != m_ssRecords->end(); ++iter1)
-    {
-        SSRecord* ssRecord = *iter1;
-        if (ssRecord->GetBasicCid() == cid || ssRecord->GetPrimaryCid() == cid)
-        {
-            return ssRecord;
-        }
-        else
-        {
-            std::vector<ServiceFlow*> sf = ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_ALL);
-            for (auto iter2 = sf.begin(); iter2 != sf.end(); ++iter2)
-            {
-                if ((*iter2)->GetConnection()->GetCid() == cid)
-                {
-                    return ssRecord;
-                }
-            }
-        }
-    }
-
-    NS_LOG_DEBUG("GetSSRecord: SSRecord not found!");
-    return nullptr;
-}
-
-std::vector<SSRecord*>*
-SSManager::GetSSRecords() const
-{
-    return m_ssRecords;
-}
-
-bool
-SSManager::IsInRecord(const Mac48Address& macAddress) const
-{
-    for (auto iter = m_ssRecords->begin(); iter != m_ssRecords->end(); ++iter)
-    {
-        if ((*iter)->GetMacAddress() == macAddress)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool
-SSManager::IsRegistered(const Mac48Address& macAddress) const
-{
-    SSRecord* ssRecord = GetSSRecord(macAddress);
-    return ssRecord != nullptr &&
-           ssRecord->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_SUCCESS;
-}
-
-void
-SSManager::DeleteSSRecord(Cid cid)
-{
-    for (auto iter1 = m_ssRecords->begin(); iter1 != m_ssRecords->end(); ++iter1)
-    {
-        SSRecord* ssRecord = *iter1;
-        if (ssRecord->GetBasicCid() == cid || ssRecord->GetPrimaryCid() == cid)
-        {
-            m_ssRecords->erase(iter1);
-            return;
-        }
-        else
-        {
-            std::vector<ServiceFlow*> sf = ssRecord->GetServiceFlows(ServiceFlow::SF_TYPE_ALL);
-            for (auto iter2 = sf.begin(); iter2 != sf.end(); ++iter2)
-            {
-                if ((*iter2)->GetConnection()->GetCid() == cid)
-                {
-                    m_ssRecords->erase(iter1);
-                    return;
-                }
-            }
-        }
-    }
-}
-
-Mac48Address
-SSManager::GetMacAddress(Cid cid) const
-{
-    return GetSSRecord(cid)->GetMacAddress();
-}
-
-uint32_t
-SSManager::GetNSSs() const
-{
-    return m_ssRecords->size();
-}
-
-uint32_t
-SSManager::GetNRegisteredSSs() const
-{
-    uint32_t nrSS = 0;
-    for (auto iter = m_ssRecords->begin(); iter != m_ssRecords->end(); ++iter)
-    {
-        if ((*iter)->GetRangingStatus() == WimaxNetDevice::RANGING_STATUS_SUCCESS)
-        {
-            nrSS++;
-        }
-    }
-    return nrSS;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-manager.h ns-3.46/src/wimax/model/ss-manager.h
--- ns-3.45/src/wimax/model/ss-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef SS_MANAGER_H
-#define SS_MANAGER_H
-
-#include "cid.h"
-#include "ss-record.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief this class manages a list of SSrecords
- * @see SSrecord
- */
-class SSManager : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    SSManager();
-    ~SSManager() override;
-    /**
-     * Create SS record
-     * @param macAddress the MAC address
-     * @returns pointer to the SS record
-     */
-    SSRecord* CreateSSRecord(const Mac48Address& macAddress);
-    /**
-     * Get SS record
-     * @param macAddress the MAC address
-     * @returns pointer to the SS record
-     */
-    SSRecord* GetSSRecord(const Mac48Address& macAddress) const;
-    /**
-     * @brief returns the ssrecord which has been assigned this cid. Since
-     *        different types of cids (basic, primary, transport) are assigned
-     *        different values, all cids (basic, primary and transport) of the
-     *        ssrecord are matched.
-     * @param cid the cid to be matched
-     * @return pointer to the ss record matching the cid
-     */
-    SSRecord* GetSSRecord(Cid cid) const;
-    /**
-     * Get SS records
-     * @returns a vector of pointers to the SS records
-     */
-    std::vector<SSRecord*>* GetSSRecords() const;
-    /**
-     * Check if address is in record
-     * @param macAddress the MAC address
-     * @returns whether the address is in the record
-     */
-    bool IsInRecord(const Mac48Address& macAddress) const;
-    /**
-     * Check if address is registered
-     * @param macAddress the MAC address
-     * @returns whether the address is registered
-     */
-    bool IsRegistered(const Mac48Address& macAddress) const;
-    /**
-     * Delete SS record
-     * @param cid the CID
-     */
-    void DeleteSSRecord(Cid cid);
-    /**
-     * Get MAC address by CID
-     * @param cid the CID
-     * @returns the MAC address
-     */
-    Mac48Address GetMacAddress(Cid cid) const;
-    /**
-     * Get number of SSs
-     * @returns the number of SSs
-     */
-    uint32_t GetNSSs() const;
-    /**
-     * Get number of registered SSs
-     * @returns the number of registered SSs
-     */
-    uint32_t GetNRegisteredSSs() const;
-
-  private:
-    std::vector<SSRecord*>* m_ssRecords; ///< the SS records
-};
-
-} // namespace ns3
-
-#endif /* SS_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-net-device.cc ns-3.46/src/wimax/model/ss-net-device.cc
--- ns-3.45/src/wimax/model/ss-net-device.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-net-device.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,1356 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "ss-net-device.h"
-
-#include "bandwidth-manager.h"
-#include "burst-profile-manager.h"
-#include "connection-manager.h"
-#include "dl-mac-messages.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-link-manager.h"
-#include "ss-scheduler.h"
-#include "ul-mac-messages.h"
-#include "wimax-mac-queue.h"
-#include "wimax-phy.h"
-
-#include "ns3/config.h"
-#include "ns3/enum.h"
-#include "ns3/node.h"
-#include "ns3/packet-burst.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-#include "ns3/trace-source-accessor.h"
-
-#include <algorithm>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SubscriberStationNetDevice");
-
-NS_OBJECT_ENSURE_REGISTERED(SubscriberStationNetDevice);
-
-Time
-SubscriberStationNetDevice::GetDefaultLostDlMapInterval()
-{
-    return MicroSeconds(500000);
-}
-
-TypeId
-SubscriberStationNetDevice::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::SubscriberStationNetDevice")
-
-            .SetParent<WimaxNetDevice>()
-            .SetGroupName("Wimax")
-
-            .AddConstructor<SubscriberStationNetDevice>()
-
-            .AddAttribute("BasicConnection",
-                          "Basic connection",
-                          PointerValue(),
-                          MakePointerAccessor(&SubscriberStationNetDevice::m_basicConnection),
-                          MakePointerChecker<WimaxConnection>())
-
-            .AddAttribute("PrimaryConnection",
-                          "Primary connection",
-                          PointerValue(),
-                          MakePointerAccessor(&SubscriberStationNetDevice::m_primaryConnection),
-                          MakePointerChecker<WimaxConnection>())
-
-            .AddAttribute("LostDlMapInterval",
-                          "Time since last received DL-MAP message before downlink synchronization "
-                          "is considered lost. Maximum is 600ms",
-                          TimeValue(Seconds(0.5)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetLostDlMapInterval,
-                                           &SubscriberStationNetDevice::SetLostDlMapInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("LostUlMapInterval",
-                          "Time since last received UL-MAP before uplink synchronization is "
-                          "considered lost, maximum is 600.",
-                          TimeValue(MilliSeconds(500)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetLostUlMapInterval,
-                                           &SubscriberStationNetDevice::SetLostUlMapInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("MaxDcdInterval",
-                          "Maximum time between transmission of DCD messages. Maximum is 10s",
-                          TimeValue(Seconds(10)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetMaxDcdInterval,
-                                           &SubscriberStationNetDevice::SetMaxDcdInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("MaxUcdInterval",
-                          "Maximum time between transmission of UCD messages. Maximum is 10s",
-                          TimeValue(Seconds(10)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetMaxUcdInterval,
-                                           &SubscriberStationNetDevice::SetMaxUcdInterval),
-                          MakeTimeChecker())
-
-            .AddAttribute("IntervalT1",
-                          "Wait for DCD timeout. Maximum is 5*maxDcdInterval",
-                          TimeValue(Seconds(50)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT1,
-                                           &SubscriberStationNetDevice::SetIntervalT1),
-                          MakeTimeChecker())
-
-            .AddAttribute("IntervalT2",
-                          "Wait for broadcast ranging timeout, i.e., wait for initial ranging "
-                          "opportunity. Maximum is 5*Ranging interval",
-                          TimeValue(Seconds(10)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT2,
-                                           &SubscriberStationNetDevice::SetIntervalT2),
-                          MakeTimeChecker())
-
-            .AddAttribute("IntervalT3",
-                          "ranging Response reception timeout following the transmission of a "
-                          "ranging request. Maximum is 200ms",
-                          TimeValue(Seconds(0.2)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT3,
-                                           &SubscriberStationNetDevice::SetIntervalT3),
-                          MakeTimeChecker())
-
-            .AddAttribute("IntervalT7",
-                          "wait for DSA/DSC/DSD Response timeout. Maximum is 1s",
-                          TimeValue(Seconds(0.1)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT7,
-                                           &SubscriberStationNetDevice::SetIntervalT7),
-                          MakeTimeChecker())
-
-            .AddAttribute("IntervalT12",
-                          "Wait for UCD descriptor.Maximum is 5*MaxUcdInterval",
-                          TimeValue(Seconds(10)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT12,
-                                           &SubscriberStationNetDevice::SetIntervalT12),
-                          MakeTimeChecker())
-
-            .AddAttribute(
-                "IntervalT20",
-                "Time the SS searches for preambles on a given channel. Minimum is 2 MAC frames",
-                TimeValue(Seconds(0.5)),
-                MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT20,
-                                 &SubscriberStationNetDevice::SetIntervalT20),
-                MakeTimeChecker())
-
-            .AddAttribute("IntervalT21",
-                          "time the SS searches for (decodable) DL-MAP on a given channel",
-                          TimeValue(Seconds(10)),
-                          MakeTimeAccessor(&SubscriberStationNetDevice::GetIntervalT21,
-                                           &SubscriberStationNetDevice::SetIntervalT21),
-                          MakeTimeChecker())
-
-            .AddAttribute(
-                "MaxContentionRangingRetries",
-                "Number of retries on contention Ranging Requests",
-                UintegerValue(16),
-                MakeUintegerAccessor(&SubscriberStationNetDevice::GetMaxContentionRangingRetries,
-                                     &SubscriberStationNetDevice::SetMaxContentionRangingRetries),
-                MakeUintegerChecker<uint8_t>(1, 16))
-
-            .AddAttribute("SSScheduler",
-                          "The ss scheduler attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&SubscriberStationNetDevice::GetScheduler,
-                                              &SubscriberStationNetDevice::SetScheduler),
-                          MakePointerChecker<SSScheduler>())
-
-            .AddAttribute("LinkManager",
-                          "The ss link manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&SubscriberStationNetDevice::GetLinkManager,
-                                              &SubscriberStationNetDevice::SetLinkManager),
-                          MakePointerChecker<SSLinkManager>())
-
-            .AddAttribute("Classifier",
-                          "The ss classifier attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&SubscriberStationNetDevice::GetIpcsClassifier,
-                                              &SubscriberStationNetDevice::SetIpcsPacketClassifier),
-                          MakePointerChecker<IpcsClassifier>())
-
-            .AddTraceSource(
-                "SSTxDrop",
-                "A packet has been dropped in the MAC layer before being queued for transmission.",
-                MakeTraceSourceAccessor(&SubscriberStationNetDevice::m_ssTxDropTrace),
-                "ns3::Packet::TracedCallback")
-
-            .AddTraceSource(
-                "SSPromiscRx",
-                "A packet has been received by this device, has been passed up from the physical "
-                "layer "
-                "and is being forwarded up the local protocol stack.  This is a promiscuous trace,",
-                MakeTraceSourceAccessor(&SubscriberStationNetDevice::m_ssPromiscRxTrace),
-                "ns3::Packet::TracedCallback")
-
-            .AddTraceSource("SSRx",
-                            "A packet has been received by this device, has been passed up from "
-                            "the physical layer "
-                            "and is being forwarded up the local protocol stack.  This is a "
-                            "non-promiscuous trace,",
-                            MakeTraceSourceAccessor(&SubscriberStationNetDevice::m_ssRxTrace),
-                            "ns3::Packet::TracedCallback")
-
-            .AddTraceSource("SSRxDrop",
-                            "A packet has been dropped in the MAC layer after it has been passed "
-                            "up from the physical "
-                            "layer.",
-                            MakeTraceSourceAccessor(&SubscriberStationNetDevice::m_ssRxDropTrace),
-                            "ns3::Packet::TracedCallback");
-    return tid;
-}
-
-SubscriberStationNetDevice::SubscriberStationNetDevice()
-{
-    InitSubscriberStationNetDevice();
-}
-
-void
-SubscriberStationNetDevice::InitSubscriberStationNetDevice()
-{
-    m_lostDlMapInterval = MilliSeconds(500);
-    m_lostUlMapInterval = MilliSeconds(500);
-    m_maxDcdInterval = Seconds(10);
-    m_maxUcdInterval = Seconds(10);
-    m_intervalT1 = Seconds(5 * m_maxDcdInterval.GetSeconds());
-    m_intervalT2 = Seconds(5 * 2); // shall be 5 * RangingInterval, if ranging interval=see T2 at
-                                   // page 638) means Initial Ranging Interval=see page 637)
-    m_intervalT3 = MilliSeconds(200);
-    m_intervalT7 = Seconds(0.1); // maximum is 1
-    m_intervalT12 = Seconds(5 * m_maxUcdInterval.GetSeconds());
-    m_intervalT21 = Seconds(11);
-    m_maxContentionRangingRetries = 16;
-    m_dcdCount = 0;
-    m_baseStationId = Mac48Address("00:00:00:00:00:00");
-    m_ucdCount = 0;
-    m_allocationStartTime = 0;
-    m_nrDlMapElements = 0;
-    m_nrUlMapElements = 0;
-    m_nrDlMapRecvd = 0;
-    m_nrUlMapRecvd = 0;
-    m_nrDcdRecvd = 0;
-    m_nrUcdRecvd = 0;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    m_areManagementConnectionsAllocated = false;
-    m_areServiceFlowsAllocated = false;
-
-    m_basicConnection = nullptr;
-    m_primaryConnection = nullptr;
-
-    m_dlBurstProfile = new OfdmDlBurstProfile();
-    m_ulBurstProfile = new OfdmUlBurstProfile();
-    m_classifier = CreateObject<IpcsClassifier>();
-    m_linkManager = CreateObject<SSLinkManager>(this);
-    m_scheduler = CreateObject<SSScheduler>(this);
-    m_serviceFlowManager = CreateObject<SsServiceFlowManager>(this);
-}
-
-SubscriberStationNetDevice::SubscriberStationNetDevice(Ptr<Node> node, Ptr<WimaxPhy> phy)
-{
-    InitSubscriberStationNetDevice();
-    this->SetNode(node);
-    this->SetPhy(phy);
-}
-
-SubscriberStationNetDevice::~SubscriberStationNetDevice()
-{
-}
-
-void
-SubscriberStationNetDevice::DoDispose()
-{
-    delete m_dlBurstProfile;
-    delete m_ulBurstProfile;
-    m_scheduler = nullptr;
-    m_serviceFlowManager = nullptr;
-    m_basicConnection = nullptr;
-    m_primaryConnection = nullptr;
-    m_classifier = nullptr;
-    m_dlBurstProfile = nullptr;
-    m_ulBurstProfile = nullptr;
-
-    m_linkManager = nullptr;
-
-    m_asciiTxQueueEnqueueCb.Nullify();
-    m_asciiTxQueueDequeueCb.Nullify();
-    m_asciiTxQueueDropCb.Nullify();
-
-    WimaxNetDevice::DoDispose();
-}
-
-void
-SubscriberStationNetDevice::SetLostDlMapInterval(Time lostDlMapInterval)
-{
-    m_lostDlMapInterval = lostDlMapInterval;
-}
-
-Time
-SubscriberStationNetDevice::GetLostDlMapInterval() const
-{
-    return m_lostDlMapInterval;
-}
-
-void
-SubscriberStationNetDevice::SetLostUlMapInterval(Time lostUlMapInterval)
-{
-    m_lostUlMapInterval = lostUlMapInterval;
-}
-
-Time
-SubscriberStationNetDevice::GetLostUlMapInterval() const
-{
-    return m_lostUlMapInterval;
-}
-
-void
-SubscriberStationNetDevice::SetMaxDcdInterval(Time maxDcdInterval)
-{
-    m_maxDcdInterval = maxDcdInterval;
-}
-
-Time
-SubscriberStationNetDevice::GetMaxDcdInterval() const
-{
-    return m_maxDcdInterval;
-}
-
-void
-SubscriberStationNetDevice::SetMaxUcdInterval(Time maxUcdInterval)
-{
-    m_maxUcdInterval = maxUcdInterval;
-}
-
-Time
-SubscriberStationNetDevice::GetMaxUcdInterval() const
-{
-    return m_maxUcdInterval;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT1(Time interval)
-{
-    m_intervalT1 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT1() const
-{
-    return m_intervalT1;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT2(Time interval)
-{
-    m_intervalT2 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT2() const
-{
-    return m_intervalT2;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT3(Time interval)
-{
-    m_intervalT3 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT3() const
-{
-    return m_intervalT3;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT7(Time interval)
-{
-    m_intervalT7 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT7() const
-{
-    return m_intervalT7;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT12(Time interval)
-{
-    m_intervalT12 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT12() const
-{
-    return m_intervalT12;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT20(Time interval)
-{
-    m_intervalT20 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT20() const
-{
-    return m_intervalT20;
-}
-
-void
-SubscriberStationNetDevice::SetIntervalT21(Time interval)
-{
-    m_intervalT21 = interval;
-}
-
-Time
-SubscriberStationNetDevice::GetIntervalT21() const
-{
-    return m_intervalT21;
-}
-
-void
-SubscriberStationNetDevice::SetMaxContentionRangingRetries(uint8_t maxContentionRangingRetries)
-{
-    m_maxContentionRangingRetries = maxContentionRangingRetries;
-}
-
-uint8_t
-SubscriberStationNetDevice::GetMaxContentionRangingRetries() const
-{
-    return m_maxContentionRangingRetries;
-}
-
-void
-SubscriberStationNetDevice::SetBasicConnection(Ptr<WimaxConnection> basicConnection)
-{
-    m_basicConnection = basicConnection;
-    uint32_t nodeId = GetNode()->GetId();
-    uint32_t ifaceId = GetIfIndex();
-
-    if (!m_asciiTxQueueEnqueueCb.IsNull())
-    {
-        std::ostringstream oss;
-        oss << "/NodeList/" << nodeId << "/DeviceList/" << ifaceId
-            << "/$ns3::SubscriberStationNetDevice/BasicConnection/TxQueue/Enqueue";
-        Config::Connect(oss.str(), m_asciiTxQueueEnqueueCb);
-    }
-    if (!m_asciiTxQueueDequeueCb.IsNull())
-    {
-        std::ostringstream oss;
-        oss << "/NodeList/" << nodeId << "/DeviceList/" << ifaceId
-            << "/$ns3::SubscriberStationNetDevice/BasicConnection/TxQueue/Dequeue";
-        Config::Connect(oss.str(), m_asciiTxQueueDequeueCb);
-    }
-    if (!m_asciiTxQueueDropCb.IsNull())
-    {
-        std::ostringstream oss;
-        oss << "/NodeList/" << nodeId << "/DeviceList/" << ifaceId
-            << "/$ns3::SubscriberStationNetDevice/BasicConnection/TxQueue/Drop";
-        Config::Connect(oss.str(), m_asciiTxQueueDropCb);
-    }
-}
-
-Ptr<WimaxConnection>
-SubscriberStationNetDevice::GetBasicConnection() const
-{
-    return m_basicConnection;
-}
-
-void
-SubscriberStationNetDevice::SetPrimaryConnection(Ptr<WimaxConnection> primaryConnection)
-{
-    m_primaryConnection = primaryConnection;
-
-    uint32_t nodeId = GetNode()->GetId();
-    uint32_t ifaceId = GetIfIndex();
-
-    if (!m_asciiTxQueueEnqueueCb.IsNull())
-    {
-        std::ostringstream oss;
-        oss << "/NodeList/" << nodeId << "/DeviceList/" << ifaceId
-            << "/$ns3::SubscriberStationNetDevice/PrimaryConnection/TxQueue/Enqueue";
-        Config::Connect(oss.str(), m_asciiTxQueueEnqueueCb);
-    }
-    if (!m_asciiTxQueueDequeueCb.IsNull())
-    {
-        std::ostringstream oss;
-        oss << "/NodeList/" << nodeId << "/DeviceList/" << ifaceId
-            << "/$ns3::SubscriberStationNetDevice/PrimaryConnection/TxQueue/Dequeue";
-        Config::Connect(oss.str(), m_asciiTxQueueDequeueCb);
-    }
-    if (!m_asciiTxQueueDropCb.IsNull())
-    {
-        std::ostringstream oss;
-        oss << "/NodeList/" << nodeId << "/DeviceList/" << ifaceId
-            << "/$ns3::SubscriberStationNetDevice/PrimaryConnection/TxQueue/Drop";
-        Config::Connect(oss.str(), m_asciiTxQueueDropCb);
-    }
-}
-
-Ptr<WimaxConnection>
-SubscriberStationNetDevice::GetPrimaryConnection() const
-{
-    return m_primaryConnection;
-}
-
-Cid
-SubscriberStationNetDevice::GetBasicCid() const
-{
-    return m_basicConnection->GetCid();
-}
-
-Cid
-SubscriberStationNetDevice::GetPrimaryCid() const
-{
-    return m_primaryConnection->GetCid();
-}
-
-void
-SubscriberStationNetDevice::SetModulationType(WimaxPhy::ModulationType modulationType)
-{
-    m_modulationType = modulationType;
-}
-
-WimaxPhy::ModulationType
-SubscriberStationNetDevice::GetModulationType() const
-{
-    return m_modulationType;
-}
-
-void
-SubscriberStationNetDevice::SetAreManagementConnectionsAllocated(
-    bool areManagementConnectionsAllocated)
-{
-    m_areManagementConnectionsAllocated = areManagementConnectionsAllocated;
-}
-
-bool
-SubscriberStationNetDevice::GetAreManagementConnectionsAllocated() const
-{
-    return m_areManagementConnectionsAllocated;
-}
-
-void
-SubscriberStationNetDevice::SetAreServiceFlowsAllocated(bool areServiceFlowsAllocated)
-{
-    m_areServiceFlowsAllocated = areServiceFlowsAllocated;
-}
-
-bool
-SubscriberStationNetDevice::GetAreServiceFlowsAllocated() const
-{
-    return m_areServiceFlowsAllocated;
-}
-
-Ptr<SSScheduler>
-SubscriberStationNetDevice::GetScheduler() const
-{
-    return m_scheduler;
-}
-
-void
-SubscriberStationNetDevice::SetScheduler(Ptr<SSScheduler> scheduler)
-{
-    m_scheduler = scheduler;
-}
-
-bool
-SubscriberStationNetDevice::HasServiceFlows() const
-{
-    return !GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_ALL).empty();
-}
-
-Ptr<IpcsClassifier>
-SubscriberStationNetDevice::GetIpcsClassifier() const
-{
-    return m_classifier;
-}
-
-void
-SubscriberStationNetDevice::SetIpcsPacketClassifier(Ptr<IpcsClassifier> classifier)
-{
-    m_classifier = classifier;
-}
-
-Ptr<SSLinkManager>
-SubscriberStationNetDevice::GetLinkManager() const
-{
-    return m_linkManager;
-}
-
-void
-SubscriberStationNetDevice::SetLinkManager(Ptr<SSLinkManager> linkManager)
-{
-    m_linkManager = linkManager;
-}
-
-Ptr<SsServiceFlowManager>
-SubscriberStationNetDevice::GetServiceFlowManager() const
-{
-    return m_serviceFlowManager;
-}
-
-void
-SubscriberStationNetDevice::SetServiceFlowManager(Ptr<SsServiceFlowManager> sfm)
-{
-    m_serviceFlowManager = sfm;
-}
-
-void
-SubscriberStationNetDevice::Start()
-{
-    SetReceiveCallback();
-
-    GetPhy()->SetPhyParameters();
-    GetPhy()->SetDataRates();
-    m_intervalT20 = Seconds(4 * GetPhy()->GetFrameDuration().GetSeconds());
-
-    CreateDefaultConnections();
-    Simulator::ScheduleNow(&SSLinkManager::StartScanning, m_linkManager, EVENT_NONE, false);
-}
-
-void
-SubscriberStationNetDevice::Stop()
-{
-    SetState(SS_STATE_STOPPED);
-}
-
-void
-SubscriberStationNetDevice::AddServiceFlow(ServiceFlow sf) const
-{
-    GetServiceFlowManager()->AddServiceFlow(sf);
-}
-
-void
-SubscriberStationNetDevice::AddServiceFlow(ServiceFlow* sf) const
-{
-    GetServiceFlowManager()->AddServiceFlow(sf);
-}
-
-bool
-SubscriberStationNetDevice::DoSend(Ptr<Packet> packet,
-                                   const Mac48Address& source,
-                                   const Mac48Address& dest,
-                                   uint16_t protocolNumber)
-{
-    NS_LOG_INFO("SS (" << source << "):");
-    NS_LOG_INFO("\tSending packet...");
-    NS_LOG_INFO("\t\tDestination: " << dest);
-    NS_LOG_INFO("\t\tPacket Size:  " << packet->GetSize());
-    NS_LOG_INFO("\t\tProtocol:    " << protocolNumber);
-
-    ServiceFlow* serviceFlow = nullptr;
-
-    if (IsRegistered())
-    {
-        NS_LOG_DEBUG("SS (Basic CID: " << m_basicConnection->GetCid() << ")");
-    }
-    else
-    {
-        NS_LOG_DEBUG("SS (" << GetMacAddress() << ")");
-        NS_LOG_INFO("\tCan't send packet! (NotRegistered with the network)");
-        return false;
-    }
-
-    NS_LOG_DEBUG("packet to send, size : " << packet->GetSize() << ", destination : " << dest);
-
-    if (GetServiceFlowManager()->GetNrServiceFlows() == 0)
-    {
-        NS_LOG_INFO("\tCan't send packet! (No service Flow)");
-        return false;
-    }
-
-    if (protocolNumber == 2048)
-    {
-        serviceFlow =
-            m_classifier->Classify(packet, GetServiceFlowManager(), ServiceFlow::SF_DIRECTION_UP);
-    }
-
-    if ((protocolNumber != 2048) || (serviceFlow == nullptr))
-    {
-        serviceFlow = *GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_ALL).begin();
-        NS_LOG_INFO("\tNo service flows matches...using the default one.");
-    }
-
-    NS_LOG_INFO("\tPacket classified in the service flow SFID =  "
-                << serviceFlow->GetSfid() << " CID = " << serviceFlow->GetCid());
-    if (serviceFlow->GetIsEnabled())
-    {
-        if (!Enqueue(packet, MacHeaderType(), serviceFlow->GetConnection()))
-        {
-            NS_LOG_INFO("\tEnqueue ERROR!!");
-            m_ssTxDropTrace(packet);
-            return false;
-        }
-        else
-        {
-            m_ssTxTrace(packet);
-        }
-    }
-    else
-    {
-        NS_LOG_INFO("Error!! The Service Flow is not enabled");
-        m_ssTxDropTrace(packet);
-        return false;
-    }
-
-    return true;
-}
-
-bool
-SubscriberStationNetDevice::Enqueue(Ptr<Packet> packet,
-                                    const MacHeaderType& hdrType,
-                                    Ptr<WimaxConnection> connection)
-{
-    NS_ASSERT_MSG(connection,
-                  "SS: Can not enqueue the packet: the selected connection is nor initialized");
-
-    GenericMacHeader hdr;
-
-    if (hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        hdr.SetLen(packet->GetSize() + hdr.GetSerializedSize());
-        hdr.SetCid(connection->GetCid());
-    }
-
-    if (connection->GetType() == Cid::TRANSPORT)
-    {
-        if (connection->GetSchedulingType() == ServiceFlow::SF_TYPE_UGS && m_scheduler->GetPollMe())
-        {
-            NS_ASSERT_MSG(hdrType.GetType() != MacHeaderType::HEADER_TYPE_BANDWIDTH,
-                          "Error while enqueuing  packet: incorrect header type");
-
-            GrantManagementSubheader grantMgmntSubhdr;
-            grantMgmntSubhdr.SetPm(1);
-            packet->AddHeader(grantMgmntSubhdr);
-        }
-    }
-    NS_LOG_INFO("ServiceFlowManager: enqueuing packet");
-    return connection->Enqueue(packet, hdrType, hdr);
-}
-
-void
-SubscriberStationNetDevice::SendBurst(uint8_t uiuc,
-                                      uint16_t nrSymbols,
-                                      Ptr<WimaxConnection> connection,
-                                      MacHeaderType::HeaderType packetType)
-{
-    WimaxPhy::ModulationType modulationType;
-
-    if (uiuc == OfdmUlBurstProfile::UIUC_INITIAL_RANGING ||
-        uiuc == OfdmUlBurstProfile::UIUC_REQ_REGION_FULL)
-    {
-        modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    }
-    else
-    {
-        modulationType = GetBurstProfileManager()->GetModulationType(uiuc, DIRECTION_UPLINK);
-    }
-    Ptr<PacketBurst> burst =
-        m_scheduler->Schedule(nrSymbols, modulationType, packetType, connection);
-
-    if (burst->GetNPackets() == 0)
-    {
-        return;
-    }
-
-    if (IsRegistered())
-    {
-        NS_LOG_DEBUG("SS (Basic CID: " << m_basicConnection->GetCid() << ")");
-    }
-    else
-    {
-        NS_LOG_DEBUG("SS (" << GetMacAddress() << ")");
-    }
-
-    if (connection->GetType() == Cid::TRANSPORT)
-    {
-        ServiceFlowRecord* record = connection->GetServiceFlow()->GetRecord();
-        record->UpdatePktsSent(burst->GetNPackets());
-        record->UpdateBytesSent(burst->GetSize());
-
-        NS_LOG_DEBUG(" sending burst, SFID: " << connection->GetServiceFlow()->GetSfid()
-                                              << ", pkts sent: " << record->GetPktsSent()
-                                              << ", pkts rcvd: " << record->GetPktsRcvd()
-                                              << ", bytes sent: " << record->GetBytesSent()
-                                              << ", bytes rcvd: " << record->GetBytesRcvd());
-    }
-
-    ForwardDown(burst, modulationType);
-}
-
-void
-SubscriberStationNetDevice::DoReceive(Ptr<Packet> packet)
-{
-    GenericMacHeader gnrcMacHdr;
-    ManagementMessageType msgType;
-    RngRsp rngrsp;
-    Cid cid;
-    uint32_t pktSize = packet->GetSize();
-    packet->RemoveHeader(gnrcMacHdr);
-    FragmentationSubheader fragSubhdr;
-    bool fragmentation = false; // it becomes true when there is a fragmentation subheader
-
-    if (gnrcMacHdr.GetHt() == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        if (!gnrcMacHdr.check_hcs())
-        {
-            // The header is noisy
-            NS_LOG_INFO("Header HCS ERROR");
-            m_ssRxDropTrace(packet);
-            return;
-        }
-
-        cid = gnrcMacHdr.GetCid();
-
-        // checking for subheaders
-        uint8_t type = gnrcMacHdr.GetType();
-        if (type)
-        {
-            // Check if there is a fragmentation Subheader
-            uint8_t tmpType = type;
-            if (((tmpType >> 2) & 1) == 1)
-            {
-                // a TRANSPORT packet with fragmentation subheader has been received!
-                fragmentation = true;
-                NS_LOG_INFO("SS DoReceive -> the packet is a fragment" << std::endl);
-            }
-        }
-
-        if (cid == GetBroadcastConnection()->GetCid() && !fragmentation)
-        {
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_DL_MAP: {
-                if (GetState() == SS_STATE_SYNCHRONIZING)
-                {
-                    Simulator::Cancel(m_linkManager->GetDlMapSyncTimeoutEvent());
-                }
-
-                if (m_lostDlMapEvent.IsPending())
-                {
-                    Simulator::Cancel(m_lostDlMapEvent);
-                }
-
-                m_linkManager->ScheduleScanningRestart(m_lostDlMapInterval,
-                                                       EVENT_LOST_DL_MAP,
-                                                       false,
-                                                       m_lostDlMapEvent);
-
-                if (m_dcdWaitTimeoutEvent.IsPending())
-                {
-                    Simulator::Cancel(m_dcdWaitTimeoutEvent);
-                }
-
-                m_linkManager->ScheduleScanningRestart(m_intervalT1,
-                                                       EVENT_DCD_WAIT_TIMEOUT,
-                                                       false,
-                                                       m_dcdWaitTimeoutEvent);
-
-                if (m_ucdWaitTimeoutEvent.IsPending())
-                {
-                    Simulator::Cancel(m_ucdWaitTimeoutEvent);
-                }
-
-                m_linkManager->ScheduleScanningRestart(m_intervalT12,
-                                                       EVENT_UCD_WAIT_TIMEOUT,
-                                                       true,
-                                                       m_ucdWaitTimeoutEvent);
-
-                DlMap dlmap;
-                packet->RemoveHeader(dlmap);
-                ProcessDlMap(dlmap);
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_UL_MAP: {
-                if (m_lostUlMapEvent.IsPending())
-                {
-                    Simulator::Cancel(m_lostUlMapEvent);
-                    m_linkManager->ScheduleScanningRestart(m_lostUlMapInterval,
-                                                           EVENT_LOST_UL_MAP,
-                                                           true,
-                                                           m_lostUlMapEvent);
-                }
-
-                UlMap ulmap;
-                packet->RemoveHeader(ulmap);
-
-                ProcessUlMap(ulmap);
-
-                if (GetState() == SS_STATE_WAITING_REG_RANG_INTRVL)
-                {
-                    if (m_linkManager->GetRangingIntervalFound())
-                    {
-                        if (m_rangOppWaitTimeoutEvent.IsPending())
-                        {
-                            Simulator::Cancel(m_rangOppWaitTimeoutEvent);
-                        }
-                        m_linkManager->PerformBackoff();
-                    }
-                }
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_DCD: {
-                if (GetState() == SS_STATE_SYNCHRONIZING)
-                {
-                    SetState(SS_STATE_ACQUIRING_PARAMETERS);
-                }
-
-                if (m_dcdWaitTimeoutEvent.IsPending())
-                {
-                    Simulator::Cancel(m_dcdWaitTimeoutEvent);
-                    m_linkManager->ScheduleScanningRestart(m_intervalT1,
-                                                           EVENT_DCD_WAIT_TIMEOUT,
-                                                           false,
-                                                           m_dcdWaitTimeoutEvent);
-                }
-
-                Dcd dcd;
-                // number of burst profiles is set to number of DL-MAP IEs after processing DL-MAP,
-                // not a very good solution dcd.SetNrDlBurstProfiles (m_nrDlMapElements);
-                dcd.SetNrDlBurstProfiles(7);
-                packet->RemoveHeader(dcd);
-
-                ProcessDcd(dcd);
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_UCD: {
-                Ucd ucd;
-                // number of burst profiles is set to number of UL-MAP IEs after processing UL-MAP,
-                // not a very good solution ucd.SetNrUlBurstProfiles (m_nrUlMapElements);
-                ucd.SetNrUlBurstProfiles(7);
-                packet->RemoveHeader(ucd);
-
-                ProcessUcd(ucd);
-
-                if (m_ucdWaitTimeoutEvent.IsPending())
-                {
-                    Simulator::Cancel(m_ucdWaitTimeoutEvent);
-                    m_linkManager->ScheduleScanningRestart(m_intervalT12,
-                                                           EVENT_UCD_WAIT_TIMEOUT,
-                                                           true,
-                                                           m_ucdWaitTimeoutEvent);
-                }
-
-                if (GetState() == SS_STATE_ACQUIRING_PARAMETERS)
-                {
-                    /*state indicating that SS has completed scanning, synchronization and parameter
-                     acquisition successfully and now waiting for UL-MAP to start initial ranging.*/
-                    SetState(SS_STATE_WAITING_REG_RANG_INTRVL);
-
-                    m_linkManager->ScheduleScanningRestart(m_intervalT2,
-                                                           EVENT_RANG_OPP_WAIT_TIMEOUT,
-                                                           false,
-                                                           m_rangOppWaitTimeoutEvent);
-                    m_linkManager->ScheduleScanningRestart(m_lostUlMapInterval,
-                                                           EVENT_LOST_UL_MAP,
-                                                           true,
-                                                           m_lostUlMapEvent);
-                }
-                break;
-            }
-            default:
-                NS_FATAL_ERROR("Invalid management message type");
-            }
-        }
-        else if (GetInitialRangingConnection() && cid == GetInitialRangingConnection()->GetCid() &&
-                 !fragmentation)
-        {
-            m_traceSSRx(packet, GetMacAddress(), cid);
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_RNG_REQ:
-                // intended for base station, ignore
-                break;
-            case ManagementMessageType::MESSAGE_TYPE_RNG_RSP:
-                NS_ASSERT_MSG(GetState() >= SS_STATE_WAITING_REG_RANG_INTRVL,
-                              "SS: Error while receiving a ranging response message: SS state "
-                              "should be at least SS_STATE_WAITING_REG_RANG_INTRVL");
-                packet->RemoveHeader(rngrsp);
-                m_linkManager->PerformRanging(cid, rngrsp);
-                break;
-            default:
-                NS_LOG_ERROR("Invalid management message type");
-            }
-        }
-        else if (m_basicConnection && cid == m_basicConnection->GetCid() && !fragmentation)
-        {
-            m_traceSSRx(packet, GetMacAddress(), cid);
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_RNG_REQ:
-                // intended for base station, ignore
-                break;
-            case ManagementMessageType::MESSAGE_TYPE_RNG_RSP:
-                NS_ASSERT_MSG(GetState() == SS_STATE_WAITING_RNG_RSP,
-                              "SS: Error while receiving a ranging response message: SS state "
-                              "should be SS_STATE_WAITING_RNG_RSP");
-                packet->RemoveHeader(rngrsp);
-                m_linkManager->PerformRanging(cid, rngrsp);
-                break;
-            default:
-                NS_LOG_ERROR("Invalid management message type");
-            }
-        }
-        else if (m_primaryConnection && cid == m_primaryConnection->GetCid() && !fragmentation)
-        {
-            m_traceSSRx(packet, GetMacAddress(), cid);
-            packet->RemoveHeader(msgType);
-            switch (msgType.GetType())
-            {
-            case ManagementMessageType::MESSAGE_TYPE_REG_REQ:
-                // not yet implemented
-            case ManagementMessageType::MESSAGE_TYPE_REG_RSP:
-                // intended for base station, ignore
-            case ManagementMessageType::MESSAGE_TYPE_DSA_REQ:
-                /*from other station as DSA initiation
-                 by BS is not supported, ignore*/
-                break;
-            case ManagementMessageType::MESSAGE_TYPE_DSA_RSP: {
-                Simulator::Cancel(GetServiceFlowManager()->GetDsaRspTimeoutEvent());
-                DsaRsp dsaRsp;
-                packet->RemoveHeader(dsaRsp);
-                GetServiceFlowManager()->ProcessDsaRsp(dsaRsp);
-                break;
-            }
-            case ManagementMessageType::MESSAGE_TYPE_DSA_ACK:
-                /*from other station as DSA initiation
-                 by BS is not supported, ignore*/
-                break;
-            default:
-                NS_LOG_ERROR("Invalid management message type");
-            }
-        }
-        else if (GetConnectionManager()->GetConnection(cid)) // transport connection
-        {
-            ServiceFlow* serviceFlow = GetConnectionManager()->GetConnection(cid)->GetServiceFlow();
-            ServiceFlowRecord* record = serviceFlow->GetRecord();
-
-            record->UpdatePktsRcvd(1);
-            record->UpdateBytesRcvd(pktSize);
-
-            // If fragmentation is true, the packet is a fragment.
-            if (!fragmentation)
-            {
-                m_ssRxTrace(packet);
-                ForwardUp(packet,
-                          m_baseStationId,
-                          GetMacAddress()); // source shall be BS's address or sender SS's?
-            }
-            else
-            {
-                NS_LOG_INFO("FRAG_DEBUG: SS DoReceive, the Packet is a fragment" << std::endl);
-                packet->RemoveHeader(fragSubhdr);
-                uint32_t fc = fragSubhdr.GetFc();
-                NS_LOG_INFO("\t fragment size = " << packet->GetSize() << std::endl);
-
-                if (fc == 2)
-                {
-                    // This is the latest fragment.
-                    // Take the fragment queue, defragment a packet and send it to the upper layer
-                    NS_LOG_INFO("\t Received the latest fragment" << std::endl);
-                    GetConnectionManager()->GetConnection(cid)->FragmentEnqueue(packet);
-
-                    WimaxConnection::FragmentsQueue fragmentsQueue =
-                        GetConnectionManager()->GetConnection(cid)->GetFragmentsQueue();
-
-                    Ptr<Packet> fullPacket = Create<Packet>();
-
-                    // DEFRAGMENTATION
-                    NS_LOG_INFO("\t SS PACKET DEFRAGMENTATION" << std::endl);
-                    for (auto iter = fragmentsQueue.begin(); iter != fragmentsQueue.end(); ++iter)
-                    {
-                        // Create the whole Packet
-                        fullPacket->AddAtEnd(*iter);
-                    }
-                    GetConnectionManager()->GetConnection(cid)->ClearFragmentsQueue();
-                    NS_LOG_INFO("\t fullPacket size = " << fullPacket->GetSize() << std::endl);
-
-                    m_ssRxTrace(fullPacket);
-                    ForwardUp(fullPacket,
-                              m_baseStationId,
-                              GetMacAddress()); // source shall be BS's address or sender SS's?
-                }
-                else
-                {
-                    // This is the first or middle fragment.
-                    // Take the fragment queue, store the fragment into the queue
-                    NS_LOG_INFO("\t Received the first or the middle fragment" << std::endl);
-                    GetConnectionManager()->GetConnection(cid)->FragmentEnqueue(packet);
-                }
-            }
-        }
-        else if (cid.IsMulticast())
-        {
-            m_traceSSRx(packet, GetMacAddress(), cid);
-            ForwardUp(packet,
-                      m_baseStationId,
-                      GetMacAddress()); // source shall be BS's address or sender SS's?
-        }
-        else if (IsPromisc())
-        {
-            NotifyPromiscTrace(packet);
-            m_ssPromiscRxTrace(packet);
-
-            // not for me, ignore
-        }
-        else
-        {
-            // not for me drop
-        }
-    }
-    else
-    {
-        // from other SS, ignore
-    }
-}
-
-void
-SubscriberStationNetDevice::ProcessDlMap(const DlMap& dlmap)
-{
-    m_nrDlMapRecvd++;
-    m_dcdCount = dlmap.GetDcdCount();
-    m_baseStationId = dlmap.GetBaseStationId();
-    std::list<OfdmDlMapIe> dlMapElements = dlmap.GetDlMapElements();
-
-    for (auto iter = dlMapElements.begin(); iter != dlMapElements.end(); ++iter)
-    {
-        if (iter->GetDiuc() == OfdmDlBurstProfile::DIUC_END_OF_MAP)
-        {
-            break;
-        }
-
-        if (iter->GetCid() == m_basicConnection->GetCid())
-        {
-            /*here the SS shall actually acquire the start time it shall start receiving the burst
-             at. start time is used for power saving which is not implemented here, furthermore
-             there is no need since the simulator architecture automatically callbacks the receive
-             function. shall acquire the DIUC (burst profile) as well to decode the burst, again not
-             required again because the callback mechanism automatically passes it as parameter.*/
-        }
-
-#if 0 /* a template for future implementation following */
-      uint8_t temp = iter->GetDiuc ();
-      temp = iter->GetPreamblePresent ();
-      temp = iter->GetStartTime ();
-#endif
-    }
-}
-
-void
-SubscriberStationNetDevice::ProcessUlMap(const UlMap& ulmap)
-{
-    m_nrUlMapRecvd++;
-    m_ucdCount = ulmap.GetUcdCount();
-    m_allocationStartTime = ulmap.GetAllocationStartTime();
-    const auto& ulMapElements = ulmap.GetUlMapElements();
-    m_linkManager->SetRangingIntervalFound(false);
-
-    for (const auto& ulMapIe : ulMapElements)
-    {
-        if (ulMapIe.GetUiuc() == OfdmUlBurstProfile::UIUC_END_OF_MAP)
-        {
-            break;
-        }
-
-        Cid cid = ulMapIe.GetCid();
-
-        if (ulMapIe.GetUiuc() == OfdmUlBurstProfile::UIUC_INITIAL_RANGING &&
-            cid == GetBroadcastConnection()->GetCid())
-        {
-            m_linkManager->SetRangingIntervalFound(true);
-        }
-
-        if (m_areManagementConnectionsAllocated && cid == m_basicConnection->GetCid())
-        {
-            Time timeToAllocation = GetTimeToAllocation(
-                Seconds(ulMapIe.GetStartTime() * GetPhy()->GetSymbolDuration().GetSeconds()));
-
-            if (ulMapIe.GetUiuc() ==
-                OfdmUlBurstProfile::UIUC_INITIAL_RANGING) // invited ranging interval
-
-            {
-                m_linkManager->IncrementNrInvitedPollsRecvd();
-                NS_ASSERT_MSG(GetState() == SS_STATE_WAITING_INV_RANG_INTRVL,
-                              "SS: Error while processing UL MAP: SS state should be "
-                              "SS_STATE_WAITING_INV_RANG_INTRVL");
-                Simulator::Schedule(timeToAllocation,
-                                    &SSLinkManager::SendRangingRequest,
-                                    m_linkManager,
-                                    ulMapIe.GetUiuc(),
-                                    ulMapIe.GetDuration());
-            }
-            else if (ulMapIe.GetUiuc() == OfdmUlBurstProfile::UIUC_REQ_REGION_FULL) // unicast poll
-
-            {
-                Simulator::Schedule(timeToAllocation,
-                                    &BandwidthManager::SendBandwidthRequest,
-                                    GetBandwidthManager(),
-                                    ulMapIe.GetUiuc(),
-                                    ulMapIe.GetDuration());
-            }
-            else // regular allocation/grant for data, for UGS flows or in response of requests for
-                 // non-UGS flows
-
-            {
-                Ptr<WimaxConnection> connection = nullptr;
-                Simulator::Schedule(timeToAllocation,
-                                    &SubscriberStationNetDevice::SendBurst,
-                                    this,
-                                    ulMapIe.GetUiuc(),
-                                    ulMapIe.GetDuration(),
-                                    connection,
-                                    MacHeaderType::HEADER_TYPE_GENERIC);
-            }
-        }
-        else
-        {
-            if (ulMapIe.GetUiuc() == OfdmUlBurstProfile::UIUC_INITIAL_RANGING &&
-                cid == GetBroadcastConnection()->GetCid()) // regular ranging interval
-
-            {
-                if (GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize() != 0)
-                {
-                    m_linkManager->SetNrRangingTransOpps(
-                        (ulMapIe.GetDuration() * GetPhy()->GetPsPerSymbol()) /
-                        GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize());
-                }
-
-                if (GetState() == SS_STATE_WAITING_REG_RANG_INTRVL ||
-                    GetState() == SS_STATE_ADJUSTING_PARAMETERS)
-                {
-                    m_linkManager->StartContentionResolution();
-                }
-            }
-        }
-    }
-}
-
-void
-SubscriberStationNetDevice::ProcessDcd(const Dcd& dcd)
-{
-    m_nrDcdRecvd++;
-    if (dcd.GetConfigurationChangeCount() == GetCurrentDcd().GetConfigurationChangeCount())
-    {
-        return; // nothing new in DCD so don't read
-    }
-    SetCurrentDcd(dcd);
-    OfdmDcdChannelEncodings dcdChnlEncodings = dcd.GetChannelEncodings();
-
-    // parameters for initial ranging
-    m_linkManager->SetBsEirp(dcdChnlEncodings.GetBsEirp());
-    m_linkManager->SetEirXPIrMax(dcdChnlEncodings.GetEirxPIrMax());
-
-    GetPhy()->GetFrameDuration(dcdChnlEncodings.GetFrameDurationCode());
-
-    const auto& dlBurstProfiles = dcd.GetDlBurstProfiles();
-
-    for (const auto& brstProfile : dlBurstProfiles)
-    {
-        /*NS-2 does this, may be not correct, assumes DIUC/UIUC to
-         modulation type mapping in DCD/UCD may change over time*/
-        if (brstProfile.GetFecCodeType() == m_modulationType)
-        {
-            m_dlBurstProfile->SetFecCodeType(brstProfile.GetFecCodeType());
-            m_dlBurstProfile->SetDiuc(brstProfile.GetDiuc());
-        }
-    }
-}
-
-void
-SubscriberStationNetDevice::ProcessUcd(const Ucd& ucd)
-{
-    m_nrUcdRecvd++;
-    if (!m_linkManager->IsUlChannelUsable())
-    {
-        m_linkManager->StartScanning(EVENT_NONE, false);
-        return;
-    }
-
-    if (ucd.GetConfigurationChangeCount() == GetCurrentUcd().GetConfigurationChangeCount())
-    {
-        return; // nothing new in UCD so don't read
-    }
-    SetCurrentUcd(ucd);
-    m_linkManager->SetRangingCW((uint8_t)std::pow(2.0, (double)ucd.GetRangingBackoffStart()) -
-                                1); // initializing ranging CW
-    OfdmUcdChannelEncodings ucdChnlEncodings = ucd.GetChannelEncodings();
-
-    const auto& ulBurstProfiles = ucd.GetUlBurstProfiles();
-    for (const auto& brstProfile : ulBurstProfiles)
-    {
-        /*NS-2 does this, may be not correct, assumes DIUC/UIUC to
-         modulation type mapping in DCD/UCD may change over time*/
-        if (brstProfile.GetFecCodeType() == m_modulationType)
-        {
-            m_ulBurstProfile->SetFecCodeType(brstProfile.GetFecCodeType());
-            m_ulBurstProfile->SetUiuc(brstProfile.GetUiuc());
-        }
-    }
-}
-
-/*temporarily assuming registered if ranging is complete,
- shall actually consider the registration step also */
-bool
-SubscriberStationNetDevice::IsRegistered() const
-{
-    return GetState() >= SS_STATE_REGISTERED;
-}
-
-Time
-SubscriberStationNetDevice::GetTimeToAllocation(Time deferTime)
-{
-    Time timeAlreadyElapsed = Simulator::Now() - m_frameStartTime;
-    Time timeToUlSubframe =
-        Seconds(m_allocationStartTime * GetPhy()->GetPsDuration().GetSeconds()) -
-        timeAlreadyElapsed;
-    return timeToUlSubframe + deferTime;
-}
-
-void
-SubscriberStationNetDevice::SetTimer(EventId eventId, EventId& event)
-{
-    if (GetState() == SS_STATE_STOPPED)
-    {
-        Simulator::Cancel(eventId); // cancelling this event (already scheduled in function call)
-        return;
-    }
-
-    event = eventId;
-}
-
-void
-SubscriberStationNetDevice::SetAsciiTxQueueEnqueueCallback(AsciiTraceCallback cb)
-{
-    m_asciiTxQueueEnqueueCb = cb;
-}
-
-void
-SubscriberStationNetDevice::SetAsciiTxQueueDequeueCallback(AsciiTraceCallback cb)
-{
-    m_asciiTxQueueDequeueCb = cb;
-}
-
-void
-SubscriberStationNetDevice::SetAsciiTxQueueDropCallback(AsciiTraceCallback cb)
-{
-    m_asciiTxQueueDropCb = cb;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-net-device.h ns-3.46/src/wimax/model/ss-net-device.h
--- ns-3.45/src/wimax/model/ss-net-device.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-net-device.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,527 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef WIMAX_SS_NET_DEVICE_H
-#define WIMAX_SS_NET_DEVICE_H
-
-#include "ipcs-classifier.h"
-#include "ss-service-flow-manager.h"
-#include "wimax-mac-header.h"
-#include "wimax-net-device.h"
-
-#include "ns3/event-id.h"
-#include "ns3/nstime.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-class Node;
-class OfdmDlBurstProfile;
-class OfdmUlBurstProfile;
-class SSScheduler;
-class SSLinkManager;
-class SsServiceFlowManager;
-class IpcsClassifier;
-
-/**
- * @ingroup wimax
- * SubscriberStationNetDevice subclass of WimaxNetDevice
- */
-class SubscriberStationNetDevice : public WimaxNetDevice
-{
-  public:
-    /// State enumeration
-    enum State
-    {
-        SS_STATE_IDLE,
-        SS_STATE_SCANNING,
-        SS_STATE_SYNCHRONIZING,
-        SS_STATE_ACQUIRING_PARAMETERS,
-        SS_STATE_WAITING_REG_RANG_INTRVL, // regular ranging interval
-        SS_STATE_WAITING_INV_RANG_INTRVL, // invited ranging interval
-        SS_STATE_WAITING_RNG_RSP,
-        SS_STATE_ADJUSTING_PARAMETERS,
-        SS_STATE_REGISTERED,
-        SS_STATE_TRANSMITTING, // currently not being used anywhere
-        SS_STATE_STOPPED
-    };
-
-    /// EventType enumeration
-    enum EventType
-    {
-        EVENT_NONE,
-        EVENT_WAIT_FOR_RNG_RSP,
-        EVENT_DL_MAP_SYNC_TIMEOUT,
-        EVENT_LOST_DL_MAP,
-        EVENT_LOST_UL_MAP,
-        EVENT_DCD_WAIT_TIMEOUT,
-        EVENT_UCD_WAIT_TIMEOUT,
-        EVENT_RANG_OPP_WAIT_TIMEOUT
-    };
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    SubscriberStationNetDevice();
-    /**
-     * Constructor
-     *
-     * @param node the node
-     * @param phy the wimax phy
-     */
-    SubscriberStationNetDevice(Ptr<Node> node, Ptr<WimaxPhy> phy);
-    ~SubscriberStationNetDevice() override;
-
-    /**
-     * @brief initializes the net device and sets the parameters to the default values
-     */
-    void InitSubscriberStationNetDevice();
-    /**
-     * @param lostDlMapInterval time since last received DL-MAP message before downlink
-     * synchronization is considered lost
-     */
-    void SetLostDlMapInterval(Time lostDlMapInterval);
-    /**
-     * @returns the time since last received DL-MAP message before downlink synchronization is
-     * considered lost
-     */
-    Time GetLostDlMapInterval() const;
-    /**
-     * @param lostUlMapInterval Time since last received UL-MAP before uplink synchronization is
-     * considered lost
-     */
-    void SetLostUlMapInterval(Time lostUlMapInterval);
-    /**
-     * @returns the time since last received UL-MAP before uplink synchronization is considered lost
-     */
-    Time GetLostUlMapInterval() const;
-    /**
-     * @param maxDcdInterval Maximum time between transmission of DCD messages
-     */
-    void SetMaxDcdInterval(Time maxDcdInterval);
-    /**
-     * @returns the maximum time between transmission of DCD messages
-     */
-    Time GetMaxDcdInterval() const;
-    /**
-     * @param maxUcdInterval Maximum time between transmission of UCD messages
-     */
-    void SetMaxUcdInterval(Time maxUcdInterval);
-    /**
-     * @returns the maximum time between transmission of UCD messages
-     */
-    Time GetMaxUcdInterval() const;
-    /**
-     * @param interval1 Wait for DCD timeout value
-     */
-    void SetIntervalT1(Time interval1);
-    /**
-     * @returns the wait for DCD timeout
-     */
-    Time GetIntervalT1() const;
-    /**
-     * @param interval2 the wait for broadcast ranging timeout, i.e., wait for initial ranging
-     * opportunity
-     */
-    void SetIntervalT2(Time interval2);
-    /**
-     * @returns the wait for broadcast ranging timeout, i.e., wait for initial ranging opportunity
-     */
-    Time GetIntervalT2() const;
-    /**
-     * @param interval3 the ranging Response reception timeout following the transmission of a
-     * ranging request
-     */
-    void SetIntervalT3(Time interval3);
-    /**
-     * @returns the ranging Response reception timeout following the transmission of a ranging
-     * request
-     */
-    Time GetIntervalT3() const;
-    /**
-     * @param interval7 the wait for DSA/DSC/DSD Response timeout
-     */
-    void SetIntervalT7(Time interval7);
-    /**
-     * @returns the wait for DSA/DSC/DSD Response timeout
-     */
-    Time GetIntervalT7() const;
-    /**
-     * @param interval12 the Wait for UCD descriptor timeout
-     */
-    void SetIntervalT12(Time interval12);
-    /**
-     * @returns the wait for UCD descriptor timeout
-     */
-    Time GetIntervalT12() const;
-    /**
-     * @param interval20 the Time the SS searches for preambles on a given channel
-     */
-    void SetIntervalT20(Time interval20);
-    /**
-     * @returns the Time the SS searches for preambles on a given channel
-     */
-    Time GetIntervalT20() const;
-    /**
-     * @param interval21 the time the SS searches for (decodable) DL-MAP on a given channel
-     */
-    void SetIntervalT21(Time interval21);
-    /**
-     * @returns the time the SS searches for (decodable) DL-MAP on a given channel
-     */
-    Time GetIntervalT21() const;
-    /**
-     * @param maxContentionRangingRetries the Number of retries on contention Ranging Requests
-     */
-    void SetMaxContentionRangingRetries(uint8_t maxContentionRangingRetries);
-    /**
-     * @returns the Number of retries on contention Ranging Requests
-     */
-    uint8_t GetMaxContentionRangingRetries() const;
-    /**
-     * @param basicConnection the basic connection to be used
-     */
-    void SetBasicConnection(Ptr<WimaxConnection> basicConnection);
-    /**
-     * @return the basic connection currently in use
-     */
-    Ptr<WimaxConnection> GetBasicConnection() const;
-    /**
-     * @param primaryConnection the primary connection to be used
-     */
-    void SetPrimaryConnection(Ptr<WimaxConnection> primaryConnection);
-    /**
-     * @returns the primary connection currently used
-     */
-    Ptr<WimaxConnection> GetPrimaryConnection() const;
-    /**
-     * @returns the basic CID
-     */
-    Cid GetBasicCid() const;
-    /**
-     * @returns the primary CID
-     */
-    Cid GetPrimaryCid() const;
-
-    /**
-     * @brief Set the most efficient modulation and coding scheme (MCS) supported by the device
-     * @param modulationType the most robust MCS supported
-     */
-    void SetModulationType(WimaxPhy::ModulationType modulationType);
-    /**
-     * @returns the most efficient modulation and coding scheme (MCS) supported by the device
-     */
-    WimaxPhy::ModulationType GetModulationType() const;
-    /**
-     * @param areManagementConnectionsAllocated true if the management connections are allocated,
-     * false otherwise
-     */
-    void SetAreManagementConnectionsAllocated(bool areManagementConnectionsAllocated);
-    /**
-     * @returns true if the management connections are allocated, false otherwise
-     */
-    bool GetAreManagementConnectionsAllocated() const;
-    /**
-     * @param areServiceFlowsAllocated true if the service flows are allocated, false otherwise
-     */
-    void SetAreServiceFlowsAllocated(bool areServiceFlowsAllocated);
-    /**
-     * @returns true if the service flows are allocated, false otherwise
-     */
-    bool GetAreServiceFlowsAllocated() const;
-    /**
-     * @return the scheduler installed on the device
-     */
-    Ptr<SSScheduler> GetScheduler() const;
-    /**
-     * @param ssScheduler the scheduler to be installed on the device
-     */
-    void SetScheduler(Ptr<SSScheduler> ssScheduler);
-    /**
-     * @returns true if the device has at least one active service flow, false otherwise
-     */
-    bool HasServiceFlows() const;
-    /**
-     * @brief Enqueue a packet into a connection queue
-     * @param packet the packet to be enqueued
-     * @param hdrType the mac header type to be appended to the packet
-     * @param connection the connection to be used
-     * @returns true if successful
-     */
-    bool Enqueue(Ptr<Packet> packet,
-                 const MacHeaderType& hdrType,
-                 Ptr<WimaxConnection> connection) override;
-    /**
-     * @brief Sends a burst on the uplink frame
-     * @param uiuc theOfdmUlBurstProfile
-     * @param nrSymbols number of symbols
-     * @param connection connection to use
-     * @param packetType optional HeaderType (default HEADER_TYPE_GENERIC)
-     */
-    void SendBurst(uint8_t uiuc,
-                   uint16_t nrSymbols,
-                   Ptr<WimaxConnection> connection,
-                   MacHeaderType::HeaderType packetType = MacHeaderType::HEADER_TYPE_GENERIC);
-
-    /**
-     * @brief Start the device
-     */
-    void Start() override;
-    /**
-     * @brief Stop the device
-     */
-    void Stop() override;
-
-    /**
-     * @brief adds a new service flow
-     * @param sf pointer to service flow to add
-     */
-    void AddServiceFlow(ServiceFlow* sf) const;
-    /**
-     * @brief adds a new service flow
-     * @param sf service flow to add
-     */
-    void AddServiceFlow(ServiceFlow sf) const;
-    /**
-     * @brief Set timer.  If in stopped state, the EventId passed in the first
-     * argument will be cancelled.  If not, the second parameter will be set
-     * to the value of the first parameter.
-     *
-     * @param eventId EventId to cancel or to map to the second argument
-     * @param event EventId is set to first argument if not in stopped state
-     */
-    void SetTimer(EventId eventId, EventId& event);
-    /**
-     * @returns true if the SS is registered to a BS, false otherwise
-     */
-    bool IsRegistered() const;
-    /**
-     * @brief Get time to allocation
-     * @param deferTime defer time
-     * @returns the time to allocation
-     */
-    Time GetTimeToAllocation(Time deferTime);
-
-    Ptr<SSLinkManager> m_linkManager; ///< link manager
-    /**
-     * @returns a pointer to the CS packet classifier
-     */
-    Ptr<IpcsClassifier> GetIpcsClassifier() const;
-    /**
-     * @brief Sets the packet classifier to be used
-     * @param classifier the classifier to use
-     */
-    void SetIpcsPacketClassifier(Ptr<IpcsClassifier> classifier);
-    /**
-     * @returns a pointer to the link manager currently used
-     */
-    Ptr<SSLinkManager> GetLinkManager() const;
-    /**
-     * @brief sets the link manager to be used
-     * @param linkManager link manager to use
-     */
-    void SetLinkManager(Ptr<SSLinkManager> linkManager);
-    /**
-     * @returns a pointer to the service flow manager installed on the device
-     */
-    Ptr<SsServiceFlowManager> GetServiceFlowManager() const;
-    /**
-     * @brief Sets the service flow manager to be installed on the device
-     * @param sfm service flow manager to be used
-     */
-    void SetServiceFlowManager(Ptr<SsServiceFlowManager> sfm);
-
-    /// Callback for logging packets on ASCII traces
-    typedef Callback<void, std::string, Ptr<const Packet>> AsciiTraceCallback;
-
-    /**
-     * Set the Enqueue callback for ASCII tracing
-     * @param cb callback for ASCII tracing
-     */
-    void SetAsciiTxQueueEnqueueCallback(AsciiTraceCallback cb);
-
-    /**
-     * Set the Dequeue callback for ASCII tracing
-     * @param cb callback for ASCII tracing
-     */
-    void SetAsciiTxQueueDequeueCallback(AsciiTraceCallback cb);
-
-    /**
-     * Set the Drop callback for ASCII tracing
-     * @param cb callback for ASCII tracing
-     */
-    void SetAsciiTxQueueDropCallback(AsciiTraceCallback cb);
-
-  private:
-    /**
-     * Get default lost DL map interval
-     * @returns the default lost DL map interval
-     */
-    static Time GetDefaultLostDlMapInterval();
-
-    void DoDispose() override;
-    /**
-     * Send a packet
-     * @param packet the packet to send
-     * @param source the source MAC address
-     * @param dest the destination MAC address
-     * @param protocolNumber the protocol number
-     * @returns true if successful
-     */
-    bool DoSend(Ptr<Packet> packet,
-                const Mac48Address& source,
-                const Mac48Address& dest,
-                uint16_t protocolNumber) override;
-    /**
-     * Receive a packet
-     * @param packet the packet received
-     */
-    void DoReceive(Ptr<Packet> packet) override;
-
-    /**
-     * Process DL map
-     * @param dlmap the DL map
-     */
-    void ProcessDlMap(const DlMap& dlmap);
-    /**
-     * Process UL map
-     * @param ulmap the UL map
-     */
-    void ProcessUlMap(const UlMap& ulmap);
-    /**
-     * Process DCD
-     * @param dcd the DCD
-     */
-    void ProcessDcd(const Dcd& dcd);
-    /**
-     * Process UCD
-     * @param ucd the UCD
-     */
-    void ProcessUcd(const Ucd& ucd);
-
-    // parameters defined in Table 342
-    Time m_lostDlMapInterval; ///< in milliseconds, time since last received DL-MAP before downlink
-                              ///< synchronization is considered lost, maximum is 600
-    Time m_lostUlMapInterval; ///< in milliseconds, time since last received UL-MAP before uplink
-                              ///< synchronization is considered lost, maximum is 600
-    Time m_maxDcdInterval;    ///< in seconds, maximum time between transmission of DCD messages
-    Time m_maxUcdInterval;    ///< in seconds, maximum time between transmission of UCD messages
-    Time m_intervalT1;        ///< in seconds, wait for DCD timeout
-    Time m_intervalT2;  ///< in seconds, wait for broadcast ranging timeout, i.e., wait for initial
-                        ///< ranging opportunity
-    Time m_intervalT3;  ///< in milliseconds, ranging Response reception timeout following the
-                        ///< transmission of a ranging request
-    Time m_intervalT7;  ///< in seconds, wait for DSA/DSC/DSD Response timeout
-    Time m_intervalT12; ///< in seconds, wait for UCD descriptor
-    Time m_intervalT20; ///< in seconds, time the SS searches for preambles on a given channel
-    Time m_intervalT21; ///< in seconds, time the SS searches for (decodable) DL-MAP on a given
-                        ///< channel
-    uint8_t m_maxContentionRangingRetries; ///< maximum contention ranging retries
-
-    // parameters obtained from DL-MAP
-    uint8_t m_dcdCount;           ///< DCD count
-    Mac48Address m_baseStationId; ///< base station ID
-
-    // parameters obtained from UL-MAP
-    uint8_t m_ucdCount;           ///< UCD count
-    double m_allocationStartTime; ///< allocation start time
-
-    // to keep the number of DL-MAP/UL-MAP IEs found in the last DL-MAP/U-MAP messages
-    uint16_t m_nrDlMapElements; ///< number DL Map elements
-    uint16_t m_nrUlMapElements; ///< number UL Map elements
-
-    Ptr<WimaxConnection> m_basicConnection;   ///< basic connection
-    Ptr<WimaxConnection> m_primaryConnection; ///< primary connection
-
-    EventId m_lostDlMapEvent;          ///< lost DL map event
-    EventId m_lostUlMapEvent;          ///< lost UL map event
-    EventId m_dcdWaitTimeoutEvent;     ///< DCD wait timeout event
-    EventId m_ucdWaitTimeoutEvent;     ///< UCD wait timeout event
-    EventId m_rangOppWaitTimeoutEvent; ///< range opp wait timeout event
-
-    uint32_t m_nrDlMapRecvd; ///< number DL map received
-    uint32_t m_nrUlMapRecvd; ///< number UL map received
-    uint32_t m_nrDcdRecvd;   ///< number DCD received
-    uint32_t m_nrUcdRecvd;   ///< number UCD received
-
-    OfdmDlBurstProfile* m_dlBurstProfile; ///< DL burst profile
-    OfdmUlBurstProfile* m_ulBurstProfile; ///< UL burst profile
-
-    /*represents the (least robust) modulation type of the SS which it then requests in RNG-REQ and
-     if accepted by BS uses it for receiving and transmitting. currently it is set by user in
-     simulation script, shall actually be determined based on SS's distance, power, signal etc*/
-    WimaxPhy::ModulationType m_modulationType; ///< modulation type
-
-    bool m_areManagementConnectionsAllocated; ///< are management connections allocated
-    bool m_areServiceFlowsAllocated;          ///< are service flows allocated
-
-    Ptr<SSScheduler> m_scheduler;                   ///< the scheduler
-    Ptr<SsServiceFlowManager> m_serviceFlowManager; ///< the service flow manager
-    Ptr<IpcsClassifier> m_classifier;               ///< the classifier
-
-    TracedCallback<Ptr<const Packet>, Mac48Address, const Cid&>
-        m_traceSSRx; ///< trace SS receive callback
-
-    /**
-     * The trace source fired when packets come into the "top" of the device
-     * at the L3/L2 transition, before being queued for transmission.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_ssTxTrace;
-
-    /**
-     * The trace source fired when packets coming into the "top" of the device
-     * are dropped at the MAC layer during transmission.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_ssTxDropTrace;
-
-    /**
-     * The trace source fired for packets successfully received by the device
-     * immediately before being forwarded up to higher layers (at the L2/L3
-     * transition).  This is a promiscuous trace.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_ssPromiscRxTrace;
-
-    /**
-     * The trace source fired for packets successfully received by the device
-     * immediately before being forwarded up to higher layers (at the L2/L3
-     * transition).  This is a non- promiscuous trace.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_ssRxTrace;
-
-    /**
-     * The trace source fired when packets coming into the "top" of the device
-     * are dropped at the MAC layer during reception.
-     *
-     * @see class CallBackTraceSource
-     */
-    TracedCallback<Ptr<const Packet>> m_ssRxDropTrace;
-
-    /// Bound callback to perform ASCII logging for Enqueue events
-    AsciiTraceCallback m_asciiTxQueueEnqueueCb;
-    /// Bound callback to perform ASCII logging for Dequeue events
-    AsciiTraceCallback m_asciiTxQueueDequeueCb;
-    /// Bound callback to perform ASCII logging for Drop events
-    AsciiTraceCallback m_asciiTxQueueDropCb;
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_SS_NET_DEVICE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-record.cc ns-3.46/src/wimax/model/ss-record.cc
--- ns-3.45/src/wimax/model/ss-record.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-record.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,342 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#include "ss-record.h"
-
-#include "service-flow.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-SSRecord::SSRecord()
-{
-    Initialize();
-}
-
-SSRecord::SSRecord(Mac48Address macAddress)
-{
-    m_macAddress = macAddress;
-    Initialize();
-}
-
-SSRecord::SSRecord(Mac48Address macAddress, Ipv4Address IPaddress)
-{
-    m_macAddress = macAddress;
-    m_IPAddress = IPaddress;
-    Initialize();
-}
-
-void
-SSRecord::Initialize()
-{
-    m_basicCid = Cid();
-    m_primaryCid = Cid();
-
-    m_rangingCorrectionRetries = 0;
-    m_invitedRangingRetries = 0;
-    m_modulationType = WimaxPhy::MODULATION_TYPE_BPSK_12;
-    m_rangingStatus = WimaxNetDevice::RANGING_STATUS_EXPIRED;
-    m_pollForRanging = false;
-    m_areServiceFlowsAllocated = false;
-    m_pollMeBit = false;
-
-    m_sfTransactionId = 0;
-    m_dsaRspRetries = 0;
-
-    m_serviceFlows = new std::vector<ServiceFlow*>();
-    m_dsaRsp = DsaRsp();
-    m_broadcast = false;
-}
-
-SSRecord::~SSRecord()
-{
-    delete m_serviceFlows;
-    m_serviceFlows = nullptr;
-}
-
-void
-SSRecord::SetIPAddress(Ipv4Address IPAddress)
-{
-    m_IPAddress = IPAddress;
-}
-
-Ipv4Address
-SSRecord::GetIPAddress()
-{
-    return m_IPAddress;
-}
-
-void
-SSRecord::SetBasicCid(Cid basicCid)
-{
-    m_basicCid = basicCid;
-}
-
-Cid
-SSRecord::GetBasicCid() const
-{
-    return m_basicCid;
-}
-
-void
-SSRecord::SetPrimaryCid(Cid primaryCid)
-{
-    m_primaryCid = primaryCid;
-}
-
-Cid
-SSRecord::GetPrimaryCid() const
-{
-    return m_primaryCid;
-}
-
-void
-SSRecord::SetMacAddress(Mac48Address macAddress)
-{
-    m_macAddress = macAddress;
-}
-
-Mac48Address
-SSRecord::GetMacAddress() const
-{
-    return m_macAddress;
-}
-
-uint8_t
-SSRecord::GetRangingCorrectionRetries() const
-{
-    return m_rangingCorrectionRetries;
-}
-
-void
-SSRecord::ResetRangingCorrectionRetries()
-{
-    m_rangingCorrectionRetries = 0;
-}
-
-void
-SSRecord::IncrementRangingCorrectionRetries()
-{
-    m_rangingCorrectionRetries++;
-}
-
-uint8_t
-SSRecord::GetInvitedRangRetries() const
-{
-    return m_invitedRangingRetries;
-}
-
-void
-SSRecord::ResetInvitedRangingRetries()
-{
-    m_invitedRangingRetries = 0;
-}
-
-void
-SSRecord::IncrementInvitedRangingRetries()
-{
-    m_invitedRangingRetries++;
-}
-
-void
-SSRecord::SetModulationType(WimaxPhy::ModulationType modulationType)
-{
-    m_modulationType = modulationType;
-}
-
-WimaxPhy::ModulationType
-SSRecord::GetModulationType() const
-{
-    return m_modulationType;
-}
-
-void
-SSRecord::SetRangingStatus(WimaxNetDevice::RangingStatus rangingStatus)
-{
-    m_rangingStatus = rangingStatus;
-}
-
-WimaxNetDevice::RangingStatus
-SSRecord::GetRangingStatus() const
-{
-    return m_rangingStatus;
-}
-
-void
-SSRecord::EnablePollForRanging()
-{
-    m_pollForRanging = true;
-}
-
-void
-SSRecord::DisablePollForRanging()
-{
-    m_pollForRanging = false;
-}
-
-bool
-SSRecord::GetPollForRanging() const
-{
-    return m_pollForRanging;
-}
-
-void
-SSRecord::SetAreServiceFlowsAllocated(bool val)
-{
-    m_areServiceFlowsAllocated = val;
-}
-
-bool
-SSRecord::GetAreServiceFlowsAllocated() const
-{
-    return m_areServiceFlowsAllocated;
-}
-
-void
-SSRecord::SetPollMeBit(bool pollMeBit)
-{
-    m_pollMeBit = pollMeBit;
-}
-
-bool
-SSRecord::GetPollMeBit() const
-{
-    return m_pollMeBit;
-}
-
-void
-SSRecord::AddServiceFlow(ServiceFlow* serviceFlow)
-{
-    m_serviceFlows->push_back(serviceFlow);
-}
-
-std::vector<ServiceFlow*>
-SSRecord::GetServiceFlows(ServiceFlow::SchedulingType schedulingType) const
-{
-    std::vector<ServiceFlow*> tmpServiceFlows;
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if (((*iter)->GetSchedulingType() == schedulingType) ||
-            (schedulingType == ServiceFlow::SF_TYPE_ALL))
-        {
-            tmpServiceFlows.push_back(*iter);
-        }
-    }
-    return tmpServiceFlows;
-}
-
-void
-SSRecord::SetIsBroadcastSS(bool broadcast_enable)
-{
-    m_broadcast = broadcast_enable;
-}
-
-bool
-SSRecord::GetIsBroadcastSS() const
-{
-    return m_broadcast;
-}
-
-bool
-SSRecord::GetHasServiceFlowUgs() const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetSchedulingType() == ServiceFlow::SF_TYPE_UGS)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool
-SSRecord::GetHasServiceFlowRtps() const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetSchedulingType() == ServiceFlow::SF_TYPE_RTPS)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool
-SSRecord::GetHasServiceFlowNrtps() const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetSchedulingType() == ServiceFlow::SF_TYPE_NRTPS)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool
-SSRecord::GetHasServiceFlowBe() const
-{
-    for (auto iter = m_serviceFlows->begin(); iter != m_serviceFlows->end(); ++iter)
-    {
-        if ((*iter)->GetSchedulingType() == ServiceFlow::SF_TYPE_BE)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-void
-SSRecord::SetSfTransactionId(uint16_t sfTransactionId)
-{
-    m_sfTransactionId = sfTransactionId;
-}
-
-uint16_t
-SSRecord::GetSfTransactionId() const
-{
-    return m_sfTransactionId;
-}
-
-void
-SSRecord::SetDsaRspRetries(uint8_t dsaRspRetries)
-{
-    m_dsaRspRetries = dsaRspRetries;
-}
-
-void
-SSRecord::IncrementDsaRspRetries()
-{
-    m_dsaRspRetries++;
-}
-
-uint8_t
-SSRecord::GetDsaRspRetries() const
-{
-    return m_dsaRspRetries;
-}
-
-void
-SSRecord::SetDsaRsp(DsaRsp dsaRsp)
-{
-    m_dsaRsp = dsaRsp;
-}
-
-DsaRsp
-SSRecord::GetDsaRsp() const
-{
-    return m_dsaRsp;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-record.h ns-3.46/src/wimax/model/ss-record.h
--- ns-3.45/src/wimax/model/ss-record.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-record.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,277 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef SS_RECORD_H
-#define SS_RECORD_H
-
-#include "service-flow.h"
-#include "wimax-connection.h"
-#include "wimax-net-device.h"
-#include "wimax-phy.h"
-
-#include "ns3/ipv4-address.h"
-#include "ns3/mac48-address.h"
-
-#include <ostream>
-#include <stdint.h>
-
-namespace ns3
-{
-
-class ServiceFlow;
-
-/**
- * @ingroup wimax
- * @brief This class is used by the base station to store some information related to subscriber
- * station in the cell.
- */
-class SSRecord
-{
-  public:
-    SSRecord();
-    /**
-     * Constructor
-     *
-     * @param macAddress MAC address
-     */
-    SSRecord(Mac48Address macAddress);
-    /**
-     * Constructor
-     *
-     * @param macAddress MAC address
-     * @param IPaddress IP address
-     */
-    SSRecord(Mac48Address macAddress, Ipv4Address IPaddress);
-    ~SSRecord();
-
-    /**
-     * Set basic CID
-     * @param basicCid the basic CID
-     */
-    void SetBasicCid(Cid basicCid);
-    /**
-     * Get basic CID
-     * @returns the basic CID
-     */
-    Cid GetBasicCid() const;
-
-    /**
-     * Set primary CID
-     * @param primaryCid priamry CID
-     */
-    void SetPrimaryCid(Cid primaryCid);
-    /**
-     * Get primary CID
-     * @returns the CID
-     */
-    Cid GetPrimaryCid() const;
-
-    /**
-     * Set MAC address
-     * @param macAddress the MAC address
-     */
-    void SetMacAddress(Mac48Address macAddress);
-    /**
-     * Get MAC address
-     * @returns the MAC address
-     */
-    Mac48Address GetMacAddress() const;
-
-    /**
-     * Get ranging correction retries
-     * @returns the ranging correction retries
-     */
-    uint8_t GetRangingCorrectionRetries() const;
-    /// Reset ranging correction retries
-    void ResetRangingCorrectionRetries();
-    /// Increment ranging correction retries
-    void IncrementRangingCorrectionRetries();
-    /**
-     * Get invited range retries
-     * @returns the invited range retries
-     */
-    uint8_t GetInvitedRangRetries() const;
-    /// Reset invited ranging retries
-    void ResetInvitedRangingRetries();
-    /// Increment invited ranging retries
-    void IncrementInvitedRangingRetries();
-    /**
-     * Set modulation type
-     * @param modulationType the modulation type
-     */
-    void SetModulationType(WimaxPhy::ModulationType modulationType);
-    /**
-     * Get modulation type
-     * @returns the modulation type
-     */
-    WimaxPhy::ModulationType GetModulationType() const;
-
-    /**
-     * Set ranging status
-     * @param rangingStatus the ranging status
-     */
-    void SetRangingStatus(WimaxNetDevice::RangingStatus rangingStatus);
-    /**
-     * Get ranging status
-     * @returns the ranging status
-     */
-    WimaxNetDevice::RangingStatus GetRangingStatus() const;
-
-    /// Enable poll for ranging function
-    void EnablePollForRanging();
-    /// Disable poll for ranging
-    void DisablePollForRanging();
-    /**
-     * Get poll for ranging
-     * @returns the poll for ranging flag
-     */
-    bool GetPollForRanging() const;
-
-    /**
-     * Check if service flows are allocated
-     * @returns true if service flows are allocated
-     */
-    bool GetAreServiceFlowsAllocated() const;
-
-    /**
-     * Set poll ME bit
-     * @param pollMeBit the poll me bit
-     */
-    void SetPollMeBit(bool pollMeBit);
-    /**
-     * Get poll ME bit
-     * @returns the poll me bit
-     */
-    bool GetPollMeBit() const;
-
-    /**
-     * Add service flow
-     * @param serviceFlow the service flow
-     */
-    void AddServiceFlow(ServiceFlow* serviceFlow);
-    /**
-     * Get service flows
-     * @param schedulingType the scheduling type
-     * @returns the service flow
-     */
-    std::vector<ServiceFlow*> GetServiceFlows(ServiceFlow::SchedulingType schedulingType) const;
-    /**
-     * Check if at least one flow has scheduling type SF_TYPE_UGS
-     * @return true if at least one flow has scheduling type SF_TYPE_UGS
-     */
-    bool GetHasServiceFlowUgs() const;
-    /**
-     * Check if at least one flow has scheduling type SF_TYPE_RTPS
-     * @return true if at least one flow has scheduling type SF_TYPE_RTPS
-     */
-    bool GetHasServiceFlowRtps() const;
-    /**
-     * Check if at least one flow has scheduling type SF_TYPE_NRTPS
-     * @return true if at least one flow has scheduling type SF_TYPE_NRTPS
-     */
-    bool GetHasServiceFlowNrtps() const;
-    /**
-     * Check if at least one flow has scheduling type SF_TYPE_BE
-     * @return true if at least one flow has scheduling type SF_TYPE_BE
-     */
-    bool GetHasServiceFlowBe() const;
-
-    /**
-     * Set SF transaction ID
-     * @param sfTransactionId the SF transaction ID
-     */
-    void SetSfTransactionId(uint16_t sfTransactionId);
-    /**
-     * Get SF transaction ID
-     * @returns the SF transaction ID
-     */
-    uint16_t GetSfTransactionId() const;
-
-    /**
-     * Set DSA response retries
-     * @param dsaRspRetries the DSA response retries
-     */
-    void SetDsaRspRetries(uint8_t dsaRspRetries);
-    /// Increment DAS response retries
-    void IncrementDsaRspRetries();
-    /**
-     * Get DSA response retries
-     * @returns the DSA response retries
-     */
-    uint8_t GetDsaRspRetries() const;
-
-    /**
-     * Set DSA response
-     * @param dsaRsp the DSA response
-     */
-    void SetDsaRsp(DsaRsp dsaRsp);
-    /**
-     * Get DSA response
-     * @returns the DSA response
-     */
-    DsaRsp GetDsaRsp() const;
-    /**
-     * Set is broadcast SS
-     * @param broadcast_enable the broadcast enable flag
-     */
-    void SetIsBroadcastSS(bool broadcast_enable);
-    /**
-     * Get is broadcast SS
-     * @returns the is broadcast SS flag
-     */
-    bool GetIsBroadcastSS() const;
-
-    /**
-     * Get IP address
-     * @returns the IP address
-     */
-    Ipv4Address GetIPAddress();
-    /**
-     * Set IP address
-     * @param IPaddress the IP address
-     */
-    void SetIPAddress(Ipv4Address IPaddress);
-    /**
-     * Set are service flows allocated
-     * @param val the service flows allocated flag
-     */
-    void SetAreServiceFlowsAllocated(bool val);
-
-  private:
-    /// Initialize
-    void Initialize();
-
-    Mac48Address m_macAddress; ///< MAC address
-    Ipv4Address m_IPAddress;   ///< IP address
-
-    Cid m_basicCid;   ///< basic CID
-    Cid m_primaryCid; ///< primary CID
-
-    uint8_t m_rangingCorrectionRetries; ///< ranging correction retries
-    uint8_t m_invitedRangingRetries;    ///< invited ranging retries
-
-    WimaxPhy::ModulationType
-        m_modulationType; ///< least robust burst profile (modulation type) for this SS
-    WimaxNetDevice::RangingStatus m_rangingStatus; ///< ranging status
-    bool m_pollForRanging;                         ///< poll for ranging
-    bool m_areServiceFlowsAllocated;               ///< are service floes allowed
-    bool m_pollMeBit;                              ///< if PM (poll me) bit set for this SS
-    bool m_broadcast;                              ///< broadcast?
-
-    std::vector<ServiceFlow*>* m_serviceFlows; ///< service flows
-
-    // fields for service flow creation
-    uint16_t m_sfTransactionId; ///< SF transaction ID
-    uint8_t m_dsaRspRetries;    ///< DAS response retries
-    DsaRsp m_dsaRsp;            ///< DSA response
-};
-
-} // namespace ns3
-
-#endif /* SS_RECORD_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-scheduler.cc ns-3.46/src/wimax/model/ss-scheduler.cc
--- ns-3.45/src/wimax/model/ss-scheduler.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-scheduler.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "ss-scheduler.h"
-
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-net-device.h"
-#include "wimax-connection.h"
-#include "wimax-mac-queue.h"
-#include "wimax-phy.h"
-
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/simulator.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SSScheduler");
-
-NS_OBJECT_ENSURE_REGISTERED(SSScheduler);
-
-TypeId
-SSScheduler::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::SSScheduler").SetParent<Object>().SetGroupName("Wimax");
-    return tid;
-}
-
-SSScheduler::SSScheduler(Ptr<SubscriberStationNetDevice> ss)
-    : m_ss(ss),
-      m_pollMe(false)
-{
-}
-
-SSScheduler::~SSScheduler()
-{
-}
-
-void
-SSScheduler::DoDispose()
-{
-    m_ss = nullptr;
-}
-
-void
-SSScheduler::SetPollMe(bool pollMe)
-{
-    m_pollMe = pollMe;
-}
-
-bool
-SSScheduler::GetPollMe() const
-{
-    return m_pollMe;
-}
-
-Ptr<PacketBurst>
-SSScheduler::Schedule(uint16_t availableSymbols,
-                      WimaxPhy::ModulationType modulationType,
-                      MacHeaderType::HeaderType packetType,
-                      Ptr<WimaxConnection>& connection)
-{
-    Time timeStamp;
-    Ptr<PacketBurst> burst = Create<PacketBurst>();
-    uint16_t nrSymbolsRequired = 0;
-
-    if (!connection)
-    {
-        connection = SelectConnection();
-    }
-    else
-    {
-        NS_ASSERT_MSG(connection->HasPackets(),
-                      "SS: Error while scheduling packets: The selected connection has no packets");
-    }
-
-    Ptr<Packet> packet;
-
-    while (connection && connection->HasPackets(packetType))
-    {
-        NS_LOG_INFO("FRAG_DEBUG: SS Scheduler" << std::endl);
-
-        uint32_t availableByte = m_ss->GetPhy()->GetNrBytes(availableSymbols, modulationType);
-
-        uint32_t requiredByte = connection->GetQueue()->GetFirstPacketRequiredByte(packetType);
-
-        NS_LOG_INFO("\t availableByte = " << availableByte << ", requiredByte = " << requiredByte);
-
-        if (availableByte >= requiredByte)
-        {
-            // The SS could sent a packet without a other fragmentation
-            NS_LOG_INFO("\t availableByte >= requiredByte"
-                        "\n\t Send packet without other fragmentation"
-                        << std::endl);
-
-            packet = connection->Dequeue(packetType);
-            burst->AddPacket(packet);
-
-            nrSymbolsRequired = m_ss->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-            availableSymbols -= nrSymbolsRequired;
-        }
-        else
-        {
-            if (connection->GetType() == Cid::TRANSPORT)
-            {
-                NS_LOG_INFO("\t availableByte < requiredByte"
-                            "\n\t Check if the fragmentation is possible");
-
-                uint32_t headerSize = connection->GetQueue()->GetFirstPacketHdrSize(packetType);
-                if (!connection->GetQueue()->CheckForFragmentation(packetType))
-                {
-                    NS_LOG_INFO("\t Add fragmentSubhdrSize = 2");
-                    headerSize += 2;
-                }
-                NS_LOG_INFO("\t availableByte = " << availableByte
-                                                  << " headerSize = " << headerSize);
-
-                if (availableByte > headerSize)
-                {
-                    NS_LOG_INFO("\t Fragmentation IS possible");
-                    packet = connection->Dequeue(packetType, availableByte);
-                    burst->AddPacket(packet);
-
-                    nrSymbolsRequired =
-                        m_ss->GetPhy()->GetNrSymbols(packet->GetSize(), modulationType);
-                    availableSymbols -= nrSymbolsRequired;
-                }
-                else
-                {
-                    NS_LOG_INFO("\t Fragmentation IS NOT possible" << std::endl);
-                    break;
-                }
-            }
-            else
-            {
-                NS_LOG_INFO("\t no Transport Connection "
-                            "\n\t Fragmentation IS NOT possible, "
-                            << std::endl);
-                break;
-            }
-        }
-    }
-    return burst;
-}
-
-Ptr<WimaxConnection>
-SSScheduler::SelectConnection()
-{
-    Time currentTime = Simulator::Now();
-
-    NS_LOG_INFO("SS Scheduler: Selecting connection...");
-    if (m_ss->GetInitialRangingConnection()->HasPackets())
-    {
-        NS_LOG_INFO("Return GetInitialRangingConnection");
-        return m_ss->GetInitialRangingConnection();
-    }
-    if (m_ss->GetBasicConnection()->HasPackets())
-    {
-        NS_LOG_INFO("Return GetBasicConnection");
-        return m_ss->GetBasicConnection();
-    }
-    if (m_ss->GetPrimaryConnection()->HasPackets())
-    {
-        NS_LOG_INFO("Return GetPrimaryConnection");
-        return m_ss->GetPrimaryConnection();
-    }
-
-    auto serviceFlows = m_ss->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_UGS);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        // making sure that this grant was actually intended for this UGS
-
-        if ((*iter)->HasPackets() && (currentTime + m_ss->GetPhy()->GetFrameDuration() >
-                                      MilliSeconds((*iter)->GetUnsolicitedGrantInterval())))
-        {
-            NS_LOG_INFO("Return UGS SF: CID = " << (*iter)->GetCid()
-                                                << "SFID = " << (*iter)->GetSfid());
-            return (*iter)->GetConnection();
-        }
-    }
-
-    /* In the following cases (rtPS, nrtPS and BE flows) connection is seletected only for data
-     packets, for bandwidth request packets connection will itself be passed to Schedule () and
-     hence this function will never be called. */
-
-    serviceFlows = m_ss->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_RTPS);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        if ((*iter)->HasPackets(MacHeaderType::HEADER_TYPE_GENERIC) &&
-            (currentTime + m_ss->GetPhy()->GetFrameDuration() >
-             MilliSeconds((*iter)->GetUnsolicitedPollingInterval())))
-        {
-            NS_LOG_INFO("Return RTPS SF: CID = " << (*iter)->GetCid()
-                                                 << "SFID = " << (*iter)->GetSfid());
-            return (*iter)->GetConnection();
-        }
-    }
-
-    serviceFlows = m_ss->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_NRTPS);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        if ((*iter)->HasPackets(MacHeaderType::HEADER_TYPE_GENERIC))
-        {
-            NS_LOG_INFO("Return NRTPS SF: CID = " << (*iter)->GetCid()
-                                                  << "SFID = " << (*iter)->GetSfid());
-            return (*iter)->GetConnection();
-        }
-    }
-
-    serviceFlows = m_ss->GetServiceFlowManager()->GetServiceFlows(ServiceFlow::SF_TYPE_BE);
-    for (auto iter = serviceFlows.begin(); iter != serviceFlows.end(); ++iter)
-    {
-        if ((*iter)->HasPackets(MacHeaderType::HEADER_TYPE_GENERIC))
-        {
-            NS_LOG_INFO("Return BE SF: CID = " << (*iter)->GetCid()
-                                               << "SFID = " << (*iter)->GetSfid());
-            return (*iter)->GetConnection();
-        }
-    }
-
-    if (m_ss->GetBroadcastConnection()->HasPackets())
-    {
-        return m_ss->GetBroadcastConnection();
-    }
-    NS_LOG_INFO("NO connection is selected!");
-    return nullptr;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-scheduler.h ns-3.46/src/wimax/model/ss-scheduler.h
--- ns-3.45/src/wimax/model/ss-scheduler.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-scheduler.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-/* SS outbound scheduler as per in Section 6.3.5.1 */
-
-#ifndef SS_SCHEDULER_H
-#define SS_SCHEDULER_H
-
-#include "wimax-mac-header.h"
-#include "wimax-phy.h"
-
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class SubscriberStationNetDevice;
-class WimaxConnection;
-
-/**
- * @ingroup wimax
- * @param SSScheduler class
- */
-class SSScheduler : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    /**
-     * Constructor
-     *
-     * @param ss subscriber station device
-     */
-    SSScheduler(Ptr<SubscriberStationNetDevice> ss);
-    ~SSScheduler() override;
-
-    // Delete copy constructor and assignment operator to avoid misuse
-    SSScheduler(const SSScheduler&) = delete;
-    SSScheduler& operator=(const SSScheduler&) = delete;
-
-    /**
-     * Set poll me value
-     * @param pollMe the poll me flag
-     */
-    void SetPollMe(bool pollMe);
-    /**
-     * Get the poll me value
-     * @returns the poll me flag
-     */
-    bool GetPollMe() const;
-    /**
-     * @return a list of packet to be sent in the next opportunity
-     * @param availableSymbols the available resources in symbols
-     * @param modulationType the used modulation
-     * @param packetType the type of packets to select from
-     * @param connection the connection from which packets will be selected
-     */
-    Ptr<PacketBurst> Schedule(uint16_t availableSymbols,
-                              WimaxPhy::ModulationType modulationType,
-                              MacHeaderType::HeaderType packetType,
-                              Ptr<WimaxConnection>& connection);
-
-    void DoDispose() override;
-
-  private:
-    /**
-     * Select connection
-     * @returns pointer to the wimax connection
-     */
-    Ptr<WimaxConnection> SelectConnection();
-    Ptr<SubscriberStationNetDevice> m_ss; ///< the subscriber station
-    bool m_pollMe;                        ///< poll me flag
-};
-
-} // namespace ns3
-
-#endif /* SS_SCHEDULER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-service-flow-manager.cc ns-3.46/src/wimax/model/ss-service-flow-manager.cc
--- ns-3.45/src/wimax/model/ss-service-flow-manager.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-service-flow-manager.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#include "bs-net-device.h"
-#include "bs-uplink-scheduler.h"
-#include "connection-manager.h"
-#include "service-flow-manager.h"
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-manager.h"
-#include "ss-net-device.h"
-#include "ss-record.h"
-#include "ss-scheduler.h"
-#include "wimax-connection.h"
-#include "wimax-net-device.h"
-
-#include "ns3/buffer.h"
-#include "ns3/enum.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("SsServiceFlowManager");
-
-SsServiceFlowManager::SsServiceFlowManager(Ptr<SubscriberStationNetDevice> device)
-    : m_device(device),
-      m_maxDsaReqRetries(100),
-      m_dsaReq(DsaReq()),
-      m_dsaAck(DsaAck()),
-      m_currentTransactionId(0),
-      m_transactionIdIndex(1),
-      m_dsaReqRetries(0),
-      m_pendingServiceFlow(nullptr)
-{
-}
-
-SsServiceFlowManager::~SsServiceFlowManager()
-{
-}
-
-/* static */
-TypeId
-SsServiceFlowManager::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::SsServiceFlowManager").SetParent<ServiceFlowManager>().SetGroupName("Wimax")
-        // No AddConstructor because this is an abstract class.
-        ;
-    return tid;
-}
-
-void
-SsServiceFlowManager::DoDispose()
-{
-    ServiceFlowManager::DoDispose();
-}
-
-void
-SsServiceFlowManager::SetMaxDsaReqRetries(uint8_t maxDsaReqRetries)
-{
-    m_maxDsaReqRetries = maxDsaReqRetries;
-}
-
-uint8_t
-SsServiceFlowManager::GetMaxDsaReqRetries() const
-{
-    return m_maxDsaReqRetries;
-}
-
-EventId
-SsServiceFlowManager::GetDsaRspTimeoutEvent() const
-{
-    return m_dsaRspTimeoutEvent;
-}
-
-EventId
-SsServiceFlowManager::GetDsaAckTimeoutEvent() const
-{
-    return m_dsaAckTimeoutEvent;
-}
-
-void
-SsServiceFlowManager::AddServiceFlow(ServiceFlow serviceFlow)
-{
-    auto sf = new ServiceFlow();
-    sf->CopyParametersFrom(serviceFlow);
-    ServiceFlowManager::AddServiceFlow(sf);
-}
-
-void
-SsServiceFlowManager::AddServiceFlow(ServiceFlow* serviceFlow)
-{
-    ServiceFlowManager::AddServiceFlow(serviceFlow);
-}
-
-void
-SsServiceFlowManager::InitiateServiceFlows()
-{
-    ServiceFlow* serviceFlow = GetNextServiceFlowToAllocate();
-    NS_ASSERT_MSG(
-        serviceFlow != nullptr,
-        "Error while initiating a new service flow: All service flows have been initiated");
-    m_pendingServiceFlow = serviceFlow;
-    ScheduleDsaReq(m_pendingServiceFlow);
-}
-
-DsaReq
-SsServiceFlowManager::CreateDsaReq(const ServiceFlow* serviceFlow)
-{
-    DsaReq dsaReq;
-    dsaReq.SetTransactionId(m_transactionIdIndex);
-    m_currentTransactionId = m_transactionIdIndex++;
-
-    /*as it is SS-initiated DSA therefore SFID and CID will
-     not be included, see 6.3.2.3.10.1 and 6.3.2.3.11.1*/
-    dsaReq.SetServiceFlow(*serviceFlow);
-    // dsaReq.SetParameterSet (*serviceFlow->GetParameterSet ());
-    return dsaReq;
-}
-
-Ptr<Packet>
-SsServiceFlowManager::CreateDsaAck()
-{
-    DsaAck dsaAck;
-    dsaAck.SetTransactionId(m_dsaReq.GetTransactionId());
-    dsaAck.SetConfirmationCode(CONFIRMATION_CODE_SUCCESS);
-    m_dsaAck = dsaAck;
-    Ptr<Packet> p = Create<Packet>();
-    p->AddHeader(dsaAck);
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_DSA_ACK));
-    return p;
-}
-
-void
-SsServiceFlowManager::ScheduleDsaReq(const ServiceFlow* serviceFlow)
-{
-    Ptr<Packet> p = Create<Packet>();
-    DsaReq dsaReq;
-    Ptr<SubscriberStationNetDevice> ss = m_device->GetObject<SubscriberStationNetDevice>();
-
-    if (m_dsaReqRetries == 0)
-    {
-        dsaReq = CreateDsaReq(serviceFlow);
-        p->AddHeader(dsaReq);
-        m_dsaReq = dsaReq;
-    }
-    else
-    {
-        if (m_dsaReqRetries <= m_maxDsaReqRetries)
-        {
-            p->AddHeader(m_dsaReq);
-        }
-        else
-        {
-            NS_LOG_DEBUG("Service flows could not be initialized!");
-        }
-    }
-
-    m_dsaReqRetries++;
-    p->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_DSA_REQ));
-
-    if (m_dsaRspTimeoutEvent.IsPending())
-    {
-        Simulator::Cancel(m_dsaRspTimeoutEvent);
-    }
-
-    m_dsaRspTimeoutEvent = Simulator::Schedule(ss->GetIntervalT7(),
-                                               &SsServiceFlowManager::ScheduleDsaReq,
-                                               this,
-                                               serviceFlow);
-
-    m_device->Enqueue(p, MacHeaderType(), ss->GetPrimaryConnection());
-}
-
-void
-SsServiceFlowManager::ProcessDsaRsp(const DsaRsp& dsaRsp)
-{
-    Ptr<SubscriberStationNetDevice> ss = m_device->GetObject<SubscriberStationNetDevice>();
-
-    // already received DSA-RSP for that particular DSA-REQ
-    if (dsaRsp.GetTransactionId() != m_currentTransactionId)
-    {
-        return;
-    }
-
-    Ptr<Packet> dsaAck = CreateDsaAck();
-    m_device->Enqueue(dsaAck, MacHeaderType(), ss->GetPrimaryConnection());
-
-    m_dsaReqRetries = 0;
-    if (m_pendingServiceFlow == nullptr)
-    {
-        // May be the DSA-ACK was not received by the SS
-        return;
-    }
-    ServiceFlow sf = dsaRsp.GetServiceFlow();
-    (*m_pendingServiceFlow) = sf;
-    m_pendingServiceFlow->SetUnsolicitedGrantInterval(1);
-    m_pendingServiceFlow->SetUnsolicitedPollingInterval(1);
-    Ptr<WimaxConnection> transportConnection =
-        CreateObject<WimaxConnection>(sf.GetCid(), Cid::TRANSPORT);
-
-    m_pendingServiceFlow->SetConnection(transportConnection);
-    transportConnection->SetServiceFlow(m_pendingServiceFlow);
-    ss->GetConnectionManager()->AddConnection(transportConnection, Cid::TRANSPORT);
-    m_pendingServiceFlow->SetIsEnabled(true);
-    m_pendingServiceFlow = nullptr;
-    // check if all service flow have been initiated
-    ServiceFlow* serviceFlow = GetNextServiceFlowToAllocate();
-    if (serviceFlow == nullptr)
-    {
-        ss->SetAreServiceFlowsAllocated(true);
-    }
-    else
-    {
-        m_pendingServiceFlow = serviceFlow;
-        ScheduleDsaReq(m_pendingServiceFlow);
-    }
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ss-service-flow-manager.h ns-3.46/src/wimax/model/ss-service-flow-manager.h
--- ns-3.45/src/wimax/model/ss-service-flow-manager.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ss-service-flow-manager.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *  Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef SS_SERVICE_FLOW_MANAGER_H
-#define SS_SERVICE_FLOW_MANAGER_H
-
-#include "mac-messages.h"
-#include "service-flow-manager.h"
-#include "ss-net-device.h"
-
-#include "ns3/buffer.h"
-#include "ns3/event-id.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class Packet;
-class ServiceFlow;
-class WimaxNetDevice;
-class WimaxConnection;
-class SubscriberStationNetDevice;
-
-/**
- * @ingroup wimax
- * @brief SsServiceFlowManager class
- */
-class SsServiceFlowManager : public ServiceFlowManager
-{
-  public:
-    /// Confirmation code enumeration
-    enum ConfirmationCode // as per Table 384 (not all codes implemented)
-    {
-        CONFIRMATION_CODE_SUCCESS,
-        CONFIRMATION_CODE_REJECT
-    };
-
-    /**
-     * Constructor
-     *
-     * Creates a service flow manager and attaches it to a device
-     *
-     * @param device the device to which the service flow manager will be attached
-     */
-    SsServiceFlowManager(Ptr<SubscriberStationNetDevice> device);
-    ~SsServiceFlowManager() override;
-    void DoDispose() override;
-
-    /**
-     * Register this type.
-     * @return The TypeId.
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * @brief add a service flow to the list
-     * @param serviceFlow the service flow to add
-     */
-    void AddServiceFlow(ServiceFlow* serviceFlow);
-    /**
-     * @brief add a service flow to the list
-     * @param serviceFlow the service flow to add
-     */
-    void AddServiceFlow(ServiceFlow serviceFlow);
-    /**
-     * @brief sets the maximum retries on DSA request message
-     * @param maxDsaReqRetries the maximum retries on DSA request message
-     */
-    void SetMaxDsaReqRetries(uint8_t maxDsaReqRetries);
-    /**
-     * @return the maximum retries on DSA request message
-     */
-    uint8_t GetMaxDsaReqRetries() const;
-
-    /**
-     * Get DSA response timeout event
-     * @returns the DSA response timeout event
-     */
-    EventId GetDsaRspTimeoutEvent() const;
-    /**
-     * Get DSA ack timeout event
-     * @returns the DSA ack timeout event
-     */
-    EventId GetDsaAckTimeoutEvent() const;
-
-    /// Initiate service flows
-    void InitiateServiceFlows();
-
-    /**
-     * Create DSA request
-     * @param serviceFlow the service flow
-     * @returns the DSA request
-     */
-    DsaReq CreateDsaReq(const ServiceFlow* serviceFlow);
-
-    /**
-     * Create DSA ack
-     * @returns the packet
-     */
-    Ptr<Packet> CreateDsaAck();
-
-    /**
-     * Schedule DSA response
-     * @param serviceFlow the service flow
-     */
-    void ScheduleDsaReq(const ServiceFlow* serviceFlow);
-
-    /**
-     * Process DSA response
-     * @param dsaRsp the DSA response
-     */
-    void ProcessDsaRsp(const DsaRsp& dsaRsp);
-
-  private:
-    Ptr<SubscriberStationNetDevice> m_device; ///< the device
-
-    uint8_t m_maxDsaReqRetries; ///< maximum DSA request retries
-
-    EventId m_dsaRspTimeoutEvent; ///< DSA response timeout event
-    EventId m_dsaAckTimeoutEvent; ///< DSA ack timeout event
-
-    DsaReq m_dsaReq; ///< DSA request
-    DsaAck m_dsaAck; ///< DSA ack
-
-    uint16_t m_currentTransactionId; ///< current transaction ID
-    uint16_t m_transactionIdIndex;   ///< transaction ID index
-    uint8_t m_dsaReqRetries;         ///< DSA request retries
-
-    // pointer to the service flow currently being configured
-    ServiceFlow* m_pendingServiceFlow; ///< pending service flow
-};
-
-} // namespace ns3
-
-#endif /* SS_SERVICE_FLOW_MANAGER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ul-job.cc ns-3.46/src/wimax/model/ul-job.cc
--- ns-3.45/src/wimax/model/ul-job.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ul-job.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,163 +0,0 @@
-/*
- * Copyright (c)
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author:  Juliana Freitag Borin, Flavio Kubota and Nelson L.
- * S. da Fonseca - wimaxgroup@lrc.ic.unicamp.br
- */
-
-#include "ul-job.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-UlJob::UlJob()
-    : m_deadline(),
-      m_size(0)
-{
-}
-
-UlJob::~UlJob()
-{
-}
-
-SSRecord*
-UlJob::GetSsRecord() const
-{
-    return m_ssRecord;
-}
-
-void
-UlJob::SetSsRecord(SSRecord* ssRecord)
-{
-    m_ssRecord = ssRecord;
-}
-
-ServiceFlow::SchedulingType
-UlJob::GetSchedulingType() const
-{
-    return m_schedulingType;
-}
-
-void
-UlJob::SetSchedulingType(ServiceFlow::SchedulingType schedulingType)
-{
-    m_schedulingType = schedulingType;
-}
-
-ReqType
-UlJob::GetType() const
-{
-    return m_type;
-}
-
-void
-UlJob::SetType(ReqType type)
-{
-    m_type = type;
-}
-
-ServiceFlow*
-UlJob::GetServiceFlow() const
-{
-    return m_serviceFlow;
-}
-
-void
-UlJob::SetServiceFlow(ServiceFlow* serviceFlow)
-{
-    m_serviceFlow = serviceFlow;
-}
-
-Time
-UlJob::GetReleaseTime() const
-{
-    return m_releaseTime;
-}
-
-void
-UlJob::SetReleaseTime(Time releaseTime)
-{
-    m_releaseTime = releaseTime;
-}
-
-Time
-UlJob::GetPeriod() const
-{
-    return m_period;
-}
-
-void
-UlJob::SetPeriod(Time period)
-{
-    m_period = period;
-}
-
-Time
-UlJob::GetDeadline() const
-{
-    return m_deadline;
-}
-
-void
-UlJob::SetDeadline(Time deadline)
-{
-    m_deadline = deadline;
-}
-
-uint32_t
-UlJob::GetSize() const
-{
-    return m_size;
-}
-
-void
-UlJob::SetSize(uint32_t size)
-{
-    m_size = size;
-}
-
-/**
- * @brief equality operator
- * @param a first ULJob
- * @param b second ULJob
- * @returns true if equal
- */
-bool
-operator==(const UlJob& a, const UlJob& b)
-{
-    return a.GetServiceFlow() == b.GetServiceFlow() && a.GetSsRecord() == b.GetSsRecord();
-}
-
-PriorityUlJob::PriorityUlJob()
-{
-}
-
-int
-PriorityUlJob::GetPriority() const
-{
-    return m_priority;
-}
-
-void
-PriorityUlJob::SetPriority(int priority)
-{
-    m_priority = priority;
-}
-
-Ptr<UlJob>
-PriorityUlJob::GetUlJob() const
-{
-    return m_job;
-}
-
-void
-PriorityUlJob::SetUlJob(Ptr<UlJob> job)
-{
-    m_job = job;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ul-job.h ns-3.46/src/wimax/model/ul-job.h
--- ns-3.45/src/wimax/model/ul-job.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ul-job.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,253 +0,0 @@
-/*
- * Copyright (c)
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author:  Juliana Freitag Borin, Flavio Kubota and Nelson L.
- * S. da Fonseca - wimaxgroup@lrc.ic.unicamp.br
- */
-
-#ifndef UL_JOB_H
-#define UL_JOB_H
-
-#include "service-flow-record.h"
-#include "service-flow.h"
-#include "ss-record.h"
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-class SSRecord;
-class ServiceFlow;
-
-/// Request type enumeration
-enum ReqType
-{
-    DATA,
-    UNICAST_POLLING
-};
-
-/**
- * @ingroup wimax
- * @brief this class implements a structure to compute the priority of service flows
- */
-class UlJob : public Object
-{
-  public:
-    /// Job priority enumeration
-    enum JobPriority
-    {
-        LOW,
-        INTERMEDIATE,
-        HIGH
-    };
-
-    UlJob();
-    ~UlJob() override;
-    /**
-     * Get SS record
-     * @returns the SS record
-     */
-    SSRecord* GetSsRecord() const;
-    /**
-     * Set SS record
-     * @param ssRecord the SS record
-     */
-    void SetSsRecord(SSRecord* ssRecord);
-    /**
-     * Get scheduling type
-     * @returns the scheduling type
-     */
-    ServiceFlow::SchedulingType GetSchedulingType() const;
-    /**
-     * Set scheduling type
-     * @param schedulingType the scheduling type
-     */
-    void SetSchedulingType(ServiceFlow::SchedulingType schedulingType);
-    /**
-     * Get service flow
-     * @returns the service flow
-     */
-    ServiceFlow* GetServiceFlow() const;
-    /**
-     * Set service flow
-     * @param serviceFlow
-     */
-    void SetServiceFlow(ServiceFlow* serviceFlow);
-
-    /**
-     * Get type
-     * @returns the request type
-     */
-    ReqType GetType() const;
-    /**
-     * Set type
-     * @param type the type
-     */
-    void SetType(ReqType type);
-
-    /**
-     * Get release time
-     * @returns the release time
-     */
-    Time GetReleaseTime() const;
-    /**
-     * Set release time
-     * @param releaseTime the release time
-     */
-    void SetReleaseTime(Time releaseTime);
-
-    /**
-     * Get period
-     * @returns the period time
-     */
-    Time GetPeriod() const;
-    /**
-     * Set period
-     * @param period the period
-     */
-    void SetPeriod(Time period);
-
-    /**
-     * Get deadline
-     * @returns the deadline time
-     */
-    Time GetDeadline() const;
-    /**
-     * Set deadline
-     * @param deadline the dead line
-     */
-    void SetDeadline(Time deadline);
-
-    /**
-     * Get size
-     * @returns the size
-     */
-    uint32_t GetSize() const;
-    /**
-     * Set size
-     * @param size the size
-     */
-    void SetSize(uint32_t size);
-
-  private:
-    /// equality operator
-    friend bool operator==(const UlJob& a, const UlJob& b);
-
-    Time m_releaseTime;                           ///< The time after which the job can be processed
-    Time m_period;                                ///< For periodic jobs
-    Time m_deadline;                              ///< Request should be satisfied by this time
-    uint32_t m_size;                              ///< Number of minislots requested
-    ServiceFlow::SchedulingType m_schedulingType; ///< Scheduling type of flow
-
-    SSRecord* m_ssRecord; ///< Pointer to SSRecord
-
-    ReqType m_type;             ///< Type of request, DATA or Unicast req slots
-    ServiceFlow* m_serviceFlow; ///< service flow
-};
-
-/**
- * PriorityUlJob class
- */
-class PriorityUlJob : public Object
-{
-    /**
-     * @brief this class implements an auxiliary struct to compute the priority of the rtPS and
-     * nrtPS in the intermediate queue
-     */
-  public:
-    PriorityUlJob();
-    /**
-     * Get priority
-     * @returns the priority
-     */
-    int GetPriority() const;
-    /**
-     * Set priority
-     * @param priority the priority
-     */
-    void SetPriority(int priority);
-
-    /**
-     * Get UL job function
-     * @returns the UL job
-     */
-    Ptr<UlJob> GetUlJob() const;
-    /**
-     * Set UL job
-     * @param job the UL job
-     */
-    void SetUlJob(Ptr<UlJob> job);
-
-  private:
-    int m_priority;   ///< the priority
-    Ptr<UlJob> m_job; ///< the job
-};
-
-/// SortProcess structure
-struct SortProcess
-{
-    /**
-     * @brief comparison operator
-     * @param left left side input
-     * @param right right side input
-     * @returns true if left is logically less then right for given comparison
-     */
-    bool operator()(PriorityUlJob& left, PriorityUlJob& right) const
-    {
-        if (left.GetPriority() < right.GetPriority())
-        {
-            return true;
-        }
-        else if (left.GetPriority() == right.GetPriority())
-        {
-            int32_t leftBacklogged =
-                left.GetUlJob()->GetServiceFlow()->GetRecord()->GetBacklogged();
-            int32_t rightBacklogged =
-                left.GetUlJob()->GetServiceFlow()->GetRecord()->GetBacklogged();
-            return leftBacklogged <= rightBacklogged;
-        }
-        else
-        {
-            return false;
-        }
-    }
-};
-
-/// SortProcessPtr structure
-struct SortProcessPtr
-{
-    /**
-     * @brief comparison operator
-     * @param left left side input
-     * @param right right side input
-     * @returns true if left is logically less then right for given comparison
-     */
-    bool operator()(Ptr<PriorityUlJob>& left, Ptr<PriorityUlJob>& right) const
-    {
-        if (left->GetPriority() < right->GetPriority())
-        {
-            return true;
-        }
-        else if (left->GetPriority() == right->GetPriority())
-        {
-            int32_t leftBacklogged =
-                left->GetUlJob()->GetServiceFlow()->GetRecord()->GetBacklogged();
-            int32_t rightBacklogged =
-                left->GetUlJob()->GetServiceFlow()->GetRecord()->GetBacklogged();
-            return leftBacklogged <= rightBacklogged;
-        }
-        else
-        {
-            return false;
-        }
-    }
-};
-
-} // namespace ns3
-
-#endif /* UL_JOB_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ul-mac-messages.cc ns-3.46/src/wimax/model/ul-mac-messages.cc
--- ns-3.45/src/wimax/model/ul-mac-messages.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ul-mac-messages.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,689 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "ul-mac-messages.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-NS_OBJECT_ENSURE_REGISTERED(Ucd);
-
-UcdChannelEncodings::UcdChannelEncodings()
-    : m_bwReqOppSize(0),
-      m_rangReqOppSize(0),
-      m_frequency(0)
-{
-}
-
-UcdChannelEncodings::~UcdChannelEncodings()
-{
-}
-
-void
-UcdChannelEncodings::SetBwReqOppSize(uint16_t bwReqOppSize)
-{
-    m_bwReqOppSize = bwReqOppSize;
-}
-
-void
-UcdChannelEncodings::SetRangReqOppSize(uint16_t rangReqOppSize)
-{
-    m_rangReqOppSize = rangReqOppSize;
-}
-
-void
-UcdChannelEncodings::SetFrequency(uint32_t frequency)
-{
-    m_frequency = frequency;
-}
-
-uint16_t
-UcdChannelEncodings::GetBwReqOppSize() const
-{
-    return m_bwReqOppSize;
-}
-
-uint16_t
-UcdChannelEncodings::GetRangReqOppSize() const
-{
-    return m_rangReqOppSize;
-}
-
-uint32_t
-UcdChannelEncodings::GetFrequency() const
-{
-    return m_frequency;
-}
-
-uint16_t
-UcdChannelEncodings::GetSize() const
-{
-    return 2 + 2 + 4;
-}
-
-Buffer::Iterator
-UcdChannelEncodings::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU16(m_bwReqOppSize);
-    i.WriteU16(m_rangReqOppSize);
-    i.WriteU32(m_frequency);
-    return DoWrite(i);
-}
-
-Buffer::Iterator
-UcdChannelEncodings::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_bwReqOppSize = i.ReadU16();
-    m_rangReqOppSize = i.ReadU16();
-    m_frequency = i.ReadU32();
-    return DoRead(i);
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-OfdmUcdChannelEncodings::OfdmUcdChannelEncodings()
-    : m_sbchnlReqRegionFullParams(0),
-      m_sbchnlFocContCodes(0)
-{
-}
-
-OfdmUcdChannelEncodings::~OfdmUcdChannelEncodings()
-{
-}
-
-void
-OfdmUcdChannelEncodings::SetSbchnlReqRegionFullParams(uint8_t sbchnlReqRegionFullParams)
-{
-    m_sbchnlReqRegionFullParams = sbchnlReqRegionFullParams;
-}
-
-void
-OfdmUcdChannelEncodings::SetSbchnlFocContCodes(uint8_t sbchnlFocContCodes)
-{
-    m_sbchnlFocContCodes = sbchnlFocContCodes;
-}
-
-uint8_t
-OfdmUcdChannelEncodings::GetSbchnlReqRegionFullParams() const
-{
-    return m_sbchnlReqRegionFullParams;
-}
-
-uint8_t
-OfdmUcdChannelEncodings::GetSbchnlFocContCodes() const
-{
-    return m_sbchnlFocContCodes;
-}
-
-uint16_t
-OfdmUcdChannelEncodings::GetSize() const
-{
-    return UcdChannelEncodings::GetSize() + 1 + 1;
-}
-
-Buffer::Iterator
-OfdmUcdChannelEncodings::DoWrite(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_sbchnlReqRegionFullParams);
-    i.WriteU8(m_sbchnlFocContCodes);
-    return i;
-}
-
-Buffer::Iterator
-OfdmUcdChannelEncodings::DoRead(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_sbchnlReqRegionFullParams = i.ReadU8();
-    m_sbchnlFocContCodes = i.ReadU8();
-    return i;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-OfdmUlBurstProfile::OfdmUlBurstProfile()
-    : m_type(0),
-      m_length(0),
-      m_uiuc(0),
-      m_fecCodeType(0)
-{
-}
-
-OfdmUlBurstProfile::~OfdmUlBurstProfile()
-{
-}
-
-void
-OfdmUlBurstProfile::SetType(uint8_t type)
-{
-    m_type = type;
-}
-
-void
-OfdmUlBurstProfile::SetLength(uint8_t length)
-{
-    m_length = length;
-}
-
-void
-OfdmUlBurstProfile::SetUiuc(uint8_t uiuc)
-{
-    m_uiuc = uiuc;
-}
-
-void
-OfdmUlBurstProfile::SetFecCodeType(uint8_t fecCodeType)
-{
-    m_fecCodeType = fecCodeType;
-}
-
-uint8_t
-OfdmUlBurstProfile::GetType() const
-{
-    return m_type;
-}
-
-uint8_t
-OfdmUlBurstProfile::GetLength() const
-{
-    return m_length;
-}
-
-uint8_t
-OfdmUlBurstProfile::GetUiuc() const
-{
-    return m_uiuc;
-}
-
-uint8_t
-OfdmUlBurstProfile::GetFecCodeType() const
-{
-    return m_fecCodeType;
-}
-
-uint16_t
-OfdmUlBurstProfile::GetSize() const
-{
-    return 1 + 1 + 1 + 1;
-}
-
-Buffer::Iterator
-OfdmUlBurstProfile::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_type);
-    i.WriteU8(m_length);
-    i.WriteU8(m_uiuc);
-    i.WriteU8(m_fecCodeType);
-    return i;
-}
-
-Buffer::Iterator
-OfdmUlBurstProfile::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_type = i.ReadU8();
-    m_length = i.ReadU8();
-    m_uiuc = i.ReadU8();
-    m_fecCodeType = i.ReadU8();
-    return i;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-Ucd::Ucd()
-    : m_configurationChangeCount(0),
-      m_rangingBackoffStart(0),
-      m_rangingBackoffEnd(0),
-      m_requestBackoffStart(0),
-      m_requestBackoffEnd(0),
-      m_nrUlBurstProfiles(0)
-{
-}
-
-Ucd::~Ucd()
-{
-}
-
-void
-Ucd::SetConfigurationChangeCount(uint8_t configurationChangeCount)
-{
-    m_configurationChangeCount = configurationChangeCount;
-}
-
-void
-Ucd::SetRangingBackoffStart(uint8_t rangingBackoffStart)
-{
-    m_rangingBackoffStart = rangingBackoffStart;
-}
-
-void
-Ucd::SetRangingBackoffEnd(uint8_t rangingBackoffEnd)
-{
-    m_rangingBackoffEnd = rangingBackoffEnd;
-}
-
-void
-Ucd::SetRequestBackoffStart(uint8_t requestBackoffStart)
-{
-    m_requestBackoffStart = requestBackoffStart;
-}
-
-void
-Ucd::SetRequestBackoffEnd(uint8_t requestBackoffEnd)
-{
-    m_requestBackoffEnd = requestBackoffEnd;
-}
-
-void
-Ucd::SetChannelEncodings(OfdmUcdChannelEncodings channelEncodings)
-{
-    m_channelEncodings = channelEncodings;
-}
-
-void
-Ucd::AddUlBurstProfile(OfdmUlBurstProfile ulBurstProfile)
-{
-    m_ulBurstProfiles.push_back(ulBurstProfile);
-}
-
-void
-Ucd::SetNrUlBurstProfiles(uint8_t nrUlBurstProfiles)
-{
-    // number of burst profiles is set to number of UL-MAP IEs after processing UL-MAP
-    m_nrUlBurstProfiles = nrUlBurstProfiles;
-}
-
-uint8_t
-Ucd::GetConfigurationChangeCount() const
-{
-    return m_configurationChangeCount;
-}
-
-uint8_t
-Ucd::GetRangingBackoffStart() const
-{
-    return m_rangingBackoffStart;
-}
-
-uint8_t
-Ucd::GetRangingBackoffEnd() const
-{
-    return m_rangingBackoffEnd;
-}
-
-uint8_t
-Ucd::GetRequestBackoffStart() const
-{
-    return m_requestBackoffStart;
-}
-
-uint8_t
-Ucd::GetRequestBackoffEnd() const
-{
-    return m_requestBackoffEnd;
-}
-
-OfdmUcdChannelEncodings
-Ucd::GetChannelEncodings() const
-{
-    return m_channelEncodings;
-}
-
-std::vector<OfdmUlBurstProfile>
-Ucd::GetUlBurstProfiles() const
-{
-    return m_ulBurstProfiles;
-}
-
-uint8_t
-Ucd::GetNrUlBurstProfiles() const
-{
-    return m_nrUlBurstProfiles;
-}
-
-std::string
-Ucd::GetName() const
-{
-    return "UCD";
-}
-
-TypeId
-Ucd::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::Ucd").SetParent<Header>().SetGroupName("Wimax").AddConstructor<Ucd>();
-    return tid;
-}
-
-TypeId
-Ucd::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-Ucd::Print(std::ostream& os) const
-{
-    os << " configuration change count = " << (uint32_t)m_configurationChangeCount
-       << ", ranging backoff start = " << (uint32_t)m_rangingBackoffStart
-       << ", ranging backoff end = " << (uint32_t)m_rangingBackoffEnd
-       << ", request backoff start = " << (uint32_t)m_requestBackoffStart
-       << ", request backoff end = " << (uint32_t)m_requestBackoffEnd
-       << ", number of ul burst profiles = " << m_ulBurstProfiles.size();
-}
-
-uint32_t
-Ucd::GetSerializedSize() const
-{
-    uint32_t ulBurstProfilesSize = 0;
-
-    for (const auto& burstProfile : m_ulBurstProfiles)
-    {
-        ulBurstProfilesSize += burstProfile.GetSize();
-    }
-
-    return 5 + m_channelEncodings.GetSize() + ulBurstProfilesSize;
-}
-
-void
-Ucd::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_configurationChangeCount);
-    i.WriteU8(m_rangingBackoffStart);
-    i.WriteU8(m_rangingBackoffEnd);
-    i.WriteU8(m_requestBackoffStart);
-    i.WriteU8(m_requestBackoffEnd);
-    i = m_channelEncodings.Write(i);
-
-    for (const auto& burstProfile : m_ulBurstProfiles)
-    {
-        i = burstProfile.Write(i);
-    }
-}
-
-uint32_t
-Ucd::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_configurationChangeCount = i.ReadU8();
-    m_rangingBackoffStart = i.ReadU8();
-    m_rangingBackoffEnd = i.ReadU8();
-    m_requestBackoffStart = i.ReadU8();
-    m_requestBackoffEnd = i.ReadU8();
-    i = m_channelEncodings.Read(i);
-
-    for (uint8_t j = 0; j < m_nrUlBurstProfiles; j++)
-    {
-        OfdmUlBurstProfile burstProfile;
-        i = burstProfile.Read(i);
-        AddUlBurstProfile(burstProfile);
-    }
-
-    return i.GetDistanceFrom(start);
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-OfdmUlMapIe::OfdmUlMapIe()
-    : m_cid(),
-      m_startTime(0),
-      m_subchannelIndex(0),
-      m_uiuc(0),
-      m_duration(0),
-      m_midambleRepetitionInterval(0)
-{
-}
-
-OfdmUlMapIe::~OfdmUlMapIe()
-{
-}
-
-void
-OfdmUlMapIe::SetCid(const Cid& cid)
-{
-    m_cid = cid;
-}
-
-void
-OfdmUlMapIe::SetStartTime(uint16_t startTime)
-{
-    m_startTime = startTime;
-}
-
-void
-OfdmUlMapIe::SetSubchannelIndex(uint8_t subchannelIndex)
-{
-    m_subchannelIndex = subchannelIndex;
-}
-
-void
-OfdmUlMapIe::SetUiuc(uint8_t uiuc)
-{
-    m_uiuc = uiuc;
-}
-
-void
-OfdmUlMapIe::SetDuration(uint16_t duration)
-{
-    m_duration = duration;
-}
-
-void
-OfdmUlMapIe::SetMidambleRepetitionInterval(uint8_t midambleRepetitionInterval)
-{
-    m_midambleRepetitionInterval = midambleRepetitionInterval;
-}
-
-Cid
-OfdmUlMapIe::GetCid() const
-{
-    return m_cid;
-}
-
-uint16_t
-OfdmUlMapIe::GetStartTime() const
-{
-    return m_startTime;
-}
-
-uint8_t
-OfdmUlMapIe::GetSubchannelIndex() const
-{
-    return m_subchannelIndex;
-}
-
-uint8_t
-OfdmUlMapIe::GetUiuc() const
-{
-    return m_uiuc;
-}
-
-uint16_t
-OfdmUlMapIe::GetDuration() const
-{
-    return m_duration;
-}
-
-uint8_t
-OfdmUlMapIe::GetMidambleRepetitionInterval() const
-{
-    return m_midambleRepetitionInterval;
-}
-
-uint16_t
-OfdmUlMapIe::GetSize() const
-{
-    return 2 + 2 + 1 + 1 + 2 + 1;
-}
-
-Buffer::Iterator
-OfdmUlMapIe::Write(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU16(m_cid.GetIdentifier());
-    i.WriteU16(m_startTime);
-    i.WriteU8(m_subchannelIndex);
-    i.WriteU8(m_uiuc);
-    i.WriteU16(m_duration);
-    i.WriteU8(m_midambleRepetitionInterval);
-    return i;
-}
-
-Buffer::Iterator
-OfdmUlMapIe::Read(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_cid = i.ReadU16();
-    m_startTime = i.ReadU16();
-    m_subchannelIndex = i.ReadU8();
-    m_uiuc = i.ReadU8();
-    m_duration = i.ReadU16();
-    m_midambleRepetitionInterval = i.ReadU8();
-    return i;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(UlMap);
-
-UlMap::UlMap()
-    : m_reserved(0),
-      m_ucdCount(0),
-      m_allocationStartTime(0)
-{
-}
-
-UlMap::~UlMap()
-{
-}
-
-void
-UlMap::SetUcdCount(uint8_t ucdCount)
-{
-    m_ucdCount = ucdCount;
-}
-
-void
-UlMap::SetAllocationStartTime(uint32_t allocationStartTime)
-{
-    m_allocationStartTime = allocationStartTime;
-}
-
-void
-UlMap::AddUlMapElement(OfdmUlMapIe ulMapElement)
-{
-    m_ulMapElements.push_back(ulMapElement);
-}
-
-uint8_t
-UlMap::GetUcdCount() const
-{
-    return m_ucdCount;
-}
-
-uint32_t
-UlMap::GetAllocationStartTime() const
-{
-    return m_allocationStartTime;
-}
-
-std::list<OfdmUlMapIe>
-UlMap::GetUlMapElements() const
-{
-    return m_ulMapElements;
-}
-
-std::string
-UlMap::GetName() const
-{
-    return "UL-MAP";
-}
-
-TypeId
-UlMap::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::UlMap").SetParent<Header>().SetGroupName("Wimax").AddConstructor<UlMap>();
-    return tid;
-}
-
-TypeId
-UlMap::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-UlMap::Print(std::ostream& os) const
-{
-    os << " ucd count = " << (uint32_t)m_ucdCount
-       << ", allocation start time = " << m_allocationStartTime
-       << ", number of ul-map elements = " << m_ulMapElements.size();
-}
-
-uint32_t
-UlMap::GetSerializedSize() const
-{
-    uint32_t ulMapElementsSize = 0;
-
-    for (const auto& ulMapIe : m_ulMapElements)
-    {
-        ulMapElementsSize += ulMapIe.GetSize();
-    }
-
-    return 1 + 1 + 4 + ulMapElementsSize;
-}
-
-void
-UlMap::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_reserved);
-    i.WriteU8(m_ucdCount);
-    i.WriteU32(m_allocationStartTime);
-
-    for (const auto& ulMapIe : m_ulMapElements)
-    {
-        i = ulMapIe.Write(i);
-    }
-}
-
-uint32_t
-UlMap::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_reserved = i.ReadU8();
-    m_ucdCount = i.ReadU8();
-    m_allocationStartTime = i.ReadU32();
-
-    m_ulMapElements.clear(); // only for printing, otherwise it shows wrong number of elements
-
-    while (true)
-    {
-        OfdmUlMapIe ulMapIe;
-        i = ulMapIe.Read(i);
-
-        AddUlMapElement(ulMapIe);
-
-        if (ulMapIe.GetUiuc() == 14) // End of Map IE
-        {
-            break;
-        }
-    }
-    return i.GetDistanceFrom(start);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/ul-mac-messages.h ns-3.46/src/wimax/model/ul-mac-messages.h
--- ns-3.45/src/wimax/model/ul-mac-messages.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/ul-mac-messages.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#ifndef UCD_CHANNEL_ENCODINGS_H
-#define UCD_CHANNEL_ENCODINGS_H
-
-#include "ns3/buffer.h"
-
-#include <list>
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the UCD channel encodings as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 11.3.1 UCD channel encodings, page 651
- */
-class UcdChannelEncodings
-{
-  public:
-    UcdChannelEncodings();
-    virtual ~UcdChannelEncodings();
-
-    /**
-     * Set BW request opp size
-     * @param bwReqOppSize the bandwidth request opp size
-     */
-    void SetBwReqOppSize(uint16_t bwReqOppSize);
-    /**
-     * Set range request opp size
-     * @param rangReqOppSize the ranging request opp size
-     */
-    void SetRangReqOppSize(uint16_t rangReqOppSize);
-    /**
-     * Set frequency
-     * @param frequency the frequency
-     */
-    void SetFrequency(uint32_t frequency);
-
-    /**
-     * Get BW request opp size
-     * @returns the bandwidth request opp size
-     */
-    uint16_t GetBwReqOppSize() const;
-    /**
-     * Get range request opp size
-     * @returns the ragning request opp size
-     */
-    uint16_t GetRangReqOppSize() const;
-    /**
-     * Get frequency
-     * @returns the frequency
-     */
-    uint32_t GetFrequency() const;
-
-    /**
-     * Get size
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    virtual Buffer::Iterator DoWrite(Buffer::Iterator start) const = 0;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    virtual Buffer::Iterator DoRead(Buffer::Iterator start) = 0;
-
-    uint16_t m_bwReqOppSize;   ///< BW request opp size
-    uint16_t m_rangReqOppSize; ///< range request opp size
-    uint32_t m_frequency;      ///< frequency
-};
-
-} // namespace ns3
-
-#endif /* UCD_CHANNEL_ENCODINGS_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef OFDM_UCD_CHANNEL_ENCODINGS_H
-#define OFDM_UCD_CHANNEL_ENCODINGS_H
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * This class implements the OFDM UCD channel encodings as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 11.3.1 UCD channel encodings, page 651
- */
-class OfdmUcdChannelEncodings : public UcdChannelEncodings
-{
-  public:
-    OfdmUcdChannelEncodings();
-    ~OfdmUcdChannelEncodings() override;
-
-    /**
-     * Set SB channel reguest region full parameters
-     * @param sbchnlReqRegionFullParams the channel request region full parameters
-     */
-    void SetSbchnlReqRegionFullParams(uint8_t sbchnlReqRegionFullParams);
-    /**
-     * Set SB channel for control codes
-     * @param sbchnlFocContCodes the channel control codes
-     */
-    void SetSbchnlFocContCodes(uint8_t sbchnlFocContCodes);
-
-    /**
-     * Get SB channel request region full parameters
-     * @returns the channel request region full parameters
-     */
-    uint8_t GetSbchnlReqRegionFullParams() const;
-    /**
-     * Get SB channel for control codes
-     * @returns the channel for control codes
-     */
-    uint8_t GetSbchnlFocContCodes() const;
-
-    /**
-     * Get size
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-  private:
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator DoWrite(Buffer::Iterator start) const override;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator DoRead(Buffer::Iterator start) override;
-
-    uint8_t m_sbchnlReqRegionFullParams; ///< SB channel request region full parameters
-    uint8_t m_sbchnlFocContCodes;        ///< SB channel for control codes
-};
-
-} // namespace ns3
-
-#endif /* OFDM_UCD_CHANNEL_ENCODINGS_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef OFDM_UL_BURST_PROFILE_H
-#define OFDM_UL_BURST_PROFILE_H
-
-#include "ns3/buffer.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * This class implements the UL burst profile as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 11.3.1.1 Uplink burst profile encodings, page 655
- */
-class OfdmUlBurstProfile
-{
-  public:
-    /// UIUC enumeraton
-    enum Uiuc
-    {
-        UIUC_INITIAL_RANGING = 1,
-        UIUC_REQ_REGION_FULL,
-        UIUC_REQ_REGION_FOCUSED,
-        UIUC_FOCUSED_CONTENTION_IE,
-        UIUC_BURST_PROFILE_5,
-        UIUC_BURST_PROFILE_6,
-        UIUC_BURST_PROFILE_7,
-        UIUC_BURST_PROFILE_8,
-        UIUC_BURST_PROFILE_9,
-        UIUC_BURST_PROFILE_10,
-        UIUC_BURST_PROFILE_11,
-        UIUC_BURST_PROFILE_12,
-        UIUC_SUBCH_NETWORK_ENTRY,
-        UIUC_END_OF_MAP
-    };
-
-    OfdmUlBurstProfile();
-    ~OfdmUlBurstProfile();
-
-    /**
-     * Set type
-     * @param type the type
-     */
-    void SetType(uint8_t type);
-    /**
-     * Set length
-     * @param length the length
-     */
-    void SetLength(uint8_t length);
-    /**
-     * Set UIUC
-     * @param uiuc the UIUC
-     */
-    void SetUiuc(uint8_t uiuc);
-    /**
-     * Set FEC code type
-     * @param fecCodeType the FEC code type
-     */
-    void SetFecCodeType(uint8_t fecCodeType);
-
-    /**
-     * Get type
-     * @returns the type
-     */
-    uint8_t GetType() const;
-    /**
-     * Get length
-     * @returns the length
-     */
-    uint8_t GetLength() const;
-    /**
-     * Get UIUC
-     * @returns the UIUC
-     */
-    uint8_t GetUiuc() const;
-    /**
-     * Get FEC code type
-     * @returns the FEC code type
-     */
-    uint8_t GetFecCodeType() const;
-
-    /**
-     * Get size
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    uint8_t m_type;   ///< type
-    uint8_t m_length; ///< length
-    uint8_t m_uiuc;   ///< UIUC
-
-    // TLV Encoded information
-    uint8_t m_fecCodeType; ///< FEC code type
-};
-
-} // namespace ns3
-
-#endif /* OFDM_UL_BURST_PROFILE_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef UCD_H
-#define UCD_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-#include <vector>
-
-namespace ns3
-{
-
-/**
- * This class implements the UCD message as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.3 Uplink Channel Descriptor (UCD) message, page 47
- */
-class Ucd : public Header
-{
-  public:
-    Ucd();
-    ~Ucd() override;
-
-    /**
-     * Set configuration change count
-     * @param ucdCount the UCD count
-     */
-    void SetConfigurationChangeCount(uint8_t ucdCount);
-    /**
-     * Set ranging backoff start
-     * @param rangingBackoffStart ranging backoff start
-     */
-    void SetRangingBackoffStart(uint8_t rangingBackoffStart);
-    /**
-     * Set ranging backoff end
-     * @param rangingBackoffEnd the ranging backoff end
-     */
-    void SetRangingBackoffEnd(uint8_t rangingBackoffEnd);
-    /**
-     * Set request backoff start
-     * @param requestBackoffStart the request backoff start
-     */
-    void SetRequestBackoffStart(uint8_t requestBackoffStart);
-    /**
-     * Set request backoff end
-     * @param requestBackoffEnd the request backoff end
-     */
-    void SetRequestBackoffEnd(uint8_t requestBackoffEnd);
-    /**
-     * Set channel encodings
-     * @param channelEncodings the channel encodings
-     */
-    void SetChannelEncodings(OfdmUcdChannelEncodings channelEncodings);
-    /**
-     * Add UL burst profile
-     * @param ulBurstProfile the UL burst profile
-     */
-    void AddUlBurstProfile(OfdmUlBurstProfile ulBurstProfile);
-    /**
-     * Set NR UL burst profiles
-     * @param nrUlBurstProfiles the NR UL burst profiles
-     */
-    void SetNrUlBurstProfiles(uint8_t nrUlBurstProfiles);
-
-    /**
-     * Get configuration change count
-     * @returns the configuration change count
-     */
-    uint8_t GetConfigurationChangeCount() const;
-    /**
-     * Get ranging backoff start
-     * @returns the ranging backoff start
-     */
-    uint8_t GetRangingBackoffStart() const;
-    /**
-     * Get ranging backoff end
-     * @returns the ranging backoff end value
-     */
-    uint8_t GetRangingBackoffEnd() const;
-    /**
-     * Get request backoff start
-     * @returns the request backoff start value
-     */
-    uint8_t GetRequestBackoffStart() const;
-    /**
-     * Get request backoff end
-     * @returns the request backoff end value
-     */
-    uint8_t GetRequestBackoffEnd() const;
-    /**
-     * Get channel encodings
-     * @returns the OFDM UCD channel encodings
-     */
-    OfdmUcdChannelEncodings GetChannelEncodings() const;
-    /**
-     * Get UL burst profiles
-     * @returns the UL burst profile
-     */
-    std::vector<OfdmUlBurstProfile> GetUlBurstProfiles() const;
-    /**
-     * Get number UL burst profiles
-     * @returns the number of UL burst profiles
-     */
-    uint8_t GetNrUlBurstProfiles() const;
-
-    /**
-     * Get name
-     * @returns the name string
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_configurationChangeCount;         ///< configuration change count
-    uint8_t m_rangingBackoffStart;              ///< ranging backoff start
-    uint8_t m_rangingBackoffEnd;                ///< ranging backoff end
-    uint8_t m_requestBackoffStart;              ///< request backoff start
-    uint8_t m_requestBackoffEnd;                ///< request backoff end
-    OfdmUcdChannelEncodings m_channelEncodings; ///< TLV Encoded information for the overall channel
-    std::vector<OfdmUlBurstProfile> m_ulBurstProfiles; ///< UL burst profiles
-
-    uint8_t m_nrUlBurstProfiles; ///< number UL burst profiles
-};
-
-} // namespace ns3
-
-#endif /* UCD_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef OFDM_UL_MAP_IE_H
-#define OFDM_UL_MAP_IE_H
-
-#include "cid.h"
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * This class implements the UL-MAP_IE message as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 6.3.2.3.43.7 UL-MAP_IE, page 115
- */
-class OfdmUlMapIe
-{
-  public:
-    OfdmUlMapIe();
-    ~OfdmUlMapIe();
-
-    /**
-     * Set CID
-     * @param cid the CID
-     */
-    void SetCid(const Cid& cid);
-    /**
-     * Set start time
-     * @param startTime the start time
-     */
-    void SetStartTime(uint16_t startTime);
-    /**
-     * Set subchannel index
-     * @param subchannelIndex
-     */
-    void SetSubchannelIndex(uint8_t subchannelIndex);
-    /**
-     * Set UIUC
-     * @param uiuc the UIUC
-     */
-    void SetUiuc(uint8_t uiuc);
-    /**
-     * Set duration
-     * @param duration the duration
-     */
-    void SetDuration(uint16_t duration);
-    /**
-     * Set midambe repetition interval
-     * @param midambleRepetitionInterval the midambe repetition interval
-     */
-    void SetMidambleRepetitionInterval(uint8_t midambleRepetitionInterval);
-
-    /**
-     * Get CID
-     * @returns the CID
-     */
-    Cid GetCid() const;
-    /**
-     * Get start time
-     * @returns the start time
-     */
-    uint16_t GetStartTime() const;
-    /**
-     * Get subchannel index
-     * @returns the subchannel index
-     */
-    uint8_t GetSubchannelIndex() const;
-    /**
-     * Get UIUC
-     * @returns the UIUC
-     */
-    uint8_t GetUiuc() const;
-    /**
-     * Get duration
-     * @returns the duration
-     */
-    uint16_t GetDuration() const;
-    /**
-     * Get Midamble repetition interval
-     * @returns the midamble repetition interval
-     */
-    uint8_t GetMidambleRepetitionInterval() const;
-
-    /**
-     * Get size
-     * @returns the size
-     */
-    uint16_t GetSize() const;
-
-    /**
-     * Write item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Write(Buffer::Iterator start) const;
-    /**
-     * Read item
-     * @param start the iterator
-     * @returns the updated iterator
-     */
-    Buffer::Iterator Read(Buffer::Iterator start);
-
-  private:
-    Cid m_cid;                            ///< CID
-    uint16_t m_startTime;                 ///< start time
-    uint8_t m_subchannelIndex;            ///< subchannel index
-    uint8_t m_uiuc;                       ///< UIUC
-    uint16_t m_duration;                  ///< duration
-    uint8_t m_midambleRepetitionInterval; ///< midamble repetition interval
-
-    // fields to be implemented later on:
-    // m_focusedContentionIe()
-    // m_subchannelizedNetworkEntryIe()
-    // m_ulExtendedIe()
-    // m_paddingNibble;
-};
-
-} // namespace ns3
-
-#endif /* OFDM_UL_MAP_IE_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef UL_MAP_H
-#define UL_MAP_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-#include <vector>
-
-namespace ns3
-{
-
-/**
- * This class implements the UL-MAP_IE message as described by "IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems" 8.2.1.8.2 Compressed UL-MAP, page 404
- */
-class UlMap : public Header
-{
-  public:
-    UlMap();
-    ~UlMap() override;
-
-    /**
-     * Set UCD count
-     * @param ucdCount the UCD count
-     */
-    void SetUcdCount(uint8_t ucdCount);
-    /**
-     * Set allocation start time
-     * @param allocationStartTime the allocation start time
-     */
-    void SetAllocationStartTime(uint32_t allocationStartTime);
-    /**
-     * Add UL map element
-     * @param ulMapElement the UL map element
-     */
-    void AddUlMapElement(OfdmUlMapIe ulMapElement);
-
-    /**
-     * Get UCD count
-     * @returns the UCD count
-     */
-    uint8_t GetUcdCount() const;
-    /**
-     * Get allocation start time
-     * @returns the allocation start time
-     */
-    uint32_t GetAllocationStartTime() const;
-    /**
-     * Get UL map elements
-     * @returns the UL map elements
-     */
-    std::list<OfdmUlMapIe> GetUlMapElements() const;
-
-    /**
-     * Get name
-     * @returns the name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_reserved; ///< changed as per the amendment 802.16e-2005
-
-    uint8_t m_ucdCount;                     ///< UCD count
-    uint32_t m_allocationStartTime;         ///< allocation start time
-    std::list<OfdmUlMapIe> m_ulMapElements; ///< UL map elements
-};
-
-} // namespace ns3
-
-#endif /* UL_MAP_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-channel.cc ns-3.46/src/wimax/model/wimax-channel.cc
--- ns-3.45/src/wimax/model/wimax-channel.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-channel.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "wimax-channel.h"
-
-#include "wimax-phy.h"
-
-#include "ns3/assert.h"
-#include "ns3/net-device.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("WimaxChannel");
-
-NS_OBJECT_ENSURE_REGISTERED(WimaxChannel);
-
-TypeId
-WimaxChannel::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::WimaxChannel").SetParent<Channel>().SetGroupName("Wimax");
-    return tid;
-}
-
-WimaxChannel::WimaxChannel()
-{
-}
-
-WimaxChannel::~WimaxChannel()
-{
-}
-
-void
-WimaxChannel::Attach(Ptr<WimaxPhy> phy)
-{
-    DoAttach(phy);
-}
-
-std::size_t
-WimaxChannel::GetNDevices() const
-{
-    return DoGetNDevices();
-}
-
-Ptr<NetDevice>
-WimaxChannel::GetDevice(std::size_t index) const
-{
-    return DoGetDevice(index);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-channel.h ns-3.46/src/wimax/model/wimax-channel.h
--- ns-3.45/src/wimax/model/wimax-channel.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-channel.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef WIMAX_CHANNEL_H
-#define WIMAX_CHANNEL_H
-
-#include "wimax-connection.h"
-
-#include "ns3/channel.h"
-#include "ns3/log.h"
-
-#include <list>
-
-namespace ns3
-{
-
-class WimaxPhy;
-class Packet;
-class Position;
-class PacketBurst;
-
-/**
- * @ingroup wimax
- * The channel object to attach Wimax NetDevices
- */
-class WimaxChannel : public Channel
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    WimaxChannel();
-    ~WimaxChannel() override;
-    /**
-     * @brief attach the channel to a physical layer of a device
-     * @param phy the physical layer to which the channel will be attached
-     */
-    void Attach(Ptr<WimaxPhy> phy);
-    /**
-     * @return the number of attached devices
-     */
-    std::size_t GetNDevices() const override;
-    /**
-     * @param i the ith device
-     * @return the ith attached device
-     */
-    Ptr<NetDevice> GetDevice(std::size_t i) const override;
-
-    /**
-     * Assign a fixed random variable stream number to the random variables
-     * used by this model.  Return the number of streams (possibly zero) that
-     * have been assigned.
-     *
-     * @param stream first stream index to use
-     * @return the number of stream indices assigned by this model
-     */
-    virtual int64_t AssignStreams(int64_t stream) = 0;
-
-  private:
-    /**
-     * Attach a phy to the channel
-     * @param phy the phy object to attach
-     */
-    virtual void DoAttach(Ptr<WimaxPhy> phy) = 0;
-
-    /**
-     * Get number of devices on the channel
-     * @returns the number of devices
-     */
-    virtual std::size_t DoGetNDevices() const = 0;
-    /**
-     * Get device corresponding to index
-     * @param i the device index
-     * @returns the device
-     */
-    virtual Ptr<NetDevice> DoGetDevice(std::size_t i) const = 0;
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_CHANNEL_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-connection.cc ns-3.46/src/wimax/model/wimax-connection.cc
--- ns-3.45/src/wimax/model/wimax-connection.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-connection.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#include "wimax-connection.h"
-
-#include "service-flow.h"
-
-#include "ns3/enum.h"
-#include "ns3/pointer.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_OBJECT_ENSURE_REGISTERED(WimaxConnection);
-
-TypeId
-WimaxConnection::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::WimaxConnection")
-
-                            .SetParent<Object>()
-
-                            .SetGroupName("Wimax")
-
-                            .AddAttribute("Type",
-                                          "Connection type",
-                                          EnumValue(Cid::INITIAL_RANGING),
-                                          MakeEnumAccessor<Cid::Type>(&WimaxConnection::GetType),
-                                          MakeEnumChecker(Cid::BROADCAST,
-                                                          "Broadcast",
-                                                          Cid::INITIAL_RANGING,
-                                                          "InitialRanging",
-                                                          Cid::BASIC,
-                                                          "Basic",
-                                                          Cid::PRIMARY,
-                                                          "Primary",
-                                                          Cid::TRANSPORT,
-                                                          "Transport",
-                                                          Cid::MULTICAST,
-                                                          "Multicast",
-                                                          Cid::PADDING,
-                                                          "Padding"))
-
-                            .AddAttribute("TxQueue",
-                                          "Transmit queue",
-                                          PointerValue(),
-                                          MakePointerAccessor(&WimaxConnection::GetQueue),
-                                          MakePointerChecker<WimaxMacQueue>());
-    return tid;
-}
-
-WimaxConnection::WimaxConnection(Cid cid, Cid::Type type)
-    : m_cid(cid),
-      m_cidType(type),
-      m_queue(CreateObject<WimaxMacQueue>(1024)),
-      m_serviceFlow(nullptr)
-{
-}
-
-WimaxConnection::~WimaxConnection()
-{
-}
-
-void
-WimaxConnection::DoDispose()
-{
-    m_queue = nullptr;
-    // m_serviceFlow = 0;
-}
-
-Cid
-WimaxConnection::GetCid() const
-{
-    return m_cid;
-}
-
-Cid::Type
-WimaxConnection::GetType() const
-{
-    return m_cidType;
-}
-
-Ptr<WimaxMacQueue>
-WimaxConnection::GetQueue() const
-{
-    return m_queue;
-}
-
-void
-WimaxConnection::SetServiceFlow(ServiceFlow* serviceFlow)
-{
-    m_serviceFlow = serviceFlow;
-}
-
-ServiceFlow*
-WimaxConnection::GetServiceFlow() const
-{
-    return m_serviceFlow;
-}
-
-uint8_t
-WimaxConnection::GetSchedulingType() const
-{
-    return m_serviceFlow->GetSchedulingType();
-}
-
-bool
-WimaxConnection::Enqueue(Ptr<Packet> packet,
-                         const MacHeaderType& hdrType,
-                         const GenericMacHeader& hdr)
-{
-    return m_queue->Enqueue(packet, hdrType, hdr);
-}
-
-Ptr<Packet>
-WimaxConnection::Dequeue(MacHeaderType::HeaderType packetType)
-{
-    return m_queue->Dequeue(packetType);
-}
-
-Ptr<Packet>
-WimaxConnection::Dequeue(MacHeaderType::HeaderType packetType, uint32_t availableByte)
-{
-    return m_queue->Dequeue(packetType, availableByte);
-}
-
-bool
-WimaxConnection::HasPackets() const
-{
-    return !m_queue->IsEmpty();
-}
-
-bool
-WimaxConnection::HasPackets(MacHeaderType::HeaderType packetType) const
-{
-    return !m_queue->IsEmpty(packetType);
-}
-
-std::string
-WimaxConnection::GetTypeStr() const
-{
-    switch (m_cidType)
-    {
-    case Cid::BROADCAST:
-        return "Broadcast";
-    case Cid::INITIAL_RANGING:
-        return "Initial Ranging";
-    case Cid::BASIC:
-        return "Basic";
-    case Cid::PRIMARY:
-        return "Primary";
-    case Cid::TRANSPORT:
-        return "Transport";
-    case Cid::MULTICAST:
-        return "Multicast";
-    default:
-        NS_FATAL_ERROR("Invalid connection type");
-    }
-
-    return "";
-}
-
-// Defragmentation Function
-const WimaxConnection::FragmentsQueue
-WimaxConnection::GetFragmentsQueue() const
-{
-    return m_fragmentsQueue;
-}
-
-void
-WimaxConnection::FragmentEnqueue(Ptr<const Packet> fragment)
-{
-    m_fragmentsQueue.push_back(fragment);
-}
-
-void
-WimaxConnection::ClearFragmentsQueue()
-{
-    m_fragmentsQueue.clear();
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-connection.h ns-3.46/src/wimax/model/wimax-connection.h
--- ns-3.45/src/wimax/model/wimax-connection.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-connection.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef WIMAX_CONNECTION_H
-#define WIMAX_CONNECTION_H
-
-#include "cid.h"
-#include "service-flow.h"
-#include "wimax-mac-header.h"
-#include "wimax-mac-queue.h"
-
-#include "ns3/object.h"
-
-#include <ostream>
-#include <stdint.h>
-
-namespace ns3
-{
-
-class ServiceFlow;
-class Cid;
-
-/**
- * @ingroup wimax
- * Class to represent WiMAX connections
- */
-class WimaxConnection : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-
-    /**
-     * Constructor
-     *
-     * @param cid connection ID
-     * @param type CID type
-     */
-    WimaxConnection(Cid cid, Cid::Type type);
-    ~WimaxConnection() override;
-
-    /**
-     * Get CID function
-     * @returns the CID
-     */
-    Cid GetCid() const;
-
-    /**
-     * Get type function
-     * @returns the type
-     */
-    Cid::Type GetType() const;
-    /**
-     * @return the queue of the connection
-     */
-    Ptr<WimaxMacQueue> GetQueue() const;
-    /**
-     * @brief set the service flow associated to this connection
-     * @param serviceFlow The service flow to be associated to this connection
-     */
-    void SetServiceFlow(ServiceFlow* serviceFlow);
-    /**
-     * @return the service flow associated to this connection
-     */
-    ServiceFlow* GetServiceFlow() const;
-
-    // wrapper functions
-    /**
-     * @return the scheduling type of this connection
-     */
-    uint8_t GetSchedulingType() const;
-    /**
-     * @brief enqueue a packet in the queue of the connection
-     * @param packet the packet to be enqueued
-     * @param hdrType the header type of the packet
-     * @param hdr the header of the packet
-     * @return true if successful
-     */
-    bool Enqueue(Ptr<Packet> packet, const MacHeaderType& hdrType, const GenericMacHeader& hdr);
-    /**
-     * @brief dequeue a packet from the queue of the connection
-     * @param packetType the type of the packet to dequeue
-     * @return packet dequeued
-     */
-    Ptr<Packet> Dequeue(MacHeaderType::HeaderType packetType = MacHeaderType::HEADER_TYPE_GENERIC);
-    /**
-     * @brief dequeue a packet from the queue of the connection
-     * Dequeue the first packet in the queue if its size is lower than
-     * availableByte, the first availableByte of the first packet otherwise
-     *
-     * @param packetType the type of the packet to dequeue
-     * @param availableByte the number of available bytes
-     * @return packet dequeued
-     */
-    Ptr<Packet> Dequeue(MacHeaderType::HeaderType packetType, uint32_t availableByte);
-    /**
-     * @return true if the connection has at least one packet in its queue, false otherwise
-     */
-    bool HasPackets() const;
-    /**
-     * @return true if the connection has at least one packet of type packetType in its queue, false
-     * otherwise
-     * @param packetType type of packet to check in the queue
-     * @return true if packets available
-     */
-    bool HasPackets(MacHeaderType::HeaderType packetType) const;
-
-    /**
-     * Get type string
-     * @returns the type string
-     */
-    std::string GetTypeStr() const;
-
-    /// Definition of Fragments Queue data type
-    typedef std::list<Ptr<const Packet>> FragmentsQueue;
-    /**
-     * @brief get a queue of received fragments
-     * @returns the fragments queue
-     */
-    const FragmentsQueue GetFragmentsQueue() const;
-    /**
-     * @brief enqueue a received packet (that is a fragment) into the fragments queue
-     * @param fragment received fragment
-     */
-    void FragmentEnqueue(Ptr<const Packet> fragment);
-    /**
-     * @brief delete all enqueued fragments
-     */
-    void ClearFragmentsQueue();
-
-  private:
-    void DoDispose() override;
-
-    Cid m_cid;                  ///< CID
-    Cid::Type m_cidType;        ///< CID type
-    Ptr<WimaxMacQueue> m_queue; ///< queue
-    ServiceFlow* m_serviceFlow; ///< service flow
-
-    // FragmentsQueue stores all received fragments
-    FragmentsQueue m_fragmentsQueue; ///< fragments queue
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_CONNECTION_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-mac-header.cc ns-3.46/src/wimax/model/wimax-mac-header.cc
--- ns-3.45/src/wimax/model/wimax-mac-header.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-mac-header.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,719 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-
-#include "wimax-mac-header.h"
-
-#include "crc8.h"
-
-namespace ns3
-{
-
-NS_OBJECT_ENSURE_REGISTERED(MacHeaderType);
-
-MacHeaderType::MacHeaderType()
-    : m_type(0)
-{
-}
-
-MacHeaderType::MacHeaderType(uint8_t type)
-    : m_type(type)
-{
-}
-
-MacHeaderType::~MacHeaderType()
-{
-}
-
-void
-MacHeaderType::SetType(uint8_t type)
-{
-    m_type = type;
-}
-
-uint8_t
-MacHeaderType::GetType() const
-{
-    return m_type;
-}
-
-std::string
-MacHeaderType::GetName() const
-{
-    return "MAC Header Type";
-}
-
-TypeId
-MacHeaderType::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::MacHeaderType")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<MacHeaderType>();
-    return tid;
-}
-
-TypeId
-MacHeaderType::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-MacHeaderType::Print(std::ostream& os) const
-{
-    os << " header type = " << (uint32_t)m_type;
-}
-
-uint32_t
-MacHeaderType::GetSerializedSize() const
-{
-    return 0;
-}
-
-void
-MacHeaderType::Serialize(Buffer::Iterator start) const
-{
-}
-
-uint32_t
-MacHeaderType::Deserialize(Buffer::Iterator start)
-{
-    return 0;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(GenericMacHeader);
-
-GenericMacHeader::GenericMacHeader()
-    : m_ht(0),
-      m_ec(0),
-      m_type(0),
-      m_ci(0),
-      m_eks(0),
-      m_len(0),
-      m_cid(Cid())
-{
-    m_esf = 0;
-    m_hcs = 0;
-    m_rsv1 = 0;
-    c_hcs = 0;
-}
-
-GenericMacHeader::~GenericMacHeader()
-{
-}
-
-void
-GenericMacHeader::SetHt(uint8_t ht)
-{
-    m_ht = ht;
-}
-
-void
-GenericMacHeader::SetEc(uint8_t ec)
-{
-    m_ec = ec;
-}
-
-void
-GenericMacHeader::SetType(uint8_t type)
-{
-    m_type = type;
-}
-
-void
-GenericMacHeader::SetCi(uint8_t ci)
-{
-    m_ci = ci;
-}
-
-void
-GenericMacHeader::SetEks(uint8_t eks)
-{
-    m_eks = eks;
-}
-
-void
-GenericMacHeader::SetLen(uint16_t len)
-{
-    m_len = len;
-}
-
-void
-GenericMacHeader::SetCid(Cid cid)
-{
-    m_cid = cid;
-}
-
-void
-GenericMacHeader::SetHcs(uint8_t hcs)
-{
-    m_hcs = hcs;
-}
-
-uint8_t
-GenericMacHeader::GetHt() const
-{
-    return m_ht;
-}
-
-uint8_t
-GenericMacHeader::GetEc() const
-{
-    return m_ec;
-}
-
-uint8_t
-GenericMacHeader::GetType() const
-{
-    return m_type;
-}
-
-uint8_t
-GenericMacHeader::GetCi() const
-{
-    return m_ci;
-}
-
-uint8_t
-GenericMacHeader::GetEks() const
-{
-    return m_eks;
-}
-
-uint16_t
-GenericMacHeader::GetLen() const
-{
-    return m_len;
-}
-
-Cid
-GenericMacHeader::GetCid() const
-{
-    return m_cid;
-}
-
-uint8_t
-GenericMacHeader::GetHcs() const
-{
-    return m_hcs;
-}
-
-std::string
-GenericMacHeader::GetName() const
-{
-    return "Generic Mac Header";
-}
-
-TypeId
-GenericMacHeader::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::GenericMacHeader")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<GenericMacHeader>();
-    return tid;
-}
-
-TypeId
-GenericMacHeader::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-GenericMacHeader::Print(std::ostream& os) const
-{
-    os << " ec (encryption control) = " << (uint32_t)m_ec << ", type = " << (uint32_t)m_type
-       << ", ci (crc indicator) = " << (uint32_t)m_ci
-       << ", eks (encryption key sequence) = " << (uint32_t)m_eks << ", len (length) = " << m_len
-       << ", cid = " << m_cid << ", hcs (header check sequence) = " << (uint32_t)m_hcs;
-}
-
-uint32_t
-GenericMacHeader::GetSerializedSize() const
-{
-    return 6;
-}
-
-void
-GenericMacHeader::Serialize(Buffer::Iterator start) const
-{
-    /*
-     * AI:Serialize function according to the
-     * IEEE 8002.16e.
-     * Please send bug and comments to
-     * amine.ismail@udcast.com
-     * amine.ismail@sophia.inria.fr
-     */
-
-    Buffer::Iterator i = start;
-
-    uint8_t headerBuffer[6];
-    memset(headerBuffer, 0, 6);
-
-    headerBuffer[0] = ((m_ht << 7) & 0x80) | ((m_ec << 6) & 0x40) | (m_type & 0x3F);
-    headerBuffer[1] = ((m_esf << 7) & 0x80) | ((m_ci << 6) & 0x40) | ((m_eks << 4) & 0x30) |
-                      ((m_rsv1 << 3) & 0x08) | (((uint8_t)(m_len >> 8)) & 0x07);
-    headerBuffer[2] = (uint8_t)(m_len);
-    headerBuffer[3] = (uint8_t)(m_cid.GetIdentifier() >> 8);
-    headerBuffer[4] = (uint8_t)(m_cid.GetIdentifier());
-    uint8_t crc = CRC8Calculate(headerBuffer, 5);
-    headerBuffer[5] = crc;
-    for (int j = 0; j < 6; j++)
-    {
-        i.WriteU8(headerBuffer[j]);
-    }
-}
-
-uint32_t
-GenericMacHeader::Deserialize(Buffer::Iterator start)
-{
-    /*
-     * AI:Deserialize function according to the
-     * IEEE 8002.16e.
-     * Please send bug and comments to
-     * amine.ismail@udcast.com
-     * amine.ismail@sophia.inria.fr
-     */
-
-    Buffer::Iterator i = start;
-
-    uint8_t headerBuffer[6];
-    for (int j = 0; j < 6; j++)
-    {
-        headerBuffer[j] = i.ReadU8();
-    }
-    m_ht = (headerBuffer[0] >> 7) & 0x01;
-    m_ec = (headerBuffer[0] >> 6) & 0x01;
-    m_type = (headerBuffer[0]) & 0x3F;
-    m_esf = (headerBuffer[1] >> 7) & 0x01;
-    m_ci = (headerBuffer[1] >> 6) & 0x01;
-    m_eks = (headerBuffer[1] >> 4) & 0x03;
-    m_rsv1 = (headerBuffer[1] >> 3) & 0x01;
-    uint16_t lenmsb = (headerBuffer[1] & 0x07);
-    uint16_t lenlsb = headerBuffer[2];
-    m_len = ((lenmsb << 8) & 0x0700) | (lenlsb & 0x00FF);
-    uint16_t cidmsb = headerBuffer[3];
-    uint16_t cidlsb = headerBuffer[4];
-    uint16_t cid = ((cidmsb << 8) & 0xFF00) | (cidlsb & 0x00FF);
-    m_cid = Cid(cid);
-    m_hcs = headerBuffer[5];
-    c_hcs = CRC8Calculate(headerBuffer, 5);
-    return i.GetDistanceFrom(start);
-}
-
-bool
-GenericMacHeader::check_hcs() const
-{
-    return m_hcs == c_hcs;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(BandwidthRequestHeader);
-
-BandwidthRequestHeader::BandwidthRequestHeader()
-    : m_ht(1),
-      m_ec(0),
-      m_type(0),
-      m_br(0),
-      m_cid(Cid()),
-      m_hcs(0)
-{
-}
-
-BandwidthRequestHeader::~BandwidthRequestHeader()
-{
-}
-
-void
-BandwidthRequestHeader::SetHt(uint8_t ht)
-{
-    m_ht = ht;
-}
-
-void
-BandwidthRequestHeader::SetEc(uint8_t ec)
-{
-    m_ec = ec;
-}
-
-void
-BandwidthRequestHeader::SetType(uint8_t type)
-{
-    m_type = type;
-}
-
-void
-BandwidthRequestHeader::SetBr(uint32_t br)
-{
-    m_br = br;
-}
-
-void
-BandwidthRequestHeader::SetCid(Cid cid)
-{
-    m_cid = cid;
-}
-
-void
-BandwidthRequestHeader::SetHcs(uint8_t hcs)
-{
-    m_hcs = hcs;
-}
-
-uint8_t
-BandwidthRequestHeader::GetHt() const
-{
-    return m_ht;
-}
-
-uint8_t
-BandwidthRequestHeader::GetEc() const
-{
-    return m_ec;
-}
-
-uint8_t
-BandwidthRequestHeader::GetType() const
-{
-    return m_type;
-}
-
-uint32_t
-BandwidthRequestHeader::GetBr() const
-{
-    return m_br;
-}
-
-Cid
-BandwidthRequestHeader::GetCid() const
-{
-    return m_cid;
-}
-
-uint8_t
-BandwidthRequestHeader::GetHcs() const
-{
-    return m_hcs;
-}
-
-std::string
-BandwidthRequestHeader::GetName() const
-{
-    return "Bandwidth Request Header";
-}
-
-TypeId
-BandwidthRequestHeader::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::BandwidthRequestHeader")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<BandwidthRequestHeader>();
-    return tid;
-}
-
-TypeId
-BandwidthRequestHeader::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-BandwidthRequestHeader::Print(std::ostream& os) const
-{
-    os << " ec (encryption control) = " << (uint32_t)m_ec << ", type = " << (uint32_t)m_type
-       << ", br (bandwidth request) = " << m_br << ", cid = ";
-    m_cid.GetIdentifier();
-    os << ", hcs (header check sequence) = " << (uint32_t)m_hcs;
-}
-
-uint32_t
-BandwidthRequestHeader::GetSerializedSize() const
-{
-    /*
-     * The size of the BandwidthRequest mac header is always 6 bytes
-     */
-    return 6;
-}
-
-void
-BandwidthRequestHeader::Serialize(Buffer::Iterator start) const
-{
-    /*
-     * AI:Serialize function according to the
-     * IEEE 8002.16e.
-     * please send bug and comments to
-     * amine.ismail@udcast.com
-     * amine.ismail@sophia.inria.fr
-     */
-
-    Buffer::Iterator i = start;
-    uint8_t headerBuffer[6];
-    uint8_t br_msb1 = (((uint32_t)m_br) >> 16) & 0x00000007;
-    uint8_t br_msb2 = (((uint32_t)m_br) >> 8) & 0x000000FF;
-    uint8_t br_lsb = m_br & 0x000000FF;
-    headerBuffer[0] =
-        ((m_ht << 7) & 0x80) | ((m_ec << 6) & 0x40) | ((m_type << 3) & 0x38) | br_msb1;
-    headerBuffer[1] = br_msb2;
-    headerBuffer[2] = br_lsb;
-    headerBuffer[3] = (uint8_t)((m_cid.GetIdentifier() >> 8) & 0x00FF);
-    headerBuffer[4] = (uint8_t)(m_cid.GetIdentifier() & 0x00FF);
-    headerBuffer[5] = CRC8Calculate(headerBuffer, 5);
-
-    for (int j = 0; j < 6; j++)
-    {
-        i.WriteU8(headerBuffer[j]);
-    }
-}
-
-uint32_t
-BandwidthRequestHeader::Deserialize(Buffer::Iterator start)
-{
-    /*
-     * AI:Deserialize function according to the
-     * IEEE 8002.16e.
-     * Please send bug and comments to
-     * amine.ismail@udcast.com
-     * amine.ismail@sophia.inria.fr
-     */
-
-    Buffer::Iterator i = start;
-
-    uint8_t headerBuffer[6];
-    for (int j = 0; j < 6; j++)
-    {
-        headerBuffer[j] = i.ReadU8();
-    }
-
-    m_ht = (headerBuffer[0] >> 7) & 0x01;
-    m_ec = (headerBuffer[0] >> 6) & 0x01;
-    m_type = (headerBuffer[0] >> 3) & 0x07;
-    uint32_t br_msb1 = headerBuffer[0] & 0x00000007;
-    uint32_t br_msb2 = headerBuffer[1] & 0x000000FF;
-    uint32_t br_lsb = headerBuffer[2] & 0x000000FF;
-    m_br = ((uint32_t)br_msb1 << 14) | ((uint32_t)br_msb2 << 8) | br_lsb;
-    uint16_t cidmsb = headerBuffer[3];
-    uint16_t cidlsb = headerBuffer[4];
-    uint16_t cid = ((cidmsb << 8) & 0xFF00) | (cidlsb & 0x00FF);
-    m_cid = Cid(cid);
-    m_hcs = headerBuffer[5];
-    c_hcs = CRC8Calculate(headerBuffer, 5);
-
-    return i.GetDistanceFrom(start);
-}
-
-bool
-BandwidthRequestHeader::check_hcs() const
-{
-    return m_hcs == c_hcs;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(GrantManagementSubheader);
-
-GrantManagementSubheader::GrantManagementSubheader()
-    : m_si(0),
-      m_pm(0),
-      m_pbr(0)
-{
-}
-
-GrantManagementSubheader::~GrantManagementSubheader()
-{
-}
-
-void
-GrantManagementSubheader::SetSi(uint8_t si)
-{
-    m_si = si;
-}
-
-void
-GrantManagementSubheader::SetPm(uint8_t pm)
-{
-    m_pm = pm;
-}
-
-void
-GrantManagementSubheader::SetPbr(uint16_t pbr)
-{
-    m_pbr = pbr;
-}
-
-uint8_t
-GrantManagementSubheader::GetSi() const
-{
-    return m_si;
-}
-
-uint8_t
-GrantManagementSubheader::GetPm() const
-{
-    return m_pm;
-}
-
-uint16_t
-GrantManagementSubheader::GetPbr() const
-{
-    return m_pbr;
-}
-
-std::string
-GrantManagementSubheader::GetName() const
-{
-    return "Grant Management Subheader";
-}
-
-TypeId
-GrantManagementSubheader::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::GrantManagementSubheader")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<GrantManagementSubheader>();
-    return tid;
-}
-
-TypeId
-GrantManagementSubheader::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-GrantManagementSubheader::Print(std::ostream& os) const
-{
-    os << " si (slip indicator) = " << (uint32_t)m_si << ", pm (poll me) = " << (uint32_t)m_pm
-       << ", pbr (piggyback request) = " << m_pbr;
-}
-
-uint32_t
-GrantManagementSubheader::GetSerializedSize() const
-{
-    return 1 + 1 + 2;
-}
-
-void
-GrantManagementSubheader::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_si);
-    i.WriteU8(m_pm);
-    i.WriteU16(m_pbr);
-}
-
-uint32_t
-GrantManagementSubheader::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_si = i.ReadU8();
-    m_pm = i.ReadU8();
-    m_pbr = i.ReadU16();
-
-    return i.GetDistanceFrom(start);
-}
-
-// ----------------------------------------------------------------------------------------------------------
-
-NS_OBJECT_ENSURE_REGISTERED(FragmentationSubheader);
-
-FragmentationSubheader::FragmentationSubheader()
-    : m_fc(0),
-      m_fsn(0)
-{
-}
-
-FragmentationSubheader::~FragmentationSubheader()
-{
-}
-
-void
-FragmentationSubheader::SetFc(uint8_t fc)
-{
-    m_fc = fc;
-}
-
-void
-FragmentationSubheader::SetFsn(uint8_t fsn)
-{
-    m_fsn = fsn;
-}
-
-uint8_t
-FragmentationSubheader::GetFc() const
-{
-    return m_fc;
-}
-
-uint8_t
-FragmentationSubheader::GetFsn() const
-{
-    return m_fsn;
-}
-
-std::string
-FragmentationSubheader::GetName() const
-{
-    return "Fragmentation Subheader";
-}
-
-TypeId
-FragmentationSubheader::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::FragmentationSubheader")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<FragmentationSubheader>();
-    return tid;
-}
-
-TypeId
-FragmentationSubheader::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-FragmentationSubheader::Print(std::ostream& os) const
-{
-    os << " fc (fragment control) = " << (uint32_t)m_fc
-       << ", fsn (fragmentation sequence number) = " << (uint32_t)m_fsn << "\n";
-}
-
-uint32_t
-FragmentationSubheader::GetSerializedSize() const
-{
-    return 2;
-}
-
-void
-FragmentationSubheader::Serialize(Buffer::Iterator start) const
-{
-    Buffer::Iterator i = start;
-    i.WriteU8(m_fc);
-    i.WriteU8(m_fsn);
-}
-
-uint32_t
-FragmentationSubheader::Deserialize(Buffer::Iterator start)
-{
-    Buffer::Iterator i = start;
-    m_fc = i.ReadU8();
-    m_fsn = i.ReadU8();
-
-    return i.GetDistanceFrom(start);
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-mac-header.h ns-3.46/src/wimax/model/wimax-mac-header.h
--- ns-3.45/src/wimax/model/wimax-mac-header.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-mac-header.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,510 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef MAC_HEADER_TYPE_H
-#define MAC_HEADER_TYPE_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class Represents the HT (Header Type) field of generic MAC and bandwidth request headers
- * @see GenericMacHeader
- * @see BandwidthRequestHeader
- */
-class MacHeaderType : public Header
-{
-  public:
-    /// Header type enumeration
-    enum HeaderType
-    {
-        HEADER_TYPE_GENERIC,
-        HEADER_TYPE_BANDWIDTH
-    };
-
-    /**
-     * Constructor
-     */
-    MacHeaderType();
-    /**
-     * Constructor
-     *
-     * @param type MAC header type
-     */
-    MacHeaderType(uint8_t type);
-    ~MacHeaderType() override;
-    /**
-     * Set type field
-     * @param type the type
-     */
-    void SetType(uint8_t type);
-    /**
-     * Get type field
-     * @returns the type
-     */
-    uint8_t GetType() const;
-
-    /**
-     * Get name field
-     * @returns the name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_type; ///< MAC header type
-};
-
-} // namespace ns3
-
-#endif /* MAC_HEADER_TYPE_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef GENERIC_MAC_HEADER_H
-#define GENERIC_MAC_HEADER_H
-
-#include "cid.h"
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the Generic mac Header as described by IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems 6.3.2.1.1 Generic MAC header, page 36
- */
-class GenericMacHeader : public Header
-{
-  public:
-    GenericMacHeader();
-    ~GenericMacHeader() override;
-
-    /**
-     * Set EC field
-     * @param ec the EC
-     */
-    void SetEc(uint8_t ec);
-    /**
-     * Set type field
-     * @param type the type
-     */
-    void SetType(uint8_t type);
-    /**
-     * Set CI field
-     * @param ci the CI
-     */
-    void SetCi(uint8_t ci);
-    /**
-     * Set EKS field
-     * @param eks the EKS
-     */
-    void SetEks(uint8_t eks);
-    /**
-     * Set length field
-     * @param len the length
-     */
-    void SetLen(uint16_t len);
-    /**
-     * Set CID field
-     * @param cid the CID
-     */
-    void SetCid(Cid cid);
-    /**
-     * Set HCS field
-     * @param hcs the HCS
-     */
-    void SetHcs(uint8_t hcs);
-    /**
-     * Set HT field
-     * @param ht the HT
-     */
-    void SetHt(uint8_t ht);
-
-    /**
-     * Get EC field
-     * @returns the EC
-     */
-    uint8_t GetEc() const;
-    /**
-     * Get type field
-     * @returns the type
-     */
-    uint8_t GetType() const;
-    /**
-     * Get CI field
-     * @returns the CI
-     */
-    uint8_t GetCi() const;
-    /**
-     * Get EKS field
-     * @returns the EKS
-     */
-    uint8_t GetEks() const;
-    /**
-     * Get length field
-     * @returns the length
-     */
-    uint16_t GetLen() const;
-    /**
-     * Get CID field
-     * @returns the CID
-     */
-    Cid GetCid() const;
-    /**
-     * Get HCS field
-     * @returns the HCS
-     */
-    uint8_t GetHcs() const;
-    /**
-     * Get HT field
-     * @returns the HT
-     */
-    uint8_t GetHt() const;
-    /**
-     * Get name field
-     * @returns the name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-    /**
-     * Check HCS
-     * @returns true if HCS is validated
-     */
-    bool check_hcs() const;
-
-  private:
-    uint8_t m_ht;   ///< Header type
-    uint8_t m_ec;   ///< Encryption Control
-    uint8_t m_type; ///< type
-    uint8_t m_esf;  ///< ESF
-    uint8_t m_ci;   ///< CRC Indicator
-    uint8_t m_eks;  ///< Encryption Key Sequence
-    uint8_t m_rsv1; ///< RSV
-    uint16_t m_len; ///< length
-    Cid m_cid;      ///< CID
-    uint8_t m_hcs;  ///< Header Check Sequence
-    uint8_t c_hcs;  ///< calculated header check sequence; this is used to check if the received
-                    ///< header is correct or not
-};
-
-} // namespace ns3
-
-#endif /* GENERIC_MAC_HEADER */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef BANDWIDTH_REQUEST_HEADER_H
-#define BANDWIDTH_REQUEST_HEADER_H
-
-#include "cid.h"
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-/**
- * @ingroup wimax
- * This class implements the bandwidth-request mac Header as described by IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems 6.3.2.1.2 Bandwidth request header, page 38
- */
-class BandwidthRequestHeader : public Header
-{
-  public:
-    /// Header type enumeration
-    enum HeaderType
-    {
-        HEADER_TYPE_INCREMENTAL,
-        HEADER_TYPE_AGGREGATE
-    };
-
-    BandwidthRequestHeader();
-    ~BandwidthRequestHeader() override;
-
-    /**
-     * Set HT field
-     * @param ht the HT
-     */
-    void SetHt(uint8_t ht);
-    /**
-     * Set EC field
-     * @param ec the EC
-     */
-    void SetEc(uint8_t ec);
-    /**
-     * Set type field
-     * @param type the type
-     */
-    void SetType(uint8_t type);
-    /**
-     * Set BR field
-     * @param br the BR
-     */
-    void SetBr(uint32_t br);
-    /**
-     * Set CID field
-     * @param cid the CID
-     */
-    void SetCid(Cid cid);
-    /**
-     * Set HCS field
-     * @param hcs the HCS
-     */
-    void SetHcs(uint8_t hcs);
-
-    /**
-     * Get HT field
-     * @returns the HT
-     */
-    uint8_t GetHt() const;
-    /**
-     * Get EC field
-     * @returns the EC
-     */
-    uint8_t GetEc() const;
-    /**
-     * Get type field
-     * @returns the type
-     */
-    uint8_t GetType() const;
-    /**
-     * Get BR field
-     * @returns the BR
-     */
-    uint32_t GetBr() const;
-    /**
-     * Get CID field
-     * @returns the CID
-     */
-    Cid GetCid() const;
-    /**
-     * Get HCS field
-     * @returns the HCS
-     */
-    uint8_t GetHcs() const;
-
-    /**
-     * Get name field
-     * @returns the name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-    /**
-     * Check HCS
-     * @returns true if HCS is validated
-     */
-    bool check_hcs() const;
-
-  private:
-    uint8_t m_ht;   ///< Header type
-    uint8_t m_ec;   ///< Encryption Control
-    uint8_t m_type; ///< type
-    uint32_t m_br;  ///< Bandwidth Request
-    Cid m_cid;      ///< Connection identifier
-    uint8_t m_hcs;  ///< Header Check Sequence
-    uint8_t c_hcs;  ///< calculated header check sequence; this is used to check if the received
-                    ///< header is correct or not
-};
-
-} // namespace ns3
-
-#endif /* BANDWIDTH_REQUEST_HEADER_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef GRANT_MANAGEMENT_SUBHEADER_H
-#define GRANT_MANAGEMENT_SUBHEADER_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * This class implements the grant management sub-header as described by IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems 6.3.2.2.2 Grant Management subheader, page 40
- */
-class GrantManagementSubheader : public Header
-{
-  public:
-    GrantManagementSubheader();
-    ~GrantManagementSubheader() override;
-
-    /**
-     * Set SI field
-     * @param si the SI
-     */
-    void SetSi(uint8_t si);
-    /**
-     * Set PM field
-     * @param pm the PM
-     */
-    void SetPm(uint8_t pm);
-    /**
-     * Set PRR field
-     * @param pbr the PBR
-     */
-    void SetPbr(uint16_t pbr);
-
-    /**
-     * Get SI field
-     * @returns the SI
-     */
-    uint8_t GetSi() const;
-    /**
-     * Get PM field
-     * @returns the PM
-     */
-    uint8_t GetPm() const;
-    /**
-     * Get PBR field
-     * @returns the PBR
-     */
-    uint16_t GetPbr() const;
-
-    /**
-     * Get name field
-     * @returns the name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    // size of the Grant Management Subheader shall actually be 2 bytes
-
-    uint8_t m_si;   ///< Slip Indicator
-    uint8_t m_pm;   ///< Poll-Me bit (byte in this case)
-    uint16_t m_pbr; ///< PiggyBack Request
-};
-
-} // namespace ns3
-
-#endif /* GRANT_MANAGEMENT_SUBHEADER_H */
-
-// ----------------------------------------------------------------------------------------------------------
-
-#ifndef FRAGMENTATION_SUBHEADER_H
-#define FRAGMENTATION_SUBHEADER_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-/**
- * @ingroup wimax
- * This class implements the fragmentation sub-header as described by IEEE Standard for
- * Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband Wireless Access
- * Systems 6.3.2.2.1 Fragmentation subheader, page 39
- */
-class FragmentationSubheader : public Header
-{
-  public:
-    FragmentationSubheader();
-    ~FragmentationSubheader() override;
-
-    /**
-     * Set FC field
-     * @param fc the FC
-     */
-    void SetFc(uint8_t fc);
-    /**
-     * Set FSN field
-     * @param fsn the FSN
-     */
-    void SetFsn(uint8_t fsn);
-
-    /**
-     * Get FC field
-     * @returns the FC
-     */
-    uint8_t GetFc() const;
-    /**
-     * Get FSN field
-     * @returns the FSN
-     */
-    uint8_t GetFsn() const;
-
-    /**
-     * Get name field
-     * @returns the name
-     */
-    std::string GetName() const;
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-
-  private:
-    uint8_t m_fc;  ///< Fragment Control
-    uint8_t m_fsn; ///< Fragment Sequence Number
-};
-} // namespace ns3
-
-#endif /* FRAGMENTATION_SUBHEADER_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-mac-queue.cc ns-3.46/src/wimax/model/wimax-mac-queue.cc
--- ns-3.45/src/wimax/model/wimax-mac-queue.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-mac-queue.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,642 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *         Mohamed Amine Ismail <Amine.Ismail@sophia.inria.fr>
- *                              <Amine.Ismail@UDcast.com>
- */
-
-#include "wimax-mac-queue.h"
-
-#include "ns3/log.h"
-#include "ns3/packet.h"
-#include "ns3/simulator.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("WimaxMacQueue");
-
-NS_OBJECT_ENSURE_REGISTERED(WimaxMacQueue);
-
-WimaxMacQueue::QueueElement::QueueElement()
-    : m_packet(Create<Packet>()),
-      m_hdrType(MacHeaderType()),
-      m_hdr(GenericMacHeader()),
-      m_timeStamp(),
-      m_fragmentation(false),
-      m_fragmentNumber(0),
-      m_fragmentOffset(0)
-{
-}
-
-WimaxMacQueue::QueueElement::QueueElement(Ptr<Packet> packet,
-                                          const MacHeaderType& hdrType,
-                                          const GenericMacHeader& hdr,
-                                          Time timeStamp)
-    : m_packet(packet),
-      m_hdrType(hdrType),
-      m_hdr(hdr),
-      m_timeStamp(timeStamp),
-      m_fragmentation(false),
-      m_fragmentNumber(0),
-      m_fragmentOffset(0)
-{
-}
-
-uint32_t
-WimaxMacQueue::QueueElement::GetSize() const
-{
-    uint32_t size = m_packet->GetSize() + m_hdrType.GetSerializedSize();
-
-    /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
-     Header has already been added to the packet) in which case Generic MAC Header will not be added
-     to it. this will only happen in the case of SS as only SS sends the bandwidth request packet.
-   */
-    if (m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        size += m_hdr.GetSerializedSize();
-    }
-
-    return size;
-}
-
-TypeId
-WimaxMacQueue::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::WimaxMacQueue")
-                            .SetParent<Object>()
-                            .SetGroupName("Wimax")
-                            .AddAttribute("MaxSize",
-                                          "Maximum size",
-                                          UintegerValue(1024),
-                                          MakeUintegerAccessor(&WimaxMacQueue::GetMaxSize,
-                                                               &WimaxMacQueue::SetMaxSize),
-                                          MakeUintegerChecker<uint32_t>())
-                            .AddTraceSource("Enqueue",
-                                            "Enqueue trace",
-                                            MakeTraceSourceAccessor(&WimaxMacQueue::m_traceEnqueue),
-                                            "ns3::Packet::TracedCallback")
-                            .AddTraceSource("Dequeue",
-                                            "Dequeue trace",
-                                            MakeTraceSourceAccessor(&WimaxMacQueue::m_traceDequeue),
-                                            "ns3::Packet::TracedCallback")
-                            .AddTraceSource("Drop",
-                                            "Drop trace",
-                                            MakeTraceSourceAccessor(&WimaxMacQueue::m_traceDrop),
-                                            "ns3::Packet::TracedCallback");
-    return tid;
-}
-
-WimaxMacQueue::WimaxMacQueue()
-    : m_maxSize(0),
-      m_bytes(0),
-      m_nrDataPackets(0),
-      m_nrRequestPackets(0)
-{
-}
-
-WimaxMacQueue::WimaxMacQueue(uint32_t maxSize)
-    : m_maxSize(maxSize),
-      m_bytes(0),
-      m_nrDataPackets(0),
-      m_nrRequestPackets(0)
-{
-}
-
-WimaxMacQueue::~WimaxMacQueue()
-{
-}
-
-void
-WimaxMacQueue::SetMaxSize(uint32_t maxSize)
-{
-    m_maxSize = maxSize;
-}
-
-uint32_t
-WimaxMacQueue::GetMaxSize() const
-{
-    return m_maxSize;
-}
-
-bool
-WimaxMacQueue::Enqueue(Ptr<Packet> packet,
-                       const MacHeaderType& hdrType,
-                       const GenericMacHeader& hdr)
-{
-    if (m_queue.size() == m_maxSize)
-    {
-        m_traceDrop(packet);
-        return false;
-    }
-
-    m_traceEnqueue(packet);
-    QueueElement element(packet, hdrType, hdr, Simulator::Now());
-    m_queue.push_back(element);
-
-    if (hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        m_nrDataPackets++;
-    }
-    else
-    {
-        m_nrRequestPackets++;
-    }
-
-    m_bytes += element.GetSize();
-    return true;
-}
-
-Ptr<Packet>
-WimaxMacQueue::Dequeue(MacHeaderType::HeaderType packetType)
-{
-    if (!IsEmpty())
-    {
-        QueueElement element = Front(packetType);
-        Pop(packetType);
-
-        if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-        {
-            NS_LOG_INFO("Enqueued Packet IS A data packet");
-            NS_ASSERT_MSG(m_nrDataPackets >= 1,
-                          "Can not enqueue more packets: no space left in the queue");
-            m_nrDataPackets--;
-        }
-        else
-        {
-            NS_LOG_INFO("Enqueued Packet IS A Request BW packet");
-            NS_ASSERT_MSG(m_nrRequestPackets >= 1,
-                          "Can not enqueue more packets: no space left in the queue");
-            m_nrRequestPackets--;
-        }
-
-        Ptr<Packet> packet = element.m_packet;
-
-        if (!element.m_fragmentation)
-        {
-            NS_LOG_INFO("FRAG_DEBUG: Enqueued Packet IS NOT a fragment" << std::endl);
-            /*check because may be it is a bandwidth request packet (in which case a Bandwidth
-              Request Header has already been added to the packet) in which case Generic MAC Header
-              will not be added to it. this will only happen in the case of SS as only SS sends the
-              bandwidth request packet. */
-            m_bytes -= element.GetSize();
-            if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-            {
-                packet->AddHeader(element.m_hdr);
-            }
-            packet->AddHeader(element.m_hdrType);
-
-            m_traceDequeue(packet);
-            return packet;
-        }
-        else
-        {
-            /*
-             The enqueued packet is a fragment (the latest fragment)
-             We must modify type field of the m_hdr and add a fragmentation Subhdr
-             */
-            NS_LOG_INFO("\t Enqueued Packet IS a fragment, add subhdr" << std::endl);
-
-            // Create a fragment
-            uint32_t fragmentOffset = element.m_fragmentOffset;
-            uint32_t fragmentSize = element.m_packet->GetSize() - fragmentOffset;
-
-            NS_LOG_INFO("\t Create a fragment"
-                        "\n\t\t fragmentOffset="
-                        << fragmentOffset << "\n\t\t packetSize=" << element.m_packet->GetSize()
-                        << "\n\t\t fragmentSize=" << fragmentSize << std::endl);
-
-            Ptr<Packet> fragment = packet->CreateFragment(fragmentOffset, fragmentSize);
-
-            FragmentationSubheader fragmentSubhdr;
-            NS_LOG_INFO("\t Latest Fragment" << std::endl);
-            fragmentSubhdr.SetFc(2); // This is the latest fragment
-            fragmentSubhdr.SetFsn(element.m_fragmentNumber);
-
-            NS_LOG_INFO("\t FragmentSize=" << fragment->GetSize() << std::endl);
-            fragment->AddHeader(fragmentSubhdr);
-
-            /*check because may be it is a bandwidth request packet (in which case a Bandwidth
-            Request Header has already been added to the packet) in which case Generic MAC Header
-            will not be added to it. this will only happen in the case of SS as only SS sends the
-            bandwidth request packet. */
-            if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-            {
-                uint8_t tmpType = element.m_hdr.GetType();
-                tmpType |= 4;
-                element.m_hdr.SetType(tmpType);
-
-                uint32_t length = fragmentSize + element.m_hdr.GetSerializedSize() +
-                                  fragmentSubhdr.GetSerializedSize();
-                element.m_hdr.SetLen((uint16_t)length);
-
-                fragment->AddHeader(element.m_hdr);
-            }
-            fragment->AddHeader(element.m_hdrType);
-            m_bytes -= fragmentSize;
-
-            m_traceDequeue(fragment);
-            return fragment;
-        }
-    }
-    return nullptr;
-}
-
-Ptr<Packet>
-WimaxMacQueue::Dequeue(MacHeaderType::HeaderType packetType, uint32_t availableByte)
-{
-    if (!IsEmpty())
-    {
-        NS_LOG_INFO("FRAG_DEBUG: Dequeue function" << std::endl);
-        QueueElement element = Front(packetType);
-
-        uint32_t headerSize =
-            2 + element.m_hdr.GetSerializedSize() + element.m_hdrType.GetSerializedSize();
-
-        // Create a fragment
-        uint32_t maxFragmentSize = availableByte - headerSize;
-        uint32_t fragmentOffset = element.m_fragmentOffset; // It is the latest byte sent.
-
-        Ptr<Packet> packet = element.m_packet->Copy();
-        NS_LOG_INFO("\t Create a fragment"
-                    "\n\t\t availableByte="
-                    << availableByte << "\n\t\t headerSize=" << headerSize
-                    << "\n\t\t maxFragmentSize=" << maxFragmentSize
-                    << ""
-                       "\n\t\t fragmentOffset="
-                    << fragmentOffset << "\n\t\t payloadSize=" << packet->GetSize() << std::endl);
-        Ptr<Packet> fragment = packet->CreateFragment(fragmentOffset, maxFragmentSize);
-        m_bytes -= maxFragmentSize;
-
-        FragmentationSubheader fragmentSubhdr;
-        if (!element.m_fragmentation)
-        {
-            NS_LOG_INFO("\t First Fragment" << std::endl);
-            SetFragmentation(packetType);
-            fragmentSubhdr.SetFc(1);
-        }
-        else
-        {
-            NS_LOG_INFO("\t Middle Fragment" << std::endl);
-            fragmentSubhdr.SetFc(3);
-        }
-        fragmentSubhdr.SetFsn(element.m_fragmentNumber);
-        NS_LOG_INFO("\t FragmentSize=" << fragment->GetSize() << std::endl);
-        fragment->AddHeader(fragmentSubhdr);
-
-        SetFragmentNumber(packetType);
-        SetFragmentOffset(packetType, maxFragmentSize);
-
-        /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
-          Header has already been added to the packet) in which case Generic MAC Header will not be
-          added to it. this will only happen in the case of SS as only SS sends the bandwidth
-          request packet. */
-        if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-        {
-            uint8_t tmpType = element.m_hdr.GetType();
-            tmpType |= 4;
-            element.m_hdr.SetType(tmpType);
-
-            uint32_t length = maxFragmentSize + element.m_hdr.GetSerializedSize() +
-                              fragmentSubhdr.GetSerializedSize();
-            element.m_hdr.SetLen((uint16_t)length);
-
-            fragment->AddHeader(element.m_hdr);
-        }
-        fragment->AddHeader(element.m_hdrType);
-
-        m_traceDequeue(fragment);
-        return fragment;
-    }
-    return nullptr;
-}
-
-Ptr<Packet>
-WimaxMacQueue::Peek(GenericMacHeader& hdr) const
-{
-    if (!IsEmpty())
-    {
-        QueueElement element = m_queue.front();
-        hdr = element.m_hdr;
-        Ptr<Packet> packet = element.m_packet->Copy();
-
-        // this function must not be used by SS as it may be then a bandwidth request header
-        packet->AddHeader(element.m_hdr);
-        return packet;
-    }
-
-    return nullptr;
-}
-
-Ptr<Packet>
-WimaxMacQueue::Peek(GenericMacHeader& hdr, Time& timeStamp) const
-{
-    if (!IsEmpty())
-    {
-        QueueElement element = m_queue.front();
-        hdr = element.m_hdr;
-        timeStamp = element.m_timeStamp;
-        Ptr<Packet> packet = element.m_packet->Copy();
-
-        // this function must not be used for by SS as it may be then a bandwidth request header
-        packet->AddHeader(element.m_hdr);
-        return packet;
-    }
-
-    return nullptr;
-}
-
-Ptr<Packet>
-WimaxMacQueue::Peek(MacHeaderType::HeaderType packetType) const
-{
-    if (!IsEmpty())
-    {
-        QueueElement element = Front(packetType);
-        Ptr<Packet> packet = element.m_packet->Copy();
-
-        /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
-         Header has already been added to the packet) in which case Generic MAC Header will not be
-         added to it. this will only happen in the case of SS as only SS sends the bandwidth request
-         packet. */
-        if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-        {
-            packet->AddHeader(element.m_hdr);
-        }
-        return packet;
-    }
-
-    return nullptr;
-}
-
-Ptr<Packet>
-WimaxMacQueue::Peek(MacHeaderType::HeaderType packetType, Time& timeStamp) const
-{
-    if (!IsEmpty())
-    {
-        QueueElement element = Front(packetType);
-        timeStamp = element.m_timeStamp;
-        Ptr<Packet> packet = element.m_packet->Copy();
-
-        /*check because may be it is a bandwidth request packet (in which case a Bandwidth Request
-         Header has already been added to the packet) in which case Generic MAC Header will not be
-         added to it. this will only happen in the case of SS as only SS sends the bandwidth request
-         packet. */
-        if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-        {
-            packet->AddHeader(element.m_hdr);
-        }
-        return packet;
-    }
-
-    return nullptr;
-}
-
-uint32_t
-WimaxMacQueue::GetSize() const
-{
-    return m_queue.size();
-}
-
-uint32_t
-WimaxMacQueue::GetNBytes() const
-{
-    return m_bytes;
-}
-
-uint32_t
-WimaxMacQueue::GetQueueLengthWithMACOverhead()
-{
-    uint32_t queueSize = GetNBytes();
-    // Add MAC Overhead
-    queueSize += GetSize() * 6;
-    MacHeaderType::HeaderType packetType = MacHeaderType::HEADER_TYPE_GENERIC;
-    if (CheckForFragmentation(packetType))
-    {
-        queueSize += 2;
-    }
-    return queueSize;
-}
-
-WimaxMacQueue::QueueElement
-WimaxMacQueue::Front(MacHeaderType::HeaderType packetType) const
-{
-    QueueElement element;
-
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        element = *iter;
-        if (element.m_hdrType.GetType() == packetType)
-        {
-            break;
-        }
-    }
-
-    return element;
-}
-
-void
-WimaxMacQueue::Pop(MacHeaderType::HeaderType packetType)
-{
-    QueueElement element;
-
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        element = *iter;
-        if (element.m_hdrType.GetType() == packetType)
-        {
-            m_queue.erase(iter);
-            break;
-        }
-    }
-}
-
-bool
-WimaxMacQueue::IsEmpty() const
-{
-    return m_queue.empty();
-}
-
-bool
-WimaxMacQueue::IsEmpty(MacHeaderType::HeaderType packetType) const
-{
-    if (packetType == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        return m_nrDataPackets == 0;
-    }
-    else
-    {
-        return m_nrRequestPackets == 0;
-    }
-
-    return true;
-}
-
-const WimaxMacQueue::PacketQueue&
-WimaxMacQueue::GetPacketQueue() const
-{
-    return m_queue;
-}
-
-bool
-WimaxMacQueue::CheckForFragmentation(MacHeaderType::HeaderType packetType)
-{
-    QueueElement element;
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        element = *iter;
-        if (element.m_hdrType.GetType() == packetType)
-        {
-            break;
-        }
-    }
-
-    if (element.m_fragmentation)
-    {
-        NS_LOG_INFO("FRAG_DEBUG: CheckForFragmentation"
-                    "\n\t\t m_fragmentation is true "
-                    << std::endl);
-    }
-
-    return element.m_fragmentation;
-}
-
-uint32_t
-WimaxMacQueue::GetFirstPacketHdrSize(MacHeaderType::HeaderType packetType)
-{
-    QueueElement element;
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        element = *iter;
-        if (element.m_hdrType.GetType() == packetType)
-        {
-            break;
-        }
-    }
-
-    NS_LOG_INFO("\t\t GetFirstPacketHdrSize ()");
-
-    uint32_t hdrSize = 0;
-    if (element.m_hdrType.GetType() == MacHeaderType::HEADER_TYPE_GENERIC)
-    {
-        hdrSize += element.m_hdr.GetSerializedSize();
-        NS_LOG_INFO("\t\t\t m_hdr.GetSerializedSize=" << element.m_hdr.GetSerializedSize());
-    }
-
-    hdrSize += element.m_hdrType.GetSerializedSize();
-    NS_LOG_INFO("\t\t\t m_hdrType.GetSerializedSize=" << element.m_hdrType.GetSerializedSize());
-
-    if (CheckForFragmentation(packetType))
-    {
-        NS_LOG_INFO("\t\t\t fragSubhdrSize=2");
-        hdrSize += 2;
-    }
-
-    NS_LOG_INFO("\t\t hdrSize=" << hdrSize);
-
-    return hdrSize;
-}
-
-uint32_t
-WimaxMacQueue::GetFirstPacketPayloadSize(MacHeaderType::HeaderType packetType)
-{
-    QueueElement element;
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        element = *iter;
-        if (element.m_hdrType.GetType() == packetType)
-        {
-            break;
-        }
-    }
-
-    NS_LOG_INFO("\t\t GetFirstPacketPayloadSize ()");
-
-    if (CheckForFragmentation(packetType))
-    {
-        NS_LOG_INFO("\t\t\t fullPayloadSize="
-                    << element.m_packet->GetSize() << "\n\t\t\t fragmentOffset="
-                    << element.m_fragmentOffset << "\n\t\t\t (fragment)payloadSize="
-                    << element.m_packet->GetSize() - element.m_fragmentOffset);
-
-        return element.m_packet->GetSize() - element.m_fragmentOffset;
-    }
-    NS_LOG_INFO("\t\t payloadSize=" << element.m_packet->GetSize());
-
-    return element.m_packet->GetSize();
-}
-
-uint32_t
-WimaxMacQueue::GetFirstPacketRequiredByte(MacHeaderType::HeaderType packetType)
-{
-    NS_LOG_INFO("\t GetFirstPacketRequiredByte ()");
-
-    uint32_t requiredByte =
-        GetFirstPacketPayloadSize(packetType) + GetFirstPacketHdrSize(packetType);
-
-    NS_LOG_INFO("\t Required Bytes = " << requiredByte << std::endl);
-
-    return requiredByte;
-}
-
-void
-WimaxMacQueue::SetFragmentation(MacHeaderType::HeaderType packetType)
-{
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        if (iter->m_hdrType.GetType() == packetType)
-        {
-            iter->SetFragmentation();
-            break;
-        }
-    }
-}
-
-void
-WimaxMacQueue::SetFragmentNumber(MacHeaderType::HeaderType packetType)
-{
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        if (iter->m_hdrType.GetType() == packetType)
-        {
-            iter->SetFragmentNumber();
-            break;
-        }
-    }
-}
-
-void
-WimaxMacQueue::SetFragmentOffset(MacHeaderType::HeaderType packetType, uint32_t offset)
-{
-    for (auto iter = m_queue.begin(); iter != m_queue.end(); ++iter)
-    {
-        if (iter->m_hdrType.GetType() == packetType)
-        {
-            iter->SetFragmentOffset(offset);
-            break;
-        }
-    }
-}
-
-void
-WimaxMacQueue::QueueElement::SetFragmentation()
-{
-    m_fragmentation = true;
-}
-
-void
-WimaxMacQueue::QueueElement::SetFragmentNumber()
-{
-    m_fragmentNumber++;
-}
-
-void
-WimaxMacQueue::QueueElement::SetFragmentOffset(uint32_t offset)
-{
-    m_fragmentOffset += offset;
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-mac-queue.h ns-3.46/src/wimax/model/wimax-mac-queue.h
--- ns-3.45/src/wimax/model/wimax-mac-queue.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-mac-queue.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,267 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef WIMAX_MAC_QUEUE_H
-#define WIMAX_MAC_QUEUE_H
-
-#include "wimax-mac-header.h"
-
-#include "ns3/nstime.h"
-#include "ns3/object.h"
-#include "ns3/packet.h"
-#include "ns3/traced-callback.h"
-
-#include <queue>
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * Class implementing the device packet queue
- */
-class WimaxMacQueue : public Object
-{
-  public:
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    WimaxMacQueue();
-    /**
-     * Constructor
-     *
-     * @param maxSize maximum size of queue
-     */
-    WimaxMacQueue(uint32_t maxSize);
-    ~WimaxMacQueue() override;
-    /**
-     * @brief set the maximum queue size
-     * @param maxSize the max queue size
-     */
-    void SetMaxSize(uint32_t maxSize);
-    /**
-     * @return the maximum queue size
-     */
-    uint32_t GetMaxSize() const;
-    /**
-     * @brief Enqueue a packet
-     * @param packet the packet to enqueue
-     * @param hdrType the mac header type of the packet
-     * @param hdr the header of the packet
-     * @return true if successful
-     */
-    bool Enqueue(Ptr<Packet> packet, const MacHeaderType& hdrType, const GenericMacHeader& hdr);
-    /**
-     * @brief Dequeue a packet of type packetType from the queue
-     * @param packetType the type of the packet
-     * @return the first packet in the queue
-     */
-    Ptr<Packet> Dequeue(MacHeaderType::HeaderType packetType);
-    /**
-     * @brief Dequeue a fragment of size availableByte from the queue
-     * @param packetType the type of the packet
-     * @param availableByte the size of the fragment
-     * @return the first packet in the queue if its size is lower than availableByte, the first
-     * availableByte of the first packet otherwise
-     */
-    Ptr<Packet> Dequeue(MacHeaderType::HeaderType packetType, uint32_t availableByte);
-
-    /**
-     * @brief Exclusively for BS.
-     *  Two versions of Peek function (with Generic MAC Header as parameter) only
-     *  for BS, as BS's scheduler needs to know the CID in Generic MAC Header.
-     * @param hdr the header of the packet
-     * @return the first packet in the queue
-     */
-    Ptr<Packet> Peek(GenericMacHeader& hdr) const;
-    /**
-     * @brief Exclusively for BS.
-     *  Two versions of Peek function (with Generic MAC Header as parameter) only
-     *  for BS, as BS's scheduler needs to know the CID in Generic MAC Header.
-     * @param hdr the header of the packet
-     * @param timeStamp the timestamp of the packet
-     * @return the first packet in the queue
-     */
-    Ptr<Packet> Peek(GenericMacHeader& hdr, Time& timeStamp) const;
-
-    /**
-     * @brief Two versions for SS without Generic MAC Header parameter, as SS's
-     *  scheduler does not require to know the CID in Generic MAC Header.
-     * @param packetType the type of the packet
-     * @return the first packet in the queue
-     */
-    Ptr<Packet> Peek(MacHeaderType::HeaderType packetType) const;
-    /**
-     * @brief Two versions for SS without Generic MAC Header parameter, as SS's
-     *  scheduler does not require to know the CID in Generic MAC Header.
-     * @param packetType the type of the packet
-     * @param timeStamp the timestamp of the packet
-     * @return the first packet in the queue
-     */
-    Ptr<Packet> Peek(MacHeaderType::HeaderType packetType, Time& timeStamp) const;
-
-    /**
-     * Check if queue is empty
-     * @returns true if empty
-     */
-    bool IsEmpty() const;
-
-    /**
-     * Exclusively for SS.
-     * @return true if queue is empty of type packetType
-     * @param packetType packet type to check
-     */
-    bool IsEmpty(MacHeaderType::HeaderType packetType) const;
-
-    /**
-     * Get size of queue
-     * @returns the size
-     */
-    uint32_t GetSize() const;
-    /**
-     * Get number of bytes in queue
-     * @returns the number of bytes
-     */
-    uint32_t GetNBytes() const;
-
-    /**
-     * Check for fragmentation of the first packet of the specified type
-     * @param packetType the packet type
-     * @returns true if fragmented
-     */
-    bool CheckForFragmentation(MacHeaderType::HeaderType packetType);
-    /**
-     * Get first packet header size of the specified type
-     * @param packetType the packet type
-     * @returns the first packet header size
-     */
-    uint32_t GetFirstPacketHdrSize(MacHeaderType::HeaderType packetType);
-    /**
-     * Get first packet payload size of the specified type
-     * @param packetType the packet type
-     * @returns the first packet payload size
-     */
-    uint32_t GetFirstPacketPayloadSize(MacHeaderType::HeaderType packetType);
-    /**
-     * Get required number of bytes to hold first packet of packetType
-     * @param packetType the packet type
-     * @returns the sum of the first packet header and payload (of specified type)
-     */
-    uint32_t GetFirstPacketRequiredByte(MacHeaderType::HeaderType packetType);
-    /**
-     * Get queue length considering also the MAC overhead
-     * @return queue length
-     */
-    uint32_t GetQueueLengthWithMACOverhead();
-    /// Set fragmentation function
-    /**
-     * Set fragmentation state for first packet of type packetType
-     * @param packetType packetType to check
-     */
-    void SetFragmentation(MacHeaderType::HeaderType packetType);
-    /**
-     * Set fragment number for first packet of type packetType
-     * @param packetType packetType to check
-     */
-    void SetFragmentNumber(MacHeaderType::HeaderType packetType);
-    /**
-     * Set fragment offset for first packet of type packetType
-     * @param packetType packetType to check
-     * @param offset offset value to set
-     */
-    void SetFragmentOffset(MacHeaderType::HeaderType packetType, uint32_t offset);
-
-    /// QueueElement structure
-    struct QueueElement
-    {
-        QueueElement();
-        /**
-         * Constructor
-         *
-         * @param packet the packet
-         * @param hdrType MAC header type
-         * @param hdr MAC header
-         * @param timeStamp time stamp
-         */
-        QueueElement(Ptr<Packet> packet,
-                     const MacHeaderType& hdrType,
-                     const GenericMacHeader& hdr,
-                     Time timeStamp);
-        /**
-         * Get size function
-         * @returns the size
-         */
-        uint32_t GetSize() const;
-        Ptr<Packet> m_packet;    ///< packet
-        MacHeaderType m_hdrType; ///< header type
-        GenericMacHeader m_hdr;  ///< header
-        Time m_timeStamp;        ///< timestamp
-
-        /**
-         To manage fragmentation feature, each QueueElement have 3 new fields:
-         m_fragmentation that becomes true when the fragmentation starts;
-         m_fragmentNumber that is incremented when a new fragment is sent
-         m_fragmentOffset that tracks the start of the next fragment into the packet
-         */
-        bool m_fragmentation;      ///< becomes true when the fragmentation starts
-        uint32_t m_fragmentNumber; ///< incremented when a new fragment is sent
-        uint32_t m_fragmentOffset; ///< tracks the start of the next fragment into the packet
-
-        /// Set fragmentation
-        void SetFragmentation();
-        /// Set fragment number
-        void SetFragmentNumber();
-        /**
-         * Set fragment offset
-         * @param offset the offset
-         */
-        void SetFragmentOffset(uint32_t offset);
-    };
-
-  private:
-    /**
-     In the case of non-UGS service flows at the SS side the queue will store both data packets
-     and bandwidth request packets. The two are distinguished by their headers. The below two
-     functions are for this purpose exclusively. The Front function returns the first packet of a
-     specific packet type from the queue (which may not necessarily be at the front of the queue),
-     and the Pop function pops that elements.
-     * @param packetType the type of the packet
-     * @returns the first packet in the queue of the specified type
-     */
-    WimaxMacQueue::QueueElement Front(MacHeaderType::HeaderType packetType) const;
-    /**
-     * Pop function
-     * @param packetType the packet type
-     */
-    void Pop(MacHeaderType::HeaderType packetType);
-
-    /// PacketQueue typedef
-    typedef std::deque<QueueElement> PacketQueue;
-    PacketQueue m_queue;         ///< the queue
-    uint32_t m_maxSize;          ///< maximum size
-    uint32_t m_bytes;            ///< bytes
-    uint32_t m_nrDataPackets;    ///< number data packets
-    uint32_t m_nrRequestPackets; ///< number request packets
-
-    TracedCallback<Ptr<const Packet>> m_traceEnqueue; ///< enqueue trace callback
-    TracedCallback<Ptr<const Packet>> m_traceDequeue; ///< dequeue trace callback
-    TracedCallback<Ptr<const Packet>> m_traceDrop;    ///< drop trace callback
-  public:
-    /**
-     * Get packet queue function
-     * @returns the packet queue
-     */
-    const WimaxMacQueue::PacketQueue& GetPacketQueue() const;
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_MAC_QUEUE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-mac-to-mac-header.cc ns-3.46/src/wimax/model/wimax-mac-to-mac-header.cc
--- ns-3.45/src/wimax/model/wimax-mac-to-mac-header.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-mac-to-mac-header.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,136 +0,0 @@
-/*
- *  Copyright (c) 2010 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-#include "wimax-mac-to-mac-header.h"
-
-#include "ns3/address-utils.h"
-#include "ns3/log.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_OBJECT_ENSURE_REGISTERED(WimaxMacToMacHeader);
-
-WimaxMacToMacHeader::WimaxMacToMacHeader()
-    : m_len(0)
-{
-}
-
-WimaxMacToMacHeader::WimaxMacToMacHeader(uint32_t len)
-    : m_len(len)
-{
-}
-
-WimaxMacToMacHeader::~WimaxMacToMacHeader()
-{
-}
-
-TypeId
-WimaxMacToMacHeader::GetTypeId()
-{
-    static TypeId tid = TypeId("ns3::WimaxMacToMacHeader")
-                            .SetParent<Header>()
-                            .SetGroupName("Wimax")
-                            .AddConstructor<WimaxMacToMacHeader>();
-    return tid;
-}
-
-TypeId
-WimaxMacToMacHeader::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-uint8_t
-WimaxMacToMacHeader::GetSizeOfLen() const
-{
-    uint8_t sizeOfLen = 1;
-
-    if (m_len > 127)
-    {
-        sizeOfLen = 2;
-        uint64_t testValue = 0xFF;
-        while (m_len > testValue)
-        {
-            sizeOfLen++;
-            testValue *= 0xFF;
-        }
-    }
-    return sizeOfLen;
-}
-
-uint32_t
-WimaxMacToMacHeader::GetSerializedSize() const
-{
-    uint8_t sizeOfLen = GetSizeOfLen();
-    if (sizeOfLen == 1)
-    {
-        return 20;
-    }
-    else
-    {
-        return 20 + sizeOfLen - 1;
-    }
-    // return 19+sizeOfLen;
-}
-
-void
-WimaxMacToMacHeader::Serialize(Buffer::Iterator i) const
-{
-    // The following header encoding was reverse-engineered by looking
-    // at existing live pcap traces which could be opened with wireshark
-    // i.e., we have no idea where this is coming from.
-    //
-    // 6 zeros for mac destination
-    // 6 zeros for mac source
-    // 2 bytes for length/type: 0x08f0
-    // 2 bytes for sequence number: 0x0001
-    // 2 bytes for number of tlvs: 0x0001
-    // 1 byte for type of first tlv: 0x09
-    // 1 byte to indicate the length of the length field of the tlv : 0x80 | 0x04
-    // n bytes to indicate the size of the packet (network order)
-    // n bytes for the packet data
-
-    uint8_t zero = 0;
-
-    for (int j = 0; j < 12; j++)
-    {
-        i.WriteU8(zero);
-    }
-    i.WriteU16(0xf008); // eth length/type
-    i.WriteU16(0x0100); // sequence number
-    i.WriteU16(0x0100); // number of tlvs
-    i.WriteU8(0x09);    // type of first tlv
-    uint8_t lenSize = GetSizeOfLen();
-    if (lenSize == 1)
-    {
-        i.WriteU8(m_len);
-    }
-    else
-    {
-        i.WriteU8((lenSize - 1) | 0x80);
-        for (int j = 0; j < lenSize - 1; j++)
-        {
-            i.WriteU8((uint8_t)(m_len >> ((lenSize - 1 - 1 - j) * 8)));
-        }
-    }
-}
-
-uint32_t
-WimaxMacToMacHeader::Deserialize(Buffer::Iterator start)
-{
-    // not needed here
-    return 20;
-}
-
-void
-WimaxMacToMacHeader::Print(std::ostream& os) const
-{
-}
-}; // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-mac-to-mac-header.h ns-3.46/src/wimax/model/wimax-mac-to-mac-header.h
--- ns-3.45/src/wimax/model/wimax-mac-to-mac-header.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-mac-to-mac-header.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,57 +0,0 @@
-/*
- *  Copyright (c) 2010 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-#ifndef WIMAX_MAC_TO_MAC_HEADER_H
-#define WIMAX_MAC_TO_MAC_HEADER_H
-
-#include "ns3/header.h"
-
-#include <stdint.h>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * @brief this class implements the mac to mac header needed to dump a wimax pcap file
- * The header format was reverse-engineered by looking  at existing live pcap traces which
- * could be opened with wireshark  i.e., we have no idea where this is coming from.
- */
-class WimaxMacToMacHeader : public Header
-{
-  public:
-    WimaxMacToMacHeader();
-    ~WimaxMacToMacHeader() override;
-    /**
-     * Constructor
-     *
-     * @param len length
-     */
-    WimaxMacToMacHeader(uint32_t len);
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-    /**
-     * Get size of length field
-     * @returns the size of length field
-     */
-    uint8_t GetSizeOfLen() const;
-    void Print(std::ostream& os) const override;
-
-  private:
-    uint32_t m_len; ///< length
-};
-}; // namespace ns3
-#endif
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-net-device.cc ns-3.46/src/wimax/model/wimax-net-device.cc
--- ns-3.45/src/wimax/model/wimax-net-device.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-net-device.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,638 +0,0 @@
-/*
- * Copyright (c) 2007,2008,2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                               <amine.ismail@UDcast.com>
- */
-
-#include "wimax-net-device.h"
-
-#include "bandwidth-manager.h"
-#include "burst-profile-manager.h"
-#include "connection-manager.h"
-#include "send-params.h"
-#include "service-flow-manager.h"
-#include "wimax-channel.h"
-
-#include "ns3/callback.h"
-#include "ns3/enum.h"
-#include "ns3/llc-snap-header.h"
-#include "ns3/node.h"
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-
-#include <list>
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("WimaxNetDevice");
-
-NS_OBJECT_ENSURE_REGISTERED(WimaxNetDevice);
-
-uint32_t WimaxNetDevice::m_nrFrames = 0;
-uint8_t WimaxNetDevice::m_direction = ~0;
-Time WimaxNetDevice::m_frameStartTime = Seconds(0);
-
-TypeId
-WimaxNetDevice::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::WimaxNetDevice")
-
-            .SetParent<NetDevice>()
-            .SetGroupName("Wimax")
-
-            // No AddConstructor because this is an abstract class.
-
-            .AddAttribute("Mtu",
-                          "The MAC-level Maximum Transmission Unit",
-                          UintegerValue(DEFAULT_MSDU_SIZE),
-                          MakeUintegerAccessor(&WimaxNetDevice::SetMtu, &WimaxNetDevice::GetMtu),
-                          MakeUintegerChecker<uint16_t>(0, MAX_MSDU_SIZE))
-
-            .AddAttribute("Phy",
-                          "The PHY layer attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxNetDevice::GetPhy, &WimaxNetDevice::SetPhy),
-                          MakePointerChecker<WimaxPhy>())
-
-            .AddAttribute(
-                "Channel",
-                "The channel attached to this device.",
-                PointerValue(),
-                MakePointerAccessor(&WimaxNetDevice::GetPhyChannel, &WimaxNetDevice::SetChannel),
-                MakePointerChecker<WimaxChannel>())
-
-            .AddAttribute("RTG",
-                          "receive/transmit transition gap.",
-                          UintegerValue(0),
-                          MakeUintegerAccessor(&WimaxNetDevice::GetRtg, &WimaxNetDevice::SetRtg),
-                          MakeUintegerChecker<uint16_t>(0, 120))
-
-            .AddAttribute("TTG",
-                          "transmit/receive transition gap.",
-                          UintegerValue(0),
-                          MakeUintegerAccessor(&WimaxNetDevice::GetTtg, &WimaxNetDevice::SetTtg),
-                          MakeUintegerChecker<uint16_t>(0, 120))
-
-            .AddAttribute("ConnectionManager",
-                          "The connection manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxNetDevice::GetConnectionManager,
-                                              &WimaxNetDevice::SetConnectionManager),
-                          MakePointerChecker<ConnectionManager>())
-
-            .AddAttribute("BurstProfileManager",
-                          "The burst profile manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxNetDevice::GetBurstProfileManager,
-                                              &WimaxNetDevice::SetBurstProfileManager),
-                          MakePointerChecker<BurstProfileManager>())
-
-            .AddAttribute("BandwidthManager",
-                          "The bandwidth manager attached to this device.",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxNetDevice::GetBandwidthManager,
-                                              &WimaxNetDevice::SetBandwidthManager),
-                          MakePointerChecker<BandwidthManager>())
-
-            .AddAttribute("InitialRangingConnection",
-                          "Initial ranging connection",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxNetDevice::m_initialRangingConnection),
-                          MakePointerChecker<WimaxConnection>())
-
-            .AddAttribute("BroadcastConnection",
-                          "Broadcast connection",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxNetDevice::m_broadcastConnection),
-                          MakePointerChecker<WimaxConnection>())
-
-            .AddTraceSource("Rx",
-                            "Receive trace",
-                            MakeTraceSourceAccessor(&WimaxNetDevice::m_traceRx),
-                            "ns3::WimaxNetDevice::TxRxTracedCallback")
-
-            .AddTraceSource("Tx",
-                            "Transmit trace",
-                            MakeTraceSourceAccessor(&WimaxNetDevice::m_traceTx),
-                            "ns3::WimaxNetDevice::TxRxTracedCallback");
-    return tid;
-}
-
-WimaxNetDevice::WimaxNetDevice()
-    : m_state(0),
-      m_symbolIndex(0),
-      m_ttg(0),
-      m_rtg(0)
-{
-    InitializeChannels();
-    m_connectionManager = CreateObject<ConnectionManager>();
-    m_burstProfileManager = CreateObject<BurstProfileManager>(this);
-    m_bandwidthManager = CreateObject<BandwidthManager>(this);
-    m_nrFrames = 0;
-    m_direction = ~0;
-    m_frameStartTime = Seconds(0);
-}
-
-WimaxNetDevice::~WimaxNetDevice()
-{
-}
-
-void
-WimaxNetDevice::DoDispose()
-{
-    m_phy->Dispose();
-    m_phy = nullptr;
-    m_node = nullptr;
-    m_initialRangingConnection = nullptr;
-    m_broadcastConnection = nullptr;
-    m_connectionManager = nullptr;
-    m_burstProfileManager = nullptr;
-    m_bandwidthManager = nullptr;
-
-    NetDevice::DoDispose();
-}
-
-void
-WimaxNetDevice::SetTtg(uint16_t ttg)
-{
-    m_ttg = ttg;
-}
-
-uint16_t
-WimaxNetDevice::GetTtg() const
-{
-    return m_ttg;
-}
-
-void
-WimaxNetDevice::SetRtg(uint16_t rtg)
-{
-    m_rtg = rtg;
-}
-
-uint16_t
-WimaxNetDevice::GetRtg() const
-{
-    return m_rtg;
-}
-
-void
-WimaxNetDevice::SetName(const std::string name)
-{
-    m_name = name;
-}
-
-std::string
-WimaxNetDevice::GetName() const
-{
-    return m_name;
-}
-
-void
-WimaxNetDevice::SetIfIndex(const uint32_t index)
-{
-    m_ifIndex = index;
-}
-
-uint32_t
-WimaxNetDevice::GetIfIndex() const
-{
-    return m_ifIndex;
-}
-
-Ptr<Channel>
-WimaxNetDevice::GetChannel() const
-{
-    return DoGetChannel();
-}
-
-Ptr<Channel>
-WimaxNetDevice::GetPhyChannel() const
-{
-    return DoGetChannel();
-}
-
-bool
-WimaxNetDevice::SetMtu(const uint16_t mtu)
-{
-    if (mtu > MAX_MSDU_SIZE)
-    {
-        return false;
-    }
-    m_mtu = mtu;
-    return true;
-}
-
-uint16_t
-WimaxNetDevice::GetMtu() const
-{
-    return m_mtu;
-}
-
-bool
-WimaxNetDevice::IsLinkUp() const
-{
-    return m_phy && m_linkUp;
-}
-
-void
-WimaxNetDevice::SetLinkChangeCallback(Callback<void> callback)
-{
-    m_linkChange = callback;
-}
-
-bool
-WimaxNetDevice::IsBroadcast() const
-{
-    return true;
-}
-
-Address
-WimaxNetDevice::GetBroadcast() const
-{
-    return Mac48Address::GetBroadcast();
-}
-
-bool
-WimaxNetDevice::IsMulticast() const
-{
-    return false;
-}
-
-Address
-WimaxNetDevice::GetMulticast() const
-{
-    return Mac48Address("01:00:5e:00:00:00");
-}
-
-Address
-WimaxNetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
-{
-    return GetMulticast();
-}
-
-bool
-WimaxNetDevice::IsPointToPoint() const
-{
-    return false;
-}
-
-bool
-WimaxNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
-{
-    Mac48Address to = Mac48Address::ConvertFrom(dest);
-    LlcSnapHeader llcHdr;
-    llcHdr.SetType(protocolNumber);
-    packet->AddHeader(llcHdr);
-
-    m_traceTx(packet, to);
-
-    return DoSend(packet, Mac48Address::ConvertFrom(GetAddress()), to, protocolNumber);
-}
-
-void
-WimaxNetDevice::SetNode(Ptr<Node> node)
-{
-    m_node = node;
-}
-
-Ptr<Node>
-WimaxNetDevice::GetNode() const
-{
-    return m_node;
-}
-
-bool
-WimaxNetDevice::NeedsArp() const
-{
-    return false;
-    /*
-     * Modified by Mohamed Amine ISMAIL.
-     * see "Transmission of IPv4 packets over IEEE 802.16's IP Convergence
-     *      Sublayer draft-ietf-16ng-ipv4-over-802-dot-16-ipcs-04.txt" section
-     * 5.2
-     */
-}
-
-void
-WimaxNetDevice::SetReceiveCallback(ReceiveCallback cb)
-{
-    m_forwardUp = cb;
-}
-
-void
-WimaxNetDevice::ForwardUp(Ptr<Packet> packet, const Mac48Address& source, const Mac48Address& dest)
-{
-    m_traceRx(packet, source);
-    LlcSnapHeader llc;
-    packet->RemoveHeader(llc);
-    m_forwardUp(this, packet, llc.GetType(), source);
-}
-
-void
-WimaxNetDevice::Attach(Ptr<WimaxChannel> channel)
-{
-    m_phy->Attach(channel);
-}
-
-void
-WimaxNetDevice::SetPhy(Ptr<WimaxPhy> phy)
-{
-    m_phy = phy;
-}
-
-Ptr<WimaxPhy>
-WimaxNetDevice::GetPhy() const
-{
-    return m_phy;
-}
-
-void
-WimaxNetDevice::SetChannel(Ptr<WimaxChannel> channel)
-{
-    if (m_phy)
-    {
-        m_phy->Attach(channel);
-    }
-}
-
-uint64_t
-WimaxNetDevice::GetChannel(uint8_t index) const
-{
-    return m_dlChannels.at(index);
-}
-
-void
-WimaxNetDevice::SetNrFrames(uint32_t nrFrames)
-{
-    m_nrFrames = nrFrames;
-}
-
-uint32_t
-WimaxNetDevice::GetNrFrames() const
-{
-    return m_nrFrames;
-}
-
-void
-WimaxNetDevice::SetAddress(Address address)
-{
-    m_address = Mac48Address::ConvertFrom(address);
-}
-
-void
-WimaxNetDevice::SetMacAddress(Mac48Address address)
-{
-    m_address = address;
-}
-
-Address
-WimaxNetDevice::GetAddress() const
-{
-    return m_address;
-}
-
-Mac48Address
-WimaxNetDevice::GetMacAddress() const
-{
-    return m_address;
-}
-
-void
-WimaxNetDevice::SetState(uint8_t state)
-{
-    m_state = state;
-}
-
-uint8_t
-WimaxNetDevice::GetState() const
-{
-    return m_state;
-}
-
-Ptr<WimaxConnection>
-WimaxNetDevice::GetInitialRangingConnection() const
-{
-    return m_initialRangingConnection;
-}
-
-Ptr<WimaxConnection>
-WimaxNetDevice::GetBroadcastConnection() const
-{
-    return m_broadcastConnection;
-}
-
-void
-WimaxNetDevice::SetCurrentDcd(Dcd dcd)
-{
-    m_currentDcd = dcd;
-}
-
-Dcd
-WimaxNetDevice::GetCurrentDcd() const
-{
-    return m_currentDcd;
-}
-
-void
-WimaxNetDevice::SetCurrentUcd(Ucd ucd)
-{
-    m_currentUcd = ucd;
-}
-
-Ucd
-WimaxNetDevice::GetCurrentUcd() const
-{
-    return m_currentUcd;
-}
-
-Ptr<ConnectionManager>
-WimaxNetDevice::GetConnectionManager() const
-{
-    return m_connectionManager;
-}
-
-void
-WimaxNetDevice::SetConnectionManager(Ptr<ConnectionManager> cm)
-{
-    m_connectionManager = cm;
-}
-
-Ptr<BurstProfileManager>
-WimaxNetDevice::GetBurstProfileManager() const
-{
-    return m_burstProfileManager;
-}
-
-void
-WimaxNetDevice::SetBurstProfileManager(Ptr<BurstProfileManager> bpm)
-{
-    m_burstProfileManager = bpm;
-}
-
-Ptr<BandwidthManager>
-WimaxNetDevice::GetBandwidthManager() const
-{
-    return m_bandwidthManager;
-}
-
-void
-WimaxNetDevice::SetBandwidthManager(Ptr<BandwidthManager> bwm)
-{
-    m_bandwidthManager = bwm;
-}
-
-void
-WimaxNetDevice::CreateDefaultConnections()
-{
-    m_initialRangingConnection =
-        CreateObject<WimaxConnection>(Cid::InitialRanging(), Cid::INITIAL_RANGING);
-    m_broadcastConnection = CreateObject<WimaxConnection>(Cid::Broadcast(), Cid::BROADCAST);
-}
-
-void
-WimaxNetDevice::Receive(Ptr<const PacketBurst> burst)
-{
-    NS_LOG_DEBUG("WimaxNetDevice::Receive, station = " << GetMacAddress());
-
-    Ptr<PacketBurst> b = burst->Copy();
-    for (auto iter = b->Begin(); iter != b->End(); ++iter)
-    {
-        Ptr<Packet> packet = *iter;
-        DoReceive(packet);
-    }
-}
-
-Ptr<WimaxChannel>
-WimaxNetDevice::DoGetChannel() const
-{
-    return m_phy->GetChannel();
-}
-
-void
-WimaxNetDevice::SetReceiveCallback()
-{
-    m_phy->SetReceiveCallback(MakeCallback(&WimaxNetDevice::Receive, this));
-}
-
-bool
-WimaxNetDevice::SendFrom(Ptr<Packet> packet,
-                         const Address& source,
-                         const Address& dest,
-                         uint16_t protocolNumber)
-{
-    Mac48Address from = Mac48Address::ConvertFrom(source);
-    Mac48Address to = Mac48Address::ConvertFrom(dest);
-
-    LlcSnapHeader llcHdr;
-    llcHdr.SetType(protocolNumber);
-    packet->AddHeader(llcHdr);
-
-    m_traceTx(packet, to);
-    return DoSend(packet, from, to, protocolNumber);
-}
-
-void
-WimaxNetDevice::SetPromiscReceiveCallback(PromiscReceiveCallback cb)
-{
-    m_promiscRx = cb;
-}
-
-bool
-WimaxNetDevice::IsPromisc()
-{
-    return !(m_promiscRx.IsNull());
-}
-
-void
-WimaxNetDevice::NotifyPromiscTrace(Ptr<Packet> p)
-{
-    // m_promiscRx(p);
-}
-
-bool
-WimaxNetDevice::SupportsSendFrom() const
-{
-    return false;
-}
-
-void
-WimaxNetDevice::ForwardDown(Ptr<PacketBurst> burst, WimaxPhy::ModulationType modulationType)
-{
-    SendParams* params = new OfdmSendParams(burst, modulationType, m_direction);
-    m_phy->Send(params);
-    delete params;
-}
-
-void
-WimaxNetDevice::InitializeChannels()
-{
-    // initializing vector of channels (or frequencies)
-    // Values according to WirelessMAN-OFDM RF profile for 10 MHz channelization
-    // Section 12.3.3.1 from IEEE 802.16-2004 standard
-    // profR10_3 :
-    // channels: 5000 + n ⋅ 5 MHz, ∀n ∈ { 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167 }
-    // from a range 5GHz to 6GHz, according to Section 8.5.1.
-    uint64_t frequency = 5000;
-
-    for (uint8_t i = 0; i < 200; i++)
-    {
-        m_dlChannels.push_back(frequency);
-        frequency += 5;
-    }
-}
-
-bool
-WimaxNetDevice::IsBridge() const
-{
-    NS_LOG_FUNCTION_NOARGS();
-    return false;
-}
-
-Address
-WimaxNetDevice::GetMulticast(Ipv4Address multicastGroup) const
-{
-    NS_LOG_FUNCTION(multicastGroup);
-
-    Mac48Address ad = Mac48Address::GetMulticast(multicastGroup);
-
-    //
-    // Implicit conversion (operator Address ()) is defined for Mac48Address, so
-    // use it by just returning the EUI-48 address which is automagically converted
-    // to an Address.
-    //
-    NS_LOG_LOGIC("multicast address is " << ad);
-
-    return ad;
-}
-
-Address
-WimaxNetDevice::GetMulticast(Ipv6Address addr) const
-{
-    Mac48Address ad = Mac48Address::GetMulticast(addr);
-
-    NS_LOG_LOGIC("MAC IPv6 multicast address is " << ad);
-    return ad;
-}
-
-void
-WimaxNetDevice::AddLinkChangeCallback(Callback<void> callback)
-{
-    /* \todo Add a callback invoked whenever the link
-     * status changes to UP. This callback is typically used
-     * by the IP/ARP layer to flush the ARP cache and by IPv6 stack
-     * to flush NDISC cache whenever the link goes up.
-     */
-    NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-}
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-net-device.h ns-3.46/src/wimax/model/wimax-net-device.h
--- ns-3.45/src/wimax/model/wimax-net-device.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-net-device.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,559 +0,0 @@
-/*
- * Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- *          Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- */
-
-#ifndef WIMAX_NET_DEVICE_H
-#define WIMAX_NET_DEVICE_H
-
-#include "cid-factory.h"
-#include "cid.h"
-#include "dl-mac-messages.h"
-#include "mac-messages.h"
-#include "ul-mac-messages.h"
-#include "wimax-connection.h"
-#include "wimax-mac-header.h"
-#include "wimax-phy.h"
-
-#include "ns3/event-id.h"
-#include "ns3/log.h"
-#include "ns3/mac48-address.h"
-#include "ns3/net-device.h"
-#include "ns3/nstime.h"
-#include "ns3/traced-callback.h"
-
-namespace ns3
-{
-
-class Node;
-class Packet;
-class TraceContext;
-class TraceResolver;
-class Channel;
-class WimaxChannel;
-class PacketBurst;
-class BurstProfileManager;
-class ConnectionManager;
-class ServiceFlowManager;
-class BandwidthManager;
-class UplinkScheduler;
-
-/**
- * @defgroup wimax WiMAX Models
- * This section documents the API of the ns-3 wimax module. For a generic functional description,
- * please refer to the ns-3 manual.
- */
-
-/**
- * @brief Hold together all WiMAX-related objects in a NetDevice.
- * @ingroup wimax
- *
- * This class holds together ns3::WimaxPhy, ns3::WimaxConnection,
- * ns3::ConnectionManager, ns3::BurstProfileManager, and
- * ns3::BandwidthManager.
- */
-class WimaxNetDevice : public NetDevice
-{
-  public:
-    /// Direction enumeration
-    enum Direction
-    {
-        DIRECTION_DOWNLINK,
-        DIRECTION_UPLINK
-    };
-
-    /// RangingStatus enumeration
-    enum RangingStatus
-    {
-        RANGING_STATUS_EXPIRED,
-        RANGING_STATUS_CONTINUE,
-        RANGING_STATUS_ABORT,
-        RANGING_STATUS_SUCCESS
-    };
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    WimaxNetDevice();
-    ~WimaxNetDevice() override;
-    /**
-     * Set transmission/receive transition gap
-     * @param ttg transmit/receive transition gap
-     */
-    void SetTtg(uint16_t ttg);
-    /**
-     * Get transmission/receive transition gap
-     * @returns transmit/receive transition gap
-     */
-    uint16_t GetTtg() const;
-    /**
-     * Set receive/transmit transition gap
-     * @param rtg receive/transmit transition gap
-     */
-    void SetRtg(uint16_t rtg);
-    /**
-     * Get receive/transmit transition gap
-     * @returns receive/transmit transition gap
-     */
-    uint16_t GetRtg() const;
-    /**
-     * Attach device to channel
-     * @param channel channel to attach
-     */
-    void Attach(Ptr<WimaxChannel> channel);
-    /**
-     * Set the physical layer object
-     * @param phy the phy layer object to use
-     */
-    void SetPhy(Ptr<WimaxPhy> phy);
-    /**
-     * Get the physical layer object
-     * @returns a pointer to the physical layer object
-     */
-    Ptr<WimaxPhy> GetPhy() const;
-
-    /**
-     * Set the channel object
-     * @param wimaxChannel the channel to be used
-     */
-    void SetChannel(Ptr<WimaxChannel> wimaxChannel);
-
-    /**
-     * Get the channel object by index
-     * @param index the channel index
-     * @returns the channel being used.
-     */
-    uint64_t GetChannel(uint8_t index) const;
-
-    /**
-     * Set the number of frames
-     * @param nrFrames the number of frames
-     */
-    void SetNrFrames(uint32_t nrFrames);
-    /**
-     * Get the number of frames
-     * @returns the number of frames.
-     */
-    uint32_t GetNrFrames() const;
-    /**
-     * Set the MAC address
-     * @param address the mac address of the net device
-     */
-    void SetMacAddress(Mac48Address address);
-    /**
-     * Get the MAC address
-     * @returns the mac address of the net device
-     */
-    Mac48Address GetMacAddress() const;
-    /**
-     * Set the device state
-     * @param state the state
-     */
-    void SetState(uint8_t state);
-    /**
-     * Get the device state
-     * @returns the state
-     */
-    uint8_t GetState() const;
-    /**
-     * Get the initial ranging connection
-     * @returns the initial ranging connection
-     */
-    Ptr<WimaxConnection> GetInitialRangingConnection() const;
-    /**
-     * Get the broadcast connection
-     * @returns the broadcast connection
-     */
-    Ptr<WimaxConnection> GetBroadcastConnection() const;
-
-    /**
-     * Set the current DCD
-     * @param dcd the DCD
-     */
-    void SetCurrentDcd(Dcd dcd);
-    /**
-     * Get the current DCD
-     * @returns the DCD
-     */
-    Dcd GetCurrentDcd() const;
-    /**
-     * Set the current UCD
-     * @param ucd the UCD
-     */
-    void SetCurrentUcd(Ucd ucd);
-    /**
-     * Get the current UCD
-     * @returns the UCD
-     */
-    Ucd GetCurrentUcd() const;
-    /**
-     * Get the connection manager of the device
-     * @returns the connection manager of the device
-     */
-    Ptr<ConnectionManager> GetConnectionManager() const;
-
-    /**
-     * Set the connection manager of the device
-     * @param  connectionManager the connection manager to be installed in the device
-     */
-    virtual void SetConnectionManager(Ptr<ConnectionManager> connectionManager);
-
-    /**
-     * Get the burst profile manager
-     * @returns the burst profile manager currently installed in the device
-     */
-    Ptr<BurstProfileManager> GetBurstProfileManager() const;
-
-    /**
-     * Set the burst profile manager
-     * @param burstProfileManager the burst profile manager to be installed on the device
-     */
-    void SetBurstProfileManager(Ptr<BurstProfileManager> burstProfileManager);
-
-    /**
-     * Get the bandwidth manager on the device
-     * @returns the bandwidth manager installed on the device
-     */
-    Ptr<BandwidthManager> GetBandwidthManager() const;
-
-    /**
-     * Set the bandwidth manager on the device
-     * @param bandwidthManager the bandwidth manager to be installed on the device
-     */
-    void SetBandwidthManager(Ptr<BandwidthManager> bandwidthManager);
-
-    /**
-     * @brief Creates the initial ranging and broadcast connections
-     */
-    void CreateDefaultConnections();
-
-    /// Start function
-    virtual void Start() = 0;
-    /// Stop function
-    virtual void Stop() = 0;
-
-    /// Set receive callback function
-    void SetReceiveCallback();
-
-    /**
-     * Forward a packet to the next layer above the device
-     * @param packet the packet
-     * @param source the source MAC address
-     * @param dest the destination MAC address
-     */
-    void ForwardUp(Ptr<Packet> packet, const Mac48Address& source, const Mac48Address& dest);
-
-    /**
-     * Enqueue a packet
-     * @param packet the packet
-     * @param hdrType the header type
-     * @param connection the wimax connection
-     * @returns true if successful
-     */
-    virtual bool Enqueue(Ptr<Packet> packet,
-                         const MacHeaderType& hdrType,
-                         Ptr<WimaxConnection> connection) = 0;
-    /**
-     * Forward a packet down the stack
-     * @param burst the packet burst
-     * @param modulationType the modulation type
-     */
-    void ForwardDown(Ptr<PacketBurst> burst, WimaxPhy::ModulationType modulationType);
-
-    // temp, shall be private
-    static uint8_t m_direction; ///< downlink or uplink
-
-    static Time m_frameStartTime; ///< temp, to determine the frame start time at SS side, shall
-                                  ///< actually be determined by frame start preamble
-
-    /**
-     * Set device name
-     * @param name the device name
-     */
-    virtual void SetName(const std::string name);
-    /**
-     * Get device name
-     * @returns the device name
-     */
-    virtual std::string GetName() const;
-    /**
-     * Set interface index
-     * @param index the index
-     */
-    void SetIfIndex(const uint32_t index) override;
-    /**
-     * Get interface index
-     * @returns the interface index
-     */
-    uint32_t GetIfIndex() const override;
-    /**
-     * Get the channel (this method is redundant with GetChannel())
-     * @returns the channel used by the phy layer
-     */
-    virtual Ptr<Channel> GetPhyChannel() const;
-    /**
-     * Get the channel
-     * @returns the channel
-     */
-    Ptr<Channel> GetChannel() const override;
-    /**
-     * Set address of the device
-     * @param address the address
-     */
-    void SetAddress(Address address) override;
-    /**
-     * Get address of the device
-     * @returns the address
-     */
-    Address GetAddress() const override;
-    /**
-     * Set MTU value for the device
-     * @param mtu the MTU
-     * @returns true if successful
-     */
-    bool SetMtu(const uint16_t mtu) override;
-    /**
-     * Get MTU of the device
-     * @returns the MTU
-     */
-    uint16_t GetMtu() const override;
-    /**
-     * Check if link is up
-     * @return true if the link is up
-     */
-    bool IsLinkUp() const override;
-    /**
-     * Set link change callback function
-     * @param callback the callback function
-     */
-    virtual void SetLinkChangeCallback(Callback<void> callback);
-    /**
-     * Check if broadcast enabled
-     * @returns true if broadcast
-     */
-    bool IsBroadcast() const override;
-    /**
-     * Get broadcast address
-     * @returns the address
-     */
-    Address GetBroadcast() const override;
-    /**
-     * Check if multicast enabled
-     * @returns true if multicast
-     */
-    bool IsMulticast() const override;
-    /**
-     * Get multicast address
-     * @returns the multicast address
-     */
-    virtual Address GetMulticast() const;
-    /**
-     * Make multicast address
-     * @param multicastGroup the IPv4 address
-     * @returns the multicast address
-     */
-    virtual Address MakeMulticastAddress(Ipv4Address multicastGroup) const;
-    /**
-     * Check if device is a point-to-point device
-     * @returns true if point to point
-     */
-    bool IsPointToPoint() const override;
-    /**
-     * Send function
-     * @param packet the packet
-     * @param dest the destination address
-     * @param protocolNumber the protocol number
-     * @returns true if successful
-     */
-    bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber) override;
-    /**
-     * Set node pointer
-     * @param node the node pointer
-     */
-    void SetNode(Ptr<Node> node) override;
-    /**
-     * Get node pointer
-     * @returns the node pointer
-     */
-    Ptr<Node> GetNode() const override;
-    /**
-     * Check if device needs ARP
-     * @returns true if ARP required
-     */
-    bool NeedsArp() const override;
-    /**
-     * Set receive callback function
-     * @param cb the receive callback function
-     */
-    void SetReceiveCallback(NetDevice::ReceiveCallback cb) override;
-    /**
-     * Add link change callback function
-     * @param callback the link change callback function
-     */
-    void AddLinkChangeCallback(Callback<void> callback) override;
-    /**
-     * Send a packet
-     * @param packet the packet
-     * @param source the source address
-     * @param dest the destination address
-     * @param protocolNumber the protocol number
-     * @returns true if successful
-     */
-    bool SendFrom(Ptr<Packet> packet,
-                  const Address& source,
-                  const Address& dest,
-                  uint16_t protocolNumber) override;
-    /**
-     * Set promiscuous receive callback function
-     * @param cb the promiscuous mode callback
-     */
-    void SetPromiscReceiveCallback(PromiscReceiveCallback cb) override;
-    /**
-     * Get promiscuous receive callback function
-     * @returns the promiscuous mode callback
-     */
-    NetDevice::PromiscReceiveCallback GetPromiscReceiveCallback();
-    /**
-     * Check if device supports the SendFrom method
-     * @returns true if SendFrom is supported
-     */
-    bool SupportsSendFrom() const override;
-
-    /**
-     * TracedCallback signature for packet and Mac48Address.
-     *
-     * @param [in] packet The packet.
-     * @param [in] mac The Mac48Address.
-     * @deprecated The `const Mac48Address &` argument is deprecated
-     * and will be changed to \c Mac48Address in a future release.
-     * The TracedCallback signature will then match \c Packet::Mac48Address
-     * and this typedef can be removed.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    typedef void (*TxRxTracedCallback)(Ptr<const Packet> packet, const Mac48Address& mac);
-    /**
-     * @deprecated The `const Mac48Address &` argument is deprecated
-     * and will be changed to \c Mac48Address in a future release.
-     * The TracedCallback signature will then match \c Packet::Mac48Address
-     * and this typedef can be removed.
-     * @todo This member variable should be private.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<const Packet>, const Mac48Address&> m_traceRx;
-    /**
-     * @deprecated The `const Mac48Address &` argument is deprecated
-     * and will be changed to \c Mac48Address in a future release.
-     * The TracedCallback signature will then match \c Packet::Mac48Address
-     * and this typedef can be removed.
-     * @todo This member variable should be private.
-     */
-    // NS_DEPRECATED() - tag for future removal
-    TracedCallback<Ptr<const Packet>, const Mac48Address&> m_traceTx;
-
-    void DoDispose() override;
-    Address GetMulticast(Ipv6Address addr) const override;
-    Address GetMulticast(Ipv4Address multicastGroup) const override;
-    bool IsBridge() const override;
-
-    /**
-     * Check if device is promiscuous
-     * @returns true if promiscuous
-     */
-    bool IsPromisc();
-    /**
-     * Notify promiscuous trace of a packet arrival
-     * @param p the packet
-     */
-    void NotifyPromiscTrace(Ptr<Packet> p);
-
-  private:
-    /// copy constructor (disabled)
-    WimaxNetDevice(const WimaxNetDevice&);
-    /**
-     * assignment operator (disabled)
-     * @returns the wimax net device
-     */
-    WimaxNetDevice& operator=(const WimaxNetDevice&);
-
-    /// Maximum MSDU size
-    static const uint16_t MAX_MSDU_SIZE = 1500;
-    /// recommended by wimax forum.
-    static const uint16_t DEFAULT_MSDU_SIZE = 1400;
-
-    /**
-     * Send a packet
-     * @param packet the packet
-     * @param source the source MAC address
-     * @param dest the destination MAC address
-     * @param protocolNumber the protocol number
-     * @returns true if successful
-     */
-    virtual bool DoSend(Ptr<Packet> packet,
-                        const Mac48Address& source,
-                        const Mac48Address& dest,
-                        uint16_t protocolNumber) = 0;
-    /**
-     * Receive a packet
-     * @param packet the packet received
-     */
-    virtual void DoReceive(Ptr<Packet> packet) = 0;
-    /**
-     * Get the channel
-     * @returns the wimax channel
-     */
-    virtual Ptr<WimaxChannel> DoGetChannel() const;
-    /**
-     * Receive a packet burst
-     * @param burst the packet burst
-     */
-    void Receive(Ptr<const PacketBurst> burst);
-    /// Initialize channels function
-    void InitializeChannels();
-
-    Ptr<Node> m_node;                              ///< the node
-    Ptr<WimaxPhy> m_phy;                           ///< the phy
-    NetDevice::ReceiveCallback m_forwardUp;        ///< forward up callback function
-    NetDevice::PromiscReceiveCallback m_promiscRx; ///< promiscuous receive callback function
-
-    uint32_t m_ifIndex;          ///< IF index
-    std::string m_name;          ///< service name
-    bool m_linkUp;               ///< link up?
-    Callback<void> m_linkChange; ///< link change callback
-    mutable uint16_t m_mtu;      ///< MTU
-
-    /// temp, shall be in BS. defined here to allow SS to access. SS shall actually determine it
-    /// from DLFP, shall be moved to BS after DLFP is implemented
-    static uint32_t m_nrFrames;
-
-    /// not sure if it shall be included here
-    std::vector<uint64_t> m_dlChannels;
-
-    Mac48Address m_address; ///< MAC address
-    uint8_t m_state;        ///< state
-    uint32_t m_symbolIndex; ///< symbol index
-
-    /// length of TTG in units of PSs
-    uint16_t m_ttg;
-    /// length of RTG in units of PSs
-    uint16_t m_rtg;
-
-    Dcd m_currentDcd; ///< DCD
-    Ucd m_currentUcd; ///< UCD
-
-    Ptr<WimaxConnection> m_initialRangingConnection; ///< initial rnaging connection
-    Ptr<WimaxConnection> m_broadcastConnection;      ///< broadcast connection
-
-    Ptr<ConnectionManager> m_connectionManager;     ///< connection manager
-    Ptr<BurstProfileManager> m_burstProfileManager; ///< burst profile manager
-    Ptr<BandwidthManager> m_bandwidthManager;       ///< badnwidth manager
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_NET_DEVICE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-phy.cc ns-3.46/src/wimax/model/wimax-phy.cc
--- ns-3.45/src/wimax/model/wimax-phy.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-phy.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,416 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#include "wimax-phy.h"
-
-#include "wimax-channel.h"
-#include "wimax-net-device.h"
-
-#include "ns3/double.h"
-#include "ns3/node.h"
-#include "ns3/packet-burst.h"
-#include "ns3/packet.h"
-#include "ns3/pointer.h"
-#include "ns3/simulator.h"
-#include "ns3/trace-source-accessor.h"
-#include "ns3/uinteger.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("WimaxPhy");
-
-NS_OBJECT_ENSURE_REGISTERED(WimaxPhy);
-
-TypeId
-WimaxPhy::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::WimaxPhy")
-            .SetParent<Object>()
-            .SetGroupName("Wimax")
-
-            // No AddConstructor because this is an abstract class.
-
-            .AddAttribute("Channel",
-                          "Wimax channel",
-                          PointerValue(),
-                          MakePointerAccessor(&WimaxPhy::GetChannel, &WimaxPhy::Attach),
-                          MakePointerChecker<WimaxChannel>())
-
-            .AddAttribute(
-                "FrameDuration",
-                "The frame duration in seconds.",
-                TimeValue(Seconds(0.01)),
-                MakeTimeAccessor(&WimaxPhy::SetFrameDuration, &WimaxPhy::GetFrameDurationSec),
-                MakeTimeChecker())
-
-            .AddAttribute("Frequency",
-                          "The central frequency in KHz.",
-                          UintegerValue(5000000),
-                          MakeUintegerAccessor(&WimaxPhy::SetFrequency, &WimaxPhy::GetFrequency),
-                          MakeUintegerChecker<uint32_t>(1000000, 11000000))
-
-            .AddAttribute("Bandwidth",
-                          "The channel bandwidth in Hz.",
-                          UintegerValue(10000000),
-                          MakeUintegerAccessor(&WimaxPhy::SetChannelBandwidth,
-                                               &WimaxPhy::GetChannelBandwidth),
-                          MakeUintegerChecker<uint32_t>(5000000, 30000000))
-
-        ;
-    return tid;
-}
-
-WimaxPhy::WimaxPhy()
-    : m_state(PHY_STATE_IDLE),
-      m_nrCarriers(0),
-      m_frameDuration(Seconds(0.01)),
-      m_frequency(5000000),
-      m_channelBandwidth(10000000),
-      m_psDuration(),
-      m_symbolDuration(),
-      m_psPerSymbol(0),
-      m_psPerFrame(0),
-      m_symbolsPerFrame(0)
-{
-    m_duplex = false;
-    m_txFrequency = 0;
-    m_rxFrequency = 0;
-}
-
-WimaxPhy::~WimaxPhy()
-{
-}
-
-void
-WimaxPhy::DoDispose()
-{
-    m_device = nullptr;
-    m_channel = nullptr;
-}
-
-void
-WimaxPhy::Attach(Ptr<WimaxChannel> channel)
-{
-    m_channel = channel;
-    DoAttach(channel);
-}
-
-Ptr<WimaxChannel>
-WimaxPhy::GetChannel() const
-{
-    return m_channel;
-}
-
-void
-WimaxPhy::SetDevice(Ptr<WimaxNetDevice> device)
-{
-    m_device = device;
-}
-
-Ptr<NetDevice>
-WimaxPhy::GetDevice() const
-{
-    return m_device;
-}
-
-void
-WimaxPhy::StartScanning(uint64_t frequency, Time timeout, Callback<void, bool, uint64_t> callback)
-{
-    NS_ASSERT_MSG(
-        m_state == PHY_STATE_IDLE || m_state == PHY_STATE_SCANNING,
-        "Error while scanning: The PHY state should be PHY_STATE_SCANNING or PHY_STATE_IDLE");
-
-    m_state = PHY_STATE_SCANNING;
-    m_scanningFrequency = frequency;
-    m_dlChnlSrchTimeoutEvent = Simulator::Schedule(timeout, &WimaxPhy::EndScanning, this);
-    m_scanningCallback = callback;
-}
-
-void
-WimaxPhy::EndScanning()
-{
-    m_scanningCallback(false, m_scanningFrequency);
-}
-
-void
-WimaxPhy::SetReceiveCallback(Callback<void, Ptr<const PacketBurst>> callback)
-{
-    m_rxCallback = callback;
-}
-
-Callback<void, Ptr<const PacketBurst>>
-WimaxPhy::GetReceiveCallback() const
-{
-    return m_rxCallback;
-}
-
-void
-WimaxPhy::SetDuplex(uint64_t rxFrequency, uint64_t txFrequency)
-{
-    m_txFrequency = txFrequency;
-    m_rxFrequency = rxFrequency;
-}
-
-void
-WimaxPhy::SetSimplex(uint64_t frequency)
-{
-    m_txFrequency = frequency;
-    m_rxFrequency = frequency;
-}
-
-uint64_t
-WimaxPhy::GetRxFrequency() const
-{
-    return m_rxFrequency;
-}
-
-uint64_t
-WimaxPhy::GetTxFrequency() const
-{
-    return m_txFrequency;
-}
-
-uint64_t
-WimaxPhy::GetScanningFrequency() const
-{
-    return m_scanningFrequency;
-}
-
-void
-WimaxPhy::SetState(PhyState state)
-{
-    m_state = state;
-}
-
-WimaxPhy::PhyState
-WimaxPhy::GetState() const
-{
-    return m_state;
-}
-
-bool
-WimaxPhy::IsDuplex() const
-{
-    return m_duplex;
-}
-
-EventId
-WimaxPhy::GetChnlSrchTimeoutEvent() const
-{
-    return m_dlChnlSrchTimeoutEvent;
-}
-
-void
-WimaxPhy::SetScanningCallback() const
-{
-    m_scanningCallback(true, GetScanningFrequency());
-}
-
-void
-WimaxPhy::SetDataRates()
-{
-    DoSetDataRates();
-}
-
-uint32_t
-WimaxPhy::GetDataRate(WimaxPhy::ModulationType modulationType) const
-{
-    return DoGetDataRate(modulationType);
-}
-
-Time
-WimaxPhy::GetTransmissionTime(uint32_t size, WimaxPhy::ModulationType modulationType) const
-{
-    return DoGetTransmissionTime(size, modulationType);
-}
-
-uint64_t
-WimaxPhy::GetNrSymbols(uint32_t size, WimaxPhy::ModulationType modulationType) const
-{
-    return DoGetNrSymbols(size, modulationType);
-}
-
-uint64_t
-WimaxPhy::GetNrBytes(uint32_t symbols, WimaxPhy::ModulationType modulationType) const
-{
-    return DoGetNrBytes(symbols, modulationType);
-}
-
-uint16_t
-WimaxPhy::GetTtg() const
-{
-    return DoGetTtg();
-}
-
-uint16_t
-WimaxPhy::GetRtg() const
-{
-    return DoGetRtg();
-}
-
-uint8_t
-WimaxPhy::GetFrameDurationCode() const
-{
-    return DoGetFrameDurationCode();
-}
-
-Time
-WimaxPhy::GetFrameDuration(uint8_t frameDurationCode) const
-{
-    return DoGetFrameDuration(frameDurationCode);
-}
-
-/*---------------------PHY parameters functions-----------------------*/
-
-void
-WimaxPhy::SetPhyParameters()
-{
-    DoSetPhyParameters();
-}
-
-void
-WimaxPhy::SetNrCarriers(uint8_t nrCarriers)
-{
-    m_nrCarriers = nrCarriers;
-}
-
-uint8_t
-WimaxPhy::GetNrCarriers() const
-{
-    return m_nrCarriers;
-}
-
-void
-WimaxPhy::SetFrameDuration(Time frameDuration)
-{
-    m_frameDuration = frameDuration;
-}
-
-Time
-WimaxPhy::GetFrameDuration() const
-{
-    return GetFrameDurationSec();
-}
-
-Time
-WimaxPhy::GetFrameDurationSec() const
-{
-    return m_frameDuration;
-}
-
-void
-WimaxPhy::SetFrequency(uint32_t frequency)
-{
-    m_frequency = frequency;
-}
-
-uint32_t
-WimaxPhy::GetFrequency() const
-{
-    return m_frequency;
-}
-
-void
-WimaxPhy::SetChannelBandwidth(uint32_t channelBandwidth)
-{
-    m_channelBandwidth = channelBandwidth;
-}
-
-uint32_t
-WimaxPhy::GetChannelBandwidth() const
-{
-    return m_channelBandwidth;
-}
-
-uint16_t
-WimaxPhy::GetNfft() const
-{
-    return DoGetNfft();
-}
-
-double
-WimaxPhy::GetSamplingFactor() const
-{
-    return DoGetSamplingFactor();
-}
-
-double
-WimaxPhy::GetSamplingFrequency() const
-{
-    return DoGetSamplingFrequency();
-}
-
-void
-WimaxPhy::SetPsDuration(Time psDuration)
-{
-    m_psDuration = psDuration;
-}
-
-Time
-WimaxPhy::GetPsDuration() const
-{
-    return m_psDuration;
-}
-
-void
-WimaxPhy::SetSymbolDuration(Time symbolDuration)
-{
-    m_symbolDuration = symbolDuration;
-}
-
-Time
-WimaxPhy::GetSymbolDuration() const
-{
-    return m_symbolDuration;
-}
-
-double
-WimaxPhy::GetGValue() const
-{
-    return DoGetGValue();
-}
-
-void
-WimaxPhy::SetPsPerSymbol(uint16_t psPerSymbol)
-{
-    m_psPerSymbol = psPerSymbol;
-}
-
-uint16_t
-WimaxPhy::GetPsPerSymbol() const
-{
-    return m_psPerSymbol;
-}
-
-void
-WimaxPhy::SetPsPerFrame(uint16_t psPerFrame)
-{
-    m_psPerFrame = psPerFrame;
-}
-
-uint16_t
-WimaxPhy::GetPsPerFrame() const
-{
-    return m_psPerFrame;
-}
-
-void
-WimaxPhy::SetSymbolsPerFrame(uint32_t symbolsPerFrame)
-{
-    m_symbolsPerFrame = symbolsPerFrame;
-}
-
-uint32_t
-WimaxPhy::GetSymbolsPerFrame() const
-{
-    return m_symbolsPerFrame;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-phy.h ns-3.46/src/wimax/model/wimax-phy.h
--- ns-3.45/src/wimax/model/wimax-phy.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-phy.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,480 +0,0 @@
-/*
- * Copyright (c) 2007,2008 INRIA
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
- */
-
-#ifndef WIMAX_PHY_H
-#define WIMAX_PHY_H
-
-#include "bvec.h"
-#include "send-params.h"
-
-#include "ns3/callback.h"
-#include "ns3/event-id.h"
-#include "ns3/log.h"
-#include "ns3/nstime.h"
-#include "ns3/object.h"
-#include "ns3/traced-callback.h"
-
-#include <list>
-#include <stdint.h>
-
-namespace ns3
-{
-
-class WimaxChannel;
-class WimaxNetDevice;
-class NetDevice;
-class Packet;
-
-/**
- * @ingroup wimax
- *
- * WiMAX PHY entity
- */
-class WimaxPhy : public Object
-{
-  public:
-    /// ModulationType enumeration
-    enum ModulationType // Table 356 and 362
-    {
-        MODULATION_TYPE_BPSK_12,
-        MODULATION_TYPE_QPSK_12,
-        MODULATION_TYPE_QPSK_34,
-        MODULATION_TYPE_QAM16_12,
-        MODULATION_TYPE_QAM16_34,
-        MODULATION_TYPE_QAM64_23,
-        MODULATION_TYPE_QAM64_34
-    };
-
-    /// PhyState enumeration
-    enum PhyState
-    {
-        PHY_STATE_IDLE,
-        PHY_STATE_SCANNING,
-        PHY_STATE_TX,
-        PHY_STATE_RX
-    };
-
-    /// PhyType enumeration
-    enum PhyType
-    {
-        SimpleWimaxPhy,
-        simpleOfdmWimaxPhy
-    };
-
-    /**
-     * @brief Get the type ID.
-     * @return the object TypeId
-     */
-    static TypeId GetTypeId();
-    WimaxPhy();
-    ~WimaxPhy() override;
-    /**
-     * Attach the physical layer to a channel.
-     * @param channel the channel to which the physical layer will be attached
-     */
-    void Attach(Ptr<WimaxChannel> channel);
-    /**
-     * @return the channel to which this physical layer is attached
-     */
-    Ptr<WimaxChannel> GetChannel() const;
-    /**
-     * @brief Set the device in which this physical layer is installed
-     * @param device the device in which this physical layer is installed
-     */
-    void SetDevice(Ptr<WimaxNetDevice> device);
-    /**
-     * @return the the device in which this physical layer is installed
-     */
-    Ptr<NetDevice> GetDevice() const;
-    /**
-     * @brief set the callback function to call when a burst is received
-     * @param callback the callback function to call when a burst is received
-     */
-    void SetReceiveCallback(Callback<void, Ptr<const PacketBurst>> callback);
-    /**
-     * @return the receive callback
-     */
-    Callback<void, Ptr<const PacketBurst>> GetReceiveCallback() const;
-    /**
-     * @brief send a packet on the channel
-     * @param params the parameters used to send the packet
-     */
-    virtual void Send(SendParams* params) = 0;
-    /**
-     * @brief Get the type of the physical layer
-     * @returns the phy type
-     */
-    virtual PhyType GetPhyType() const = 0;
-    /**
-     * @brief configure the physical layer in duplex mode
-     * @param rxFrequency the reception frequency
-     * @param txFrequency the transmission frequency
-     */
-    void SetDuplex(uint64_t rxFrequency, uint64_t txFrequency);
-    /**
-     * @brief configure the physical layer in simplex mode
-     * @param frequency  the frequency to be used for reception and transmission process
-     */
-    void SetSimplex(uint64_t frequency);
-    /**
-     * Get the reception frequency
-     * @return the reception frequency
-     */
-    uint64_t GetRxFrequency() const;
-    /**
-     * Get the transmission frequency
-     * @return the transmission frequency
-     */
-    uint64_t GetTxFrequency() const;
-    /**
-     * Get the scanning frequency
-     * @return the scanning frequency
-     */
-    uint64_t GetScanningFrequency() const;
-    /**
-     * Set the number of carriers in the physical frame
-     * @brief Set the number of carriers in the physical frame
-     * @param  nrCarriers the number of carriers in the frame
-     */
-    void SetNrCarriers(uint8_t nrCarriers);
-    /**
-     * Get the number of carriers in the physical frame
-     * @return the number of carriers in the physical frame
-     */
-    uint8_t GetNrCarriers() const;
-    /**
-     * @brief Set the frame duration
-     * @param frameDuration the frame duration
-     */
-    void SetFrameDuration(Time frameDuration);
-    /**
-     * @brief Get the frame duration
-     * This method is redundant with GetFrameDuration ()
-     * @return the frame duration
-     */
-    Time GetFrameDurationSec() const;
-    /**
-     * @brief Get the frame duration
-     * @return the frame duration
-     */
-    Time GetFrameDuration() const;
-    /**
-     * @brief set the frequency on which the device should lock
-     * @param frequency the frequency to configure
-     */
-    void SetFrequency(uint32_t frequency);
-    /**
-     * Get the frequency on which the device is locked
-     * @return the frequency on which the device is locked
-     */
-    uint32_t GetFrequency() const;
-    /**
-     * @brief Set the channel bandwidth
-     * @param channelBandwidth The channel bandwidth
-     */
-    void SetChannelBandwidth(uint32_t channelBandwidth);
-    /**
-     * Get the channel bandwidth
-     * @return the channel bandwidth
-     */
-    uint32_t GetChannelBandwidth() const;
-    /**
-     * Get the size of the FFT
-     * @return the size of the FFT
-     */
-    uint16_t GetNfft() const;
-    /**
-     * Get the sampling factor
-     * @return the sampling factor
-     */
-    double GetSamplingFactor() const;
-    /**
-     * Get the sampling frequency
-     * @return the sampling frequency
-     */
-    double GetSamplingFrequency() const;
-    /**
-     * @brief set the physical slot duration
-     * @param psDuration the physical slot duration
-     */
-    void SetPsDuration(Time psDuration);
-    /**
-     * Get the physical slot duration
-     * @return the physical slot duration
-     */
-    Time GetPsDuration() const;
-    /**
-     * @brief set the OFDM symbol duration
-     * @param symbolDuration the symbol duration
-     */
-    void SetSymbolDuration(Time symbolDuration);
-    /**
-     * Get the OFDM symbol duration
-     * @return the symbol duration in second
-     */
-    Time GetSymbolDuration() const;
-    /**
-     * Get the guard interval factor (the ratio TG/Td)
-     * @return the guard interval factor
-     */
-    double GetGValue() const;
-    /**
-     * @brief set the number of physical slots per symbol
-     * @param psPerSymbol the number of physical slots per symbol
-     */
-    void SetPsPerSymbol(uint16_t psPerSymbol);
-    /**
-     * Get the number of physical slots per symbol
-     * @return the number of physical slots per symbol
-     */
-    uint16_t GetPsPerSymbol() const;
-
-    /**
-     * @brief set the number of physical slots per frame
-     * @param psPerFrame the number of physical slots per frame
-     */
-    void SetPsPerFrame(uint16_t psPerFrame);
-    /**
-     * Get the number of physical slots per frame
-     * @return the number of physical slot per frame
-     */
-    uint16_t GetPsPerFrame() const;
-    /**
-     * @brief set the number of symbols per frame
-     * @param symbolsPerFrame the number of symbols per frame
-     */
-    void SetSymbolsPerFrame(uint32_t symbolsPerFrame);
-    /**
-     * Get the number of symbols per frame
-     * @return the number of symbols per frame
-     */
-    uint32_t GetSymbolsPerFrame() const;
-    /**
-     * Check if configured in duplex mode
-     * @return true if the device is configured in duplex mode
-     */
-    bool IsDuplex() const;
-    /**
-     * @brief set the state of the device
-     * @param state the state to be set (PHY_STATE_IDLE, PHY_STATE_SCANNING, PHY_STATE_TX,
-     * PHY_STATE_RX)
-     */
-    void SetState(PhyState state);
-    /**
-     * Get the state of the device
-     * @return the state of the device (PHY_STATE_IDLE, PHY_STATE_SCANNING, PHY_STATE_TX,
-     * PHY_STATE_RX)
-     */
-    PhyState GetState() const;
-    /**
-     * @brief scan a frequency for maximum timeout seconds and call the callback if the frequency
-     * can be used
-     * @param frequency the frequency to scan
-     * @param timeout the timeout before considering the channel as unusable
-     * @param callback the function to call if the channel could be used
-     */
-    void StartScanning(uint64_t frequency, Time timeout, Callback<void, bool, uint64_t> callback);
-
-    /**
-     * @brief calls the scanning call back function
-     */
-    void SetScanningCallback() const;
-    /**
-     * @brief Get channel search timeout event
-     * @return event ID
-     */
-    EventId GetChnlSrchTimeoutEvent() const;
-    /**
-     * @brief calculates the data rate of each modulation and save them for future use
-     */
-    void SetDataRates();
-    /**
-     * Get the data rate corresponding to a modulation type
-     * @return the data rate
-     * @param modulationType the modulation that you want to get its data rate
-     */
-    uint32_t GetDataRate(ModulationType modulationType) const;
-    /**
-     * Get transmission time needed to send bytes at a given modulation
-     * @return the time needed
-     * @param size the number of byte to transmit
-     * @param modulationType the modulation that will be used to transmit the bytes
-     */
-    Time GetTransmissionTime(uint32_t size, ModulationType modulationType) const;
-    /**
-     * Get the number of symbols needed to transmit size bytes using the modulation modulationType
-     * @return the number of symbols needed
-     * @param size the number of byte to transmit
-     * @param modulationType the modulation that will be used to transmit the bytes
-     */
-    uint64_t GetNrSymbols(uint32_t size, ModulationType modulationType) const;
-    /**
-     * Get the maximum number of bytes that could be carried by symbols symbols using the modulation
-     * modulationType
-     * @param symbols the number of symbols to use
-     * @param modulationType the modulation that will be used
-     * @return the maximum number of bytes
-     */
-    uint64_t GetNrBytes(uint32_t symbols, ModulationType modulationType) const;
-    /**
-     * Get the transmit/receive transition gap
-     * @return the transmit/receive transition gap
-     */
-    uint16_t GetTtg() const;
-    /**
-     * Get the receive/transmit transition gap
-     * @return the receive/transmit transition gap
-     */
-    uint16_t GetRtg() const;
-    /**
-     * Get the frame duration code
-     * @return the frame duration code
-     */
-    uint8_t GetFrameDurationCode() const;
-    /**
-     * Get the frame duration corresponding to a given code
-     * @param frameDurationCode the frame duration code to use
-     * @return the frame duration
-     */
-    Time GetFrameDuration(uint8_t frameDurationCode) const;
-    /**
-     * @brief computes the Physical parameters and store them
-     */
-    void SetPhyParameters();
-    void DoDispose() override;
-
-    /**
-     * Assign a fixed random variable stream number to the random variables
-     * used by this model.  Return the number of streams (possibly zero) that
-     * have been assigned.
-     *
-     * @param stream first stream index to use
-     * @return the number of stream indices assigned by this model
-     */
-    virtual int64_t AssignStreams(int64_t stream) = 0;
-
-  private:
-    /**
-     * Get modulation FEC parameters
-     * @param modulationType the modultion type
-     * @param bitsPerSymbol the number of bits per symbol page
-     * @param fecCode the FEC code
-     */
-    void GetModulationFecParams(ModulationType modulationType,
-                                uint8_t& bitsPerSymbol,
-                                double& fecCode) const;
-    /// End scanning
-    void EndScanning();
-    /**
-     * Get transmission time
-     * @param size the transmission size
-     * @param modulationType the modulation type
-     * @returns the transmission time
-     */
-    virtual Time DoGetTransmissionTime(uint32_t size, ModulationType modulationType) const = 0;
-    /**
-     * Attach channel
-     * @param channel the wimax channel
-     */
-    virtual void DoAttach(Ptr<WimaxChannel> channel) = 0;
-    /// Set data rates
-    virtual void DoSetDataRates() = 0;
-    /**
-     * Get data rate
-     * @param modulationType the modulation type
-     * @returns the data rate
-     */
-    virtual uint32_t DoGetDataRate(ModulationType modulationType) const = 0;
-    /**
-     * Get number of symbols
-     * @param size the transmission size
-     * @param modulationType the modulation type
-     * @returns the number of symbols
-     */
-    virtual uint64_t DoGetNrSymbols(uint32_t size, ModulationType modulationType) const = 0;
-    /**
-     * Get number of bytes
-     * @param symbols the number of symbols
-     * @param modulationType the modulation type
-     * @returns the number of bytes
-     */
-    virtual uint64_t DoGetNrBytes(uint32_t symbols, ModulationType modulationType) const = 0;
-    /**
-     * Get TTG
-     * @returns the TTG
-     */
-    virtual uint16_t DoGetTtg() const = 0;
-    /**
-     * Get RTG
-     * @returns the RTG
-     */
-    virtual uint16_t DoGetRtg() const = 0;
-
-    /**
-     * Get frame duration code
-     * @returns the frame duration code
-     */
-    virtual uint8_t DoGetFrameDurationCode() const = 0;
-    /**
-     * Get frame duration
-     * @param frameDurationCode the frame duration code
-     * @returns the frame duration time
-     */
-    virtual Time DoGetFrameDuration(uint8_t frameDurationCode) const = 0;
-    /**
-     * Set phy parameters
-     */
-    virtual void DoSetPhyParameters() = 0;
-    /**
-     * Get sampling factor
-     * @return the sampling factor
-     */
-    virtual double DoGetSamplingFactor() const = 0;
-    /**
-     * Get NFFT
-     * @returns the NFFT
-     */
-    virtual uint16_t DoGetNfft() const = 0;
-    /**
-     * Get sampling frequency
-     * @returns the sampling frequency
-     */
-    virtual double DoGetSamplingFrequency() const = 0;
-    /**
-     * Get G value
-     * @returns he G value
-     */
-    virtual double DoGetGValue() const = 0;
-
-    Ptr<WimaxNetDevice> m_device; ///< the device
-    Ptr<WimaxChannel> m_channel;  ///< channel
-
-    uint64_t m_txFrequency;           ///< transmit frequency
-    uint64_t m_rxFrequency;           ///< receive frequency
-    uint64_t m_scanningFrequency;     ///< scanning frequency
-    EventId m_dlChnlSrchTimeoutEvent; ///< DL channel search timeout event
-    bool m_duplex;                    ///< duplex
-    PhyState m_state;                 ///< state
-
-    Callback<void, Ptr<const PacketBurst>> m_rxCallback; ///< receive callback function
-    Callback<void, bool, uint64_t> m_scanningCallback;   ///< scanning callback function
-
-    uint8_t m_nrCarriers;        ///< number of carriers
-    Time m_frameDuration;        ///< in seconds
-    uint32_t m_frequency;        ///< in KHz
-    uint32_t m_channelBandwidth; ///< in Hz
-    Time m_psDuration;           ///< in seconds
-    Time m_symbolDuration;       ///< in seconds
-    uint16_t m_psPerSymbol;      ///< ps per sumbol
-    uint16_t m_psPerFrame;       ///< ps per framce
-    uint32_t m_symbolsPerFrame;  ///< symbols per frame
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_PHY_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-tlv.cc ns-3.46/src/wimax/model/wimax-tlv.cc
--- ns-3.45/src/wimax/model/wimax-tlv.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-tlv.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,1072 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-
-#include "wimax-tlv.h"
-
-namespace ns3
-{
-
-NS_LOG_COMPONENT_DEFINE("Tlv");
-
-// NS_OBJECT_ENSURE_REGISTERED ("Tlv");
-
-/* static */
-TypeId
-Tlv::GetTypeId()
-{
-    static TypeId tid =
-        TypeId("ns3::Tlv").SetParent<Header>().SetGroupName("Wimax").AddConstructor<Tlv>();
-    return tid;
-}
-
-TypeId
-Tlv::GetInstanceTypeId() const
-{
-    return GetTypeId();
-}
-
-void
-Tlv::Print(std::ostream& os) const
-{
-    os << "TLV type = " << (uint32_t)m_type << " TLV Length = " << (uint64_t)m_length;
-}
-
-Tlv::Tlv(uint8_t type, uint64_t length, const TlvValue& value)
-{
-    m_type = type;
-    m_length = length;
-    m_value = value.Copy();
-}
-
-Tlv::Tlv()
-{
-    m_type = 0;
-    m_length = 0;
-    m_value = nullptr;
-}
-
-Tlv::~Tlv()
-{
-    if (m_value != nullptr)
-    {
-        delete m_value;
-        m_value = nullptr;
-    }
-}
-
-TlvValue*
-Tlv::CopyValue() const
-{
-    return m_value->Copy();
-}
-
-Tlv::Tlv(const Tlv& tlv)
-{
-    m_type = tlv.GetType();
-    m_length = tlv.GetLength();
-    m_value = tlv.CopyValue();
-}
-
-Tlv&
-Tlv::operator=(const Tlv& o)
-{
-    if (m_value != nullptr)
-    {
-        delete m_value;
-    }
-    m_type = o.GetType();
-    m_length = o.GetLength();
-    m_value = o.CopyValue();
-
-    return *this;
-}
-
-uint32_t
-Tlv::GetSerializedSize() const
-{
-    return 1 + GetSizeOfLen() + m_value->GetSerializedSize();
-}
-
-uint8_t
-Tlv::GetSizeOfLen() const
-{
-    uint8_t sizeOfLen = 1;
-
-    if (m_length > 127)
-    {
-        sizeOfLen = 2;
-        uint64_t testValue = 0xFF;
-        while (m_length > testValue)
-        {
-            sizeOfLen++;
-            testValue *= 0xFF;
-        }
-    }
-    return sizeOfLen;
-}
-
-void
-Tlv::Serialize(Buffer::Iterator i) const
-{
-    i.WriteU8(m_type);
-    uint8_t lenSize = GetSizeOfLen();
-    if (lenSize == 1)
-    {
-        i.WriteU8(m_length);
-    }
-    else
-    {
-        i.WriteU8((lenSize - 1) | WIMAX_TLV_EXTENDED_LENGTH_MASK);
-        for (int j = 0; j < lenSize - 1; j++)
-        {
-            i.WriteU8((uint8_t)(m_length >> ((lenSize - 1 - 1 - j) * 8)));
-        }
-    }
-    m_value->Serialize(i);
-}
-
-uint32_t
-Tlv::Deserialize(Buffer::Iterator i)
-{
-    // read the type of tlv
-    m_type = i.ReadU8();
-
-    // read the length
-    uint8_t lenSize = i.ReadU8();
-    uint32_t serializedSize = 2;
-    if (lenSize < 127)
-    {
-        m_length = lenSize;
-    }
-    else
-    {
-        lenSize &= ~WIMAX_TLV_EXTENDED_LENGTH_MASK;
-        for (int j = 0; j < lenSize; j++)
-        {
-            m_length <<= 8;
-            m_length |= i.ReadU8();
-            serializedSize++;
-        }
-    }
-    switch (m_type)
-    {
-    case HMAC_TUPLE:
-        /// @todo implement Deserialize HMAC_TUPLE
-        NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-        break;
-    case MAC_VERSION_ENCODING:
-        /// @todo implement Deserialize MAC_VERSION_ENCODING
-        NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-        break;
-    case CURRENT_TRANSMIT_POWER:
-        /// @todo implement Deserialize CURRENT_TRANSMIT_POWER
-        NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-        break;
-    case DOWNLINK_SERVICE_FLOW: {
-        SfVectorTlvValue val;
-        serializedSize += val.Deserialize(i, m_length);
-        m_value = val.Copy();
-        break;
-    }
-    case UPLINK_SERVICE_FLOW: {
-        SfVectorTlvValue val;
-        serializedSize += val.Deserialize(i, m_length);
-        m_value = val.Copy();
-        break;
-    }
-    case VENDOR_ID_EMCODING:
-        /// @todo implement Deserialize VENDOR_ID_EMCODING
-        NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-        break;
-    case VENDOR_SPECIFIC_INFORMATION:
-        /// @todo implement Deserialize  VENDOR_SPECIFIC_INFORMATION
-        NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-        break;
-    default:
-        NS_ASSERT_MSG(false, "Unknown tlv type.");
-        break;
-    }
-
-    return serializedSize;
-}
-
-uint8_t
-Tlv::GetType() const
-{
-    return m_type;
-}
-
-uint64_t
-Tlv::GetLength() const
-{
-    return m_length;
-}
-
-TlvValue*
-Tlv::PeekValue()
-{
-    return m_value;
-}
-
-Tlv*
-Tlv::Copy() const
-{
-    return new Tlv(m_type, m_length, *m_value);
-}
-
-// ==============================================================================
-VectorTlvValue::VectorTlvValue()
-{
-    m_tlvList = new std::vector<Tlv*>;
-}
-
-VectorTlvValue::~VectorTlvValue()
-{
-    for (auto iter = m_tlvList->begin(); iter != m_tlvList->end(); ++iter)
-    {
-        delete (*iter);
-    }
-    m_tlvList->clear();
-    delete m_tlvList;
-}
-
-uint32_t
-VectorTlvValue::GetSerializedSize() const
-{
-    uint32_t size = 0;
-    for (auto iter = m_tlvList->begin(); iter != m_tlvList->end(); ++iter)
-    {
-        size += (*iter)->GetSerializedSize();
-    }
-    return size;
-}
-
-void
-VectorTlvValue::Serialize(Buffer::Iterator i) const
-{
-    for (auto iter = m_tlvList->begin(); iter != m_tlvList->end(); ++iter)
-    {
-        (*iter)->Serialize(i);
-        i.Next((*iter)->GetSerializedSize());
-    }
-}
-
-VectorTlvValue::Iterator
-VectorTlvValue::Begin() const
-{
-    return m_tlvList->begin();
-}
-
-VectorTlvValue::Iterator
-VectorTlvValue::End() const
-{
-    return m_tlvList->end();
-}
-
-void
-VectorTlvValue::Add(const Tlv& val)
-{
-    m_tlvList->push_back(val.Copy());
-}
-
-// ==============================================================================
-SfVectorTlvValue::SfVectorTlvValue()
-{
-}
-
-SfVectorTlvValue*
-SfVectorTlvValue::Copy() const
-{
-    auto tmp = new SfVectorTlvValue();
-    for (auto iter = Begin(); iter != End(); ++iter)
-    {
-        tmp->Add(Tlv((*iter)->GetType(), (*iter)->GetLength(), *(*iter)->PeekValue()));
-    }
-    return tmp;
-}
-
-uint32_t
-SfVectorTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLen)
-{
-    uint64_t serializedSize = 0;
-    while (serializedSize < valueLen)
-    {
-        uint8_t type = i.ReadU8();
-        // read the length
-        uint8_t lenSize = i.ReadU8();
-        serializedSize += 2;
-        uint64_t length = 0;
-        if (lenSize < 127)
-        {
-            length = lenSize;
-        }
-        else
-        {
-            lenSize &= ~WIMAX_TLV_EXTENDED_LENGTH_MASK;
-            for (int j = 0; j < lenSize; j++)
-            {
-                length <<= 8;
-                length |= i.ReadU8();
-                serializedSize++;
-            }
-        }
-        switch (type)
-        {
-        case SFID: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(SFID, 4, val));
-            break;
-        }
-        case CID: {
-            U16TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(CID, 2, val));
-            break;
-        }
-        case Service_Class_Name:
-            NS_FATAL_ERROR("Not implemented-- please implement and contribute a patch");
-            break;
-        case reserved1:
-            // NOTHING
-            break;
-        case QoS_Parameter_Set_Type: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(QoS_Parameter_Set_Type, 1, val));
-            break;
-        }
-        case Traffic_Priority: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Traffic_Priority, 1, val));
-            break;
-        }
-        case Maximum_Sustained_Traffic_Rate: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Maximum_Sustained_Traffic_Rate, 4, val));
-            break;
-        }
-        case Maximum_Traffic_Burst: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Maximum_Traffic_Burst, 4, val));
-            break;
-        }
-        case Minimum_Reserved_Traffic_Rate: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Minimum_Reserved_Traffic_Rate, 4, val));
-            break;
-        }
-        case Minimum_Tolerable_Traffic_Rate: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Minimum_Tolerable_Traffic_Rate, 4, val));
-            break;
-        }
-        case Service_Flow_Scheduling_Type: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Service_Flow_Scheduling_Type, 1, val));
-            break;
-        }
-        case Request_Transmission_Policy: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Request_Transmission_Policy, 4, val));
-            break;
-        }
-        case Tolerated_Jitter: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Tolerated_Jitter, 4, val));
-            break;
-        }
-        case Maximum_Latency: {
-            U32TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Maximum_Latency, 4, val));
-            break;
-        }
-        case Fixed_length_versus_Variable_length_SDU_Indicator: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Fixed_length_versus_Variable_length_SDU_Indicator, 1, val));
-            break;
-        }
-        case SDU_Size: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(SDU_Size, 1, val));
-            break;
-        }
-        case Target_SAID: {
-            U16TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Target_SAID, 2, val));
-            break;
-        }
-        case ARQ_Enable: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(ARQ_Enable, 1, val));
-            break;
-        }
-        case ARQ_WINDOW_SIZE: {
-            U16TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(ARQ_WINDOW_SIZE, 2, val));
-            break;
-        }
-        case ARQ_RETRY_TIMEOUT_Transmitter_Delay:
-        case ARQ_RETRY_TIMEOUT_Receiver_Delay:
-        case ARQ_BLOCK_LIFETIME:
-        case ARQ_SYNC_LOSS:
-        case ARQ_DELIVER_IN_ORDER:
-        case ARQ_PURGE_TIMEOUT:
-        case ARQ_BLOCK_SIZE:
-        case reserved2:
-            break;
-        case CS_Specification: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(CS_Specification, 1, val));
-            break;
-        }
-        case IPV4_CS_Parameters: {
-            CsParamVectorTlvValue val;
-            uint32_t size = val.Deserialize(i, length);
-            serializedSize += size;
-            Add(Tlv(IPV4_CS_Parameters, size, val));
-            break;
-        }
-        default:
-            NS_ASSERT_MSG(false, "Unknown tlv type.");
-            break;
-        }
-        i.Next(length);
-    }
-    return serializedSize;
-}
-
-// ==============================================================================
-
-U8TlvValue::U8TlvValue(uint8_t value)
-{
-    m_value = value;
-}
-
-U8TlvValue::U8TlvValue()
-{
-    m_value = 0;
-}
-
-U8TlvValue::~U8TlvValue()
-{
-}
-
-uint32_t
-U8TlvValue::GetSerializedSize() const
-{
-    return 1;
-}
-
-void
-U8TlvValue::Serialize(Buffer::Iterator i) const
-{
-    i.WriteU8(m_value);
-}
-
-uint32_t
-U8TlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLen)
-{
-    return Deserialize(i);
-}
-
-uint32_t
-U8TlvValue::Deserialize(Buffer::Iterator i)
-{
-    m_value = i.ReadU8();
-    return 1;
-}
-
-uint8_t
-U8TlvValue::GetValue() const
-{
-    return m_value;
-}
-
-U8TlvValue*
-U8TlvValue::Copy() const
-{
-    auto tmp = new U8TlvValue(m_value);
-    return tmp;
-}
-
-// ==============================================================================
-U16TlvValue::U16TlvValue(uint16_t value)
-{
-    m_value = value;
-}
-
-U16TlvValue::U16TlvValue()
-{
-    m_value = 0;
-}
-
-U16TlvValue::~U16TlvValue()
-{
-}
-
-uint32_t
-U16TlvValue::GetSerializedSize() const
-{
-    return 2;
-}
-
-void
-U16TlvValue::Serialize(Buffer::Iterator i) const
-{
-    i.WriteHtonU16(m_value);
-}
-
-uint32_t
-U16TlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLen)
-{
-    return Deserialize(i);
-}
-
-uint32_t
-U16TlvValue::Deserialize(Buffer::Iterator i)
-{
-    m_value = i.ReadNtohU16();
-    return 2;
-}
-
-uint16_t
-U16TlvValue::GetValue() const
-{
-    return m_value;
-}
-
-U16TlvValue*
-U16TlvValue::Copy() const
-{
-    auto tmp = new U16TlvValue(m_value);
-    return tmp;
-}
-
-// ==============================================================================
-U32TlvValue::U32TlvValue(uint32_t value)
-{
-    m_value = value;
-}
-
-U32TlvValue::U32TlvValue()
-{
-    m_value = 0;
-}
-
-U32TlvValue::~U32TlvValue()
-{
-}
-
-uint32_t
-U32TlvValue::GetSerializedSize() const
-{
-    return 4;
-}
-
-void
-U32TlvValue::Serialize(Buffer::Iterator i) const
-{
-    i.WriteHtonU32(m_value);
-}
-
-uint32_t
-U32TlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLen)
-{
-    return Deserialize(i);
-}
-
-uint32_t
-U32TlvValue::Deserialize(Buffer::Iterator i)
-{
-    m_value = i.ReadNtohU32();
-    return 4;
-}
-
-uint32_t
-U32TlvValue::GetValue() const
-{
-    return m_value;
-}
-
-U32TlvValue*
-U32TlvValue::Copy() const
-{
-    auto tmp = new U32TlvValue(m_value);
-    return tmp;
-}
-
-// ==============================================================================
-uint32_t
-CsParamVectorTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLength)
-{
-    uint64_t serializedSize = 0;
-    uint8_t lenSize = 0;
-    uint8_t type = 0;
-    while (serializedSize < valueLength)
-    {
-        type = i.ReadU8();
-        // read the length
-        lenSize = i.ReadU8();
-        serializedSize += 2;
-        uint64_t length = 0;
-        if (lenSize < 127)
-        {
-            length = lenSize;
-        }
-        else
-        {
-            lenSize &= ~WIMAX_TLV_EXTENDED_LENGTH_MASK;
-            for (int j = 0; j < lenSize; j++)
-            {
-                length <<= 8;
-                length |= i.ReadU8();
-                serializedSize++;
-            }
-        }
-        switch (type)
-        {
-        case Classifier_DSC_Action: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Classifier_DSC_Action, 1, val));
-            break;
-        }
-        case Packet_Classification_Rule: {
-            ClassificationRuleVectorTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(Packet_Classification_Rule, val.GetSerializedSize(), val));
-            break;
-        }
-        }
-        i.Next(length);
-    }
-    return serializedSize;
-}
-
-CsParamVectorTlvValue::CsParamVectorTlvValue()
-{
-}
-
-CsParamVectorTlvValue*
-CsParamVectorTlvValue::Copy() const
-{
-    auto tmp = new CsParamVectorTlvValue();
-    for (auto iter = Begin(); iter != End(); ++iter)
-    {
-        tmp->Add(Tlv((*iter)->GetType(), (*iter)->GetLength(), *(*iter)->PeekValue()));
-    }
-    return tmp;
-}
-
-// ==============================================================================
-
-ClassificationRuleVectorTlvValue::ClassificationRuleVectorTlvValue()
-{
-}
-
-ClassificationRuleVectorTlvValue*
-ClassificationRuleVectorTlvValue::Copy() const
-{
-    auto tmp = new ClassificationRuleVectorTlvValue();
-    for (auto iter = Begin(); iter != End(); ++iter)
-    {
-        tmp->Add(Tlv((*iter)->GetType(), (*iter)->GetLength(), *(*iter)->PeekValue()));
-    }
-    return tmp;
-}
-
-uint32_t
-ClassificationRuleVectorTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLength)
-{
-    uint64_t serializedSize = 0;
-    uint8_t lenSize = 0;
-    uint8_t type = 0;
-    while (serializedSize < valueLength)
-    {
-        type = i.ReadU8();
-        // read the length
-        lenSize = i.ReadU8();
-        serializedSize += 2;
-        uint64_t length = 0;
-        if (lenSize < 127)
-        {
-            length = lenSize;
-        }
-        else
-        {
-            lenSize &= ~WIMAX_TLV_EXTENDED_LENGTH_MASK;
-            for (int j = 0; j < lenSize; j++)
-            {
-                length <<= 8;
-                length |= i.ReadU8();
-                serializedSize++;
-            }
-        }
-        switch (type)
-        {
-        case Priority: {
-            U8TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Priority, 1, val));
-            break;
-        }
-        case ToS: {
-            TosTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(ToS, val.GetSerializedSize(), val));
-            break;
-        }
-        case Protocol: {
-            ProtocolTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(Protocol, val.GetSerializedSize(), val));
-            break;
-        }
-        case IP_src: {
-            Ipv4AddressTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(IP_src, val.GetSerializedSize(), val));
-            break;
-        }
-        case IP_dst: {
-            Ipv4AddressTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(IP_dst, val.GetSerializedSize(), val));
-            break;
-        }
-        case Port_src: {
-            PortRangeTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(Port_src, val.GetSerializedSize(), val));
-            break;
-        }
-        case Port_dst: {
-            PortRangeTlvValue val;
-            serializedSize += val.Deserialize(i, length);
-            Add(Tlv(Port_dst, val.GetSerializedSize(), val));
-            break;
-        }
-        case Index: {
-            U16TlvValue val;
-            serializedSize += val.Deserialize(i);
-            Add(Tlv(Index, 2, val));
-            break;
-        }
-        }
-        i.Next(length);
-    }
-    return serializedSize;
-}
-
-// ==============================================================================
-TosTlvValue::TosTlvValue()
-{
-    m_low = 0;
-    m_high = 0;
-    m_mask = 0;
-}
-
-TosTlvValue::TosTlvValue(uint8_t low, uint8_t high, uint8_t mask)
-{
-    m_low = low;
-    m_high = high;
-    m_mask = mask;
-}
-
-TosTlvValue::~TosTlvValue()
-{
-}
-
-uint32_t
-TosTlvValue::GetSerializedSize() const
-{
-    return 3;
-}
-
-void
-TosTlvValue::Serialize(Buffer::Iterator i) const
-{
-    i.WriteU8(m_low);
-    i.WriteU8(m_high);
-    i.WriteU8(m_mask);
-}
-
-uint32_t
-TosTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLength)
-{
-    m_low = i.ReadU8();
-    m_high = i.ReadU8();
-    m_mask = i.ReadU8();
-    return 3;
-}
-
-uint8_t
-TosTlvValue::GetLow() const
-{
-    return m_low;
-}
-
-uint8_t
-TosTlvValue::GetHigh() const
-{
-    return m_high;
-}
-
-uint8_t
-TosTlvValue::GetMask() const
-{
-    return m_mask;
-}
-
-TosTlvValue*
-TosTlvValue::Copy() const
-{
-    return new TosTlvValue(m_low, m_high, m_mask);
-}
-
-// ==============================================================================
-PortRangeTlvValue::PortRangeTlvValue()
-{
-    m_portRange = new std::vector<PortRange>;
-}
-
-PortRangeTlvValue::~PortRangeTlvValue()
-{
-    m_portRange->clear();
-    delete m_portRange;
-}
-
-uint32_t
-PortRangeTlvValue::GetSerializedSize() const
-{
-    return m_portRange->size() * 4; // a port range is defined by 2 ports, each using 2 bytes
-}
-
-void
-PortRangeTlvValue::Serialize(Buffer::Iterator i) const
-{
-    for (auto iter = m_portRange->begin(); iter != m_portRange->end(); ++iter)
-    {
-        i.WriteHtonU16((*iter).PortLow);
-        i.WriteHtonU16((*iter).PortHigh);
-    }
-}
-
-uint32_t
-PortRangeTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLength)
-{
-    uint64_t len = 0;
-    while (len < valueLength)
-    {
-        uint16_t low = i.ReadNtohU16();
-        uint16_t high = i.ReadNtohU16();
-        Add(low, high);
-        len += 4;
-    }
-    return len;
-}
-
-void
-PortRangeTlvValue::Add(uint16_t portLow, uint16_t portHigh)
-{
-    PortRange tmp;
-    tmp.PortLow = portLow;
-    tmp.PortHigh = portHigh;
-    m_portRange->push_back(tmp);
-}
-
-PortRangeTlvValue::Iterator
-PortRangeTlvValue::Begin() const
-{
-    return m_portRange->begin();
-}
-
-PortRangeTlvValue::Iterator
-PortRangeTlvValue::End() const
-{
-    return m_portRange->end();
-}
-
-PortRangeTlvValue*
-PortRangeTlvValue::Copy() const
-{
-    auto tmp = new PortRangeTlvValue();
-    for (auto iter = m_portRange->begin(); iter != m_portRange->end(); ++iter)
-    {
-        tmp->Add((*iter).PortLow, (*iter).PortHigh);
-    }
-    return tmp;
-}
-
-// ==============================================================================
-
-ProtocolTlvValue::ProtocolTlvValue()
-{
-    m_protocol = new std::vector<uint8_t>;
-}
-
-ProtocolTlvValue::~ProtocolTlvValue()
-{
-    if (m_protocol != nullptr)
-    {
-        m_protocol->clear();
-        delete m_protocol;
-        m_protocol = nullptr;
-    }
-}
-
-uint32_t
-ProtocolTlvValue::GetSerializedSize() const
-{
-    return m_protocol->size();
-}
-
-void
-ProtocolTlvValue::Serialize(Buffer::Iterator i) const
-{
-    for (auto iter = m_protocol->begin(); iter != m_protocol->end(); ++iter)
-    {
-        i.WriteU8(*iter);
-    }
-}
-
-uint32_t
-ProtocolTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLength)
-{
-    uint64_t len = 0;
-    while (len < valueLength)
-    {
-        Add(i.ReadU8());
-        len++;
-    }
-    return len;
-}
-
-void
-ProtocolTlvValue::Add(uint8_t protocol)
-{
-    m_protocol->push_back(protocol);
-}
-
-ProtocolTlvValue::Iterator
-ProtocolTlvValue::Begin() const
-{
-    return m_protocol->begin();
-}
-
-ProtocolTlvValue::Iterator
-ProtocolTlvValue::End() const
-{
-    return m_protocol->end();
-}
-
-ProtocolTlvValue*
-ProtocolTlvValue::Copy() const
-{
-    auto tmp = new ProtocolTlvValue();
-    for (auto iter = m_protocol->begin(); iter != m_protocol->end(); ++iter)
-    {
-        tmp->Add(*iter);
-    }
-    return tmp;
-}
-
-// ==============================================================================
-
-Ipv4AddressTlvValue::Ipv4AddressTlvValue()
-{
-    m_ipv4Addr = new std::vector<Ipv4Addr>;
-}
-
-Ipv4AddressTlvValue::~Ipv4AddressTlvValue()
-{
-    if (m_ipv4Addr != nullptr)
-    {
-        m_ipv4Addr->clear();
-        delete m_ipv4Addr;
-        m_ipv4Addr = nullptr;
-    }
-}
-
-uint32_t
-Ipv4AddressTlvValue::GetSerializedSize() const
-{
-    return m_ipv4Addr->size() * 8; // IPv4 address and mask are 4 bytes each
-}
-
-void
-Ipv4AddressTlvValue::Serialize(Buffer::Iterator i) const
-{
-    for (auto iter = m_ipv4Addr->begin(); iter != m_ipv4Addr->end(); ++iter)
-    {
-        i.WriteHtonU32((*iter).Address.Get());
-        i.WriteHtonU32((*iter).Mask.Get());
-    }
-}
-
-uint32_t
-Ipv4AddressTlvValue::Deserialize(Buffer::Iterator i, uint64_t valueLength)
-{
-    uint64_t len = 0;
-    while (len < valueLength)
-    {
-        uint32_t addr = i.ReadNtohU32();
-        uint32_t mask = i.ReadNtohU32();
-        Add(Ipv4Address(addr), Ipv4Mask(mask));
-        len += 8;
-    }
-    return len;
-}
-
-void
-Ipv4AddressTlvValue::Add(Ipv4Address address, Ipv4Mask mask)
-{
-    m_ipv4Addr->push_back({address, mask});
-}
-
-Ipv4AddressTlvValue::Iterator
-Ipv4AddressTlvValue::Begin() const
-{
-    return m_ipv4Addr->begin();
-}
-
-Ipv4AddressTlvValue::Iterator
-Ipv4AddressTlvValue::End() const
-{
-    return m_ipv4Addr->end();
-}
-
-Ipv4AddressTlvValue*
-Ipv4AddressTlvValue::Copy() const
-{
-    auto tmp = new Ipv4AddressTlvValue();
-    for (auto iter = m_ipv4Addr->begin(); iter != m_ipv4Addr->end(); ++iter)
-    {
-        tmp->Add((*iter).Address, (*iter).Mask);
-    }
-    return tmp;
-}
-
-} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/model/wimax-tlv.h ns-3.46/src/wimax/model/wimax-tlv.h
--- ns-3.45/src/wimax/model/wimax-tlv.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/model/wimax-tlv.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,602 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-
-#ifndef WIMAX_TLV_H
-#define WIMAX_TLV_H
-
-#define WIMAX_TLV_EXTENDED_LENGTH_MASK 0x80
-
-#include "ns3/assert.h"
-#include "ns3/header.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/log.h"
-#include "ns3/uinteger.h"
-
-#include <cstdlib>
-#include <vector>
-
-namespace ns3
-{
-
-/**
- * @ingroup wimax
- * The value field of a tlv can take different values (uint8_t, uint16,
- * vector, ...). This class is a virtual interface
- * from which all the types of tlv values should derive
- */
-class TlvValue
-{
-  public:
-    virtual ~TlvValue()
-    {
-    }
-
-    /**
-     * Get serialized size in bytes
-     * @returns the serialized size
-     */
-    virtual uint32_t GetSerializedSize() const = 0;
-    /**
-     * Serialize to a buffer
-     * @param start the iterator
-     */
-    virtual void Serialize(Buffer::Iterator start) const = 0;
-    /**
-     * Deserialize from a buffer
-     * @param start the iterator
-     * @param valueLen the maximum length of the value
-     * @returns the
-     */
-    virtual uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLen) = 0;
-    /**
-     * Copy function
-     * @returns the TLV value
-     */
-    virtual TlvValue* Copy() const = 0;
-
-  private:
-};
-
-// =============================================================================
-/**
- * @ingroup wimax
- * @brief This class implements the Type-Len-Value structure channel encodings as described by "IEEE
- * Standard for Local and metropolitan area networks Part 16: Air Interface for Fixed Broadband
- * Wireless Access Systems"
- * 11. TLV encodings, page 645
- *
- */
-class Tlv : public Header
-{
-  public:
-    /// CommonTypes enumeration
-    enum CommonTypes
-    {
-        HMAC_TUPLE = 149,
-        MAC_VERSION_ENCODING = 148,
-        CURRENT_TRANSMIT_POWER = 147,
-        DOWNLINK_SERVICE_FLOW = 146,
-        UPLINK_SERVICE_FLOW = 145,
-        VENDOR_ID_EMCODING = 144,
-        VENDOR_SPECIFIC_INFORMATION = 143
-    };
-
-    /**
-     * Constructor
-     *
-     * @param type type
-     * @param length the length
-     * @param value TLV value
-     */
-    Tlv(uint8_t type, uint64_t length, const TlvValue& value);
-    Tlv();
-    ~Tlv() override;
-    /**
-     * Register this type.
-     * @return the TypeId.
-     */
-    static TypeId GetTypeId();
-    TypeId GetInstanceTypeId() const override;
-    void Print(std::ostream& os) const override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start) override;
-    /**
-     * Get size of length field
-     * @returns the size of length field
-     */
-    uint8_t GetSizeOfLen() const;
-    /**
-     * Get type value
-     * @returns the type
-     */
-    uint8_t GetType() const;
-    /**
-     * Get length value
-     * @returns the length
-     */
-    uint64_t GetLength() const;
-    /**
-     * Peek value
-     * @returns the TLV value
-     */
-    TlvValue* PeekValue();
-    /**
-     * Copy TLV
-     * @returns a pointer to a TLV copy
-     */
-    Tlv* Copy() const;
-    /**
-     * Copy TlvValue
-     * @returns the TLV value
-     */
-    TlvValue* CopyValue() const;
-    /**
-     * assignment operator
-     * @param o the TLV to assign
-     * @returns the TLV
-     */
-    Tlv& operator=(const Tlv& o);
-    /**
-     * type conversion operator
-     * @param tlv the TLV
-     */
-    Tlv(const Tlv& tlv);
-
-  private:
-    uint8_t m_type;    ///< type
-    uint64_t m_length; ///< length
-    TlvValue* m_value; ///< value
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief U8TlvValue class
- */
-class U8TlvValue : public TlvValue
-{
-  public:
-    /**
-     * Constructor
-     *
-     * @param value value to encode
-     */
-    U8TlvValue(uint8_t value);
-    U8TlvValue();
-    ~U8TlvValue() override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLen) override;
-    /**
-     * Deserialize from a buffer
-     * @param start the iterator
-     * @returns the size of the item
-     */
-    uint32_t Deserialize(Buffer::Iterator start);
-    /**
-     * Get value
-     * @returns the value
-     */
-    uint8_t GetValue() const;
-    /**
-     * Copy
-     * @returns a U8 TLV value
-     */
-    U8TlvValue* Copy() const override;
-
-  private:
-    uint8_t m_value; ///< value
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief U16TlvValue class
- */
-class U16TlvValue : public TlvValue
-{
-  public:
-    /**
-     * Constructor
-     *
-     * @param value value to encode
-     */
-    U16TlvValue(uint16_t value);
-    U16TlvValue();
-    ~U16TlvValue() override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLen) override;
-    /**
-     * Deserialize from a buffer
-     * @param start the iterator
-     * @returns the size
-     */
-    uint32_t Deserialize(Buffer::Iterator start);
-    /**
-     * Get value
-     * @returns the value
-     */
-    uint16_t GetValue() const;
-    /**
-     * Copy
-     * @returns the U16 TLV value
-     */
-    U16TlvValue* Copy() const override;
-
-  private:
-    uint16_t m_value; ///< value
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief U32TlvValue class
- */
-class U32TlvValue : public TlvValue
-{
-  public:
-    /**
-     * Constructor
-     *
-     * @param value to encode
-     */
-    U32TlvValue(uint32_t value);
-    U32TlvValue();
-    ~U32TlvValue() override;
-
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLen) override;
-    /**
-     * Deserialize from a buffer
-     * @param start the iterator
-     * @returns the size
-     */
-    uint32_t Deserialize(Buffer::Iterator start);
-    /**
-     * Get value
-     * @returns the value
-     */
-    uint32_t GetValue() const;
-    /**
-     * Copy
-     * @returns the U32 TLV Value
-     */
-    U32TlvValue* Copy() const override;
-
-  private:
-    uint32_t m_value; ///< value
-};
-
-// ==============================================================================
-
-/**
- * @ingroup wimax
- * @brief this class is used to implement a vector of values in one tlv value field
- */
-class VectorTlvValue : public TlvValue
-{
-  public:
-    /// TLV vector iterator typedef
-    typedef std::vector<Tlv*>::const_iterator Iterator;
-    VectorTlvValue();
-    ~VectorTlvValue() override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override = 0;
-    /**
-     * Begin iterator
-     * @returns the beginning element
-     */
-    Iterator Begin() const;
-    /**
-     * End iterator
-     * @returns the ending element
-     */
-    Iterator End() const;
-    /**
-     * Add a TLV
-     * @param val the TLV value
-     */
-    void Add(const Tlv& val);
-    /**
-     * Copy
-     * @returns the vector TLV value
-     */
-    VectorTlvValue* Copy() const override = 0;
-
-  private:
-    std::vector<Tlv*>* m_tlvList; ///< tlv list
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief SfVectorTlvValue class
- */
-class SfVectorTlvValue : public VectorTlvValue
-{
-  public:
-    /// Type enumeration
-    enum Type
-    {
-        SFID = 1,
-        CID = 2,
-        Service_Class_Name = 3,
-        reserved1 = 4,
-        QoS_Parameter_Set_Type = 5,
-        Traffic_Priority = 6,
-        Maximum_Sustained_Traffic_Rate = 7,
-        Maximum_Traffic_Burst = 8,
-        Minimum_Reserved_Traffic_Rate = 9,
-        Minimum_Tolerable_Traffic_Rate = 10,
-        Service_Flow_Scheduling_Type = 11,
-        Request_Transmission_Policy = 12,
-        Tolerated_Jitter = 13,
-        Maximum_Latency = 14,
-        Fixed_length_versus_Variable_length_SDU_Indicator = 15,
-        SDU_Size = 16,
-        Target_SAID = 17,
-        ARQ_Enable = 18,
-        ARQ_WINDOW_SIZE = 19,
-        ARQ_RETRY_TIMEOUT_Transmitter_Delay = 20,
-        ARQ_RETRY_TIMEOUT_Receiver_Delay = 21,
-        ARQ_BLOCK_LIFETIME = 22,
-        ARQ_SYNC_LOSS = 23,
-        ARQ_DELIVER_IN_ORDER = 24,
-        ARQ_PURGE_TIMEOUT = 25,
-        ARQ_BLOCK_SIZE = 26,
-        reserved2 = 27,
-        CS_Specification = 28,
-        IPV4_CS_Parameters = 100
-    };
-
-    SfVectorTlvValue();
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    SfVectorTlvValue* Copy() const override;
-};
-
-// ==============================================================================
-
-/**
- * @ingroup wimax
- * @brief this class implements the convergence sub-layer descriptor as a tlv vector
- */
-class CsParamVectorTlvValue : public VectorTlvValue
-{
-  public:
-    /// Type enumeration
-    enum Type
-    {
-        Classifier_DSC_Action = 1,
-        Packet_Classification_Rule = 3,
-    };
-
-    CsParamVectorTlvValue();
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    CsParamVectorTlvValue* Copy() const override;
-
-  private:
-};
-
-// ==============================================================================
-
-/**
- * @ingroup wimax
- * @brief this class implements the classifier descriptor as a tlv vector
- */
-class ClassificationRuleVectorTlvValue : public VectorTlvValue
-{
-  public:
-    /// ClassificationRuleTlvType enumeration
-    enum ClassificationRuleTlvType
-    {
-        Priority = 1,
-        ToS = 2,
-        Protocol = 3,
-        IP_src = 4,
-        IP_dst = 5,
-        Port_src = 6,
-        Port_dst = 7,
-        Index = 14,
-    };
-
-    ClassificationRuleVectorTlvValue();
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    ClassificationRuleVectorTlvValue* Copy() const override;
-
-  private:
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief TosTlvValue class
- */
-class TosTlvValue : public TlvValue
-{
-  public:
-    TosTlvValue();
-    /**
-     * Constructor
-     *
-     * @param low low value
-     * @param high high value
-     * @param mask the mask
-     */
-    TosTlvValue(uint8_t low, uint8_t high, uint8_t mask);
-    ~TosTlvValue() override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    /**
-     * Get low part
-     * @returns the low part
-     */
-    uint8_t GetLow() const;
-    /**
-     * Get high part
-     * @returns the high part
-     */
-    uint8_t GetHigh() const;
-    /**
-     * Get the mask
-     * @returns the mask
-     */
-    uint8_t GetMask() const;
-    /**
-     * Copy
-     * @returns the TOS TLV value
-     */
-    TosTlvValue* Copy() const override;
-
-  private:
-    uint8_t m_low;  ///< low
-    uint8_t m_high; ///< high
-    uint8_t m_mask; ///< mask
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief PortRangeTlvValue class
- */
-class PortRangeTlvValue : public TlvValue
-{
-  public:
-    /// PortRange structure
-    struct PortRange
-    {
-        uint16_t PortLow;  ///< low
-        uint16_t PortHigh; ///< high
-    };
-
-    /// PortRange vector iterator typedef
-    typedef std::vector<PortRange>::const_iterator Iterator;
-    PortRangeTlvValue();
-    ~PortRangeTlvValue() override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    /**
-     * Add a range
-     * @param portLow the low port of the range
-     * @param portHigh the high port of the range
-     */
-    void Add(uint16_t portLow, uint16_t portHigh);
-    /**
-     * Begin iterator
-     * @returns the beginning element
-     */
-    Iterator Begin() const;
-    /**
-     * End iterator
-     * @returns the ending element
-     */
-    Iterator End() const;
-    /**
-     * Copy
-     * @returns the port range tlv value
-     */
-    PortRangeTlvValue* Copy() const override;
-
-  private:
-    std::vector<PortRange>* m_portRange; ///< port range
-};
-
-// ==============================================================================
-/**
- * @ingroup wimax
- * @brief ProtocolTlvValue class
- */
-class ProtocolTlvValue : public TlvValue
-{
-  public:
-    ProtocolTlvValue();
-    ~ProtocolTlvValue() override;
-    /// Iterator typedef
-    typedef std::vector<uint8_t>::const_iterator Iterator;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    /**
-     * Add protocol number
-     * @param protocol the protocol number
-     */
-    void Add(uint8_t protocol);
-    /**
-     * Begin iterator
-     * @returns the beginning element
-     */
-    Iterator Begin() const;
-    /**
-     * End iterator
-     * @return the ending element
-     */
-    Iterator End() const;
-    /**
-     * Copy
-     * @returns the protocol tlv value
-     */
-    ProtocolTlvValue* Copy() const override;
-
-  private:
-    std::vector<uint8_t>* m_protocol; ///< protocol
-};
-
-// ==============================================================================
-
-/**
- * @ingroup wimax
- * @brief Ipv4AddressTlvValue class
- */
-class Ipv4AddressTlvValue : public TlvValue
-{
-  public:
-    /// Ipv4Addr structure
-    struct Ipv4Addr
-    {
-        Ipv4Address Address; ///< address
-        Ipv4Mask Mask;       ///< mask
-    };
-
-    /// IPv4 address vector iterator typedef
-    typedef std::vector<Ipv4Addr>::const_iterator Iterator;
-    Ipv4AddressTlvValue();
-    ~Ipv4AddressTlvValue() override;
-    uint32_t GetSerializedSize() const override;
-    void Serialize(Buffer::Iterator start) const override;
-    uint32_t Deserialize(Buffer::Iterator start, uint64_t valueLength) override;
-    /**
-     * Add IPv4 address and mask
-     * @param address the IPv4 address
-     * @param mask the IPv4 mask
-     */
-    void Add(Ipv4Address address, Ipv4Mask mask);
-    /**
-     * Begin iterator
-     * @returns the beginning element
-     */
-    Iterator Begin() const;
-    /**
-     * End iterator
-     * @returns the ending element
-     */
-    Iterator End() const;
-    Ipv4AddressTlvValue* Copy() const override;
-
-  private:
-    std::vector<Ipv4Addr>* m_ipv4Addr; ///< ipv4 addr
-};
-
-} // namespace ns3
-
-#endif /* WIMAX_TLV_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/examples-to-run.py ns-3.46/src/wimax/test/examples-to-run.py
--- ns-3.45/src/wimax/test/examples-to-run.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/examples-to-run.py	1969-12-31 16:00:00.000000000 -0800
@@ -1,21 +0,0 @@
-#! /usr/bin/env python3
-
-# A list of C++ examples to run in order to ensure that they remain
-# buildable and runnable over time.  Each tuple in the list contains
-#
-#     (example_name, do_run, do_valgrind_run).
-#
-# See test.py for more information.
-cpp_examples = [
-    ("wimax-simple", "True", "True"),
-    ("wimax-ipv4", "True", "True"),
-    ("wimax-multicast", "True", "True"),
-]
-
-# A list of Python examples to run in order to ensure that they remain
-# runnable over time.  Each tuple in the list contains
-#
-#     (example_name, do_run).
-#
-# See test.py for more information.
-python_examples = []
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/mac-messages-test.cc ns-3.46/src/wimax/test/mac-messages-test.cc
--- ns-3.45/src/wimax/test/mac-messages-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/mac-messages-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,120 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *
- */
-#include "ns3/mac-messages.h"
-#include "ns3/service-flow.h"
-#include "ns3/test.h"
-
-using namespace ns3;
-
-/**
- * @ingroup wimax
- * @defgroup wimax-test wimax module tests
- */
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the DSA request message.
- */
-class DsaRequestTestCase : public TestCase
-{
-  public:
-    DsaRequestTestCase();
-    ~DsaRequestTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-DsaRequestTestCase::DsaRequestTestCase()
-    : TestCase("Test the DSA request messages")
-{
-}
-
-DsaRequestTestCase::~DsaRequestTestCase()
-{
-}
-
-void
-DsaRequestTestCase::DoRun()
-{
-    IpcsClassifierRecord classifier = IpcsClassifierRecord();
-    CsParameters csParam(CsParameters::ADD, classifier);
-    ServiceFlow sf = ServiceFlow(ServiceFlow::SF_DIRECTION_DOWN);
-
-    sf.SetSfid(100);
-    sf.SetConvergenceSublayerParam(csParam);
-    sf.SetCsSpecification(ServiceFlow::IPV4);
-    sf.SetServiceSchedulingType(ServiceFlow::SF_TYPE_UGS);
-    sf.SetMaxSustainedTrafficRate(1000000);
-    sf.SetMinReservedTrafficRate(1000000);
-    sf.SetMinTolerableTrafficRate(1000000);
-    sf.SetMaximumLatency(10);
-    sf.SetMaxTrafficBurst(1000);
-    sf.SetTrafficPriority(1);
-
-    DsaReq dsaReq(sf);
-    Ptr<Packet> packet = Create<Packet>();
-    packet->AddHeader(dsaReq);
-
-    DsaReq dsaReqRecv;
-    packet->RemoveHeader(dsaReqRecv);
-
-    ServiceFlow sfRecv = dsaReqRecv.GetServiceFlow();
-
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetDirection(),
-                          ServiceFlow::SF_DIRECTION_DOWN,
-                          "The sfRecv had the wrong direction.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetSfid(), 100, "The sfRecv had the wrong sfid.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetCsSpecification(),
-                          ServiceFlow::IPV4,
-                          "The sfRecv had the wrong cs specification.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetServiceSchedulingType(),
-                          ServiceFlow::SF_TYPE_UGS,
-                          "The sfRecv had the wrong service scheduling type.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMaxSustainedTrafficRate(),
-                          1000000,
-                          "The sfRecv had the wrong maximum sustained traffic rate.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMinReservedTrafficRate(),
-                          1000000,
-                          "The sfRecv had the wrong minimum reserved traffic rate.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMinTolerableTrafficRate(),
-                          1000000,
-                          "The sfRecv had the wrong minimum tolerable traffic rate.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMaximumLatency(),
-                          10,
-                          "The sfRecv had the wrong maximum latency.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMaxTrafficBurst(),
-                          1000,
-                          "The sfRecv had the wrong maximum traffic burst.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetTrafficPriority(),
-                          1,
-                          "The sfRecv had the wrong traffic priority.");
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax Mac Messages Test Suite
- */
-class Ns3WimaxMacMessagesTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxMacMessagesTestSuite();
-};
-
-Ns3WimaxMacMessagesTestSuite::Ns3WimaxMacMessagesTestSuite()
-    : TestSuite("wimax-mac-messages", Type::UNIT)
-{
-    AddTestCase(new DsaRequestTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxMacMessagesTestSuite ns3WimaxMacMessagesTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/phy-test.cc ns-3.46/src/wimax/test/phy-test.cc
--- ns-3.45/src/wimax/test/phy-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/phy-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,186 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-#include "ns3/log.h"
-#include "ns3/net-device-container.h"
-#include "ns3/node-container.h"
-#include "ns3/simulator.h"
-#include "ns3/snr-to-block-error-rate-manager.h"
-#include "ns3/test.h"
-#include "ns3/wimax-helper.h"
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE("WimaxPhyTest");
-
-/*
- * Configure a network with 3 SS and 1 BS
- * Install a SIMPLE OFDM PHY layer on all nodes and check that all SSs
- * could register with the BS
- *
- */
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax Simple OFDM Test Case
- */
-class Ns3WimaxSimpleOFDMTestCase : public TestCase
-{
-  public:
-    Ns3WimaxSimpleOFDMTestCase();
-    ~Ns3WimaxSimpleOFDMTestCase() override;
-
-  private:
-    void DoRun() override;
-    /**
-     * Run once function
-     * @param FrameDuration the frame duration
-     * @returns true if successful
-     */
-    bool DoRunOnce(double FrameDuration);
-};
-
-Ns3WimaxSimpleOFDMTestCase::Ns3WimaxSimpleOFDMTestCase()
-    : TestCase("Test the Phy model with different frame durations")
-{
-}
-
-Ns3WimaxSimpleOFDMTestCase::~Ns3WimaxSimpleOFDMTestCase()
-{
-}
-
-bool
-Ns3WimaxSimpleOFDMTestCase::DoRunOnce(double FrameDuration)
-{
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-    ssNodes.Create(3);
-    bsNodes.Create(1);
-
-    WimaxHelper wimax;
-
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler,
-                           FrameDuration);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler,
-                           FrameDuration);
-
-    Simulator::Stop(Seconds(1));
-    Simulator::Run();
-    for (int i = 0; i < 3; i++)
-    {
-        if (!ssDevs.Get(i)->GetObject<SubscriberStationNetDevice>()->IsRegistered())
-        {
-            NS_LOG_DEBUG("SS[" << i << "] not registered");
-            return true; // Test fail because SS[i] is not registered
-        }
-    }
-    Simulator::Destroy();
-    return false; // Test was ok, all the SSs are registered
-}
-
-void
-Ns3WimaxSimpleOFDMTestCase::DoRun()
-{
-    double frameDuratioTab[7] = {0.0025, 0.004, 0.005, 0.008, 0.01, 0.0125, 0.02};
-    for (int i = 0; i < 7; i++)
-    {
-        NS_LOG_DEBUG("Frame Duration = " << frameDuratioTab[i]);
-        if (DoRunOnce(frameDuratioTab[i]))
-        {
-            return;
-        }
-    }
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the SNr tom block error rate module
- */
-class Ns3WimaxSNRtoBLERTestCase : public TestCase
-{
-  public:
-    Ns3WimaxSNRtoBLERTestCase();
-    ~Ns3WimaxSNRtoBLERTestCase() override;
-
-  private:
-    void DoRun() override;
-    /**
-     * Run once function
-     * @param modulationType the modulation type
-     * @returns true if successful
-     */
-    bool DoRunOnce(uint8_t modulationType);
-};
-
-Ns3WimaxSNRtoBLERTestCase::Ns3WimaxSNRtoBLERTestCase()
-    : TestCase("Test the SNR to block error rate module")
-{
-}
-
-Ns3WimaxSNRtoBLERTestCase::~Ns3WimaxSNRtoBLERTestCase()
-{
-}
-
-bool
-Ns3WimaxSNRtoBLERTestCase::DoRunOnce(uint8_t modulationType)
-{
-    SNRToBlockErrorRateManager l_SNRToBlockErrorRateManager;
-    l_SNRToBlockErrorRateManager.LoadTraces();
-    SNRToBlockErrorRateRecord* BLERRec;
-
-    for (double i = -5; i < 40; i += 0.1)
-    {
-        BLERRec = l_SNRToBlockErrorRateManager.GetSNRToBlockErrorRateRecord(i, modulationType);
-        delete BLERRec;
-    }
-    return false;
-}
-
-void
-Ns3WimaxSNRtoBLERTestCase::DoRun()
-{
-    for (int i = 0; i < 7; i++)
-    {
-        DoRunOnce(i);
-    }
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief The test suite
- */
-class Ns3WimaxPhyTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxPhyTestSuite();
-};
-
-Ns3WimaxPhyTestSuite::Ns3WimaxPhyTestSuite()
-    : TestSuite("wimax-phy-layer", Type::UNIT)
-{
-    AddTestCase(new Ns3WimaxSNRtoBLERTestCase, TestCase::Duration::QUICK);
-    AddTestCase(new Ns3WimaxSimpleOFDMTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxPhyTestSuite ns3WimaxPhyTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/qos-test.cc ns-3.46/src/wimax/test/qos-test.cc
--- ns-3.45/src/wimax/test/qos-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/qos-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,309 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-#include "ns3/internet-stack-helper.h"
-#include "ns3/ipcs-classifier-record.h"
-#include "ns3/ipv4-address-helper.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4-interface-container.h"
-#include "ns3/log.h"
-#include "ns3/net-device-container.h"
-#include "ns3/node-container.h"
-#include "ns3/service-flow.h"
-#include "ns3/simulator.h"
-#include "ns3/test.h"
-#include "ns3/wimax-helper.h"
-
-using namespace ns3;
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax Scheduling Test Case
- */
-class Ns3WimaxSchedulingTestCase : public TestCase
-{
-  public:
-    Ns3WimaxSchedulingTestCase();
-    ~Ns3WimaxSchedulingTestCase() override;
-
-  private:
-    void DoRun() override;
-    /**
-     * Run once function
-     * @param scheduler the wimax scheduler type
-     * @returns true if successful
-     */
-    bool DoRunOnce(WimaxHelper::SchedulerType scheduler);
-};
-
-Ns3WimaxSchedulingTestCase::Ns3WimaxSchedulingTestCase()
-    : TestCase("Test the 2 different schedulers")
-{
-}
-
-Ns3WimaxSchedulingTestCase::~Ns3WimaxSchedulingTestCase()
-{
-}
-
-bool
-Ns3WimaxSchedulingTestCase::DoRunOnce(WimaxHelper::SchedulerType scheduler)
-{
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-    ssNodes.Create(2);
-    bsNodes.Create(1);
-    WimaxHelper wimax;
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->SetModulationType(
-        WimaxPhy::MODULATION_TYPE_QAM16_12);
-    ssDevs.Get(1)->GetObject<SubscriberStationNetDevice>()->SetModulationType(
-        WimaxPhy::MODULATION_TYPE_QAM16_12);
-
-    InternetStackHelper stack;
-    stack.Install(bsNodes);
-    stack.Install(ssNodes);
-
-    Ipv4AddressHelper address;
-    address.SetBase("10.1.1.0", "255.255.255.0");
-
-    Ipv4InterfaceContainer SSinterfaces = address.Assign(ssDevs);
-    Ipv4InterfaceContainer BSinterface = address.Assign(bsDevs);
-
-    /*------------------------------*/
-    //  UdpServerHelper udpServer;
-    //  ApplicationContainer serverApps;
-    //  UdpClientHelper udpClient;
-    //  ApplicationContainer clientApps;
-    //
-    //  udpServer = UdpServerHelper (100);
-    //  serverApps = udpServer.Install (ssNodes.Get (0));
-    //  serverApps.Start (Seconds (1));
-    //  serverApps.Stop (Seconds (2));
-    //
-    //  udpClient = UdpClientHelper (SSinterfaces.GetAddress (0), 100);
-    //  udpClient.SetAttribute ("MaxPackets", UintegerValue (1200));
-    //  udpClient.SetAttribute ("Interval", TimeValue (Seconds (0.12)));
-    //  udpClient.SetAttribute ("PacketSize", UintegerValue (1024));
-    //  clientApps = udpClient.Install (ssNodes.Get (1));
-    //  clientApps.Start (Seconds (1));
-    //  clientApps.Stop (Seconds (2));
-
-    Simulator::Stop(Seconds(2 + 0.1));
-
-    IpcsClassifierRecord DlClassifierUgs(Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         SSinterfaces.GetAddress(0),
-                                         Ipv4Mask("255.255.255.255"),
-                                         0,
-                                         65000,
-                                         100,
-                                         100,
-                                         17,
-                                         1);
-    ServiceFlow DlServiceFlowUgs = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_DOWN,
-                                                           ServiceFlow::SF_TYPE_RTPS,
-                                                           DlClassifierUgs);
-    IpcsClassifierRecord UlClassifierUgs(SSinterfaces.GetAddress(1),
-                                         Ipv4Mask("255.255.255.255"),
-                                         Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         0,
-                                         65000,
-                                         100,
-                                         100,
-                                         17,
-                                         1);
-    ServiceFlow UlServiceFlowUgs = wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_UP,
-                                                           ServiceFlow::SF_TYPE_RTPS,
-                                                           UlClassifierUgs);
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->AddServiceFlow(DlServiceFlowUgs);
-    ssDevs.Get(1)->GetObject<SubscriberStationNetDevice>()->AddServiceFlow(UlServiceFlowUgs);
-
-    Simulator::Run();
-    Simulator::Destroy();
-    return false;
-}
-
-void
-Ns3WimaxSchedulingTestCase::DoRun()
-{
-    if (DoRunOnce(WimaxHelper::SCHED_TYPE_SIMPLE))
-    {
-        return;
-    }
-    if (DoRunOnce(WimaxHelper::SCHED_TYPE_RTPS))
-    {
-        return;
-    }
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax SF Type Test Case
- */
-class Ns3WimaxSFTypeTestCase : public TestCase
-{
-  public:
-    Ns3WimaxSFTypeTestCase();
-    ~Ns3WimaxSFTypeTestCase() override;
-
-  private:
-    void DoRun() override;
-    /**
-     * Run once function
-     * @param schedulingType the scheduling type
-     * @returns true if successful
-     */
-    bool DoRunOnce(ServiceFlow::SchedulingType schedulingType);
-};
-
-Ns3WimaxSFTypeTestCase::Ns3WimaxSFTypeTestCase()
-    : TestCase("Test the service flow scheduling types")
-{
-}
-
-Ns3WimaxSFTypeTestCase::~Ns3WimaxSFTypeTestCase()
-{
-}
-
-bool
-Ns3WimaxSFTypeTestCase::DoRunOnce(ServiceFlow::SchedulingType schedulingType)
-{
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-    ssNodes.Create(2);
-    bsNodes.Create(1);
-    WimaxHelper wimax;
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           WimaxHelper::SCHED_TYPE_SIMPLE);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           WimaxHelper::SCHED_TYPE_SIMPLE);
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->SetModulationType(
-        WimaxPhy::MODULATION_TYPE_QAM16_12);
-    ssDevs.Get(1)->GetObject<SubscriberStationNetDevice>()->SetModulationType(
-        WimaxPhy::MODULATION_TYPE_QAM16_12);
-
-    InternetStackHelper stack;
-    stack.Install(bsNodes);
-    stack.Install(ssNodes);
-
-    Ipv4AddressHelper address;
-    address.SetBase("10.1.1.0", "255.255.255.0");
-
-    Ipv4InterfaceContainer SSinterfaces = address.Assign(ssDevs);
-    Ipv4InterfaceContainer BSinterface = address.Assign(bsDevs);
-
-    /*------------------------------*/
-    //  UdpServerHelper udpServer;
-    //  ApplicationContainer serverApps;
-    //  UdpClientHelper udpClient;
-    //  ApplicationContainer clientApps;
-    //
-    //  udpServer = UdpServerHelper (100);
-    //  serverApps = udpServer.Install (ssNodes.Get (0));
-    //  serverApps.Start (Seconds (1));
-    //  serverApps.Stop (Seconds (2));
-    //
-    //  udpClient = UdpClientHelper (SSinterfaces.GetAddress (0), 100);
-    //  udpClient.SetAttribute ("MaxPackets", UintegerValue (1200));
-    //  udpClient.SetAttribute ("Interval", TimeValue (Seconds (0.12)));
-    //  udpClient.SetAttribute ("PacketSize", UintegerValue (1024));
-    //  clientApps = udpClient.Install (ssNodes.Get (1));
-    //  clientApps.Start (Seconds (1));
-    //  clientApps.Stop (Seconds (2));
-
-    Simulator::Stop(Seconds(2 + 0.1));
-
-    IpcsClassifierRecord DlClassifier(Ipv4Address("0.0.0.0"),
-                                      Ipv4Mask("0.0.0.0"),
-                                      SSinterfaces.GetAddress(0),
-                                      Ipv4Mask("255.255.255.255"),
-                                      0,
-                                      65000,
-                                      100,
-                                      100,
-                                      17,
-                                      1);
-    ServiceFlow DlServiceFlow =
-        wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_DOWN, schedulingType, DlClassifier);
-    IpcsClassifierRecord UlClassifier(SSinterfaces.GetAddress(1),
-                                      Ipv4Mask("255.255.255.255"),
-                                      Ipv4Address("0.0.0.0"),
-                                      Ipv4Mask("0.0.0.0"),
-                                      0,
-                                      65000,
-                                      100,
-                                      100,
-                                      17,
-                                      1);
-    ServiceFlow UlServiceFlow =
-        wimax.CreateServiceFlow(ServiceFlow::SF_DIRECTION_UP, schedulingType, UlClassifier);
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->AddServiceFlow(DlServiceFlow);
-    ssDevs.Get(1)->GetObject<SubscriberStationNetDevice>()->AddServiceFlow(UlServiceFlow);
-
-    Simulator::Run();
-    Simulator::Destroy();
-    return false;
-}
-
-void
-Ns3WimaxSFTypeTestCase::DoRun()
-{
-    if (DoRunOnce(ServiceFlow::SF_TYPE_UGS))
-    {
-        return;
-    }
-    if (DoRunOnce(ServiceFlow::SF_TYPE_RTPS))
-    {
-        return;
-    }
-    if (DoRunOnce(ServiceFlow::SF_TYPE_BE))
-    {
-        return;
-    }
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax QoS Test Suite
- */
-class Ns3WimaxQoSTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxQoSTestSuite();
-};
-
-Ns3WimaxQoSTestSuite::Ns3WimaxQoSTestSuite()
-    : TestSuite("wimax-qos", Type::SYSTEM)
-{
-    AddTestCase(new Ns3WimaxSFTypeTestCase, TestCase::Duration::QUICK);
-    AddTestCase(new Ns3WimaxSchedulingTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxQoSTestSuite ns3WimaxQoSTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/ss-mac-test.cc ns-3.46/src/wimax/test/ss-mac-test.cc
--- ns-3.45/src/wimax/test/ss-mac-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/ss-mac-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,164 +0,0 @@
-/*
- *  Copyright (c) 2007,2008, 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- * Author: Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- */
-#include "ns3/log.h"
-#include "ns3/net-device-container.h"
-#include "ns3/node-container.h"
-#include "ns3/simulator.h"
-#include "ns3/test.h"
-#include "ns3/wimax-helper.h"
-
-using namespace ns3;
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the network entry procedure.
- * Create a network with a BS and 10 SS and check that all the SS perform the
- * network entry correctly
- *
- */
-class Ns3WimaxNetworkEntryTestCase : public TestCase
-{
-  public:
-    Ns3WimaxNetworkEntryTestCase();
-    ~Ns3WimaxNetworkEntryTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-Ns3WimaxNetworkEntryTestCase::Ns3WimaxNetworkEntryTestCase()
-    : TestCase("Test the network entry procedure")
-{
-}
-
-Ns3WimaxNetworkEntryTestCase::~Ns3WimaxNetworkEntryTestCase()
-{
-}
-
-void
-Ns3WimaxNetworkEntryTestCase::DoRun()
-{
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-
-    ssNodes.Create(10);
-    bsNodes.Create(1);
-
-    WimaxHelper wimax;
-
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    Simulator::Stop(Seconds(1));
-    Simulator::Run();
-    for (int i = 0; i < 10; i++)
-    {
-        NS_TEST_EXPECT_MSG_EQ(
-            ssDevs.Get(i)->GetObject<SubscriberStationNetDevice>()->IsRegistered(),
-            true,
-            "SS[" << i << "] IsNotRegistered");
-    }
-    Simulator::Destroy();
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test if the management connections are correctly setup.
- * Create a network with a BS and 10 SS and check that the management
- * connections are correctly setup for all SS
- *
- */
-class Ns3WimaxManagementConnectionsTestCase : public TestCase
-{
-  public:
-    Ns3WimaxManagementConnectionsTestCase();
-    ~Ns3WimaxManagementConnectionsTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-Ns3WimaxManagementConnectionsTestCase::Ns3WimaxManagementConnectionsTestCase()
-    : TestCase("Test if the management connections are correctly setup")
-{
-}
-
-Ns3WimaxManagementConnectionsTestCase::~Ns3WimaxManagementConnectionsTestCase()
-{
-}
-
-void
-Ns3WimaxManagementConnectionsTestCase::DoRun()
-{
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-
-    ssNodes.Create(10);
-    bsNodes.Create(1);
-
-    WimaxHelper wimax;
-
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    Simulator::Stop(Seconds(1));
-    Simulator::Run();
-    for (int i = 0; i < 10; i++)
-    {
-        NS_TEST_EXPECT_MSG_EQ(ssDevs.Get(i)
-                                  ->GetObject<SubscriberStationNetDevice>()
-                                  ->GetAreManagementConnectionsAllocated(),
-                              true,
-                              "Management connections for SS[" << i << "] are not allocated");
-    }
-    Simulator::Destroy();
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax SS Mac Test Suite
- */
-class Ns3WimaxSSMacTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxSSMacTestSuite();
-};
-
-Ns3WimaxSSMacTestSuite::Ns3WimaxSSMacTestSuite()
-    : TestSuite("wimax-ss-mac-layer", Type::UNIT)
-{
-    AddTestCase(new Ns3WimaxNetworkEntryTestCase, TestCase::Duration::QUICK);
-    AddTestCase(new Ns3WimaxManagementConnectionsTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxSSMacTestSuite ns3WimaxSSMacTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/wimax-fragmentation-test.cc ns-3.46/src/wimax/test/wimax-fragmentation-test.cc
--- ns-3.45/src/wimax/test/wimax-fragmentation-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/wimax-fragmentation-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,152 +0,0 @@
-/*
- *  Copyright (c) 2009-2010 TELEMATICS LAB - Poliotecnico di Bari
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Giuseppe Piro <g.piro@poliba.it>
- *                       <peppe.piro@gmail.com>
- */
-#include "ns3/cid.h"
-#include "ns3/log.h"
-#include "ns3/mac-messages.h"
-#include "ns3/packet.h"
-#include "ns3/ptr.h"
-#include "ns3/simulator.h"
-#include "ns3/test.h"
-#include "ns3/wimax-connection.h"
-#include "ns3/wimax-mac-header.h"
-
-using namespace ns3;
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the wimax packet fragmentation.
- */
-class Ns3WimaxFragmentationTestCase : public TestCase
-{
-  public:
-    Ns3WimaxFragmentationTestCase();
-    ~Ns3WimaxFragmentationTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-Ns3WimaxFragmentationTestCase::Ns3WimaxFragmentationTestCase()
-    : TestCase("Test the packet fragmentation and defragmentation.")
-{
-}
-
-Ns3WimaxFragmentationTestCase::~Ns3WimaxFragmentationTestCase()
-{
-}
-
-void
-Ns3WimaxFragmentationTestCase::DoRun()
-{
-    GenericMacHeader gnrcMacHdr;
-    ManagementMessageType msgType;
-    FragmentationSubheader fragSubhdr;
-    GenericMacHeader hdr;
-
-    Cid cid;
-    auto connectionTx = new WimaxConnection(cid, Cid::TRANSPORT);
-    auto connectionRx = new WimaxConnection(cid, Cid::TRANSPORT);
-
-    // A Packet of 1000 bytes has been created.
-    // It will be fragmentated into 4 fragments and then defragmentated into fullPacket.
-    Ptr<Packet> packet = Create<Packet>(1000);
-    Ptr<Packet> fragment;
-    Ptr<Packet> fullPacket = Create<Packet>();
-
-    // Enqueued packet
-    hdr.SetLen(packet->GetSize() + hdr.GetSerializedSize());
-    hdr.SetCid(connectionTx->GetCid());
-    MacHeaderType::HeaderType packetType = MacHeaderType::HEADER_TYPE_GENERIC;
-
-    connectionTx->Enqueue(packet, packetType, hdr);
-
-    uint32_t availableByteForFragment = 280;
-    for (int i = 0; i < 4; i++)
-    {
-        // dequeue a fragment
-        if (connectionTx->GetQueue()->GetFirstPacketRequiredByte(packetType) >
-            availableByteForFragment)
-        {
-            fragment = connectionTx->Dequeue(packetType, availableByteForFragment);
-        }
-        else
-        {
-            fragment = connectionTx->Dequeue(packetType);
-        }
-        // *** send packet -----> receive packet ----**
-
-        // check if receive packet is a fragment
-        fragment->RemoveHeader(gnrcMacHdr);
-        uint8_t type = gnrcMacHdr.GetType();
-        if (type)
-        {
-            // Check if there is a fragmentation Subheader
-            NS_TEST_EXPECT_MSG_EQ(((type >> 2) & 1), 1, "The packet is not a fragment");
-        }
-
-        // remove header from the received fragment
-        fragment->RemoveHeader(fragSubhdr);
-        uint32_t fc = fragSubhdr.GetFc();
-
-        NS_TEST_EXPECT_MSG_EQ((fc == 1 && i != 0), false, "The fragment in not the first one");
-        NS_TEST_EXPECT_MSG_EQ((fc == 2 && i != 3), false, "The fragment in not the latest one");
-        NS_TEST_EXPECT_MSG_EQ(((fc == 3 && i != 1) && (fc == 3 && i != 2)),
-                              false,
-                              "The fragment in not the middle one");
-
-        if (fc != 2)
-        {
-            // This is the first or middle fragment.
-            // Take the fragment queue, store the fragment into the queue
-            connectionRx->FragmentEnqueue(fragment);
-        }
-        else
-        {
-            // This is the latest fragment.
-            // Take the fragment queue, defragment a packet and send it to the upper layer
-            connectionRx->FragmentEnqueue(fragment);
-            WimaxConnection::FragmentsQueue fragmentsQueue = connectionRx->GetFragmentsQueue();
-
-            // DEFRAGMENTATION
-            for (auto iter = fragmentsQueue.begin(); iter != fragmentsQueue.end(); ++iter)
-            {
-                // Create the whole Packet
-                fullPacket->AddAtEnd(*iter);
-            }
-            connectionRx->ClearFragmentsQueue();
-
-            NS_TEST_EXPECT_MSG_EQ(fullPacket->GetSize(), 1000, "The defragmentation is incorrect");
-        }
-    }
-    delete connectionTx;
-    delete connectionRx;
-    Simulator::Destroy();
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax Fragmentation Test Suite
- */
-class Ns3WimaxFragmentationTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxFragmentationTestSuite();
-};
-
-Ns3WimaxFragmentationTestSuite::Ns3WimaxFragmentationTestSuite()
-    : TestSuite("wimax-fragmentation", Type::UNIT)
-{
-    AddTestCase(new Ns3WimaxFragmentationTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxFragmentationTestSuite ns3WimaxFragmentationTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/wimax-service-flow-test.cc ns-3.46/src/wimax/test/wimax-service-flow-test.cc
--- ns-3.45/src/wimax/test/wimax-service-flow-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/wimax-service-flow-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,160 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- *
- */
-#include "ns3/cs-parameters.h"
-#include "ns3/internet-stack-helper.h"
-#include "ns3/ipcs-classifier-record.h"
-#include "ns3/ipv4-address-helper.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4-interface-container.h"
-#include "ns3/service-flow.h"
-#include "ns3/simulator.h"
-#include "ns3/test.h"
-#include "ns3/wimax-helper.h"
-
-using namespace ns3;
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the service flow creation.
- */
-class Ns3WimaxSfCreationTestCase : public TestCase
-{
-  public:
-    Ns3WimaxSfCreationTestCase();
-    ~Ns3WimaxSfCreationTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-Ns3WimaxSfCreationTestCase::Ns3WimaxSfCreationTestCase()
-    : TestCase("Test the service flow tlv implementation.")
-{
-}
-
-Ns3WimaxSfCreationTestCase::~Ns3WimaxSfCreationTestCase()
-{
-}
-
-void
-Ns3WimaxSfCreationTestCase::DoRun()
-{
-    // default values
-    int duration = 2;
-    WimaxHelper::SchedulerType scheduler = WimaxHelper::SCHED_TYPE_SIMPLE;
-
-    NodeContainer ssNodes;
-    NodeContainer bsNodes;
-
-    ssNodes.Create(1);
-    bsNodes.Create(1);
-
-    WimaxHelper wimax;
-
-    NetDeviceContainer ssDevs;
-    NetDeviceContainer bsDevs;
-
-    ssDevs = wimax.Install(ssNodes,
-                           WimaxHelper::DEVICE_TYPE_SUBSCRIBER_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-    bsDevs = wimax.Install(bsNodes,
-                           WimaxHelper::DEVICE_TYPE_BASE_STATION,
-                           WimaxHelper::SIMPLE_PHY_TYPE_OFDM,
-                           scheduler);
-
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->SetModulationType(
-        WimaxPhy::MODULATION_TYPE_QAM16_12);
-    bsDevs.Get(0)->GetObject<BaseStationNetDevice>();
-
-    InternetStackHelper stack;
-    stack.Install(bsNodes);
-    stack.Install(ssNodes);
-
-    Ipv4AddressHelper address;
-    address.SetBase("10.1.1.0", "255.255.255.0");
-
-    Ipv4InterfaceContainer SSinterfaces = address.Assign(ssDevs);
-    Ipv4InterfaceContainer BSinterface = address.Assign(bsDevs);
-
-    // Create one UGS Downlink service flow between the ss and the bs
-    auto DlServiceFlowUgs = new ServiceFlow(ServiceFlow::SF_DIRECTION_DOWN);
-    IpcsClassifierRecord DlClassifierUgs(Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         3000,
-                                         3000,
-                                         0,
-                                         35000,
-                                         17,
-                                         1);
-    CsParameters DlcsParam(CsParameters::ADD, DlClassifierUgs);
-    DlServiceFlowUgs->SetConvergenceSublayerParam(DlcsParam);
-    DlServiceFlowUgs->SetCsSpecification(ServiceFlow::IPV4);
-    DlServiceFlowUgs->SetServiceSchedulingType(ServiceFlow::SF_TYPE_UGS);
-    DlServiceFlowUgs->SetMaxSustainedTrafficRate(1000000);
-    DlServiceFlowUgs->SetMinReservedTrafficRate(1000000);
-    DlServiceFlowUgs->SetMinTolerableTrafficRate(1000000);
-    DlServiceFlowUgs->SetMaximumLatency(10);
-    DlServiceFlowUgs->SetMaxTrafficBurst(1000);
-    DlServiceFlowUgs->SetTrafficPriority(1);
-
-    // Create one UGS Uplink service flow between the ss and the bs
-    auto UlServiceFlowUgs = new ServiceFlow(ServiceFlow::SF_DIRECTION_UP);
-    IpcsClassifierRecord UlClassifierUgs(Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         Ipv4Address("0.0.0.0"),
-                                         Ipv4Mask("0.0.0.0"),
-                                         0,
-                                         35000,
-                                         3000,
-                                         3000,
-                                         17,
-                                         1);
-    CsParameters UlcsParam(CsParameters::ADD, UlClassifierUgs);
-    UlServiceFlowUgs->SetConvergenceSublayerParam(UlcsParam);
-    UlServiceFlowUgs->SetCsSpecification(ServiceFlow::IPV4);
-    UlServiceFlowUgs->SetServiceSchedulingType(ServiceFlow::SF_TYPE_UGS);
-    UlServiceFlowUgs->SetMaxSustainedTrafficRate(1000000);
-    UlServiceFlowUgs->SetMinReservedTrafficRate(1000000);
-    UlServiceFlowUgs->SetMinTolerableTrafficRate(1000000);
-    UlServiceFlowUgs->SetMaximumLatency(10);
-    UlServiceFlowUgs->SetMaxTrafficBurst(1000);
-    UlServiceFlowUgs->SetTrafficPriority(1);
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->AddServiceFlow(DlServiceFlowUgs);
-    ssDevs.Get(0)->GetObject<SubscriberStationNetDevice>()->AddServiceFlow(UlServiceFlowUgs);
-
-    Simulator::Stop(Seconds(duration));
-    Simulator::Run();
-    Simulator::Destroy();
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax Service Flow Test Suite
- */
-class Ns3WimaxServiceFlowTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxServiceFlowTestSuite();
-};
-
-Ns3WimaxServiceFlowTestSuite::Ns3WimaxServiceFlowTestSuite()
-    : TestSuite("wimax-service-flow", Type::UNIT)
-{
-    AddTestCase(new Ns3WimaxSfCreationTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxServiceFlowTestSuite ns3WimaxServiceFlowTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/wimax/test/wimax-tlv-test.cc ns-3.46/src/wimax/test/wimax-tlv-test.cc
--- ns-3.45/src/wimax/test/wimax-tlv-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/wimax/test/wimax-tlv-test.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,222 +0,0 @@
-/*
- *  Copyright (c) 2009 INRIA, UDcast
- *
- * SPDX-License-Identifier: GPL-2.0-only
- *
- *         Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
- *                              <amine.ismail@udcast.com>
- *
- */
-#include "ns3/cs-parameters.h"
-#include "ns3/ipcs-classifier-record.h"
-#include "ns3/log.h"
-#include "ns3/packet.h"
-#include "ns3/ptr.h"
-#include "ns3/service-flow.h"
-#include "ns3/test.h"
-#include "ns3/wimax-helper.h"
-#include "ns3/wimax-tlv.h"
-
-using namespace ns3;
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the wimax tlv implementation.
- */
-class Ns3WimaxCsParamTlvTestCase : public TestCase
-{
-  public:
-    Ns3WimaxCsParamTlvTestCase();
-    ~Ns3WimaxCsParamTlvTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-Ns3WimaxCsParamTlvTestCase::Ns3WimaxCsParamTlvTestCase()
-    : TestCase("Test the CS parameters tlv implementation.")
-{
-}
-
-Ns3WimaxCsParamTlvTestCase::~Ns3WimaxCsParamTlvTestCase()
-{
-}
-
-void
-Ns3WimaxCsParamTlvTestCase::DoRun()
-{
-    IpcsClassifierRecord classifier(Ipv4Address("10.0.0.0"),
-                                    Ipv4Mask("255.0.0.0"),
-                                    Ipv4Address("11.0.0.0"),
-                                    Ipv4Mask("255.0.0.0"),
-                                    1000,
-                                    1100,
-                                    3000,
-                                    3100,
-                                    17,
-                                    1);
-
-    classifier.AddSrcAddr(Ipv4Address("1.0.0.0"), Ipv4Mask("255.0.0.0"));
-    classifier.AddDstAddr(Ipv4Address("16.0.0.0"), Ipv4Mask("255.0.0.0"));
-    classifier.AddProtocol(6);
-    classifier.AddSrcPortRange(1, 2);
-    classifier.AddDstPortRange(4000, 4100);
-    classifier.SetIndex(1);
-
-    CsParameters csParam(CsParameters::ADD, classifier);
-
-    SfVectorTlvValue sfVectorTlvValue;
-    sfVectorTlvValue.Add(csParam.ToTlv());
-
-    Tlv tlvSent(145, sfVectorTlvValue.GetSerializedSize(), sfVectorTlvValue);
-    Ptr<Packet> packet = Create<Packet>();
-    packet->AddHeader(tlvSent);
-
-    Tlv tlvReceived;
-    packet->RemoveHeader(tlvReceived);
-    if (tlvReceived.GetType() == Tlv::UPLINK_SERVICE_FLOW)
-    {
-        auto sfVecValue = (SfVectorTlvValue*)tlvReceived.PeekValue();
-        for (auto iter = sfVecValue->Begin(); iter != sfVecValue->End(); ++iter)
-        {
-            if ((*iter)->GetType() == SfVectorTlvValue::IPV4_CS_Parameters)
-            {
-                CsParameters csParamsRecv(*(*iter));
-                IpcsClassifierRecord classifier = csParamsRecv.GetPacketClassifierRule();
-
-                NS_TEST_ASSERT_MSG_EQ(!classifier.CheckMatch(Ipv4Address("10.1.1.1"),
-                                                             Ipv4Address("16.1.1.1"),
-                                                             1050,
-                                                             3050,
-                                                             17),
-                                      false,
-                                      "The classifier address did not match.");
-                NS_TEST_ASSERT_MSG_EQ(!classifier.CheckMatch(Ipv4Address("10.1.5.1"),
-                                                             Ipv4Address("11.1.1.23"),
-                                                             1070,
-                                                             3040,
-                                                             6),
-                                      false,
-                                      "The classifier address did not match.");
-                NS_TEST_ASSERT_MSG_EQ(classifier.CheckMatch(Ipv4Address("11.1.1.1"),
-                                                            Ipv4Address("17.1.1.1"),
-                                                            1050,
-                                                            3050,
-                                                            17),
-                                      false,
-                                      "The classifier addresses matched.");
-                NS_TEST_ASSERT_MSG_EQ(classifier.CheckMatch(Ipv4Address("10.1.1.1"),
-                                                            Ipv4Address("16.1.1.1"),
-                                                            1050,
-                                                            3050,
-                                                            8),
-                                      false,
-                                      "The classifier addresses matched.");
-            }
-        }
-    }
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Test the service flow tlv implementation.
- */
-class Ns3WimaxSfTlvTestCase : public TestCase
-{
-  public:
-    Ns3WimaxSfTlvTestCase();
-    ~Ns3WimaxSfTlvTestCase() override;
-
-  private:
-    void DoRun() override;
-};
-
-Ns3WimaxSfTlvTestCase::Ns3WimaxSfTlvTestCase()
-    : TestCase("Test the service flow tlv implementation.")
-{
-}
-
-Ns3WimaxSfTlvTestCase::~Ns3WimaxSfTlvTestCase()
-{
-}
-
-void
-Ns3WimaxSfTlvTestCase::DoRun()
-{
-    IpcsClassifierRecord classifier = IpcsClassifierRecord();
-    CsParameters csParam(CsParameters::ADD, classifier);
-    ServiceFlow sf = ServiceFlow(ServiceFlow::SF_DIRECTION_DOWN);
-
-    sf.SetSfid(100);
-    sf.SetConvergenceSublayerParam(csParam);
-    sf.SetCsSpecification(ServiceFlow::IPV4);
-    sf.SetServiceSchedulingType(ServiceFlow::SF_TYPE_UGS);
-    sf.SetMaxSustainedTrafficRate(1000000);
-    sf.SetMinReservedTrafficRate(1000000);
-    sf.SetMinTolerableTrafficRate(1000000);
-    sf.SetMaximumLatency(10);
-    sf.SetMaxTrafficBurst(1000);
-    sf.SetTrafficPriority(1);
-
-    Ptr<Packet> packet = Create<Packet>();
-    packet->AddHeader(sf.ToTlv());
-
-    Tlv tlvReceived;
-    packet->RemoveHeader(tlvReceived);
-
-    ServiceFlow sfRecv = ServiceFlow(tlvReceived);
-
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetDirection(),
-                          ServiceFlow::SF_DIRECTION_DOWN,
-                          "The sfRecv had the wrong direction.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetSfid(), 100, "The sfRecv had the wrong sfid.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetCsSpecification(),
-                          ServiceFlow::IPV4,
-                          "The sfRecv had the wrong cs specification.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetServiceSchedulingType(),
-                          ServiceFlow::SF_TYPE_UGS,
-                          "The sfRecv had the wrong service scheduling type.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMaxSustainedTrafficRate(),
-                          1000000,
-                          "The sfRecv had the wrong maximum sustained traffic rate.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMinReservedTrafficRate(),
-                          1000000,
-                          "The sfRecv had the wrong minimum reserved traffic rate.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMinTolerableTrafficRate(),
-                          1000000,
-                          "The sfRecv had the wrong minimum tolerable traffic rate.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMaximumLatency(),
-                          10,
-                          "The sfRecv had the wrong maximum latency.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetMaxTrafficBurst(),
-                          1000,
-                          "The sfRecv had the wrong maximum traffic burst.");
-    NS_TEST_ASSERT_MSG_EQ(sfRecv.GetTrafficPriority(),
-                          1,
-                          "The sfRecv had the wrong traffic priority.");
-}
-
-/**
- * @ingroup wimax-test
- * @ingroup tests
- *
- * @brief Ns3 Wimax Tlv Test Suite
- */
-class Ns3WimaxTlvTestSuite : public TestSuite
-{
-  public:
-    Ns3WimaxTlvTestSuite();
-};
-
-Ns3WimaxTlvTestSuite::Ns3WimaxTlvTestSuite()
-    : TestSuite("wimax-tlv", Type::UNIT)
-{
-    AddTestCase(new Ns3WimaxCsParamTlvTestCase, TestCase::Duration::QUICK);
-    AddTestCase(new Ns3WimaxSfTlvTestCase, TestCase::Duration::QUICK);
-}
-
-static Ns3WimaxTlvTestSuite ns3WimaxTlvTestSuite; ///< the test suite
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/CMakeLists.txt ns-3.46/src/zigbee/CMakeLists.txt
--- ns-3.45/src/zigbee/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -3,6 +3,10 @@
   SOURCE_FILES
     helper/zigbee-helper.cc
     helper/zigbee-stack-container.cc
+    model/zigbee-aps-header.cc
+    model/zigbee-aps-tables.cc
+    model/zigbee-aps.cc
+    model/zigbee-group-table.cc
     model/zigbee-nwk-fields.cc
     model/zigbee-nwk.cc
     model/zigbee-stack.cc
@@ -12,6 +16,10 @@
   HEADER_FILES
     helper/zigbee-helper.h
     helper/zigbee-stack-container.h
+    model/zigbee-aps-header.h
+    model/zigbee-aps-tables.h
+    model/zigbee-aps.h
+    model/zigbee-group-table.h
     model/zigbee-nwk-fields.h
     model/zigbee-nwk.h
     model/zigbee-stack.h
@@ -20,4 +28,5 @@
     model/zigbee-nwk-tables.h
   LIBRARIES_TO_LINK ${liblr-wpan}
   TEST_SOURCES test/zigbee-rreq-test.cc
+               test/zigbee-aps-data-test.cc
 )
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/doc/zigbee.rst ns-3.46/src/zigbee/doc/zigbee.rst
--- ns-3.45/src/zigbee/doc/zigbee.rst	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/doc/zigbee.rst	2025-10-01 18:46:32.000000000 -0700
@@ -35,28 +35,44 @@
 While other technologies like 6loWPAN can interact with the underlying MAC layer through general-purpose ``NetDevice`` interfaces, Zigbee has specific requirements that necessitate certain features from a lr-wpan MAC.
 Consequently, the |ns3| Zigbee implementation directly accesses the aggregated ``LrWpanMacBase`` and interfaces with it accordingly.
 
-The current scope of the project includes **only the NWK layer in the Zigbee stack**. However, the project can be later extended
-to support higher layers like the Application Sublayer (APS) and the Zigbee Cluster Library (ZCL).
+The current scope of the project includes **only the NWK layer and the APS layer in the Zigbee stack**. However, the project can be later extended
+to support higher layers like the application framework (AF) or services like the Zigbee Cluster Library (ZCL).
 
 
 Scope and Limitations
 ---------------------
 
-- MacInterfaceTable is not supported (Multiple interface support).
+The NWK has the following limitations:
+
+- The NWK MacInterfaceTable NIB is not supported (Multiple MAC interfaces support).
 - Security handling is not supported.
 - Source routing and Tree routing are not implemented.
 - Zigbee Stack profile 0x01 (used for tree routing and distributed address assignment) is not supported.
 - A few NIB attributes setting and NWK constants are not supported by the |ns3| attribute system.
-- Traces are not implemented yet.
+- Trace sources are not implemented yet.
 - Data broadcast do not support retries or passive acknowledgment.
 - Data broadcast to low power routers is not supported as the underlying lr-wpan netdevice has no concept of energy consumption.
 - Address duplication detection is not supported.
 - Beacon mode is not througly tested.
-- The following Zigbee layers are not supported yet:
-   - Zigbee Application Support Sub-Layer (APS)
-   - Zigbee Cluster Library (ZCL)
-   - Zigbee Device Object (ZDO)
-   - Application Framework (AF)
+- 16-bit address resolution from a IEEE address at NWK layer is not supported.
+- Route Maintenance is not supported.
+
+
+The APS has the following limitations:
+
+- No binding table support
+- No security handling
+- No fragmentation support
+- No duplicates detection
+- No acknowledged transmissions
+- No extenended address (64-bit) destinations supported
+- No trace sources
+
+The following Zigbee layers or services are not supported yet:
+
+- Zigbee Cluster Library (ZCL)
+- Zigbee Device Object (ZDO)
+- Application Framework (AF)
 
 To see a list of |ns3| Zigbee undergoing development efforts check issue `#1165 <https://gitlab.com/nsnam/ns-3-dev/-/issues/1165>`_
 
@@ -68,13 +84,13 @@
 
 The following is a list of NWK primitives supported:
 
-- NLME-NETWORK-DISCOVERY (Request, Confirm)
-- NLME-ROUTE-DISCOVERY (Request, Confirm)
-- NLME-NETWORK-FORMATION (Request, Confirm)
-- NLME-JOIN (Request, Confirm, Indication)
-- NLME-DIRECT-JOIN (Request, Confirm)
-- NLME-START-ROUTER (Request, Confirm)
-- NLDE-DATA (Request, Confirm, Indication)
+- ``NLME-NETWORK-DISCOVERY`` (Request, Confirm)
+- ``NLME-ROUTE-DISCOVERY`` (Request, Confirm)
+- ``NLME-NETWORK-FORMATION`` (Request, Confirm)
+- ``NLME-JOIN`` (Request, Confirm, Indication)
+- ``NLME-DIRECT-JOIN`` (Request, Confirm)
+- ``NLME-START-ROUTER`` (Request, Confirm)
+- ``NLDE-DATA`` (Request, Confirm, Indication)
 
 For details on how to use these primitives, please consult the Zigbee Pro specification.
 
@@ -84,7 +100,7 @@
 
 The following is a brief explanation of how users can interact with the NWK and what are the supported capabilities.
 
-Network joining
+Network Joining
 ~~~~~~~~~~~~~~~
 
 In a Zigbee network, before devices attempt to exchange data with one another, they must first be organized and related to one another based on their specific roles.
@@ -97,7 +113,8 @@
 Devices must first join a Zigbee network before they can upgrade their roles to either routers or remain as end devices.
 There are two ways for devices to join a Zigbee network: they can either go through the MAC association process or directly join the network.
 
-**MAC Association Join**
+MAC Association Join
+^^^^^^^^^^^^^^^^^^^^
 
 This method is the default approach used by Zigbee. As the name suggests, it utilizes the underlying MAC layer association mechanism to connect to the Zigbee network.
 For a comprehensive explanation of the association mechanism occurring in the MAC, please refer to the lr-wpan model documentation.
@@ -105,17 +122,17 @@
 When employing the association mechanism, devices communicate with each other to join an existing network via the network coordinator or a designated router within the network.
 As a result of this joining process, devices are assigned a short address (16-bit address) that they use for routing and data exchange operations. Below is a summary of the MAC association join process:
 
-1. At least one coordinator must be operational and capable of receiving join requests (i.e. A device successfully completed a `NLME-NETWORK-FORMATION.request` primitive).
-2. Devices must issue a `NLME-NETWORK-DISCOVERY.request` to look for candidate coordinators/routers to join. The parameters channel numbers (represented by a bitmap for channels 11-26) and scan duration (ranging from 0 to 14) must also be specified to define the channel in which the device will search for a coordinator or router and the duration of that search.
+1. At least one coordinator must be operational and capable of receiving join requests (i.e. A device successfully completed a ``NLME-NETWORK-FORMATION.request`` primitive).
+2. Devices must issue a ``NLME-NETWORK-DISCOVERY.request`` to look for candidate coordinators/routers to join. The parameters channel numbers (represented by a bitmap for channels 11-26) and scan duration (ranging from 0 to 14) must also be specified to define the channel in which the device will search for a coordinator or router and the duration of that search.
 3. If a coordinator (or a capable router) is found on the designated channel and within communication range, it will respond to the device's request with a beacon that contains both a PAN descriptor and a beacon payload describing the capabilities of the coordinator or router.
 4. Upon receiving these beacons, the device will select "the most ideal coordinator or router candidate" to join.
-5. After selecting the candidate, devices must issue a `NLME-JOIN.request` primitive with the network parameter set to `ASSOCIATION`. This will initiate the join process.
+5. After selecting the candidate, devices must issue a ``NLME-JOIN.request`` primitive with the network parameter set to ``ASSOCIATION``. This will initiate the join process.
 6. If the association is successful, the device will receive a confirmation from the coordinator or router, along with a short address that the device will use for its operations within the Zigbee network.
 7. Short addresses are assigned by the coordinator randomly, which means there could be instances of address duplication. Although the Zigbee specification includes a mechanism for detecting address duplication, this feature is not currently supported in this implementation.
-8. If the association request fails, the device will receive a confirmation with a status indicating failure, rather than `SUCCESSFUL`, and the short address FF:FF will be received (indicating that the device is not associated).
+8. If the association request fails, the device will receive a confirmation with a status indicating failure, rather than ``SUCCESSFUL``, and the short address FF:FF will be received (indicating that the device is not associated).
 
 Note: The process described above outlines the steps for joining the network using a MAC association join.
-However, devices that are required to act as routers must also issue an additional `NLME-START-ROUTER.request` primitive after joining the network in order to begin functioning as routers.
+However, devices that are required to act as routers must also issue an additional ``NLME-START-ROUTER.request`` primitive after joining the network in order to begin functioning as routers.
 
 In |ns3|, Zigbee NWK, coordinators or routers can be found using the following primitive::
 
@@ -144,8 +161,8 @@
 
 See zigbee/examples for detailed examples using network joining.
 
-**Direct Join (a.k.a. Orphaning process)**
-
+Direct Join (a.k.a. Orphaning process)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 Direct Join is employed when the number of nodes in the network and their relationships are known in advance.
 As the name suggests, this method involves registering devices directly with a coordinator or router.
 Subsequently, these devices confirm their registration with the coordinator to receive a network address.
@@ -153,12 +170,12 @@
 This process is simpler than the association method of joining a network, but it is less flexible since it requires manual intervention.
 Below is a summary of the direct join process:
 
-1. If a coordinator device or router is already operational, devices that can communicate with this coordinator must be manually registered using the primitive `NLME-DIRECT-JOIN.request`.
-2. After this registration, the devices registered in step 1 will send a `NLME-JOIN.request` with the rejoin network parameter set to `DIRECT_OR_REJOIN`. This action triggers a MAC orphaning request message, which is used to confirm the device's existence with the coordinator.
+1. If a coordinator device or router is already operational, devices that can communicate with this coordinator must be manually registered using the primitive ``NLME-DIRECT-JOIN.request``.
+2. After this registration, the devices registered in step 1 will send a ``NLME-JOIN.request`` with the rejoin network parameter set to ``DIRECT_OR_REJOIN``. This action triggers a MAC orphaning request message, which is used to confirm the device's existence with the coordinator.
 3. The coordinator or router will respond to the orphaning message by providing an assigned short address.
 4. The device accepts this short address and successfully joins the network.
 
-Similar to the MAC association mechanism, devices that want to function as routers must issue an additional `NLME-START-ROUTER.request` once the joining process is completed.
+Similar to the MAC association mechanism, devices that want to function as routers must issue an additional ``NLME-START-ROUTER.request`` once the joining process is completed.
 
 In |ns3|, a direct join primitive is used as follows::
 
@@ -195,7 +212,8 @@
 In fact, Zigbee supports not one but 4 different methods of routing: Mesh routing, Many-To-One routing, Source routing, and Tree routing.
 From these routing protocols, the current |ns3| implementation only supports the first two.
 
-**Many-To-One Routing**
+Many-To-One Routing
+^^^^^^^^^^^^^^^^^^^
 
 In Zigbee networks, it's common for multiple nodes to need to communicate with a single node, often referred to as a concentrator.
 If all nodes perform a Mesh route discovery for this single point in the network, it can lead to an overwhelming number of route request messages, which may degrade network performance.
@@ -227,12 +245,13 @@
    zstack->GetNwk()->NlmeRouteDiscoveryRequest(routeDiscParams);
 
 .. note::
-    Important: The process described above assumes that devices have already joined the network.
+    The process described above assumes that devices have already joined the network.
     A route discovery request issued before a device is part of the network (join process) will result in failure.
 
-**Mesh Routing**
+Mesh Routing
+^^^^^^^^^^^^
 
-Mesh routing in Zigbee is often attributed to the mechanisms used by the AODV routing protocol (`RFC 3561 <https://datatracker.ietf.org/doc/html/rfc3561>`_).
+Mesh routing in Zigbee is often attributed to the mechanisms used by the AODV routing protocol (:rfc3561).
 Although Zigbee mesh routing and the AODV protocol share some similarities, there are significant differences between them that directly influence performance.
 
 Firstly, AODV was designed for IP-based networks, whereas Zigbee operates without the concept of IP addresses, thus eliminating their associated overhead.
@@ -295,12 +314,140 @@
     zstack->GetNwk()->NldeDataRequest(dataReqParams, p);
 
 .. note::
-    Important: The process described above assumes that devices have already joined the network.
+    The process described above assumes that devices have already joined the network.
     A route discovery request issued before a device is part of the network (join process) will result in failure.
 
+The application support sub-layer (APS)
+---------------------------------------
+
+As its name suggests, the APS (Application Support) layer acts as an intermediate layer between the Network (NWK) layer and the Application Framework (AF).
+It provides services to both the Zigbee Device Object (ZDO) and the AF.
+
+The primary functions of the APS layer include:
+
+- Handling security and data integrity through encryption and decryption of data.
+- Managing the binding table, which establishes relationships between devices.
+- Managing the group table, which facilitates group destinations similar to multicast groups.
+- Offering various data transmission modes, such as unicast, broadcast, and groupcast.
+- Detecting and filtering duplicate data transmissions.
+- Managing the fragmentation and reassembly of data packets.
+- Providing a mechanism for data acknowledgment and retransmission.
+
+The APS layer introduces abstract concepts such as **EndPoints**, **Clusters**, and **Profiles**.
+However, it does not assign specific meanings to these concepts; instead, it simply adds ID information to the transmitted frames.
+
+Effective interpretation and management of **EndPoints**, **Clusters**, and **Profile IDs** require the use of the Zigbee Cluster Library (ZCL) and the ZDO, which are not currently supported in this implementation.
+Similarly, the APS layer can transmit data that includes information about source and destination endpoints, but it cannot initiate network formation or joining procedures. Typically, these processes are managed by the ZDO; however, since the ZDO is currently unavailable, users must interact directly with the NWK layer’s network formation and joining primitives to initiate these options.
+
+This implementation provides only the most basic functions of the APS, enabling data transmission using 16-bit or group address destinations.
+Features such as transmission to IEEE addresses (64-bit address destinations), fragmentation, duplication detection, and security are not currently supported.
+
+By default, the APS layer is integrated and active within the Zigbee stack.
+However, users can choose to work solely with the NWK layer.
+To do this, they must disable the APS by using the ``SetNwkLayerOnly()`` function in the Zigbee helper.
+
+
+The following is a list of APS primitives are included:
+
+- ``APSDE-DATA`` (Request, Confirm, Indication) : Only Address mode 0x01 and 0x02 (Regular unicast and groupcast) supported.
+- ``APSME-BIND`` (Request, Confirm)
+- ``APSME-UNBIND`` (Request, Confirm)
+- ``APSME-ADD-GROUP`` (Request, Confirm)
+- ``APSME-REMOVE-GROUP`` (Request, Confirm)
+- ``APSME-REMOVE-ALL-GROUPS`` (Request, Confirm)
+
+Data Transmission
+~~~~~~~~~~~~~~~~~
+
+The APS layer must transmit data using the ``APSD-DATA.request`` primitive. This primitive supports 4 types of destination address modes:
+
+- **0x00**: No address (Use Binding table to establish destinations) <Not supported>
+- **0x01**: Group address (Groupcasting)
+- **0x02**: 16-bit address with destination endpoint present (Regular Unicast or Broadcast)
+- **0x03**: 64-bit address with destination endpoint not present (Regular Unicast) <Not supported>
+
+
+GroupCasting (Address Mode: 0x01)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Group casting (Multicasting) is a method of transmitting data to multiple devices endpoints within a specific group.
+This is particularly useful in scenarios where a device needs to send the same data to multiple endpoints simultaneously,
+such as in lighting control systems or sensor networks.
+In Zigbee, group addresses are used to facilitate this type of communication.
+The APS layer manages group addresses and ensures that data is delivered to all devices in the group.
+To use group casting, devices must first be added to a group. This is done using the ``APSME-ADD-GROUP`` primitive, which allows a device to join a group by specifying the group ID.::
+
+    // Multiple groups can be added to the same device.
+    // Multiple endpoints can be added to the same group.
+    // The group address is a 16-bit address.
+    // In this example, group [BE:EF] and endpoint 5 is added to a device.
+    ApsmeGroupRequestParams groupParams;
+    groupParams.m_groupAddress = Mac16Address("BE:EF");
+    groupParams.m_endPoint = 5;
+    zstack->GetNwk()->GetAps()->ApsmeAddGroupRequest(groupParams);
+
+Once a device is part of a group, any device can send data to ALL the endpoints in the group using the APSDE-DATA.request primitive with
+the destination address mode ``GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT`` (i.e., 0x01 address mode) and the appropriate group address.::
+
+    // The message will be delivered to ALL the endpoints in any device in the network
+    // that is part of the group [BE:EF].
+    ApsdeDataRequestParams dataReqParams;
+    ZigbeeApsTxOptions txOptions;
+    dataReqParams.m_useAlias = false;
+    // Default, use 16 bit address destination (No option), equivalent to 0x00
+    dataReqParams.m_txOptions = txOptions.GetTxOptions();
+    dataReqParams.m_srcEndPoint = 4; // Arbitrary value, must not be 0
+    dataReqParams.m_clusterId = 5;   // Arbitrary value (depends on the application)
+    dataReqParams.m_profileId = 2;   // Arbitrary value (depends on the application)
+    dataReqParams.m_dstAddrMode = ApsDstAddressMode::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT; // dstAddrMode 0x01
+    dataReqParams.m_dstAddr16 = Mac16Address("BE:EF"); // The destination group address
+    zstack->GetNwk()->GetAps()->ApsdeDataRequest(dataReqParams, p);
+
+
+Prior Zigbee Specification Revision 22 1.0 (2017), groupcasting used a form of controlled broadcast to propagate data to all group members in the network.
+However, the current specification has changed this behavior to a more efficient group addressing scheme. In the new scheme, data transmissions,
+propagate differently depending on whether or not the receiving or initiating device is member of the group.
+If the devices are members of the group, they broadcast the data to the nearby devices (like in the old approach),
+however, if device are not a members of the group, group addresses are treated as regular unicast addresses, and a route discovery is performed
+to find the closest device which is part of the group. These route are stored in the routing table, and subsequent transmissions to the same group address will use the stored route.
+In this way, the group address is treated as a unicast address, and the APS layer will not broadcast the data to all devices in the network.
+This change improves the efficiency of groupcasting by reducing unnecessary broadcasts.
+
+
+
+UniCasting (Address Mode: 0x02)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Unicasting is a method of transmitting data to a single specific device endpoint.
+In Zigbee, this is achieved by using the ``APSDE-DATA.request`` primitive with the appropriate destination address mode and address information.
+To use unicasting, the sender must know the 16-bit address of the destination device and the endpoint it wants to communicate with.
+The ``APSDE-DATA.request`` primitive is used to send data to a specific device endpoint using the address mode 0x02 (Regular Unicast).
+
+The following example demonstrates how to send data to a specific device endpoint using the APSDE-DATA.request primitive with address mode 0x02::
+
+    // The message will be delivered to the endpoint 5 of the device with address AB:1C
+    ApsdeDataRequestParams dataReqParams;
+    ZigbeeApsTxOptions txOptions;
+    dataReqParams.m_useAlias = false;
+    // Default, use 16 bit address destination (No option), equivalent to 0x00
+    dataReqParams.m_txOptions = txOptions.GetTxOptions();
+    dataReqParams.m_srcEndPoint = 4; // Arbitrary value, must not be 0
+    dataReqParams.m_clusterId = 5;   // Arbitrary value (depends on the application)
+    dataReqParams.m_profileId = 2;   // Arbitrary value (depends on the application)
+    dataReqParams.m_dstAddrMode = ApsDstAddressMode::DST_ADDR16_DST_ENDPOINT_PRESENT; // dstAddrMode 0x02
+    dataReqParams.m_dstAddr16 = Mac16Address("AB:1C"); // The destination device address
+    dataReqParams.m_dstEndPoint = 5; // The destination endpoint, must not be 0
+    zstack->GetNwk()->GetAps()->ApsdeDataRequest(dataReqParams, p);
+
 Usage
 -----
 
+Zigbee is implemented as a |ns3| module, which means it can be used in the same way as other |ns3| modules.
+It requires the ``lr-wpan`` module to be installed and operational, as it relies on the lr-wpan MAC layer to function.
+Zigbee networks can be created by using the ``ZigbeeHelper`` class,
+which simplifies the process of configuring and installing the Zigbee stack but  it also possible to create and configure
+Zigbee stacks manually.
+
 Helpers
 ~~~~~~~
 
@@ -329,7 +476,10 @@
 
     // Install a zigbee stack on a set of devices using the helper
     ZigbeeHelper zigbee;
+    zigbee.SetNwkLayerOnly(); // Activate if you wish to have only the NWK layer in the stack
     ZigbeeStackContainer zigbeeStackContainer = zigbee.Install(lrwpanDevices);
+    // ...  ...
+    // Call to NWK primitives contained in the NWK layer in the Zigbee stack.
 
 Attributes
 ~~~~~~~~~~
@@ -353,8 +503,6 @@
 - ``NwkcMaxRREQJitter``: [Constant] The duration between retries of a broadcast RREQ (msec).
 - ``MaxPendingTxQueueSize``: The maximum size of the table storing pending packets awaiting to be transmitted after discovering a route to the destination.
 
-
-
 Traces
 ~~~~~~
 
@@ -375,11 +523,12 @@
 * ``zigbee-association-join.cc``:  An example showing the NWK layer join process of 3 devices in a zigbee network (MAC association).
 * ``zigbee-nwk-routing.cc``: Shows a simple topology of 5 router devices sequentially joining a network. Data transmission and route discovery (MESH routing) are also shown in this example
 * ``zigbee-nwk-routing-grid.cc``: Shows a complex grid topology of 50 router devices sequentially joining a network. Route discovery (MANY-TO-ONE routing) is also shown in this example.
+* ``zigbee-aps-data.cc``: Demonstrates the usage of the APS layer to transmit data (Unicast and Groupcast).)
 
 The following unit test have been developed to ensure the correct behavior of the module:
 
 * ``zigbee-rreq-test``: Test some situations in which RREQ messages should be retried during a route discovery process.
-
+* ``zigbee-aps-data-test``: Test the APS data transmission
 
 Validation
 ----------
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/examples/CMakeLists.txt ns-3.46/src/zigbee/examples/CMakeLists.txt
--- ns-3.45/src/zigbee/examples/CMakeLists.txt	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/examples/CMakeLists.txt	2025-10-01 18:46:32.000000000 -0700
@@ -3,6 +3,7 @@
     zigbee-nwk-association-join
     zigbee-nwk-routing
     zigbee-nwk-routing-grid
+    zigbee-aps-data
 )
 
 foreach(
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/examples/zigbee-aps-data.cc ns-3.46/src/zigbee/examples/zigbee-aps-data.cc
--- ns-3.45/src/zigbee/examples/zigbee-aps-data.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/examples/zigbee-aps-data.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors:
+ *
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+/**
+ * Mesh routing example with APS layer data transmission in a simple topology.
+ *
+ * This example use a Zigbee stack formed by NWK and APS layers.
+ * The APS layer is used to transmit data, the creation of the necessary routes is
+ * handle automatically by the NWK layer. There is no ZDO, therefore we need to manually
+ * use the NWK to form the network and establish the router devices.
+ *
+ * The example demonstrates the following:
+ * - Sending data using the APS layer (Unicast and Groupcast destinations).
+ * - Using the APS layer to establish groupcast groups and endpoints.
+ *
+ *
+ *  Network Extended PAN id: 0X000000000000CA:FE (based on the PAN coordinator address)
+ *
+ *  Devices Addresses:
+ *
+ *  [Coordinator] ZC  (dev0 | Node 0): [00:00:00:00:00:00:CA:FE]  [00:00]
+ *  [Router 1]    ZR1 (dev1 | Node 1): [00:00:00:00:00:00:00:01]  [short addr assigned by ZC]
+ *  [Router 2]    ZR2 (dev2 | Node 2): [00:00:00:00:00:00:00:02]  [short addr assigned by ZR1]
+ *  [Router 3]    ZR3 (dev3 | Node 3): [00:00:00:00:00:00:00:03]  [short addr assigned by ZR2]
+ *  [Router 4]    ZR4 (dev4 | Node 4): [00:00:00:00:00:00:00:04]  [short addr assigned by ZR1]
+ *
+ *  Topology:
+ *
+ *  ZC--------ZR1------------ZR2----------ZR3 (GroupID Member: [01:23] | Endpoints: 3)
+ *             |
+ *             |
+ *            ZR4 (GroupID Member: [01:23] | Endpoints: 3, 9)
+ *
+ *
+ *  In example, Both ZR4 and ZR3 are part of the multicast group [01:23].
+ *  ZR4 has two endpoints in the group, 3 and 9. ZR3 has only one endpoint in the group, 3.
+ */
+
+#include "ns3/constant-position-mobility-model.h"
+#include "ns3/core-module.h"
+#include "ns3/log.h"
+#include "ns3/lr-wpan-module.h"
+#include "ns3/packet.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/simulator.h"
+#include "ns3/single-model-spectrum-channel.h"
+#include "ns3/zigbee-module.h"
+
+#include <iostream>
+
+using namespace ns3;
+using namespace ns3::lrwpan;
+using namespace ns3::zigbee;
+
+NS_LOG_COMPONENT_DEFINE("ZigbeeRouting");
+
+ZigbeeStackContainer zigbeeStacks;
+
+static void
+ApsDataIndication(Ptr<ZigbeeStack> stack, ApsdeDataIndicationParams params, Ptr<Packet> p)
+{
+    std::cout << Simulator::Now().As(Time::S) << " Node " << stack->GetNode()->GetId() << " | ";
+    if (params.m_dstAddrMode == ApsDstAddressMode::DST_ADDR16_DST_ENDPOINT_PRESENT)
+    {
+        std::cout << "UCST | ";
+    }
+    else if (params.m_dstAddrMode == ApsDstAddressMode::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT)
+    {
+        std::cout << "GROUPCAST | ";
+    }
+    else
+    {
+        std::cout << "Unknown | ";
+    }
+    std::cout << "ApsdeDataIndication: Received DATA packet with size " << p->GetSize()
+              << " for destination EndPoint " << params.m_dstEndPoint << "\n";
+}
+
+static void
+NwkNetworkFormationConfirm(Ptr<ZigbeeStack> stack, NlmeNetworkFormationConfirmParams params)
+{
+    std::cout << Simulator::Now().As(Time::S) << " Node " << stack->GetNode()->GetId() << " | "
+              << "NlmeNetworkFormationConfirmStatus = " << params.m_status << "\n";
+}
+
+static void
+NwkNetworkDiscoveryConfirm(Ptr<ZigbeeStack> stack, NlmeNetworkDiscoveryConfirmParams params)
+{
+    // See Zigbee Specification r22.1.0, 3.6.1.4.1
+    // This method implements a simplistic version of the method implemented
+    // in a zigbee APL layer. In this layer a candidate Extended PAN Id must
+    // be selected and a NLME-JOIN.request must be issued.
+
+    if (params.m_status == NwkStatus::SUCCESS)
+    {
+        std::cout << Simulator::Now().As(Time::S) << " Node " << stack->GetNode()->GetId() << " | "
+                  << " Network discovery confirm Received. Networks found ("
+                  << params.m_netDescList.size() << ")\n";
+
+        NlmeJoinRequestParams joinParams;
+
+        zigbee::CapabilityInformation capaInfo;
+        capaInfo.SetDeviceType(ROUTER);
+        capaInfo.SetAllocateAddrOn(true);
+
+        joinParams.m_rejoinNetwork = zigbee::JoiningMethod::ASSOCIATION;
+        joinParams.m_capabilityInfo = capaInfo.GetCapability();
+        joinParams.m_extendedPanId = params.m_netDescList[0].m_extPanId;
+
+        Simulator::ScheduleNow(&ZigbeeNwk::NlmeJoinRequest, stack->GetNwk(), joinParams);
+    }
+    else
+    {
+        NS_ABORT_MSG("Unable to discover networks | status: " << params.m_status);
+    }
+}
+
+static void
+NwkJoinConfirm(Ptr<ZigbeeStack> stack, NlmeJoinConfirmParams params)
+{
+    if (params.m_status == NwkStatus::SUCCESS)
+    {
+        std::cout << Simulator::Now().As(Time::S) << " Node " << stack->GetNode()->GetId() << " | "
+                  << " The device joined the network SUCCESSFULLY with short address " << std::hex
+                  << params.m_networkAddress << " on the Extended PAN Id: 0x" << std::hex
+                  << params.m_extendedPanId << "\n"
+                  << std::dec;
+
+        // 3 - After dev 1 is associated, it should be started as a router
+        //     (i.e. it becomes able to accept request from other devices to join the network)
+        NlmeStartRouterRequestParams startRouterParams;
+        Simulator::ScheduleNow(&ZigbeeNwk::NlmeStartRouterRequest,
+                               stack->GetNwk(),
+                               startRouterParams);
+    }
+    else
+    {
+        std::cout << " The device FAILED to join the network with status " << params.m_status
+                  << "\n";
+    }
+}
+
+static void
+NwkRouteDiscoveryConfirm(Ptr<ZigbeeStack> stack, NlmeRouteDiscoveryConfirmParams params)
+{
+    std::cout << "NlmeRouteDiscoveryConfirmStatus = " << params.m_status << "\n";
+}
+
+static void
+SendDataUcst(Ptr<ZigbeeStack> stackSrc, Ptr<ZigbeeStack> stackDst)
+{
+    // Send data from a device with stackSrc to device with stackDst.
+
+    // We do not know what network address will be assigned after the JOIN procedure
+    // but we can request the network address from stackDst (the destination device) when
+    // we intend to send data. If a route do not exist, we will search for a route
+    // before transmitting data (Mesh routing).
+
+    Ptr<Packet> p = Create<Packet>(5);
+    // Src and Dst Endpoints must not be 0, because this is reserved for the ZDO.
+    // Other Endpoint numbers can help to differentiate between different applications
+    // running in the same node (similar to the concept of a port in TCP/IP).
+    // Likewise, because we currently do not have ZDO or ZCL or AF, clusterId
+    // and profileId numbers are non-sensical.
+    ApsdeDataRequestParams dataReqParams;
+    ZigbeeApsTxOptions txOptions;
+    dataReqParams.m_useAlias = false;
+    // Default, use 16 bit address destination (No option), equivalent to 0x00
+    dataReqParams.m_txOptions = txOptions.GetTxOptions();
+    dataReqParams.m_srcEndPoint = 4; // Arbitrary value, must not be 0
+    dataReqParams.m_clusterId = 5;   // Arbitrary value
+    dataReqParams.m_profileId = 2;   // Arbitrary value
+
+    dataReqParams.m_dstAddrMode = ApsDstAddressMode::DST_ADDR16_DST_ENDPOINT_PRESENT;
+    dataReqParams.m_dstAddr16 = stackDst->GetNwk()->GetNetworkAddress();
+    dataReqParams.m_dstEndPoint = 3;
+
+    Simulator::ScheduleNow(&ZigbeeAps::ApsdeDataRequest, stackSrc->GetAps(), dataReqParams, p);
+}
+
+static void
+SendDataGcst(Ptr<ZigbeeStack> stackSrc)
+{
+    Ptr<Packet> p = Create<Packet>(5);
+    // Src and Dst Endpoints must not be 0, because this is reserved for the ZDO.
+    // Other Endpoint numbers can help to differentiate between different applications
+    // running in the same node (similar to the concept of a port in TCP/IP).
+    // Likewise, because we currently do not have ZDO or ZCL or AF, clusterId
+    // and profileId numbers are non-sensical.
+    ApsdeDataRequestParams dataReqParams;
+    ZigbeeApsTxOptions txOptions;
+    dataReqParams.m_useAlias = false;
+    // Default, use 16 bit address destination (No option), equivalent to 0x00
+    dataReqParams.m_txOptions = txOptions.GetTxOptions();
+    dataReqParams.m_srcEndPoint = 4; // Arbitrary value, must not be 0
+    dataReqParams.m_clusterId = 5;   // Arbitrary value
+    dataReqParams.m_profileId = 2;   // Arbitrary value
+
+    dataReqParams.m_dstAddrMode = ApsDstAddressMode::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT;
+    dataReqParams.m_dstAddr16 = Mac16Address("01:23"); // The destination group address
+
+    Simulator::ScheduleNow(&ZigbeeAps::ApsdeDataRequest, stackSrc->GetAps(), dataReqParams, p);
+}
+
+int
+main(int argc, char* argv[])
+{
+    LogComponentEnableAll(LogLevel(LOG_PREFIX_TIME | LOG_PREFIX_FUNC | LOG_PREFIX_NODE));
+    // Enable logs for further details
+    // LogComponentEnable("ZigbeeNwk", LOG_LEVEL_DEBUG);
+    // LogComponentEnable("ZigbeeAps", LOG_LEVEL_DEBUG);
+
+    RngSeedManager::SetSeed(3);
+    RngSeedManager::SetRun(4);
+
+    NodeContainer nodes;
+    nodes.Create(5);
+
+    //// Configure MAC
+
+    LrWpanHelper lrWpanHelper;
+    NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(nodes);
+    Ptr<LrWpanNetDevice> dev0 = lrwpanDevices.Get(0)->GetObject<LrWpanNetDevice>();
+    Ptr<LrWpanNetDevice> dev1 = lrwpanDevices.Get(1)->GetObject<LrWpanNetDevice>();
+    Ptr<LrWpanNetDevice> dev2 = lrwpanDevices.Get(2)->GetObject<LrWpanNetDevice>();
+    Ptr<LrWpanNetDevice> dev3 = lrwpanDevices.Get(3)->GetObject<LrWpanNetDevice>();
+    Ptr<LrWpanNetDevice> dev4 = lrwpanDevices.Get(4)->GetObject<LrWpanNetDevice>();
+
+    // Device must ALWAYS have IEEE Address (Extended address) assigned.
+    // Network address (short address) are assigned by the the JOIN mechanism
+    dev0->GetMac()->SetExtendedAddress("00:00:00:00:00:00:CA:FE");
+    dev1->GetMac()->SetExtendedAddress("00:00:00:00:00:00:00:01");
+    dev2->GetMac()->SetExtendedAddress("00:00:00:00:00:00:00:02");
+    dev3->GetMac()->SetExtendedAddress("00:00:00:00:00:00:00:03");
+    dev4->GetMac()->SetExtendedAddress("00:00:00:00:00:00:00:04");
+
+    Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel>();
+    Ptr<LogDistancePropagationLossModel> propModel =
+        CreateObject<LogDistancePropagationLossModel>();
+
+    Ptr<ConstantSpeedPropagationDelayModel> delayModel =
+        CreateObject<ConstantSpeedPropagationDelayModel>();
+
+    channel->AddPropagationLossModel(propModel);
+    channel->SetPropagationDelayModel(delayModel);
+
+    dev0->SetChannel(channel);
+    dev1->SetChannel(channel);
+    dev2->SetChannel(channel);
+    dev3->SetChannel(channel);
+    dev4->SetChannel(channel);
+
+    // Configure the Zigbee stack, by default both the NWK and the APS are present
+
+    ZigbeeHelper zigbeeHelper;
+    ZigbeeStackContainer zigbeeStackContainer = zigbeeHelper.Install(lrwpanDevices);
+
+    Ptr<ZigbeeStack> zstack0 = zigbeeStackContainer.Get(0)->GetObject<ZigbeeStack>();
+    Ptr<ZigbeeStack> zstack1 = zigbeeStackContainer.Get(1)->GetObject<ZigbeeStack>();
+    Ptr<ZigbeeStack> zstack2 = zigbeeStackContainer.Get(2)->GetObject<ZigbeeStack>();
+    Ptr<ZigbeeStack> zstack3 = zigbeeStackContainer.Get(3)->GetObject<ZigbeeStack>();
+    Ptr<ZigbeeStack> zstack4 = zigbeeStackContainer.Get(4)->GetObject<ZigbeeStack>();
+
+    // Add the stacks to a container to later on print routes.
+    zigbeeStacks.Add(zstack0);
+    zigbeeStacks.Add(zstack1);
+    zigbeeStacks.Add(zstack2);
+    zigbeeStacks.Add(zstack3);
+    zigbeeStacks.Add(zstack4);
+
+    // Assign streams to the zigbee stacks to obtain
+    // reprodusable results from random events occurring inside the stack.
+    zstack0->GetNwk()->AssignStreams(0);
+    zstack1->GetNwk()->AssignStreams(10);
+    zstack2->GetNwk()->AssignStreams(20);
+    zstack3->GetNwk()->AssignStreams(30);
+    zstack4->GetNwk()->AssignStreams(40);
+
+    //// Configure Nodes Mobility
+
+    Ptr<ConstantPositionMobilityModel> dev0Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev0Mobility->SetPosition(Vector(0, 0, 0));
+    dev0->GetPhy()->SetMobility(dev0Mobility);
+
+    Ptr<ConstantPositionMobilityModel> dev1Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev1Mobility->SetPosition(Vector(90, 0, 0));
+    dev1->GetPhy()->SetMobility(dev1Mobility);
+
+    Ptr<ConstantPositionMobilityModel> dev2Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev2Mobility->SetPosition(Vector(170, 0, 0));
+    dev2->GetPhy()->SetMobility(dev2Mobility);
+
+    Ptr<ConstantPositionMobilityModel> dev3Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev3Mobility->SetPosition(Vector(250, 0, 0));
+    dev3->GetPhy()->SetMobility(dev3Mobility);
+
+    Ptr<ConstantPositionMobilityModel> dev4Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev4Mobility->SetPosition(Vector(90, 50, 0));
+    dev4->GetPhy()->SetMobility(dev4Mobility);
+
+    // NWK callbacks hooks
+    // These hooks are usually directly connected to the ZDO.
+    // In this case, there is no ZDO, therefore, we connect the event outputs
+    // of all devices directly to our static functions in this example.
+
+    zstack0->GetNwk()->SetNlmeNetworkFormationConfirmCallback(
+        MakeBoundCallback(&NwkNetworkFormationConfirm, zstack0));
+    zstack0->GetNwk()->SetNlmeRouteDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkRouteDiscoveryConfirm, zstack0));
+
+    zstack1->GetNwk()->SetNlmeNetworkDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkNetworkDiscoveryConfirm, zstack1));
+    zstack2->GetNwk()->SetNlmeNetworkDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkNetworkDiscoveryConfirm, zstack2));
+    zstack3->GetNwk()->SetNlmeNetworkDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkNetworkDiscoveryConfirm, zstack3));
+    zstack4->GetNwk()->SetNlmeNetworkDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkNetworkDiscoveryConfirm, zstack4));
+
+    zstack1->GetNwk()->SetNlmeJoinConfirmCallback(MakeBoundCallback(&NwkJoinConfirm, zstack1));
+    zstack2->GetNwk()->SetNlmeJoinConfirmCallback(MakeBoundCallback(&NwkJoinConfirm, zstack2));
+    zstack3->GetNwk()->SetNlmeJoinConfirmCallback(MakeBoundCallback(&NwkJoinConfirm, zstack3));
+    zstack4->GetNwk()->SetNlmeJoinConfirmCallback(MakeBoundCallback(&NwkJoinConfirm, zstack4));
+
+    // APS callback hooks
+
+    zstack0->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, zstack0));
+    zstack1->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, zstack1));
+    zstack2->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, zstack2));
+    zstack3->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, zstack3));
+    zstack4->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, zstack4));
+
+    // NWK Layer
+    // We do not have a ZDO, therefore we need to manually
+    // initiate the network formation and discovery procedures
+    // using the NWK layer.
+
+    // 1 - Initiate the Zigbee coordinator, start the network
+    // ALL_CHANNELS = 0x07FFF800 (Channels 11~26)
+    NlmeNetworkFormationRequestParams netFormParams;
+    netFormParams.m_scanChannelList.channelPageCount = 1;
+    netFormParams.m_scanChannelList.channelsField[0] = ALL_CHANNELS;
+    netFormParams.m_scanDuration = 0;
+    netFormParams.m_superFrameOrder = 15;
+    netFormParams.m_beaconOrder = 15;
+
+    Simulator::ScheduleWithContext(zstack0->GetNode()->GetId(),
+                                   Seconds(1),
+                                   &ZigbeeNwk::NlmeNetworkFormationRequest,
+                                   zstack0->GetNwk(),
+                                   netFormParams);
+
+    // 2- Schedule devices sequentially find and join the network.
+    //    After this procedure, each device make a NLME-START-ROUTER.request to become a router
+
+    NlmeNetworkDiscoveryRequestParams netDiscParams;
+    netDiscParams.m_scanChannelList.channelPageCount = 1;
+    netDiscParams.m_scanChannelList.channelsField[0] = 0x00007800; // BitMap: Channels 11~14
+    netDiscParams.m_scanDuration = 2;
+    Simulator::ScheduleWithContext(zstack1->GetNode()->GetId(),
+                                   Seconds(3),
+                                   &ZigbeeNwk::NlmeNetworkDiscoveryRequest,
+                                   zstack1->GetNwk(),
+                                   netDiscParams);
+
+    NlmeNetworkDiscoveryRequestParams netDiscParams2;
+    netDiscParams2.m_scanChannelList.channelPageCount = 1;
+    netDiscParams2.m_scanChannelList.channelsField[0] = 0x00007800; // BitMap: Channels 11~14
+    netDiscParams2.m_scanDuration = 2;
+    Simulator::ScheduleWithContext(zstack2->GetNode()->GetId(),
+                                   Seconds(4),
+                                   &ZigbeeNwk::NlmeNetworkDiscoveryRequest,
+                                   zstack2->GetNwk(),
+                                   netDiscParams2);
+
+    NlmeNetworkDiscoveryRequestParams netDiscParams3;
+    netDiscParams2.m_scanChannelList.channelPageCount = 1;
+    netDiscParams2.m_scanChannelList.channelsField[0] = 0x00007800; // BitMap: Channels 11~14
+    netDiscParams2.m_scanDuration = 2;
+    Simulator::ScheduleWithContext(zstack3->GetNode()->GetId(),
+                                   Seconds(5),
+                                   &ZigbeeNwk::NlmeNetworkDiscoveryRequest,
+                                   zstack3->GetNwk(),
+                                   netDiscParams3);
+
+    NlmeNetworkDiscoveryRequestParams netDiscParams4;
+    netDiscParams4.m_scanChannelList.channelPageCount = 1;
+    netDiscParams4.m_scanChannelList.channelsField[0] = 0x00007800; // BitMap: Channels 11~14
+    netDiscParams4.m_scanDuration = 2;
+    Simulator::ScheduleWithContext(zstack4->GetNode()->GetId(),
+                                   Seconds(6),
+                                   &ZigbeeNwk::NlmeNetworkDiscoveryRequest,
+                                   zstack4->GetNwk(),
+                                   netDiscParams4);
+
+    // APS Layer
+    // 4- Establish the Groupcast groups and its endpoints
+    // Add group [01:23] and endpoint 3 to Devices 3 and 4
+    // Also add endpoint 9 to device 4 in the same group.
+    ApsmeGroupRequestParams groupParams;
+    groupParams.m_groupAddress = Mac16Address("01:23");
+    groupParams.m_endPoint = 3;
+    Simulator::ScheduleWithContext(zstack3->GetNode()->GetId(),
+                                   Seconds(7),
+                                   &ZigbeeAps::ApsmeAddGroupRequest,
+                                   zstack3->GetAps(),
+                                   groupParams);
+
+    Simulator::ScheduleWithContext(zstack4->GetNode()->GetId(),
+                                   Seconds(7),
+                                   &ZigbeeAps::ApsmeAddGroupRequest,
+                                   zstack4->GetAps(),
+                                   groupParams);
+
+    groupParams.m_endPoint = 9; // Add endpoint 9 to the same group
+    Simulator::ScheduleWithContext(zstack4->GetNode()->GetId(),
+                                   Seconds(7),
+                                   &ZigbeeAps::ApsmeAddGroupRequest,
+                                   zstack4->GetAps(),
+                                   groupParams);
+
+    // 4- Send data using the APS layer
+
+    // GROUPCAST
+    // Transmit data to all endpoints in devices that are
+    // part of the group [01:23] (i.e. endpoints in the ZR3 and ZR4).
+    Simulator::Schedule(Seconds(9), &SendDataGcst, zstack0);
+
+    // UNICAST
+    // Transmit data to a specific endpoint in a device
+    // In this case, we send data to the endpoint 3 of ZR3.
+    // We require the destination address, but we do not know this apriori,
+    // therefore we can request it from zstack3 on runtime.
+    Simulator::Schedule(Seconds(10), &SendDataUcst, zstack0, zstack3);
+
+    // Print the contents of the routing table in the initiator device (ZC)
+    Ptr<OutputStreamWrapper> stream = Create<OutputStreamWrapper>(&std::cout);
+    Simulator::Schedule(Seconds(11), &ZigbeeNwk::PrintRoutingTable, zstack0->GetNwk(), stream);
+
+    Simulator::Stop(Seconds(20));
+    Simulator::Run();
+    Simulator::Destroy();
+    return 0;
+}
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/examples/zigbee-nwk-association-join.cc ns-3.46/src/zigbee/examples/zigbee-nwk-association-join.cc
--- ns-3.45/src/zigbee/examples/zigbee-nwk-association-join.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/examples/zigbee-nwk-association-join.cc	2025-10-01 18:46:32.000000000 -0700
@@ -160,10 +160,11 @@
     dev1->SetChannel(channel);
     dev2->SetChannel(channel);
 
-    //// Configure NWK
+    //// Configure the Zigbee Stack and use only the NWK layer
 
-    ZigbeeHelper zigbee;
-    ZigbeeStackContainer zigbeeStackContainer = zigbee.Install(lrwpanDevices);
+    ZigbeeHelper zigbeeHelper;
+    zigbeeHelper.SetNwkLayerOnly();
+    ZigbeeStackContainer zigbeeStackContainer = zigbeeHelper.Install(lrwpanDevices);
 
     Ptr<ZigbeeStack> zstack0 = zigbeeStackContainer.Get(0)->GetObject<ZigbeeStack>();
     Ptr<ZigbeeStack> zstack1 = zigbeeStackContainer.Get(1)->GetObject<ZigbeeStack>();
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/examples/zigbee-nwk-direct-join.cc ns-3.46/src/zigbee/examples/zigbee-nwk-direct-join.cc
--- ns-3.45/src/zigbee/examples/zigbee-nwk-direct-join.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/examples/zigbee-nwk-direct-join.cc	2025-10-01 18:46:32.000000000 -0700
@@ -120,10 +120,11 @@
     dev1->SetChannel(channel);
     dev2->SetChannel(channel);
 
-    //// Configure NWK
+    //// Configure the Zigbee Stack and use only the NWK layer
 
-    ZigbeeHelper zigbee;
-    ZigbeeStackContainer zigbeeStackContainer = zigbee.Install(lrwpanDevices);
+    ZigbeeHelper zigbeeHelper;
+    zigbeeHelper.SetNwkLayerOnly();
+    ZigbeeStackContainer zigbeeStackContainer = zigbeeHelper.Install(lrwpanDevices);
 
     Ptr<ZigbeeStack> zstack0 = zigbeeStackContainer.Get(0)->GetObject<ZigbeeStack>();
     Ptr<ZigbeeStack> zstack1 = zigbeeStackContainer.Get(1)->GetObject<ZigbeeStack>();
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/examples/zigbee-nwk-routing.cc ns-3.46/src/zigbee/examples/zigbee-nwk-routing.cc
--- ns-3.45/src/zigbee/examples/zigbee-nwk-routing.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/examples/zigbee-nwk-routing.cc	2025-10-01 18:46:32.000000000 -0700
@@ -275,10 +275,11 @@
     dev3->SetChannel(channel);
     dev4->SetChannel(channel);
 
-    //// Configure NWK
+    // Configure the Zigbee stack and use only the NWK layer.
 
-    ZigbeeHelper zigbee;
-    ZigbeeStackContainer zigbeeStackContainer = zigbee.Install(lrwpanDevices);
+    ZigbeeHelper zigbeeHelper;
+    zigbeeHelper.SetNwkLayerOnly();
+    ZigbeeStackContainer zigbeeStackContainer = zigbeeHelper.Install(lrwpanDevices);
 
     Ptr<ZigbeeStack> zstack0 = zigbeeStackContainer.Get(0)->GetObject<ZigbeeStack>();
     Ptr<ZigbeeStack> zstack1 = zigbeeStackContainer.Get(1)->GetObject<ZigbeeStack>();
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/examples/zigbee-nwk-routing-grid.cc ns-3.46/src/zigbee/examples/zigbee-nwk-routing-grid.cc
--- ns-3.45/src/zigbee/examples/zigbee-nwk-routing-grid.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/examples/zigbee-nwk-routing-grid.cc	2025-10-01 18:46:32.000000000 -0700
@@ -279,6 +279,7 @@
     lrWpanHelper.SetExtendedAddresses(lrwpanDevices);
 
     ZigbeeHelper zigbeeHelper;
+    zigbeeHelper.SetNwkLayerOnly();
     zigbeeStacks = zigbeeHelper.Install(lrwpanDevices);
 
     // NWK callbacks hooks
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/helper/zigbee-helper.cc ns-3.46/src/zigbee/helper/zigbee-helper.cc
--- ns-3.45/src/zigbee/helper/zigbee-helper.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/helper/zigbee-helper.cc	2025-10-01 18:46:32.000000000 -0700
@@ -24,6 +24,7 @@
 {
     NS_LOG_FUNCTION(this);
     m_stackFactory.SetTypeId("ns3::zigbee::ZigbeeStack");
+    m_nwkLayerOnly = false;
 }
 
 void
@@ -49,6 +50,12 @@
         NS_LOG_LOGIC("Installing Zigbee on node " << device->GetNode()->GetId());
 
         Ptr<zigbee::ZigbeeStack> zigbeeStack = m_stackFactory.Create<zigbee::ZigbeeStack>();
+
+        if (m_nwkLayerOnly)
+        {
+            zigbeeStack->SetOnlyNwkLayer();
+        }
+
         zigbeeStackContainer.Add(zigbeeStack);
         device->GetNode()->AggregateObject(zigbeeStack);
         zigbeeStack->SetNetDevice(device);
@@ -56,4 +63,10 @@
     return zigbeeStackContainer;
 }
 
+void
+ZigbeeHelper::SetNwkLayerOnly()
+{
+    m_nwkLayerOnly = true;
+}
+
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/helper/zigbee-helper.h ns-3.46/src/zigbee/helper/zigbee-helper.h
--- ns-3.45/src/zigbee/helper/zigbee-helper.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/helper/zigbee-helper.h	2025-10-01 18:46:32.000000000 -0700
@@ -15,6 +15,7 @@
 #include "ns3/net-device-container.h"
 #include "ns3/object-factory.h"
 
+#include <optional>
 #include <string>
 
 namespace ns3
@@ -64,6 +65,12 @@
     zigbee::ZigbeeStackContainer Install(NetDeviceContainer c);
 
     /**
+     * If this is set, the helper will only create Zigbee stacks that contain
+     * only the NWK layer
+     */
+    void SetNwkLayerOnly();
+
+    /**
      * Assign a fixed random variable stream number to the random variables
      * used by this model. Return the number of streams (possibly zero) that
      * have been assigned. The Install() method should have previously been
@@ -78,6 +85,7 @@
 
   private:
     ObjectFactory m_stackFactory; //!< Zigbee stack object factory.
+    bool m_nwkLayerOnly;          //!< Flag indicating that only the NWK layer is present
 };
 
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-aps.cc ns-3.46/src/zigbee/model/zigbee-aps.cc
--- ns-3.45/src/zigbee/model/zigbee-aps.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-aps.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,769 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors:
+ *
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#include "zigbee-aps.h"
+
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+
+namespace ns3
+{
+namespace zigbee
+{
+
+NS_LOG_COMPONENT_DEFINE("ZigbeeAps");
+NS_OBJECT_ENSURE_REGISTERED(ZigbeeAps);
+
+TypeId
+ZigbeeAps::GetTypeId()
+{
+    static TypeId tid = TypeId("ns3::zigbee::ZigbeeAps")
+                            .SetParent<Object>()
+                            .SetGroupName("Zigbee")
+                            .AddConstructor<ZigbeeAps>()
+                            .AddAttribute("ApsNonMemberRadius",
+                                          "The value to be used for the NonmemberRadius parameter"
+                                          " when using NWK layer multicast",
+                                          UintegerValue(0x02),
+                                          MakeUintegerAccessor(&ZigbeeAps::m_apsNonMemberRadius),
+                                          MakeUintegerChecker<uint8_t>());
+    return tid;
+}
+
+ZigbeeAps::ZigbeeAps()
+{
+    NS_LOG_FUNCTION(this);
+}
+
+void
+ZigbeeAps::NotifyConstructionCompleted()
+{
+    NS_LOG_FUNCTION(this);
+}
+
+ZigbeeAps::~ZigbeeAps()
+{
+    NS_LOG_FUNCTION(this);
+}
+
+void
+ZigbeeAps::DoInitialize()
+{
+    NS_LOG_FUNCTION(this);
+    Object::DoInitialize();
+}
+
+void
+ZigbeeAps::DoDispose()
+{
+    m_nwk = nullptr;
+    // m_apsBindingTable.Dispose();
+    m_apsdeDataConfirmCallback = MakeNullCallback<void, ApsdeDataConfirmParams>();
+
+    Object::DoDispose();
+}
+
+void
+ZigbeeAps::SetNwk(Ptr<ZigbeeNwk> nwk)
+{
+    m_nwk = nwk;
+}
+
+void
+ZigbeeAps::SetGroupTable(Ptr<ZigbeeGroupTable> groupTable)
+{
+    m_apsGroupTable = groupTable;
+}
+
+Ptr<ZigbeeNwk>
+ZigbeeAps::GetNwk() const
+{
+    return m_nwk;
+}
+
+void
+ZigbeeAps::ApsdeDataRequest(ApsdeDataRequestParams params, Ptr<Packet> asdu)
+{
+    NS_LOG_FUNCTION(this);
+
+    // Fill APSDE-data.confirm parameters in case we need to return an error
+    ApsdeDataConfirmParams confirmParams;
+    confirmParams.m_dstAddrMode = params.m_dstAddrMode;
+    confirmParams.m_dstAddr16 = params.m_dstAddr16;
+    confirmParams.m_dstAddr64 = params.m_dstAddr64;
+    confirmParams.m_dstEndPoint = params.m_dstEndPoint;
+    confirmParams.m_srcEndPoint = params.m_srcEndPoint;
+
+    ZigbeeApsTxOptions txOptions(params.m_txOptions);
+
+    if (txOptions.IsSecurityEnabled())
+    {
+        // TODO: Add support for security options
+        if (!m_apsdeDataConfirmCallback.IsNull())
+        {
+            confirmParams.m_status = ApsStatus::SECURITY_FAIL;
+            confirmParams.m_txTime = Simulator::Now();
+            m_apsdeDataConfirmCallback(confirmParams);
+        }
+        NS_LOG_WARN("Security is not currently supported");
+        return;
+    }
+
+    // TODO: Fragmentation
+
+    // TODO: Add ACK support
+    if (txOptions.IsAckRequired())
+    {
+        NS_ABORT_MSG("Transmission with ACK not supported");
+        return;
+    }
+
+    // See See 2.2.4.1.1
+    switch (params.m_dstAddrMode)
+    {
+    case ApsDstAddressMode::DST_ADDR_AND_DST_ENDPOINT_NOT_PRESENT: {
+        // Use BINDING TABLE to send data to one or more destinations
+        // (Groupcast or IEEE address destination transmission)
+        NS_ABORT_MSG("Binded destination groupcast not supported");
+        // SendDataWithBindingTable(params, asdu);
+        break;
+    }
+    case ApsDstAddressMode::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT: {
+        // Groupcast (a kind of multicast) support
+        SendDataGroup(params, asdu);
+        break;
+    }
+    case ApsDstAddressMode::DST_ADDR16_DST_ENDPOINT_PRESENT: {
+        // Regular UCST or BCST transmission with the 16 bit destination address
+        SendDataUcstBcst(params, asdu);
+        break;
+    }
+    case ApsDstAddressMode::DST_ADDR64_DST_ENDPOINT_PRESENT: {
+        // TODO: Add Extended address transmission support.
+        // The NWK do not accept direct extended address transmissions,
+        // therefore, the APS must translate the extended address
+        // to a short address using the nwkAddressMap NIB.
+        if (!m_apsdeDataConfirmCallback.IsNull())
+        {
+            confirmParams.m_status = ApsStatus::NO_SHORT_ADDRESS;
+            confirmParams.m_txTime = Simulator::Now();
+            m_apsdeDataConfirmCallback(confirmParams);
+        }
+        NS_LOG_WARN("Extended address mode not supported");
+        break;
+    }
+    default:
+        NS_ABORT_MSG("Invalid Option");
+        break;
+    }
+}
+
+void
+ZigbeeAps::SendDataWithBindingTable(ApsdeDataRequestParams params, Ptr<Packet> asdu)
+{
+    NS_LOG_FUNCTION(this);
+
+    // Fill APSDE-data.confirm parameters in case we need to return an error
+    ApsdeDataConfirmParams confirmParams;
+    confirmParams.m_dstAddrMode = params.m_dstAddrMode;
+    confirmParams.m_dstAddr16 = params.m_dstAddr16;
+    confirmParams.m_dstAddr64 = params.m_dstAddr64;
+    confirmParams.m_dstEndPoint = params.m_dstEndPoint;
+    confirmParams.m_srcEndPoint = params.m_srcEndPoint;
+
+    // APS Header
+    ZigbeeApsTxOptions txOptions(params.m_txOptions);
+    ZigbeeApsHeader apsHeader;
+    apsHeader.SetFrameType(ApsFrameType::APS_DATA);
+    apsHeader.SetSrcEndpoint(params.m_srcEndPoint);
+    apsHeader.SetProfileId(params.m_profileId);
+    apsHeader.SetClusterId(params.m_clusterId);
+    apsHeader.SetExtHeaderPresent(false);
+    apsHeader.SetDeliveryMode(ApsDeliveryMode::APS_UCST);
+
+    // NLDE-data.request params
+    NldeDataRequestParams nwkParams;
+    nwkParams.m_radius = params.m_radius;
+    nwkParams.m_discoverRoute = DiscoverRouteType::ENABLE_ROUTE_DISCOVERY;
+    nwkParams.m_securityEnable = txOptions.IsSecurityEnabled();
+    nwkParams.m_dstAddrMode = AddressMode::UCST_BCST;
+
+    SrcBindingEntry srcEntry;
+    std::vector<DstBindingEntry> dstEntries;
+
+    if (m_apsBindingTable.LookUpEntries(srcEntry, dstEntries))
+    {
+        for (const auto& dst : dstEntries)
+        {
+            if (dst.GetDstAddrMode() == ApsDstAddressModeBind::DST_ADDR64_DST_ENDPOINT_PRESENT)
+            {
+                // We must look into the nwkAddressMap to transform the
+                // 64 bit address destination to a 16 bit destination
+                NS_LOG_WARN("Bound destination found but 64bit destination not supported");
+                // TODO: drop trace here
+            }
+            else
+            {
+                // Send a UCST message to each destination
+                nwkParams.m_dstAddr = dst.GetDstAddr16();
+                apsHeader.SetApsCounter(m_apsCounter.GetValue());
+                m_apsCounter++;
+                Ptr<Packet> p = asdu->Copy();
+                p->AddHeader(apsHeader);
+                Simulator::ScheduleNow(&ZigbeeNwk::NldeDataRequest, m_nwk, nwkParams, p);
+            }
+        }
+
+        if (!m_apsdeDataConfirmCallback.IsNull())
+        {
+            confirmParams.m_status = ApsStatus::SUCCESS;
+            confirmParams.m_txTime = Simulator::Now();
+            m_apsdeDataConfirmCallback(confirmParams);
+        }
+    }
+    else
+    {
+        if (!m_apsdeDataConfirmCallback.IsNull())
+        {
+            confirmParams.m_status = ApsStatus::NO_BOUND_DEVICE;
+            confirmParams.m_txTime = Simulator::Now();
+            m_apsdeDataConfirmCallback(confirmParams);
+        }
+    }
+}
+
+void
+ZigbeeAps::SendDataUcstBcst(ApsdeDataRequestParams params, Ptr<Packet> asdu)
+{
+    NS_LOG_FUNCTION(this);
+
+    // Fill APSDE-data.confirm parameters in case we need to return an error
+    ApsdeDataConfirmParams confirmParams;
+    confirmParams.m_dstAddrMode = params.m_dstAddrMode;
+    confirmParams.m_dstAddr16 = params.m_dstAddr16;
+    confirmParams.m_dstAddr64 = params.m_dstAddr64;
+    confirmParams.m_dstEndPoint = params.m_dstEndPoint;
+    confirmParams.m_srcEndPoint = params.m_srcEndPoint;
+
+    // APS Header
+    ZigbeeApsTxOptions txOptions(params.m_txOptions);
+    ZigbeeApsHeader apsHeader;
+    apsHeader.SetFrameType(ApsFrameType::APS_DATA);
+    apsHeader.SetSrcEndpoint(params.m_srcEndPoint);
+    apsHeader.SetProfileId(params.m_profileId);
+    apsHeader.SetClusterId(params.m_clusterId);
+    apsHeader.SetExtHeaderPresent(false);
+    apsHeader.SetDeliveryMode(ApsDeliveryMode::APS_UCST);
+
+    // NLDE-data.request params
+    NldeDataRequestParams nwkParams;
+    nwkParams.m_radius = params.m_radius;
+    nwkParams.m_discoverRoute = DiscoverRouteType::ENABLE_ROUTE_DISCOVERY;
+    nwkParams.m_securityEnable = txOptions.IsSecurityEnabled();
+    nwkParams.m_dstAddrMode = AddressMode::UCST_BCST;
+
+    if (params.m_dstAddr16 == "FF:FF" || params.m_dstAddr16 == "FF:FD" ||
+        params.m_dstAddr16 == "FF:FC" || params.m_dstAddr16 == "FF:FB")
+    {
+        // Destination is a broadcast address
+        apsHeader.SetDeliveryMode(ApsDeliveryMode::APS_BCST);
+    }
+    else
+    {
+        // Destination is a unicast address
+        apsHeader.SetDeliveryMode(ApsDeliveryMode::APS_UCST);
+    }
+
+    if (params.m_useAlias)
+    {
+        if (txOptions.IsAckRequired()) // 0b1 = 00000001 = 1 dec
+        {
+            if (!m_apsdeDataConfirmCallback.IsNull())
+            {
+                confirmParams.m_status = ApsStatus::NOT_SUPPORTED;
+                confirmParams.m_txTime = Simulator::Now();
+                m_apsdeDataConfirmCallback(confirmParams);
+            }
+            return;
+        }
+
+        nwkParams.m_useAlias = params.m_useAlias;
+        nwkParams.m_aliasSeqNumber = params.m_aliasSeqNumb;
+        nwkParams.m_aliasSrcAddr = params.m_aliasSrcAddr;
+
+        apsHeader.SetApsCounter(params.m_aliasSeqNumb);
+    }
+    else
+    {
+        apsHeader.SetApsCounter(m_apsCounter.GetValue());
+        m_apsCounter++;
+    }
+
+    nwkParams.m_dstAddrMode = AddressMode::UCST_BCST;
+    nwkParams.m_dstAddr = params.m_dstAddr16;
+    apsHeader.SetDstEndpoint(params.m_dstEndPoint);
+
+    asdu->AddHeader(apsHeader);
+
+    Simulator::ScheduleNow(&ZigbeeNwk::NldeDataRequest, m_nwk, nwkParams, asdu);
+}
+
+void
+ZigbeeAps::SendDataGroup(ApsdeDataRequestParams params, Ptr<Packet> asdu)
+{
+    NS_LOG_FUNCTION(this);
+
+    // Fill APSDE-data.confirm parameters in case we need to return an error
+    ApsdeDataConfirmParams confirmParams;
+    confirmParams.m_dstAddrMode = params.m_dstAddrMode;
+    confirmParams.m_dstAddr16 = params.m_dstAddr16;
+    confirmParams.m_dstAddr64 = params.m_dstAddr64;
+    confirmParams.m_dstEndPoint = params.m_dstEndPoint;
+    confirmParams.m_srcEndPoint = params.m_srcEndPoint;
+
+    if (params.m_dstAddr16 == Mac16Address("00:00"))
+    {
+        if (!m_apsdeDataConfirmCallback.IsNull())
+        {
+            confirmParams.m_status = ApsStatus::INVALID_GROUP;
+            confirmParams.m_txTime = Simulator::Now();
+            m_apsdeDataConfirmCallback(confirmParams);
+        }
+        return;
+    }
+
+    // APS Header
+    ZigbeeApsTxOptions txOptions(params.m_txOptions);
+    ZigbeeApsHeader apsHeader;
+    apsHeader.SetFrameType(ApsFrameType::APS_DATA);
+    apsHeader.SetSrcEndpoint(params.m_srcEndPoint);
+    apsHeader.SetProfileId(params.m_profileId);
+    apsHeader.SetClusterId(params.m_clusterId);
+    apsHeader.SetExtHeaderPresent(false);
+    apsHeader.SetDeliveryMode(ApsDeliveryMode::APS_GROUP_ADDRESSING);
+    apsHeader.SetGroupAddress(params.m_dstAddr16.ConvertToInt());
+
+    // NLDE-data.request params
+    NldeDataRequestParams nwkParams;
+    nwkParams.m_radius = params.m_radius;
+    nwkParams.m_discoverRoute = DiscoverRouteType::ENABLE_ROUTE_DISCOVERY;
+    nwkParams.m_securityEnable = txOptions.IsSecurityEnabled();
+    nwkParams.m_dstAddrMode = AddressMode::MCST;
+    nwkParams.m_dstAddr = params.m_dstAddr16;
+    nwkParams.m_nonMemberRadius = m_apsNonMemberRadius;
+
+    asdu->AddHeader(apsHeader);
+
+    Simulator::ScheduleNow(&ZigbeeNwk::NldeDataRequest, m_nwk, nwkParams, asdu);
+}
+
+void
+ZigbeeAps::ApsmeBindRequest(ApsmeBindRequestParams params)
+{
+    ApsmeBindConfirmParams confirmParams;
+    confirmParams.m_srcAddr = params.m_srcAddr;
+    confirmParams.m_srcEndPoint = params.m_srcEndPoint;
+    confirmParams.m_clusterId = params.m_clusterId;
+    confirmParams.m_dstAddr16 = params.m_dstAddr16;
+    confirmParams.m_dstAddr64 = params.m_dstAddr64;
+    confirmParams.m_dstAddrMode = params.m_dstAddrMode;
+    confirmParams.m_dstEndPoint = params.m_dstEndPoint;
+
+    // TODO: confirm the device has joined the network
+    // How? APS have no access to join information.
+
+    // Verify params are in valid range (2.2.4.3.1)
+    if ((params.m_srcEndPoint < 0x01 || params.m_srcEndPoint > 0xfe) ||
+        (params.m_dstEndPoint < 0x01))
+    {
+        if (!m_apsmeBindConfirmCallback.IsNull())
+        {
+            confirmParams.m_status = ApsStatus::ILLEGAL_REQUEST;
+            m_apsmeBindConfirmCallback(confirmParams);
+        }
+        return;
+    }
+
+    SrcBindingEntry srcEntry(params.m_srcAddr, params.m_srcEndPoint, params.m_clusterId);
+
+    DstBindingEntry dstEntry;
+
+    if (params.m_dstAddrMode == ApsDstAddressModeBind::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT)
+    {
+        // Group Addressing binding
+        dstEntry.SetDstAddrMode(ApsDstAddressModeBind::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT);
+        dstEntry.SetDstAddr16(params.m_dstAddr16);
+    }
+    else
+    {
+        // Unicast binding
+        dstEntry.SetDstAddrMode(ApsDstAddressModeBind::DST_ADDR64_DST_ENDPOINT_PRESENT);
+        dstEntry.SetDstEndPoint(params.m_dstEndPoint);
+    }
+
+    switch (m_apsBindingTable.Bind(srcEntry, dstEntry))
+    {
+    case BindingTableStatus::BOUND:
+        confirmParams.m_status = ApsStatus::SUCCESS;
+        break;
+    case BindingTableStatus::ENTRY_EXISTS:
+        confirmParams.m_status = ApsStatus::INVALID_BINDING;
+        break;
+    case BindingTableStatus::TABLE_FULL:
+        confirmParams.m_status = ApsStatus::TABLE_FULL;
+        break;
+    default:
+        NS_LOG_ERROR("Invalid binding option");
+    }
+
+    if (!m_apsmeBindConfirmCallback.IsNull())
+    {
+        m_apsmeBindConfirmCallback(confirmParams);
+    }
+}
+
+void
+ZigbeeAps::ApsmeUnbindRequest(ApsmeBindRequestParams params)
+{
+}
+
+void
+ZigbeeAps::ApsmeAddGroupRequest(ApsmeGroupRequestParams params)
+{
+    NS_LOG_FUNCTION(this);
+
+    ApsmeGroupConfirmParams confirmParams;
+    confirmParams.m_status = ApsStatus::SUCCESS;
+    confirmParams.m_groupAddress = params.m_groupAddress;
+    confirmParams.m_endPoint = params.m_endPoint;
+
+    if (!m_apsGroupTable->AddEntry(params.m_groupAddress.ConvertToInt(), params.m_endPoint))
+    {
+        confirmParams.m_status = ApsStatus::TABLE_FULL;
+    }
+
+    if (!m_apsmeAddGroupConfirmCallback.IsNull())
+    {
+        m_apsmeAddGroupConfirmCallback(confirmParams);
+    }
+}
+
+void
+ZigbeeAps::ApsmeRemoveGroupRequest(ApsmeGroupRequestParams params)
+{
+    NS_LOG_FUNCTION(this);
+
+    ApsmeGroupConfirmParams confirmParams;
+    confirmParams.m_status = ApsStatus::SUCCESS;
+    confirmParams.m_groupAddress = params.m_groupAddress;
+    confirmParams.m_endPoint = params.m_endPoint;
+
+    if (!m_apsGroupTable->RemoveEntry(params.m_groupAddress.ConvertToInt(), params.m_endPoint))
+    {
+        confirmParams.m_status = ApsStatus::INVALID_GROUP;
+    }
+
+    if (!m_apsmeRemoveGroupConfirmCallback.IsNull())
+    {
+        m_apsmeRemoveGroupConfirmCallback(confirmParams);
+    }
+}
+
+void
+ZigbeeAps::ApsmeRemoveAllGroupsRequest(uint8_t endPoint)
+{
+    NS_LOG_FUNCTION(this);
+
+    ApsmeRemoveAllGroupsConfirmParams confirmParams;
+    confirmParams.m_status = ApsStatus::SUCCESS;
+    confirmParams.m_endPoint = endPoint;
+
+    if (!m_apsGroupTable->RemoveMembership(endPoint))
+    {
+        confirmParams.m_status = ApsStatus::INVALID_PARAMETER;
+    }
+
+    if (!m_apsmeRemoveAllGroupsConfirmCallback.IsNull())
+    {
+        m_apsmeRemoveAllGroupsConfirmCallback(confirmParams);
+    }
+}
+
+void
+ZigbeeAps::NldeDataConfirm(NldeDataConfirmParams params)
+{
+    // TODO: Handle the confirmation of the data request
+}
+
+void
+ZigbeeAps::NldeDataIndication(NldeDataIndicationParams params, Ptr<Packet> nsdu)
+{
+    NS_LOG_FUNCTION(this);
+
+    // See section 2.2.4.1.3.
+    // - TODO: Handle Security
+    // - Handle groupcast (MCST) delivery (Note group table shared by NWK and APS)
+    // - Handle UCST, BCST delivery
+    // - TODO: Handle binding
+    // - TODO: Handle fragmentation
+    // - TODO: Detect Duplicates
+    // - TODO: Handle ACK
+    // - TODO: Handle other frame types (APS Command, APS Inter-PAN)
+
+    ZigbeeApsHeader apsHeader;
+    nsdu->RemoveHeader(apsHeader);
+
+    // Check if packet is fragmented
+    if (apsHeader.IsExtHeaderPresent())
+    {
+        if (!m_apsdeDataIndicationCallback.IsNull())
+        {
+            ApsdeDataIndicationParams indicationParams;
+            indicationParams.m_status = ApsStatus::DEFRAG_UNSUPPORTED;
+            m_apsdeDataIndicationCallback(indicationParams, nsdu);
+        }
+
+        NS_LOG_WARN("Extended Header (Fragmentation) not supported");
+        return;
+        // TODO: Handle fragmentation See 2.2.8.4.5
+    }
+
+    // TODO: IF security is present, remove as described in Section 4.4.
+    if (params.m_securityUse)
+    {
+        NS_LOG_ERROR("Security is not currently supported");
+    }
+
+    // TODO: Duplicate detection here
+    // See last paragraph of section 2.2.8.4.2
+
+    switch (apsHeader.GetFrameType())
+    {
+    case ApsFrameType::APS_DATA:
+        // Zigbee Specification, Section 2.2.8.4.2
+        // Reception and Rejection
+        ReceiveData(apsHeader, params, nsdu);
+        break;
+    case ApsFrameType::APS_ACK:
+        NS_LOG_ERROR("APS ACK frames are not supported");
+        break;
+    case ApsFrameType::APS_COMMAND:
+        NS_LOG_ERROR("APS Command frames are not supported");
+        break;
+    case ApsFrameType::APS_INTERPAN_APS:
+        NS_LOG_ERROR("APS Inter-PAN frames are not supported");
+        break;
+    }
+}
+
+void
+ZigbeeAps::ReceiveData(const ZigbeeApsHeader& apsHeader,
+                       const NldeDataIndicationParams& params,
+                       Ptr<Packet> nsdu)
+{
+    NS_LOG_FUNCTION(this);
+
+    ApsdeDataIndicationParams indicationParams;
+    indicationParams.m_status = ApsStatus::SUCCESS;
+    indicationParams.m_srcAddress16 = params.m_srcAddr;
+    indicationParams.m_srcEndpoint = apsHeader.GetSrcEndpoint();
+    indicationParams.m_profileId = apsHeader.GetProfileId();
+    indicationParams.m_clusterId = apsHeader.GetClusterId();
+    indicationParams.asduLength = nsdu->GetSize();
+    indicationParams.m_securityStatus = ApsSecurityStatus::UNSECURED;
+    indicationParams.m_linkQuality = params.m_linkQuality;
+    indicationParams.m_rxTime = Simulator::Now();
+
+    // UNICAST or BROADCAST delivery
+
+    if (apsHeader.GetDeliveryMode() == ApsDeliveryMode::APS_UCST ||
+        apsHeader.GetDeliveryMode() == ApsDeliveryMode::APS_BCST)
+    {
+        if (!m_apsdeDataIndicationCallback.IsNull())
+        {
+            // Note: Extracting the Address directly from the NWK, creates a dependency on this NWK
+            // implementation. This is not a very good design, but in practice, it is unavoidable
+            // due to the quasi cross-layer design of the specification
+            //(tigly coupled design of the APS in respect to the NWK).
+            indicationParams.m_dstAddr16 = m_nwk->GetNetworkAddress();
+            indicationParams.m_dstAddrMode = ApsDstAddressMode::DST_ADDR16_DST_ENDPOINT_PRESENT;
+            indicationParams.m_dstEndPoint = apsHeader.GetDstEndpoint();
+            indicationParams.m_srcAddrMode = ApsSrcAddressMode::SRC_ADDR16_SRC_ENDPOINT_PRESENT;
+            m_apsdeDataIndicationCallback(indicationParams, nsdu);
+        }
+        return;
+    }
+
+    // GROUPCAST delivery
+
+    if (apsHeader.GetDeliveryMode() == ApsDeliveryMode::APS_GROUP_ADDRESSING &&
+        params.m_dstAddrMode == AddressMode::MCST)
+    {
+        std::vector<uint8_t> endPoints;
+        if (m_apsGroupTable->LookUpEndPoints(apsHeader.GetGroupAddress(), endPoints))
+        {
+            // Give a copy of the packet to each endpoint associated with the group ID.
+            for (const auto& endPoint : endPoints)
+            {
+                if (!m_apsdeDataIndicationCallback.IsNull())
+                {
+                    indicationParams.m_dstAddr16 = Mac16Address(apsHeader.GetGroupAddress());
+                    indicationParams.m_dstAddrMode =
+                        ApsDstAddressMode::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT;
+                    indicationParams.m_dstEndPoint = endPoint;
+                    indicationParams.m_srcAddrMode =
+                        ApsSrcAddressMode::SRC_ADDR16_SRC_ENDPOINT_PRESENT;
+                    m_apsdeDataIndicationCallback(indicationParams, nsdu->Copy());
+                }
+            }
+        }
+        return;
+    }
+}
+
+void
+ZigbeeAps::SetApsdeDataConfirmCallback(ApsdeDataConfirmCallback c)
+{
+    m_apsdeDataConfirmCallback = c;
+}
+
+void
+ZigbeeAps::SetApsdeDataIndicationCallback(ApsdeDataIndicationCallback c)
+{
+    m_apsdeDataIndicationCallback = c;
+}
+
+void
+ZigbeeAps::SetApsmeBindConfirmCallback(ApsmeBindConfirmCallback c)
+{
+    m_apsmeBindConfirmCallback = c;
+}
+
+void
+ZigbeeAps::SetApsmeUnbindConfirmCallback(ApsmeUnbindConfirmCallback c)
+{
+    m_apsmeUnbindConfirmCallback = c;
+}
+
+void
+ZigbeeAps::SetApsmeAddGroupConfirmCallback(ApsmeAddGroupConfirmCallback c)
+{
+    m_apsmeAddGroupConfirmCallback = c;
+}
+
+void
+ZigbeeAps::SetApsmeRemoveGroupConfirmCallback(ApsmeRemoveGroupConfirmCallback c)
+{
+    m_apsmeRemoveGroupConfirmCallback = c;
+}
+
+void
+ZigbeeAps::SetApsmeRemoveAllGroupsConfirmCallback(ApsmeRemoveAllGroupsConfirmCallback c)
+{
+    m_apsmeRemoveAllGroupsConfirmCallback = c;
+}
+
+//////////////////////////
+//  ZigbeeApsTxOptions  //
+//////////////////////////
+
+ZigbeeApsTxOptions::ZigbeeApsTxOptions(uint8_t value)
+    : m_txOptions(value)
+{
+}
+
+void
+ZigbeeApsTxOptions::SetSecurityEnabled(bool enable)
+{
+    SetBit(0, enable);
+}
+
+void
+ZigbeeApsTxOptions::SetUseNwkKey(bool enable)
+{
+    SetBit(1, enable);
+}
+
+void
+ZigbeeApsTxOptions::SetAckRequired(bool enable)
+{
+    SetBit(2, enable);
+}
+
+void
+ZigbeeApsTxOptions::SetFragmentationPermitted(bool enable)
+{
+    SetBit(3, enable);
+}
+
+void
+ZigbeeApsTxOptions::SetIncludeExtendedNonce(bool enable)
+{
+    SetBit(4, enable);
+}
+
+bool
+ZigbeeApsTxOptions::IsSecurityEnabled() const
+{
+    return GetBit(0);
+}
+
+bool
+ZigbeeApsTxOptions::IsUseNwkKey() const
+{
+    return GetBit(1);
+}
+
+bool
+ZigbeeApsTxOptions::IsAckRequired() const
+{
+    return GetBit(2);
+}
+
+bool
+ZigbeeApsTxOptions::IsFragmentationPermitted() const
+{
+    return GetBit(3);
+}
+
+bool
+ZigbeeApsTxOptions::IsIncludeExtendedNonce() const
+{
+    return GetBit(4);
+}
+
+uint8_t
+ZigbeeApsTxOptions::GetTxOptions() const
+{
+    return m_txOptions;
+}
+
+void
+ZigbeeApsTxOptions::SetBit(int pos, bool value)
+{
+    if (value)
+    {
+        m_txOptions |= (1 << pos);
+    }
+    else
+    {
+        m_txOptions &= ~(1 << pos);
+    }
+}
+
+bool
+ZigbeeApsTxOptions::GetBit(int pos) const
+{
+    return (m_txOptions >> pos) & 1;
+}
+
+} // namespace zigbee
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-aps.h ns-3.46/src/zigbee/model/zigbee-aps.h
--- ns-3.45/src/zigbee/model/zigbee-aps.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-aps.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors:
+ *
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#ifndef ZIGBEE_APS_H
+#define ZIGBEE_APS_H
+
+#include "zigbee-aps-header.h"
+#include "zigbee-aps-tables.h"
+#include "zigbee-group-table.h"
+#include "zigbee-nwk.h"
+
+#include "ns3/event-id.h"
+#include "ns3/mac16-address.h"
+#include "ns3/mac64-address.h"
+#include "ns3/object.h"
+#include "ns3/random-variable-stream.h"
+#include "ns3/sequence-number.h"
+#include "ns3/traced-callback.h"
+#include "ns3/traced-value.h"
+
+#include <cstdint>
+#include <iomanip>
+#include <iterator>
+
+namespace ns3
+{
+namespace zigbee
+{
+
+/**
+ * @ingroup zigbee
+ *
+ * APS Destination Address Mode,
+ * Zigbee Specification r22.1.0
+ * Table 2-2 APSDE-DATA.request Parameters
+ * See Table 2-4 APSDE-DATA.indication Parameters
+ */
+enum class ApsDstAddressMode : std::uint8_t
+{
+    DST_ADDR_AND_DST_ENDPOINT_NOT_PRESENT = 0x00, //!< Destination address and destination endpoint
+                                                  //!< not present.
+    GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT = 0x01,   //!< Group address or 16-bit destination address
+                                                  //!< present but destination endpoint not present.
+    DST_ADDR16_DST_ENDPOINT_PRESENT = 0x02,       //!< 16-bit destination address and destination
+                                                  //!< endpoint present.
+    DST_ADDR64_DST_ENDPOINT_PRESENT = 0x03,       //!< 64-bit destination address and destination
+                                                  //!< endpoint present.
+    DST_ADDR64_DST_ENDPOINT_NOT_PRESENT = 0x04    //!< 64-bit address present but destination
+                                                  //!< endpoint not present.
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * APS Source Address Mode,
+ * Zigbee Specification r22.1.0
+ * See Table 2-4 APSDE-DATA.indication Parameters
+ */
+enum class ApsSrcAddressMode : std::uint8_t
+{
+    SRC_ADDR16_SRC_ENDPOINT_PRESENT = 0x02, //!< 16-bit source address and source endpoint present
+    SRC_ADDR64_SRC_ENDPOINT_PRESENT = 0x03, //!< 64-bit source address and source endpoint present
+    SRC_ADDR64_SRC_ENDPOINT_NOT_PRESENT = 0x04 //!< 64-bit source address present but source
+                                               //!< endpoint not present
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * APS Security status
+ * See Zigbee Specification r22.1.0, Table 2-4
+ * APSDE-DATA.indication Parameters
+ */
+enum class ApsSecurityStatus : std::uint8_t
+{
+    UNSECURED = 0x00,       //!< Unsecured status
+    SECURED_NWK_KEY = 0x01, //!< Use NWK secure key
+    SECURED_LINK_KEY = 0x02 //!< Use link secure key
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * APS Sub-layer Status Values
+ * See Zigbee Specification r22.1.0, Table 2-27
+ */
+enum class ApsStatus : std::uint8_t
+{
+    SUCCESS = 0x00,              //!< A request has been executed successfully.
+    ASDU_TOO_LONG = 0xa0,        //!< A received fragmented
+                                 //!< frame could not be defragmented at the current time.
+    DEFRAG_DEFERRED = 0xa1,      //!< Defragmentation deferred.
+    DEFRAG_UNSUPPORTED = 0xa2,   //!< Defragmentation is not supported.
+    ILLEGAL_REQUEST = 0xa3,      //!< Illegal request
+    INVALID_BINDING = 0xa4,      //!< Invalid binding
+    INVALID_GROUP = 0xa5,        //!< Invalid group
+    INVALID_PARAMETER = 0xa6,    //!< A parameter value was invalid or out of range
+    NO_ACK = 0xa7,               //!< No Acknowledgment
+    NO_BOUND_DEVICE = 0xa8,      //!< No bound device
+    NO_SHORT_ADDRESS = 0xa9,     //!< No short address present
+    NOT_SUPPORTED = 0xaa,        //!< Not supported in APS
+    SECURED_LINK_KEY = 0xab,     //!< Secured link key present
+    SECURED_NWK_KEY = 0xac,      //!< Secured network key present
+    SECURITY_FAIL = 0xad,        //!< Security failed
+    TABLE_FULL = 0xae,           //!< Binding table or group table is full
+    UNSECURED = 0xaf,            //!< Unsecured
+    UNSUPPORTED_ATTRIBUTE = 0xb0 //!< Unsupported attribute
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Section 2.2.4.1.1
+ * APSDE-DATA.request params.
+ */
+struct ApsdeDataRequestParams
+{
+    ApsDstAddressMode m_dstAddrMode{
+        ApsDstAddressMode::DST_ADDR_AND_DST_ENDPOINT_NOT_PRESENT}; //!< Destination address mode.
+    Mac16Address m_dstAddr16;    //!< The destination 16-bit address
+    Mac64Address m_dstAddr64;    //!< The destination 64-bit address
+    uint8_t m_dstEndPoint{0};    //!< The destination endpoint
+    uint16_t m_profileId{0};     //!< The application profile ID
+    uint16_t m_clusterId{0};     //!< The application cluster ID
+    uint8_t m_srcEndPoint{0};    //!< The source endpoint
+    uint32_t m_asduLength{0};    //!< The ASDU length
+    uint8_t m_txOptions{0};      //!< Transmission options
+    bool m_useAlias{false};      //!< Indicates if alias is used in this transmission
+    Mac16Address m_aliasSrcAddr; //!< Alias source address
+    uint8_t m_aliasSeqNumb{0};   //!< Alias sequence number
+    uint8_t m_radius{0};         //!< Radius (Number of hops this message travels)
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Section 2.2.4.1.2
+ * APSDE-DATA.confirm params.
+ */
+struct ApsdeDataConfirmParams
+{
+    ApsDstAddressMode m_dstAddrMode{
+        ApsDstAddressMode::DST_ADDR_AND_DST_ENDPOINT_NOT_PRESENT}; //!< Destination address mode.
+    Mac16Address m_dstAddr16; //!< The destination 16-bit address.
+    Mac64Address m_dstAddr64; //!< The destination IEEE address (64-bit address).
+    uint8_t m_dstEndPoint{0}; //!< The destination endpoint.
+    uint8_t m_srcEndPoint{0}; //!< The source endpoint.
+    ApsStatus m_status{ApsStatus::UNSUPPORTED_ATTRIBUTE}; //!< The confirmation status.
+    Time m_txTime;                                        //!< The transmission timestamp.
+};
+
+/**
+ * @ingroup zigbee
+ *
+ *  Zigbee Specification r22.1.0, Section 2.2.4.1.3
+ *  APSDE-DATA.indications params.
+ */
+struct ApsdeDataIndicationParams
+{
+    ApsDstAddressMode m_dstAddrMode{
+        ApsDstAddressMode::DST_ADDR_AND_DST_ENDPOINT_NOT_PRESENT}; //!< The destination
+                                                                   //!< address mode
+    Mac16Address m_dstAddr16;    //!< The destination 16-bit address
+    Mac64Address m_dstAddr64;    //!< The destination IEEE address (64-bit address)
+    uint8_t m_dstEndPoint{0xF0}; //!< The destination endpoint
+    ApsSrcAddressMode m_srcAddrMode{
+        ApsSrcAddressMode::SRC_ADDR16_SRC_ENDPOINT_PRESENT}; //!< The
+                                                             //!< source address mode
+
+    Mac16Address m_srcAddress16;            //!< The 16-bit address
+    Mac64Address m_srcAddress64;            //!< The IEEE source address (64-bit address)
+    uint8_t m_srcEndpoint{0xF0};            //!< The application source endpoint
+    uint16_t m_profileId{0xC0DE};           //!< The application profile ID
+    uint16_t m_clusterId{0x0000};           //!< The application cluster ID
+    uint8_t asduLength{0};                  //!< The size of the the ASDU packet
+    ApsStatus m_status{ApsStatus::SUCCESS}; //!< The data indication status
+    ApsSecurityStatus m_securityStatus{ApsSecurityStatus::UNSECURED}; //!< Security status
+    uint8_t m_linkQuality{0}; //!< The link quality indication value
+    Time m_rxTime;            //!< The reception timestamp
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Sections 2.2.4.3.1 and 2.2.4.3.3
+ * APSME-BIND.request and APSME-UNBIND.request params.
+ */
+struct ApsmeBindRequestParams
+{
+    Mac64Address m_srcAddr;   //!< The source IEEE address (64-bit address)
+    uint8_t m_srcEndPoint{0}; //!< The application source endpoint
+    uint16_t m_clusterId{0};  //!< The application cluster ID
+    ApsDstAddressModeBind m_dstAddrMode{
+        ApsDstAddressModeBind::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT}; //!< Destination address mode.
+    Mac16Address m_dstAddr16;    //!< The destination 16-bit address
+    Mac64Address m_dstAddr64;    //!< The destination 64-bit address
+    uint8_t m_dstEndPoint{0xF0}; //!< The application destination endpoint
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Sections 2.2.4.3.2 and 2.2.4.3.4
+ * APSME-BIND.confirm and APSME-UNBIND.confirm params
+ */
+struct ApsmeBindConfirmParams
+{
+    ApsStatus m_status{ApsStatus::UNSUPPORTED_ATTRIBUTE}; //!< The status of the bind request
+    Mac64Address m_srcAddr;                               //!< The application source address
+    uint8_t m_srcEndPoint{0};                             //!< The application source endpoint
+    uint16_t m_clusterId{0};                              //!< The application cluster ID
+    ApsDstAddressModeBind m_dstAddrMode{
+        ApsDstAddressModeBind::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT}; //!< Destination address mode.
+    Mac16Address m_dstAddr16;    //!< The destination 16-bit address
+    Mac64Address m_dstAddr64;    //!< The destination 64-bit address
+    uint8_t m_dstEndPoint{0xF0}; //!< The application destination endpoint
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Section 2.2.4.5.1  and  2.2.4.5.3
+ * APSME-ADD-GROUP.request and APSME-REMOVE-GROUP.request params
+ */
+struct ApsmeGroupRequestParams
+{
+    Mac16Address m_groupAddress; //!< The group address to add
+    uint8_t m_endPoint{1};       //!< The endpoint to which the group address is associated
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Section 2.2.4.5.2 and 2.2.4.5.4
+ * APSME-ADD-GROUP.confirm  and APSME-REMOVE-GROUP.confirm params
+ */
+struct ApsmeGroupConfirmParams
+{
+    ApsStatus m_status{ApsStatus::INVALID_PARAMETER}; //!< The status of the add group request
+    Mac16Address m_groupAddress;                      //!< The group address being added
+    uint8_t m_endPoint{1}; //!< The endpoint to which the given group is being added.
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Section 2.2.4.5.6
+ * APSME-REMOVE-ALL-GROUPS.request params
+ */
+struct ApsmeRemoveAllGroupsConfirmParams
+{
+    ApsStatus m_status{
+        ApsStatus::INVALID_PARAMETER}; //!< The status of the remove all groups request
+    uint8_t m_endPoint{1};             //!< The endpoint from which all groups are being removed.
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Zigbee Specification r22.1.0, Section 2.2.3
+ * Class that implements the Zigbee Specification Application Support Sub-layer (APS).
+ */
+class ZigbeeAps : public Object
+{
+  public:
+    /**
+     * Get the type ID.
+     *
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId();
+
+    /**
+     * Default constructor.
+     */
+    ZigbeeAps();
+    ~ZigbeeAps() override;
+
+    /**
+     * This callback is called to confirm a successfully transmission of an ASDU.
+     */
+    using ApsdeDataConfirmCallback = Callback<void, ApsdeDataConfirmParams>;
+
+    /**
+     * This callback is called after a ASDU has successfully received and
+     *  APS push it to deliver it to the next higher layer (typically the application framework).
+     */
+    using ApsdeDataIndicationCallback = Callback<void, ApsdeDataIndicationParams, Ptr<Packet>>;
+
+    /**
+     * This callback is called to confirm a successfully addition of a destination
+     * into the binding table.
+     */
+    using ApsmeBindConfirmCallback = Callback<void, ApsmeBindConfirmParams>;
+
+    /**
+     * This callback is called to confirm a successfully  unbind request performed
+     * into the binding table.
+     */
+    using ApsmeUnbindConfirmCallback = Callback<void, ApsmeBindConfirmParams>;
+
+    /**
+     * This callback is called to confirm a successfully addition of a group address
+     * and or endPoint into the group table.
+     */
+    using ApsmeAddGroupConfirmCallback = Callback<void, ApsmeGroupConfirmParams>;
+
+    /**
+     * This callback is called to confirm a successfully removal of a group address
+     * and or endPoint from the group table.
+     */
+    using ApsmeRemoveGroupConfirmCallback = Callback<void, ApsmeGroupConfirmParams>;
+
+    /**
+     * This callback is called to confirm a successfully removal of an endpoint from
+     * all the the groups.
+     */
+    using ApsmeRemoveAllGroupsConfirmCallback = Callback<void, ApsmeRemoveAllGroupsConfirmParams>;
+
+    /**
+     * Set the underlying NWK to use in this Zigbee APS
+     *
+     * @param nwk The pointer to the underlying Zigbee NWK to set to this Zigbee APS
+     */
+    void SetNwk(Ptr<ZigbeeNwk> nwk);
+
+    /**
+     * Get the group table used by this Zigbee APS.
+     *
+     * @param groupTable The pointer to the group table to set.
+     */
+    void SetGroupTable(Ptr<ZigbeeGroupTable> groupTable);
+
+    /**
+     * Get the underlying NWK used by the current Zigbee APS.
+     *
+     * @return The pointer to the underlying NWK object currently connected to the Zigbee APS.
+     */
+    Ptr<ZigbeeNwk> GetNwk() const;
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.4.1.1
+     * APSDE-DATA.request
+     * Request the transmission of data to one or more entities.
+     *
+     * @param params The APSDE data request params
+     * @param asdu  The packet to transmit
+     */
+    void ApsdeDataRequest(ApsdeDataRequestParams params, Ptr<Packet> asdu);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.4.3.1
+     * APSME-BIND.request
+     * Bind a source entry to one or more destination entries in the binding table.
+     *
+     * @param params The APSDE bind request params
+     */
+    void ApsmeBindRequest(ApsmeBindRequestParams params);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.4.3.3
+     * APSME-BIND.request
+     * Unbind a destination entry from a source entry in the binding table.
+     *
+     * @param params The APSDE bind request params
+     */
+    void ApsmeUnbindRequest(ApsmeBindRequestParams params);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.4.5.1
+     * APSME-ADD-GROUP.request
+     * Request that group membership for a particular group be added
+     * for a particular endpoint.
+     *
+     * @param params The APSME add group request params
+     */
+    void ApsmeAddGroupRequest(ApsmeGroupRequestParams params);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.4.5.3
+     * APSME-REMOVE-GROUP.request
+     * Request that group membership for a particular group be removed
+     * for a particular endpoint.
+     *
+     * @param params The APSME remove group request params
+     */
+    void ApsmeRemoveGroupRequest(ApsmeGroupRequestParams params);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.4.5.5
+     * APSME-REMOVE-ALL-GROUPS.request
+     * Remove membership in all groups from an endpoint, so that no group-addressed frames
+     * will be delivered to that endpoint.
+     *
+     * @param endPoint The endpoint from which all groups are being removed.
+     */
+    void ApsmeRemoveAllGroupsRequest(uint8_t endPoint);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 3.2.1.2
+     * NLDE-DATA.confirm
+     * Used to report to the APS the transmission of data from the NWK.
+     *
+     * @param params The NLDE data confirm params
+     */
+    void NldeDataConfirm(NldeDataConfirmParams params);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 3.2.1.3
+     * NLDE-DATA.indication
+     * Used to report to the APS the reception of data from the NWK.
+     *
+     * @param params The NLDE data indication params
+     * @param nsdu The packet received
+     */
+    void NldeDataIndication(NldeDataIndicationParams params, Ptr<Packet> nsdu);
+
+    /**
+     * Zigbee Specification r22.1.0, Section 2.2.8.4.2
+     * Reception and Rejection of data from the NWK.
+     *
+     *  @param apsHeader The APS header of the received packet
+     *  @param params The NLDE data indication params
+     *  @param nsdu The packet received
+     */
+    void ReceiveData(const ZigbeeApsHeader& apsHeader,
+                     const NldeDataIndicationParams& params,
+                     Ptr<Packet> nsdu);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSDE-DATA.confirm
+     *
+     *  @param c the ApsdeDataConfirm callback
+     */
+    void SetApsdeDataConfirmCallback(ApsdeDataConfirmCallback c);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSDE-DATA.indication
+     *
+     *  @param c the ApsdeDataIndication callback
+     */
+    void SetApsdeDataIndicationCallback(ApsdeDataIndicationCallback c);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSME-BIND.confirm
+     *
+     *  @param c the ApsmeBindConfirm callback
+     */
+    void SetApsmeBindConfirmCallback(ApsmeBindConfirmCallback c);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSDE-UNBIND.confirm
+     *
+     *  @param c the ApsdeUnbindConfirm callback
+     */
+    void SetApsmeUnbindConfirmCallback(ApsmeUnbindConfirmCallback c);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSME-ADD-GROUP.confirm
+     *
+     *  @param c the ApsmeAddGroupConfirm callback
+     */
+    void SetApsmeAddGroupConfirmCallback(ApsmeAddGroupConfirmCallback c);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSME-REMOVE-GROUP.confirm
+     *
+     *  @param c the ApsmeRemoveGroupConfirm callback
+     */
+    void SetApsmeRemoveGroupConfirmCallback(ApsmeRemoveGroupConfirmCallback c);
+
+    /**
+     *  Set the callback as part of the interconnections between the APS and
+     *  the next layer or service (typically the application framework). The callback
+     *  implements the callback used in a APSME-REMOVE-ALL-GROUPS.confirm
+     *
+     *  @param c the ApsmeRemoveAllGroupsConfirm callback
+     */
+    void SetApsmeRemoveAllGroupsConfirmCallback(ApsmeRemoveAllGroupsConfirmCallback c);
+
+  protected:
+    void DoInitialize() override;
+    void DoDispose() override;
+    void NotifyConstructionCompleted() override;
+
+  private:
+    /**
+     * Send a Groupcast or IEEE address destination from a list of destination in
+     * the binding table.
+     *
+     * @param params The APSDE data request params
+     * @param asdu  The packet to transmit
+     */
+    void SendDataWithBindingTable(ApsdeDataRequestParams params, Ptr<Packet> asdu);
+
+    /**
+     * Send a regular UCST or BCST data transmission to a known 16-bit address destination.
+     *
+     * @param params The APSDE data request params
+     * @param asdu  The packet to transmit
+     */
+    void SendDataUcstBcst(ApsdeDataRequestParams params, Ptr<Packet> asdu);
+
+    /**
+     * Send a Groupcast to a group address destination.
+     *
+     * @param params The APSDE data request params
+     * @param asdu  The packet to transmit
+     */
+    void SendDataGroup(ApsdeDataRequestParams params, Ptr<Packet> asdu);
+
+    /**
+     *  This callback is used to to notify the results of a data transmission
+     *  request to the Application framework (AF) making the request.
+     *  See Zigbee specification r22.1.0, Section 2.2.4.1.2
+     */
+    ApsdeDataConfirmCallback m_apsdeDataConfirmCallback;
+
+    /**
+     *  This callback is used to to notify the reception of data
+     *  to the Application framework (AF).
+     *  See Zigbee specification r22.1.0, Section 2.2.4.1.3
+     */
+    ApsdeDataIndicationCallback m_apsdeDataIndicationCallback;
+
+    /**
+     *  This callback is used to to notify the result of a binding
+     *  request in the APS to the Application framework (AF).
+     *  See Zigbee specification r22.1.0, Section 2.2.4.3.2
+     */
+    ApsmeBindConfirmCallback m_apsmeBindConfirmCallback;
+
+    /**
+     *  This callback is used to to notify the result of a unbinding
+     *  request in the APS to the Application framework (AF).
+     *  See Zigbee specification r22.1.0, Section 2.2.4.3.4
+     */
+    ApsmeUnbindConfirmCallback m_apsmeUnbindConfirmCallback;
+
+    /**
+     *  This callback is used to to notify the result of endpoint addition
+     *  request in the APS to the Application framework (AF).
+     *  See Zigbee specification r22.1.0, Section 2.2.4.5.2
+     */
+    ApsmeAddGroupConfirmCallback m_apsmeAddGroupConfirmCallback;
+
+    /**
+     *  This callback is used to to notify the result of a endpoint removal
+     *  request in the APS to the Application framework (AF).
+     *  See Zigbee specification r22.1.0, Section 2.2.4.5.4
+     */
+    ApsmeRemoveGroupConfirmCallback m_apsmeRemoveGroupConfirmCallback;
+
+    /**
+     *  This callback is used to to notify the result of a endpoint removal
+     *  request in the APS to the Application framework (AF).
+     *  See Zigbee specification r22.1.0, Section 2.2.4.5.5
+     */
+    ApsmeRemoveAllGroupsConfirmCallback m_apsmeRemoveAllGroupsConfirmCallback;
+
+    /**
+     * The underlying Zigbee NWK connected to this Zigbee APS.
+     */
+    Ptr<ZigbeeNwk> m_nwk;
+
+    /**
+     * The group table used by this Zigbee APS.
+     * The group table is a shared resource with the NWK layer.
+     * Zigbee Specification r22.1.0, Section 2.2.7.2
+     */
+    Ptr<ZigbeeGroupTable> m_apsGroupTable;
+
+    /**
+     * The sequence number used in packet Tx with APS headers.
+     * Zigbee Specification r22.1.0, Section 2.2.7.2
+     */
+    SequenceNumber8 m_apsCounter;
+
+    /**
+     * The binding table used by this Zigbee APS.
+     * Zigbee Specification r22.1.0, Section 2.2.7.2
+     */
+    BindingTable m_apsBindingTable;
+
+    /**
+     * The APS non-member radius, used to limit the number of hops
+     * for non-member multicast group devices when using NWK layer multicast.
+     * Valid range 0x00 to 0x07.
+     * Zigbee Specification r22.1.0, Section 2.2.7.2
+     */
+    uint8_t m_apsNonMemberRadius;
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Helper class used to craft the transmission options bitmap used  by the
+ * APSDE-DATA.request.
+ */
+class ZigbeeApsTxOptions
+{
+  public:
+    /**
+     * The constructor of the Tx options class.
+     *
+     * @param value The value to set in the Tx options.
+     */
+    ZigbeeApsTxOptions(uint8_t value = 0);
+
+    /**
+     * Set the security enable bit of the TX options.
+     *
+     * @param enable True if security is enabled.
+     */
+    void SetSecurityEnabled(bool enable);
+
+    /**
+     * Set the use network key bit of the TX options.
+     *
+     * @param enable True if Network key should be used.
+     */
+    void SetUseNwkKey(bool enable);
+
+    /**
+     * Set the Acknowledgement required bit of the Tx options.
+     *
+     * @param enable True if ACK is required.
+     */
+    void SetAckRequired(bool enable);
+
+    /**
+     * Set the fragmentation bit of the Tx options
+     *
+     * @param enable True if fragmentation is allowed in the transmission.
+     */
+    void SetFragmentationPermitted(bool enable);
+
+    /**
+     * Set the include extended nonce bit of the Tx options
+     *
+     * @param enable True if the frame should include the extended nonce
+     */
+    void SetIncludeExtendedNonce(bool enable);
+
+    /**
+     * Show if the security enable bit of the Tx options is present.
+     *
+     * @return True if the bit is active
+     */
+    bool IsSecurityEnabled() const;
+
+    /**
+     * Show if the use network key bit of the Tx options is present.
+     *
+     * @return True if the bit is active
+     */
+    bool IsUseNwkKey() const;
+
+    /**
+     * Show if the ACK bit of the Tx options is present.
+     *
+     * @return True if the bit is active
+     */
+    bool IsAckRequired() const;
+
+    /**
+     * Show if the fragmentation permitted bit of the Tx options is present.
+     *
+     * @return True if the bit is active
+     */
+    bool IsFragmentationPermitted() const;
+
+    /**
+     * Show if the include extended nonce bit of the Tx options is present.
+     *
+     * @return True if the bit is active
+     */
+    bool IsIncludeExtendedNonce() const;
+
+    /**
+     * Get the complete bitmap containing the Tx options
+     *
+     * @return The Tx options bitmap.
+     */
+    uint8_t GetTxOptions() const;
+
+  private:
+    /**
+     * Set a bit value into a position in the uint8_t representint the Tx options.
+     *
+     * @param pos Position to shift
+     * @param value Value to set
+     */
+    void SetBit(int pos, bool value);
+
+    /**
+     * Get the value of the bit at the position indicated.
+     *
+     * @param pos The position in the uint8_t Tx options
+     * @return True if the bit value was obtained
+     */
+    bool GetBit(int pos) const;
+
+    uint8_t m_txOptions; //!< the bitmap representing the Tx options
+};
+
+} // namespace zigbee
+} // namespace ns3
+
+#endif /* ZIGBEE_APS_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-aps-header.cc ns-3.46/src/zigbee/model/zigbee-aps-header.cc
--- ns-3.45/src/zigbee/model/zigbee-aps-header.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-aps-header.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#include "zigbee-aps-header.h"
+
+#include "ns3/address-utils.h"
+
+namespace ns3
+{
+namespace zigbee
+{
+
+ZigbeeApsHeader::ZigbeeApsHeader()
+{
+    m_frameType = ApsFrameType::APS_DATA;
+    m_deliveryMode = ApsDeliveryMode::APS_UCST;
+    m_ackFormat = false;
+    m_security = false;
+    m_ackRequest = false;
+    m_extHeaderPresent = false;
+}
+
+ZigbeeApsHeader::~ZigbeeApsHeader()
+{
+}
+
+void
+ZigbeeApsHeader::SetFrameType(enum ApsFrameType type)
+{
+    m_frameType = type;
+}
+
+ApsFrameType
+ZigbeeApsHeader::GetFrameType() const
+{
+    return m_frameType;
+}
+
+void
+ZigbeeApsHeader::SetDeliveryMode(enum ApsDeliveryMode mode)
+{
+    m_deliveryMode = mode;
+}
+
+ApsDeliveryMode
+ZigbeeApsHeader::GetDeliveryMode() const
+{
+    return m_deliveryMode;
+}
+
+void
+ZigbeeApsHeader::SetSecurity(bool enabled)
+{
+    m_security = enabled;
+}
+
+bool
+ZigbeeApsHeader::IsSecurityEnabled() const
+{
+    return m_security;
+}
+
+void
+ZigbeeApsHeader::SetAckRequest(bool ack)
+{
+    m_ackRequest = ack;
+}
+
+bool
+ZigbeeApsHeader::IsAckRequested() const
+{
+    return m_ackRequest;
+}
+
+void
+ZigbeeApsHeader::SetExtHeaderPresent(bool present)
+{
+    m_extHeaderPresent = present;
+}
+
+bool
+ZigbeeApsHeader::IsExtHeaderPresent() const
+{
+    return m_extHeaderPresent;
+}
+
+void
+ZigbeeApsHeader::SetDstEndpoint(uint8_t dst)
+{
+    m_dstEndpoint = dst;
+}
+
+uint8_t
+ZigbeeApsHeader::GetDstEndpoint() const
+{
+    return m_dstEndpoint;
+}
+
+void
+ZigbeeApsHeader::SetGroupAddress(uint16_t groupAddress)
+{
+    m_groupAddress = groupAddress;
+}
+
+uint16_t
+ZigbeeApsHeader::GetGroupAddress() const
+{
+    return m_groupAddress;
+}
+
+void
+ZigbeeApsHeader::SetClusterId(uint16_t clusterId)
+{
+    m_clusterId = clusterId;
+}
+
+uint16_t
+ZigbeeApsHeader::GetClusterId() const
+{
+    return m_clusterId;
+}
+
+void
+ZigbeeApsHeader::SetProfileId(uint16_t profileId)
+{
+    m_profileId = profileId;
+}
+
+uint16_t
+ZigbeeApsHeader::GetProfileId() const
+{
+    return m_profileId;
+}
+
+void
+ZigbeeApsHeader::SetSrcEndpoint(uint8_t src)
+{
+    m_srcEndpoint = src;
+}
+
+uint8_t
+ZigbeeApsHeader::GetSrcEndpoint() const
+{
+    return m_srcEndpoint;
+}
+
+void
+ZigbeeApsHeader::SetApsCounter(uint8_t counter)
+{
+    m_apsCounter = counter;
+}
+
+uint8_t
+ZigbeeApsHeader::GetApsCounter() const
+{
+    return m_apsCounter;
+}
+
+void
+ZigbeeApsHeader::Serialize(Buffer::Iterator start) const
+{
+    Buffer::Iterator i = start;
+
+    // Frame control field
+    uint8_t frameControl = (m_frameType & 0x03) | ((m_deliveryMode & 0x03) << 2) |
+                           ((m_ackFormat ? 1 : 0) << 4) | ((m_security ? 1 : 0) << 5) |
+                           ((m_ackRequest ? 1 : 0) << 6) | ((m_extHeaderPresent ? 1 : 0) << 7);
+
+    i.WriteU8(frameControl);
+
+    // Addressing fields
+
+    if (m_deliveryMode == ApsDeliveryMode::APS_UCST || m_deliveryMode == ApsDeliveryMode::APS_BCST)
+    {
+        i.WriteU8(m_dstEndpoint);
+    }
+
+    if (m_deliveryMode == ApsDeliveryMode::APS_GROUP_ADDRESSING)
+    {
+        i.WriteHtolsbU16(m_groupAddress);
+    }
+
+    if (m_frameType == ApsFrameType::APS_DATA || m_frameType == ApsFrameType::APS_ACK)
+    {
+        i.WriteHtolsbU16(m_clusterId);
+        i.WriteHtolsbU16(m_profileId);
+    }
+
+    if (m_frameType == ApsFrameType::APS_DATA)
+    {
+        i.WriteU8(m_srcEndpoint);
+    }
+
+    i.WriteU8(m_apsCounter);
+
+    // Extended Header
+
+    if (m_extHeaderPresent)
+    {
+        // Extended Frame control field
+        uint8_t extFrameControl = (m_fragmentation & 0x03);
+        i.WriteU8(extFrameControl);
+
+        // Block control
+        if (m_fragmentation != ApsFragmentation::NOT_FRAGMENTED)
+        {
+            i.WriteU8(m_blockNumber);
+        }
+        // ACK Bitfield
+        if (m_frameType == ApsFrameType::APS_ACK)
+        {
+            i.WriteU8(m_ackBitfield);
+        }
+    }
+}
+
+uint32_t
+ZigbeeApsHeader::Deserialize(Buffer::Iterator start)
+{
+    Buffer::Iterator i = start;
+
+    uint8_t frameControl = i.ReadU8();
+    m_frameType = static_cast<ApsFrameType>(frameControl & 0x03);
+    m_deliveryMode = static_cast<ApsDeliveryMode>((frameControl >> 2) & 0x03);
+    m_ackFormat = (frameControl >> 4) & 0x01;
+    m_security = (frameControl >> 5) & 0x01;
+    m_ackRequest = (frameControl >> 6) & 0x01;
+    m_extHeaderPresent = (frameControl >> 7) & 0x01;
+
+    // Addressing fields
+
+    if (m_deliveryMode == ApsDeliveryMode::APS_UCST || m_deliveryMode == ApsDeliveryMode::APS_BCST)
+    {
+        m_dstEndpoint = i.ReadU8();
+    }
+
+    if (m_deliveryMode == ApsDeliveryMode::APS_GROUP_ADDRESSING)
+    {
+        m_groupAddress = i.ReadLsbtohU16();
+    }
+
+    if (m_frameType == ApsFrameType::APS_DATA || m_frameType == ApsFrameType::APS_ACK)
+    {
+        m_clusterId = i.ReadLsbtohU16();
+        m_profileId = i.ReadLsbtohU16();
+    }
+
+    if (m_frameType == ApsFrameType::APS_DATA)
+    {
+        m_srcEndpoint = i.ReadU8();
+    }
+
+    m_apsCounter = i.ReadU8();
+
+    // Extended Header
+
+    if (m_extHeaderPresent)
+    {
+        // Extended Frame control field
+        uint8_t extFrameControl = i.ReadU8();
+        m_fragmentation = static_cast<ApsFragmentation>(extFrameControl & 0x03);
+
+        // Block control
+        if (m_fragmentation != ApsFragmentation::NOT_FRAGMENTED)
+        {
+            m_blockNumber = i.ReadU8();
+        }
+        // ACK Bitfield
+        if (m_frameType == ApsFrameType::APS_ACK)
+        {
+            m_ackBitfield = i.ReadU8();
+        }
+    }
+
+    return i.GetDistanceFrom(start);
+}
+
+uint32_t
+ZigbeeApsHeader::GetSerializedSize() const
+{
+    uint8_t totalSize;
+    // See Zigbee Specification r22.1.0
+
+    // Fixed field:
+    // Frame Control (1) + APS Counter (1)
+    totalSize = 2;
+
+    // Variable Fields:
+    // Destination EndPoint field (1) (Section 2.2.5.1.2)
+    if (m_deliveryMode == ApsDeliveryMode::APS_UCST || m_deliveryMode == ApsDeliveryMode::APS_BCST)
+    {
+        totalSize += 1;
+    }
+
+    // Group Address field (2) (Section 2.2.5.1.3)
+    if (m_deliveryMode == ApsDeliveryMode::APS_GROUP_ADDRESSING)
+    {
+        totalSize += 2;
+    }
+
+    // Cluster identifier field and Profile identifier field (4)
+    // (Sections 2.2.5.1.4 and 2.2.5.15)
+    if (m_frameType == ApsFrameType::APS_DATA || m_frameType == ApsFrameType::APS_ACK)
+    {
+        totalSize += 4;
+    }
+
+    // Source Endpoint field  (1) (Section  2.2.5.1.6)
+    if (m_frameType == ApsFrameType::APS_DATA)
+    {
+        totalSize += 1;
+    }
+
+    // Extended header sub-frame (variable)
+    if (m_extHeaderPresent)
+    {
+        // Extended Frame control field (1)
+        totalSize += 1;
+
+        // Block control (1)
+        if (m_fragmentation != ApsFragmentation::NOT_FRAGMENTED)
+        {
+            totalSize += 1;
+        }
+        // ACK Bitfield
+        if (m_frameType == ApsFrameType::APS_ACK)
+        {
+            totalSize += 1;
+        }
+    }
+
+    return totalSize;
+}
+
+TypeId
+ZigbeeApsHeader::GetTypeId()
+{
+    static TypeId tid = TypeId("ns3::zigbee::ZigbeeApsHeader")
+                            .SetParent<Header>()
+                            .SetGroupName("Zigbee")
+                            .AddConstructor<ZigbeeApsHeader>();
+    return tid;
+}
+
+TypeId
+ZigbeeApsHeader::GetInstanceTypeId() const
+{
+    return GetTypeId();
+}
+
+void
+ZigbeeApsHeader::Print(std::ostream& os) const
+{
+    // TODO:
+    /* os << "\nAPS Frame Control = " << std::hex << std::showbase << static_cast<uint32_t>(
+         (m_frameType & 0x03) |
+         ((m_deliveryMode & 0x03) << 2) |
+         ((m_ackFormat ? 1 : 0) << 4) |
+         ((m_security ? 1 : 0) << 5) |
+         ((m_ackRequest ? 1 : 0) << 6) |
+         ((m_extHeader ? 1 : 0) << 7));
+
+     os << " | Dst EP = " << static_cast<uint32_t>(m_dstEndpoint)
+        << " | Src EP = " << static_cast<uint32_t>(m_srcEndpoint)
+        << " | Cluster ID = " << m_clusterId
+        << " | Profile ID = " << m_profileId
+        << " | Counter = " << static_cast<uint32_t>(m_counter);
+     os << "\n";*/
+}
+
+} // namespace zigbee
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-aps-header.h ns-3.46/src/zigbee/model/zigbee-aps-header.h
--- ns-3.45/src/zigbee/model/zigbee-aps-header.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-aps-header.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#ifndef ZIGBEE_APS_HEADER_H
+#define ZIGBEE_APS_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/mac16-address.h"
+#include "ns3/mac64-address.h"
+
+namespace ns3
+{
+namespace zigbee
+{
+
+/**
+ *  @ingroup zigbee
+ *
+ *  Values of the Frame Type Sub-Field.
+ *  Zigbee Specification r22.1.0, Table 2-20
+ */
+enum ApsFrameType : uint8_t
+{
+    APS_DATA = 0x00,
+    APS_COMMAND = 0x01,
+    APS_ACK = 0x02,
+    APS_INTERPAN_APS = 0x03
+};
+
+/**
+ *  @ingroup zigbee
+ *
+ *  Values of the Delivery Mode Sub-Field.
+ *  Zigbee Specification r22.1.0, Table 2-21
+ */
+enum ApsDeliveryMode : uint8_t
+{
+    APS_UCST = 0x00,
+    APS_BCST = 0x02,
+    APS_GROUP_ADDRESSING = 0x03
+};
+
+/**
+ *  @ingroup zigbee
+ *
+ *  Table 2-22 Values of the Fragmentation Sub-Field
+ *  Zigbee Specification r22.1.0, Table 2-22
+ */
+enum ApsFragmentation : uint8_t
+{
+    NOT_FRAGMENTED = 0x00,
+    FIRST_FRAGMENT = 0x01,
+    OTHER_FRAGMENT = 0x02
+};
+
+/**
+ * @ingroup zigbee
+ *
+ * Defines the APS header use by data transfer and commands issued from
+ * the APS layer. Zigbee Specification r22.1.0, Section 2.2.5.1.
+ *
+ */
+class ZigbeeApsHeader : public Header
+{
+  public:
+    ZigbeeApsHeader();
+    ~ZigbeeApsHeader() override;
+
+    /**
+     * Set the Frame type defined in the APS layer
+     *
+     * @param frameType The frame type to set on the header
+     */
+    void SetFrameType(enum ApsFrameType frameType);
+
+    /**
+     * Get the frame time present in the header
+     *
+     * @return ApsFrameType
+     */
+    ApsFrameType GetFrameType() const;
+
+    /**
+     * Defines the mode in which this frame should be transmitted.
+     *
+     * @param mode The delivery mode to set on the APS header
+     */
+    void SetDeliveryMode(enum ApsDeliveryMode mode);
+
+    /**
+     * Get the transmission mode set on the header.
+     *
+     * @return ApsDeliveryMode The delivery mode of the header
+     */
+    ApsDeliveryMode GetDeliveryMode() const;
+
+    /**
+     * Set whether or not security should be used to transmit
+     * the frame.
+     *
+     * @param enabled True if security should be used
+     */
+    void SetSecurity(bool enabled);
+
+    /**
+     * Returns whether or not security is enabled for the present frame.alignas
+     *
+     * @return True if security is enabled for the frame.
+     */
+    bool IsSecurityEnabled() const;
+
+    /**
+     * Set the acknowledment flag in the APS header.
+     *
+     * @param request True if the frame should be acknowledged
+     */
+    void SetAckRequest(bool request);
+
+    /**
+     * Indicates if the present frame requires acknowledgment.
+     *
+     * @return True if the frame requires acknowledgment
+     */
+    bool IsAckRequested() const;
+
+    /**
+     * Enables or disables the usage of the extended header.
+     * Only used when fragmentation is used.
+     *
+     * @param present True if the extended header (fragmentation) is present.
+     */
+    void SetExtHeaderPresent(bool present);
+
+    /**
+     * Indicates whether or not the extended header is present in the frame.
+     * @return True if the extended header is present.
+     */
+    bool IsExtHeaderPresent() const;
+
+    /**
+     * Set the Bitmap representing the framecontrol portion of the APS header.
+     *
+     * @param frameControl The bitmap representing the framecontrol portion.
+     */
+    void SetFrameControl(uint8_t frameControl);
+
+    /**
+     * Get the frame control portion (bitmap) of the APS header.
+     *
+     * @return The frame control portion of the APS header.
+     */
+    uint8_t GetFrameControl() const;
+
+    /**
+     * Set the destination endpoint in the APS header.
+     *
+     * @param endpoint The destination endpoint.
+     */
+    void SetDstEndpoint(uint8_t endpoint);
+
+    /**
+     * Get the destination endpoint in the APS header.
+     *
+     * @return The destination endpoint.
+     */
+    uint8_t GetDstEndpoint() const;
+
+    /**
+     * Set the group address in the APS header.
+     *
+     * @param groupAddress The group address to set.
+     */
+    void SetGroupAddress(uint16_t groupAddress);
+
+    /**
+     * Get the group address in the APS header.
+     *
+     * @return The group address.
+     */
+    uint16_t GetGroupAddress() const;
+
+    /**
+     * Set the cluster id in the APS header.
+     *
+     * @param clusterId The cluster id
+     */
+    void SetClusterId(uint16_t clusterId);
+
+    /**
+     * Get the cluster id in the APS header.
+     * @return The cluster id.
+     */
+    uint16_t GetClusterId() const;
+
+    /**
+     * Set the profile ID in the APS header.
+     *
+     * @param profileId The profile ID.
+     */
+    void SetProfileId(uint16_t profileId);
+
+    /**
+     * Get the profile ID in the APS header.
+     * @return The profile ID.
+     */
+    uint16_t GetProfileId() const;
+
+    /**
+     * Set the source endpoint in the APS header.
+     *
+     * @param endpoint The source endpoint.
+     */
+    void SetSrcEndpoint(uint8_t endpoint);
+
+    /**
+     * Get the source endpoint in the APS header.
+     * @return The source endpoint.
+     */
+    uint8_t GetSrcEndpoint() const;
+
+    /**
+     * Set the value of the APS counter in the APS header.
+     * @param counter The APS counter value.
+     */
+    void SetApsCounter(uint8_t counter);
+
+    /**
+     * Get the APS counter value present in the APS header.
+     * @return The APS counter value.
+     */
+    uint8_t GetApsCounter() const;
+
+    /**
+     * @brief Get the type ID.
+     * @return the object TypeId
+     */
+    static TypeId GetTypeId();
+    TypeId GetInstanceTypeId() const override;
+
+    void Serialize(Buffer::Iterator start) const override;
+    uint32_t Deserialize(Buffer::Iterator start) override;
+    uint32_t GetSerializedSize() const override;
+    void Print(std::ostream& os) const override;
+
+  private:
+    // Frame Control field bits
+    ApsFrameType m_frameType;       //!< Frame control field: Frame type
+    ApsDeliveryMode m_deliveryMode; //!< Frame control field: Delivery mode
+    bool m_ackFormat;               //!< Frame control field: Acknowledgment format
+    bool m_security;                //!< Frame control field: Security
+    bool m_ackRequest;              //!< Frame control field: Acknowledge requested
+    bool m_extHeaderPresent;        //!< Frame control field: Extended header present
+
+    // Addressing fields
+    uint8_t m_dstEndpoint;   //!< Addressing field: Destination endpoint.
+    uint16_t m_groupAddress; //!< Addressing field: Group or 16-bit address.
+    uint16_t m_clusterId;    //!< Addressing field: Cluster ID.
+    uint16_t m_profileId;    //!< Addressing field: Profile ID.
+    uint8_t m_srcEndpoint;   //!< Addressing field: Source endpoint.
+
+    uint8_t m_apsCounter; //!< APS counter field
+
+    // Extended header fields
+    ApsFragmentation m_fragmentation; //!< Extended header field: Fragmentation block type
+    uint8_t m_blockNumber;            //!< Extended header field: Block number
+    uint8_t m_ackBitfield;            //!< Extended header field: Acknowledgement bit field
+};
+
+} // namespace zigbee
+} // namespace ns3
+
+#endif // ZIGBEE_APS_HEADER_H
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-aps-tables.cc ns-3.46/src/zigbee/model/zigbee-aps-tables.cc
--- ns-3.45/src/zigbee/model/zigbee-aps-tables.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-aps-tables.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Authors:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#include "zigbee-aps-tables.h"
+
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/simulator.h"
+
+#include <algorithm>
+#include <iomanip>
+
+namespace ns3
+{
+namespace zigbee
+{
+
+NS_LOG_COMPONENT_DEFINE("ZigbeeApsTables");
+
+/***********************************************************
+ *                Source Binding Entry
+ ***********************************************************/
+
+SrcBindingEntry::SrcBindingEntry()
+{
+}
+
+SrcBindingEntry::SrcBindingEntry(Mac64Address address, uint8_t endPoint, uint16_t clusterId)
+{
+    m_srcAddr = address;
+    m_srcEndPoint = endPoint;
+    m_clusterId = clusterId;
+}
+
+SrcBindingEntry::~SrcBindingEntry()
+{
+}
+
+void
+SrcBindingEntry::SetSrcAddress(Mac64Address address)
+{
+    m_srcAddr = address;
+}
+
+void
+SrcBindingEntry::SetSrcEndPoint(uint8_t endPoint)
+{
+    m_srcEndPoint = endPoint;
+}
+
+void
+SrcBindingEntry::SetClusterId(uint16_t clusterId)
+{
+    m_clusterId = clusterId;
+}
+
+Mac64Address
+SrcBindingEntry::GetSrcAddress() const
+{
+    return m_srcAddr;
+}
+
+uint8_t
+SrcBindingEntry::GetSrcEndPoint() const
+{
+    return m_srcEndPoint;
+}
+
+uint16_t
+SrcBindingEntry::GetClusterId() const
+{
+    return m_clusterId;
+}
+
+/***********************************************************
+ *                Destination Binding Entry
+ ***********************************************************/
+
+DstBindingEntry::DstBindingEntry()
+{
+}
+
+DstBindingEntry::~DstBindingEntry()
+{
+}
+
+void
+DstBindingEntry::SetDstAddrMode(ApsDstAddressModeBind mode)
+{
+    m_dstAddrMode = mode;
+}
+
+void
+DstBindingEntry::SetDstAddr16(Mac16Address address)
+{
+    m_dstAddr16 = address;
+}
+
+void
+DstBindingEntry::SetDstAddr64(Mac64Address address)
+{
+    m_dstAddr64 = address;
+}
+
+void
+DstBindingEntry::SetDstEndPoint(uint8_t endPoint)
+{
+    m_dstEndPoint = endPoint;
+}
+
+ApsDstAddressModeBind
+DstBindingEntry::GetDstAddrMode() const
+{
+    return m_dstAddrMode;
+}
+
+Mac16Address
+DstBindingEntry::GetDstAddr16() const
+{
+    return m_dstAddr16;
+}
+
+Mac64Address
+DstBindingEntry::GetDstAddr64() const
+{
+    return m_dstAddr64;
+}
+
+uint8_t
+DstBindingEntry::GetDstEndPoint() const
+{
+    return m_dstEndPoint;
+}
+
+/***********************************************************
+ *                Binding Table
+ ***********************************************************/
+
+BindingTable::BindingTable()
+{
+    m_maxSrcEntries = 10;
+    m_maxDstEntries = 10;
+}
+
+bool
+BindingTable::CompareDestinations(const DstBindingEntry& first, const DstBindingEntry& second)
+{
+    if (first.GetDstAddrMode() == ApsDstAddressModeBind::GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT)
+    {
+        // Group Addressing
+        if ((first.GetDstAddr16() == second.GetDstAddr16()) &&
+            (first.GetDstEndPoint() == second.GetDstEndPoint()))
+        {
+            return true;
+        }
+    }
+    else if (first.GetDstAddrMode() == ApsDstAddressModeBind::DST_ADDR64_DST_ENDPOINT_PRESENT)
+    {
+        // IEEE Addressing
+        if ((first.GetDstAddr64() == second.GetDstAddr64()) &&
+            (first.GetDstEndPoint() == second.GetDstEndPoint()))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+BindingTable::CompareSources(const SrcBindingEntry& first, const SrcBindingEntry& second)
+{
+    return ((first.GetSrcAddress() == second.GetSrcAddress()) &&
+            (first.GetSrcEndPoint() == second.GetSrcEndPoint()) &&
+            (first.GetClusterId() == second.GetClusterId()));
+}
+
+BindingTableStatus
+BindingTable::Bind(const SrcBindingEntry& src, const DstBindingEntry& dst)
+{
+    for (auto& entry : m_bindingTable)
+    {
+        if (CompareSources(src, entry.first))
+        {
+            // The source exist, now check if the destination exist
+            for (const auto& destination : entry.second)
+            {
+                if (CompareDestinations(dst, destination))
+                {
+                    NS_LOG_WARN("Entry already exist in binding table");
+                    return BindingTableStatus::ENTRY_EXISTS;
+                }
+            }
+            // Add the new destination bound to the source
+            if (entry.second.size() >= m_maxDstEntries)
+            {
+                NS_LOG_WARN("Binding Table full, max destination entries (" << m_maxDstEntries
+                                                                            << ") reached");
+                return BindingTableStatus::TABLE_FULL;
+            }
+            else
+            {
+                entry.second.emplace_back(dst);
+                return BindingTableStatus::BOUND;
+            }
+        }
+    }
+
+    if (m_bindingTable.size() >= m_maxSrcEntries)
+    {
+        NS_LOG_WARN("Binding Table full, max source entries (" << m_maxSrcEntries << ") reached");
+        return BindingTableStatus::TABLE_FULL;
+    }
+    else
+    {
+        // New source with its first destination
+        m_bindingTable.emplace_back(src, std::vector<DstBindingEntry>{dst});
+        return BindingTableStatus::BOUND;
+    }
+}
+
+BindingTableStatus
+BindingTable::Unbind(const SrcBindingEntry& src, const DstBindingEntry& dst)
+{
+    for (auto it = m_bindingTable.begin(); it != m_bindingTable.end(); ++it)
+    {
+        if (CompareSources(src, it->first))
+        {
+            // The source exists, now check if the destination exists
+            auto& destinations = it->second;
+            for (auto destIt = destinations.begin(); destIt != destinations.end(); ++destIt)
+            {
+                if (CompareDestinations(dst, *destIt))
+                {
+                    // Destination found, remove it
+                    destinations.erase(destIt);
+
+                    // If no destinations left, remove the source entry
+                    if (destinations.empty())
+                    {
+                        m_bindingTable.erase(it);
+                    }
+                    // Successfully unbound
+                    return BindingTableStatus::UNBOUND;
+                }
+            }
+            // Destination not found
+            NS_LOG_WARN("Cannot unbind, destination entry do not exist");
+            return BindingTableStatus::ENTRY_NOT_FOUND;
+        }
+    }
+    // Source not found
+    NS_LOG_WARN("Cannot unbind, source entry do not exist");
+    return BindingTableStatus::ENTRY_NOT_FOUND;
+}
+
+bool
+BindingTable::LookUpEntries(const SrcBindingEntry& src, std::vector<DstBindingEntry>& dstEntries)
+{
+    for (auto& entry : m_bindingTable)
+    {
+        if (CompareSources(src, entry.first))
+        {
+            // The source entry exist, return all the dst entries.
+            dstEntries = entry.second;
+            return true;
+        }
+    }
+    return false;
+}
+
+} // namespace zigbee
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-aps-tables.h ns-3.46/src/zigbee/model/zigbee-aps-tables.h
--- ns-3.45/src/zigbee/model/zigbee-aps-tables.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-aps-tables.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#ifndef ZIGBEE_APS_TABLES_H
+#define ZIGBEE_APS_TABLES_H
+
+#include "ns3/mac16-address.h"
+#include "ns3/mac64-address.h"
+#include "ns3/output-stream-wrapper.h"
+#include "ns3/timer.h"
+
+#include <cassert>
+#include <deque>
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace ns3
+{
+namespace zigbee
+{
+
+/**
+ * @ingroup Zigbee
+ *
+ * APS Destination Address Mode for Binding
+ * Zigbee Specification r22.1.0, Table 2-6
+ * APSME-BIND.request Parameters
+ */
+enum class ApsDstAddressModeBind : std::uint8_t
+{
+    GROUP_ADDR_DST_ENDPOINT_NOT_PRESENT = 0x01,
+    DST_ADDR64_DST_ENDPOINT_PRESENT = 0x03
+};
+
+/**
+ * @ingroup Zigbee
+ *
+ * The status resulting of interactions with the binding table.
+ */
+enum class BindingTableStatus : std::uint8_t
+{
+    BOUND = 0,
+    UNBOUND = 1,
+    TABLE_FULL = 2,
+    ENTRY_EXISTS = 3,
+    ENTRY_NOT_FOUND = 4
+};
+
+/**
+ * @ingroup Zigbee
+ *
+ * Binding Table entry: Source portion of the table.
+ * As described in Zigbee Specification r22.1.0, Table 2-134
+ */
+class SrcBindingEntry : public SimpleRefCount<SrcBindingEntry>
+{
+  public:
+    /**
+     * The default constructor of the source binding entry.
+     */
+    SrcBindingEntry();
+
+    /**
+     * Constructor of the source binding entry.
+     *
+     * @param address The IEEE address to register, (typically the IEEE address of the source
+     * device).
+     * @param endPoint The source endpoint to register to the entry.
+     * @param clusterId The cluster ID to register to the entry.
+     */
+    SrcBindingEntry(Mac64Address address, uint8_t endPoint, uint16_t clusterId);
+    ~SrcBindingEntry();
+
+    /**
+     * Set the source IEEE address to the entry.
+     *
+     * @param address The IEEE address (64-bit address) of the entry
+     */
+    void SetSrcAddress(Mac64Address address);
+
+    /**
+     * Set the source endpoint of the source binding entry.
+     * @param endPoint The source endpoint to set in the entry.
+     */
+    void SetSrcEndPoint(uint8_t endPoint);
+
+    /**
+     * Set the cluster ID of the source binding entry.
+     * @param clusterId  The cluster ID to set in the entry.
+     */
+    void SetClusterId(uint16_t clusterId);
+
+    /**
+     * Get the IEEE address from the source binding entry.
+     * @return The IEEE address in the source binding entry.
+     */
+    Mac64Address GetSrcAddress() const;
+
+    /**
+     * Get the source endpoint from the source binding entry.
+     *
+     * @return The source endpoint.
+     */
+    uint8_t GetSrcEndPoint() const;
+
+    /**
+     * Get the cluster ID from the source binding entry.
+     * @return The cluster ID.
+     */
+    uint16_t GetClusterId() const;
+
+  private:
+    Mac64Address m_srcAddr;   //!< The source IEEE address in the source entry.
+    uint8_t m_srcEndPoint{0}; //!< The source endpoint in the source entry.
+    uint16_t m_clusterId{0};  //!< The cluster ID in the source entry.
+};
+
+/**
+ * Binding Table entry: Destination portion of the table.
+ * As described in Zigbee Specification r22.1.0, Table 2-134
+ */
+class DstBindingEntry : public SimpleRefCount<DstBindingEntry>
+{
+  public:
+    /**
+     * The default constructor of the destination binding entry.
+     */
+    DstBindingEntry();
+    ~DstBindingEntry();
+
+    /**
+     * Set the destination address mode of the destination binding entry.
+     * @param mode The destination address mode to set.
+     */
+    void SetDstAddrMode(ApsDstAddressModeBind mode);
+
+    /**
+     * Set the destination 16-bit address of the destination binding entry.
+     * @param address The 16-bit address of the destination binding entry.
+     */
+    void SetDstAddr16(Mac16Address address);
+
+    /**
+     * Set the destination IEEE Address (64-bit address) of the destination binding entry.
+     * @param address  The destination IEEE address (64-bit address) to set
+     */
+    void SetDstAddr64(Mac64Address address);
+
+    /**
+     * Set the destination endppoint to the destination binding entry.
+     * @param endPoint The destination endpoint to set.
+     */
+    void SetDstEndPoint(uint8_t endPoint);
+
+    /**
+     * Get the destination address mode used by the destination entry.
+     * @return The destination address mode used by the entry.
+     */
+    ApsDstAddressModeBind GetDstAddrMode() const;
+
+    /**
+     * Get the 16-bit address destination of the destination entry.
+     * @return The 16-bit address of the destination entry.
+     */
+    Mac16Address GetDstAddr16() const;
+
+    /**
+     * Get the 64-bit address destination of the destination entry.
+     * @return The  IEEE address (64-bit address) destination
+     */
+    Mac64Address GetDstAddr64() const;
+
+    /**
+     * Get the destination endpoint of the destination entry.
+     * @return The destination endpoint.
+     */
+    uint8_t GetDstEndPoint() const;
+
+  private:
+    ApsDstAddressModeBind m_dstAddrMode{
+        ApsDstAddressModeBind::DST_ADDR64_DST_ENDPOINT_PRESENT}; //!< The destination address mode
+                                                                 //!< used by the entry.
+    Mac16Address m_dstAddr16; //!< The destination 16-bit address in the destination entry.
+    Mac64Address
+        m_dstAddr64; //!< The destination IEEE address (64-bit address) in the destination entry.
+    uint8_t m_dstEndPoint{0xF0}; //!< The destination endpoint in the destination entry.
+};
+
+/**
+ * APS Binding Table
+ * See Zigbee specification r22.1.0, Table 2-134
+ * Similar to the z-boss implementation, the binding table is divided in two portions:
+ * The source part and the destination part. A single source can have multiple destination
+ * entries as described by the Zigbee specification. This creates a relationship one to many
+ * (a source entry with multiple destination entries) which is both useful for 64 bit Address UCST
+ * or 16-bit groupcast destination bindings.
+ */
+class BindingTable
+{
+  public:
+    /**
+     *  The constructor of the binding table.
+     */
+    BindingTable();
+
+    /**
+     * Add an entry to the binding table.
+     * In essence it binds the source entry portion to the table to one or more
+     * destination portion entries (one to many).
+     *
+     * @param src The source entry portion of the table.
+     * @param dst The destination entry portion of the table.
+     * @return The resulting status of the binding attempt.
+     */
+    BindingTableStatus Bind(const SrcBindingEntry& src, const DstBindingEntry& dst);
+
+    /**
+     * Unbinds a destination entry portion of a binding table from a source entry portion.
+     *
+     * @param src The source entry portion of the table.
+     * @param dst The destination entry portion of the table.
+     * @return The resulting status of the unbinding attempt.
+     */
+    BindingTableStatus Unbind(const SrcBindingEntry& src, const DstBindingEntry& dst);
+
+    /**
+     * Look for destination entries binded to an specific source entry portion in the binding
+     * table.
+     *
+     * @param src The source entry portion of the table to search.
+     * @param dstEntries The resulting destination entries binded to the provided source entry
+     * portion
+     * @return True if at least one destination entry portion was retrieved.
+     */
+    bool LookUpEntries(const SrcBindingEntry& src, std::vector<DstBindingEntry>& dstEntries);
+
+  private:
+    /**
+     * Compare the equality of 2 source entries
+     *
+     * @param first The first source entry to compare.
+     * @param second The second source entry to compare.
+     * @return True if the destinations entries are identical
+     */
+    bool CompareSources(const SrcBindingEntry& first, const SrcBindingEntry& second);
+
+    /**
+     * Compare the equality of 2 destination entries
+     *
+     * @param first The first destination entry to compare.
+     * @param second The second destination entry to compare.
+     * @return True if the destinations entries are identical
+     */
+    bool CompareDestinations(const DstBindingEntry& first, const DstBindingEntry& second);
+
+    std::vector<std::pair<SrcBindingEntry,
+                          std::vector<DstBindingEntry>>>
+        m_bindingTable;      //!< The binding table object
+    uint8_t m_maxSrcEntries; //!< The maximum amount of source entries allowed in the table
+    uint8_t m_maxDstEntries; //!< The maximum amount of destination entries allowed in the table
+};
+
+} // namespace zigbee
+} // namespace ns3
+
+#endif /* ZIGBEE_APS_TABLES_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-group-table.cc ns-3.46/src/zigbee/model/zigbee-group-table.cc
--- ns-3.45/src/zigbee/model/zigbee-group-table.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-group-table.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#include "zigbee-group-table.h"
+
+#include "ns3/log.h"
+
+namespace ns3
+{
+namespace zigbee
+{
+
+NS_LOG_COMPONENT_DEFINE("ZigbeeGroupTable");
+
+ZigbeeGroupTable::ZigbeeGroupTable() = default;
+
+ZigbeeGroupTable::~ZigbeeGroupTable() = default;
+
+bool
+ZigbeeGroupTable::AddEntry(uint16_t groupId, uint8_t endPoint)
+{
+    NS_LOG_FUNCTION(this << groupId << static_cast<uint16_t>(endPoint));
+
+    if (m_groupTable.size() == MAX_GROUP_ID_ENTRIES)
+    {
+        NS_LOG_WARN("Group table is full, cannot add group ID " << groupId);
+        return false; // too many groups
+    }
+
+    // Check the group entry existence, if it does not exist, create it.
+    auto& group = m_groupTable[groupId];
+    if (group[endPoint])
+    {
+        NS_LOG_INFO("Endpoint " << static_cast<uint16_t>(endPoint) << " already exists in group "
+                                << groupId);
+        return false; // endPoint already in group
+    }
+
+    NS_LOG_INFO("Adding endpoint " << static_cast<uint16_t>(endPoint) << " to group " << groupId);
+    group.set(endPoint);
+    return true;
+}
+
+bool
+ZigbeeGroupTable::RemoveEntry(uint16_t groupId, uint8_t endPoint)
+{
+    NS_LOG_FUNCTION(this << groupId << static_cast<uint16_t>(endPoint));
+
+    auto group = m_groupTable.find(groupId);
+    auto endPoints = group->second;
+
+    if (group == m_groupTable.end())
+    {
+        NS_LOG_WARN("Group ID " << groupId << " does not exist, cannot remove endpoint "
+                                << static_cast<uint16_t>(endPoint));
+        return false; // group doesn't exist
+    }
+
+    if (!endPoints[endPoint])
+    {
+        NS_LOG_WARN("Endpoint " << static_cast<uint16_t>(endPoint) << " not found in group "
+                                << groupId);
+        return false; // endpoint not in this group
+    }
+    else
+    {
+        endPoints.reset(endPoint); // Turn bit in bitset off (0)
+        NS_LOG_INFO("Removed endpoint " << static_cast<uint16_t>(endPoint) << " from group "
+                                        << groupId);
+
+        if (endPoints.none())
+        {
+            m_groupTable.erase(group); // remove group if no endpoints left
+        }
+        return true; // endpoint removed successfully
+    }
+}
+
+bool
+ZigbeeGroupTable::RemoveMembership(uint8_t endPoint)
+{
+    NS_LOG_FUNCTION(this << static_cast<uint16_t>(endPoint));
+
+    bool removed = false;
+    for (auto group = m_groupTable.begin(); group != m_groupTable.end(); ++group)
+    {
+        if (group->second[endPoint])
+        {
+            group->second.reset(endPoint); // Turn bit in bitset off (0)
+            NS_LOG_INFO("Removed endpoint " << static_cast<uint16_t>(endPoint) << " from group "
+                                            << group->first);
+
+            if (group->second.none())
+            {
+                m_groupTable.erase(group); // remove group if no endpoints left
+            }
+            removed = true; // endpoint removed successfully
+        }
+    }
+    return removed;
+}
+
+bool
+ZigbeeGroupTable::IsGroupMember(uint16_t groupId) const
+{
+    return m_groupTable.find(groupId) != m_groupTable.end();
+}
+
+bool
+ZigbeeGroupTable::LookUpEndPoints(uint16_t groupId, std::vector<uint8_t>& endPoints) const
+{
+    bool hasEndPoints = false;
+    auto group = m_groupTable.find(groupId);
+
+    if (group == m_groupTable.end())
+    {
+        NS_LOG_WARN("Group ID " << groupId << " does not exist, cannot look up endpoints");
+        return false; // group doesn't exist
+    }
+
+    for (auto endpoint = 0; endpoint < MAX_ENDPOINT_ENTRIES; ++endpoint)
+    {
+        if (group->second[endpoint])
+        {
+            endPoints.push_back(endpoint);
+            hasEndPoints = true;
+        }
+    }
+    return hasEndPoints;
+}
+
+} // namespace zigbee
+} // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-group-table.h ns-3.46/src/zigbee/model/zigbee-group-table.h
--- ns-3.45/src/zigbee/model/zigbee-group-table.h	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/model/zigbee-group-table.h	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#ifndef ZIGBEE_GROUP_TABLE_H
+#define ZIGBEE_GROUP_TABLE_H
+
+#include "ns3/simple-ref-count.h"
+
+#include <bitset>
+#include <unordered_map>
+#include <vector>
+
+namespace ns3
+{
+namespace zigbee
+{
+
+/**
+ * @ingroup zigbee
+ * The Zigbee Group Table
+ * Zigbee Specification r22.1.0, Section 2.2.8.3 and 3.6.6.1
+ * The group table is a special table that is accessible by both the
+ * Zigbee NWK and APS layers. It is used to store group IDs and associated endpoints.
+ * The group table is used in GroupCasting operations (A type of multicast in Zigbee).
+ * In this implementation, the group table is represented as a map where the key is the group ID
+ * and the value is a bitset representing the endpoints associated with that group ID.
+ * Each bit in the bitset corresponds to an endpoint, where the index of the bit represents the
+ * endpoint number.
+ */
+class ZigbeeGroupTable : public SimpleRefCount<ZigbeeGroupTable>
+{
+  public:
+    /**
+     * Constructor for Zigbee group table.
+     */
+    ZigbeeGroupTable();
+
+    /**
+     * Destructor for Zigbee group table.
+     */
+    ~ZigbeeGroupTable();
+
+    /**
+     * Add a group ID and its related endpoint. If the group ID already exists,
+     * the endpoint is added to the existing group ID entry.
+     *
+     * @param groupId The group ID to add.
+     * @param endPoint The endpoint to associate with the group ID.
+     * @return True if the entry was added successfully or the endpoint is already a member of the
+     * group, false if the table is full.
+     */
+    bool AddEntry(uint16_t groupId, uint8_t endPoint);
+
+    /**
+     * Remove endpoint from a group. If the endpoint is the last one
+     * associated with the group ID, the group ID entry is removed.
+     *
+     * @param groupId The group ID of the group to remove the endpoint from.
+     * @param endPoint The endpoint to remove from the group ID.
+     * @return True if the entry was removed successfully, false if the group does not exist, or the
+     * endpoint is not a member of the group.
+     */
+    bool RemoveEntry(uint16_t groupId, uint8_t endPoint);
+
+    /**
+     * Remove the endPoint from all groups.
+     *
+     * @param endPoint The endpoint to remove from all groups. If the removed endpoint is the last
+     * one associated with the group ID, the group ID entry is also removed.
+     * @return True if the endpoint was remmoved from at least one group, false if the endpoint was
+     * not found in any group.
+     *
+     */
+    bool RemoveMembership(uint8_t endPoint);
+
+    /**
+     * Indicates whether the group ID exists in the group table.
+     *
+     * @param groupId The group ID to query.
+     * @return True if the group ID exists, false otherwise.
+     */
+    bool IsGroupMember(uint16_t groupId) const;
+
+    /**
+     * Look up the endpoints associated with a given group ID.
+     *
+     * @param groupId The group ID to look up.
+     * @param endPoints A vector to store the endpoints associated with the group ID.
+     * @return True if the group ID was found and endpoints were retrieved, false otherwise.
+     */
+    bool LookUpEndPoints(uint16_t groupId, std::vector<uint8_t>& endPoints) const;
+
+  private:
+    static constexpr int MAX_GROUP_ID_ENTRIES{256}; //!< The maximum amount of group ID
+                                                    //!< entries allowed in the table.
+    static constexpr int MAX_ENDPOINT_ENTRIES{256}; //!< The maximum amount of endpoints
+                                                    //!< allowed per group id entry.
+    std::unordered_map<uint16_t, std::bitset<MAX_ENDPOINT_ENTRIES>>
+        m_groupTable; //!< The group table object
+};
+
+} // namespace zigbee
+} // namespace ns3
+
+#endif /* ZIGBEE_GROUP_TABLE_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk.cc ns-3.46/src/zigbee/model/zigbee-nwk.cc
--- ns-3.45/src/zigbee/model/zigbee-nwk.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk.cc	2025-10-01 18:46:32.000000000 -0700
@@ -56,7 +56,6 @@
                           TimeValue(MilliSeconds(0x2710)),
                           MakeTimeAccessor(&ZigbeeNwk::m_nwkcRouteDiscoveryTime),
                           MakeTimeChecker())
-
             .AddAttribute("NwkcInitialRREQRetries",
                           "[Constant] The number of times the first broadcast transmission"
                           "of a RREQ cmd frame is retried.",
@@ -87,6 +86,23 @@
                           DoubleValue(128),
                           MakeDoubleAccessor(&ZigbeeNwk::m_nwkcMaxRREQJitter),
                           MakeDoubleChecker<double>())
+            .AddAttribute("NwkcMaxBroadcastJitter",
+                          "[Constant] The duration between retries of a broadcast RREQ (msec)",
+                          DoubleValue(40),
+                          MakeDoubleAccessor(&ZigbeeNwk::m_nwkcMaxBroadcastJitter),
+                          MakeDoubleChecker<double>())
+            .AddAttribute("nwkMaxBroadcastRetries",
+                          "The maximum number of retries allowed after a broadcast "
+                          "transmission failure.",
+                          UintegerValue(0x03),
+                          MakeUintegerAccessor(&ZigbeeNwk::m_nwkMaxBroadcastRetries),
+                          MakeUintegerChecker<uint8_t>())
+            .AddAttribute("NwkPassiveAckTimeout",
+                          "The maximum time duration in milliseconds allowed for the parent "
+                          "all the child devices to retransmit a broadcast message.",
+                          TimeValue(MilliSeconds(500)),
+                          MakeTimeAccessor(&ZigbeeNwk::m_nwkPassiveAckTimeout),
+                          MakeTimeChecker())
             .AddAttribute("MaxPendingTxQueueSize",
                           "The maximum size of the table storing pending packets awaiting "
                           "to be transmitted after discovering a route to the destination.",
@@ -138,7 +154,6 @@
     m_nwkReportConstantCost = false;
     m_nwkSymLink = false;
 
-    m_nwkMaxBroadcastRetries = 0x03;
     m_countRREQRetries = 0;
 
     m_nwkIsConcentrator = false;
@@ -157,6 +172,10 @@
     m_rreqJitter->SetAttribute("Min", DoubleValue(m_nwkcMinRREQJitter));
     m_rreqJitter->SetAttribute("Max", DoubleValue(m_nwkcMaxRREQJitter));
 
+    m_bcstJitter = CreateObject<UniformRandomVariable>();
+    m_bcstJitter->SetAttribute("Min", DoubleValue(0));
+    m_bcstJitter->SetAttribute("Max", DoubleValue(m_nwkcMaxBroadcastJitter));
+
     m_routeExpiryTime = Seconds(255);
 }
 
@@ -211,6 +230,12 @@
     m_mac = mac;
 }
 
+void
+ZigbeeNwk::SetGroupTable(Ptr<ZigbeeGroupTable> groupTable)
+{
+    m_nwkGroupIdTable = groupTable;
+}
+
 Ptr<LrWpanMacBase>
 ZigbeeNwk::GetMac() const
 {
@@ -352,11 +377,29 @@
 
     switch (nwkHeader.GetFrameType())
     {
-    case DATA:
+    case DATA: {
         if (nwkHeader.IsMulticast())
         {
             // DATA MULTICAST
-            NS_FATAL_ERROR("Multicast DATA transmission not supported");
+            if (nwkHeader.GetMulticastMode() == MulticastMode::MEMBER)
+            {
+                // Mcst Member Mode,Zigbee specification r22.1.0 Section 3.6.6.3
+                ReceiveMulticastMemberFrame(nwkHeader, msdu, params);
+            }
+            else
+            {
+                // Mcst Non-Member Mode,Zigbee specification r22.1.0 Section 3.6.6.4
+                if (m_nwkGroupIdTable->IsGroupMember(nwkHeader.GetDstAddr().ConvertToInt()))
+                {
+                    // Treat frame as a multicast member
+                    nwkHeader.SetMulticastMode(MulticastMode::MEMBER);
+                    ReceiveMulticastMemberFrame(nwkHeader, msdu, params);
+                }
+                else
+                {
+                    ReceiveMulticastNonMemberFrame(nwkHeader, msdu, params);
+                }
+            }
         }
         else if (IsBroadcastAddress(nwkHeader.GetDstAddr()))
         {
@@ -443,6 +486,7 @@
             }
         }
         break;
+    }
     case NWK_COMMAND: {
         ZigbeePayloadType payloadType;
         msdu->RemoveHeader(payloadType);
@@ -530,7 +574,7 @@
         return;
     }
 
-    // Mesh Routing
+    // Mesh Routing (Unicast or Multicast Group)
 
     Mac16Address nextHop;
     RouteDiscoveryStatus nextHopStatus =
@@ -699,6 +743,132 @@
     }
 }
 
+void
+ZigbeeNwk::ReceiveMulticastMemberFrame(ZigbeeNwkHeader nwkHeader,
+                                       Ptr<Packet> msdu,
+                                       McpsDataIndicationParams params)
+{
+    NS_LOG_FUNCTION(this);
+
+    // As described in Zigbee specification r22.1.0 Section 3.6.6.3
+
+    // Drop if we've already seen this multicast frame
+    Ptr<BroadcastTransactionRecord> btr;
+    if (m_btt.LookUpEntry(nwkHeader.GetSeqNum(), btr))
+    {
+        return;
+    }
+
+    // Add new record to BTT
+    Ptr<BroadcastTransactionRecord> newBtr =
+        Create<BroadcastTransactionRecord>(nwkHeader.GetSrcAddr(),
+                                           nwkHeader.GetSeqNum(),
+                                           Simulator::Now() + m_nwkNetworkBroadcastDeliveryTime);
+
+    if (!m_btt.AddEntry(newBtr))
+    {
+        return;
+    }
+
+    // Verify if the device is capable of relaying multicast frames
+    // (i.e., not an end device)
+    CapabilityInformation capability(m_nwkCapabilityInformation);
+    bool canRelay = (capability.GetDeviceType() != MacDeviceType::ENDDEVICE);
+
+    // Case 1: Group Member — process and optionally retransmit
+
+    if (m_nwkGroupIdTable->IsGroupMember(nwkHeader.GetDstAddr().ConvertToInt()))
+    {
+        // Push the multicast frame to the APS layer
+        if (!m_nldeDataIndicationCallback.IsNull())
+        {
+            NldeDataIndicationParams dataParams;
+            dataParams.m_srcAddr = nwkHeader.GetSrcAddr();
+            dataParams.m_dstAddr = nwkHeader.GetDstAddr();
+            dataParams.m_dstAddrMode = AddressMode::MCST;
+            dataParams.m_linkQuality = params.m_mpduLinkQuality;
+            dataParams.m_nsduLength = msdu->GetSize();
+            dataParams.m_rxTime = Simulator::Now();
+            dataParams.m_securityUse = false;
+            m_nldeDataIndicationCallback(dataParams, msdu->Copy());
+        }
+        // TODO: Add Rx Trace here
+
+        if (canRelay)
+        {
+            nwkHeader.SetMulticastMode(MulticastMode::MEMBER);
+            nwkHeader.SetNonMemberRadius(nwkHeader.GetMaxNonMemberRadius());
+            msdu->AddHeader(nwkHeader);
+            Simulator::Schedule(MilliSeconds(m_bcstJitter->GetValue()),
+                                &ZigbeeNwk::SendDataBcst,
+                                this,
+                                msdu,
+                                0);
+        }
+        return;
+    }
+
+    // Case 2: Non Group Member — forward if non-zero radius
+
+    uint8_t radius = nwkHeader.GetNonMemberRadius();
+    if (radius == 0)
+    {
+        m_btt.Delete(nwkHeader.GetSeqNum());
+        return;
+    }
+
+    // Decrement radius and retransmit if allowed
+    nwkHeader.SetNonMemberRadius(radius - 1);
+
+    if (radius != 0 && canRelay)
+    {
+        msdu->AddHeader(nwkHeader);
+        Simulator::Schedule(MilliSeconds(m_bcstJitter->GetValue()),
+                            &ZigbeeNwk::SendDataBcst,
+                            this,
+                            msdu,
+                            0);
+    }
+}
+
+void
+ZigbeeNwk::ReceiveMulticastNonMemberFrame(ZigbeeNwkHeader nwkHeader,
+                                          Ptr<Packet> msdu,
+                                          McpsDataIndicationParams params)
+{
+    NS_LOG_FUNCTION(this);
+
+    NS_ASSERT_MSG(!nwkHeader.GetDstAddr().IsBroadcast(),
+                  "Error: Non-member multicast frame should have a Group ID address");
+
+    // As described in Zigbee specification r22.1.0 Section 3.6.6.4
+    // If the GROUP ID (destination address) is in our routing table,
+    // our non member multicast frame is transmitted as a unicast frame
+    // to the next hop in the routing table, otherwise it is discarded.
+    Ptr<RoutingTableEntry> entry;
+    if (m_nwkRoutingTable.LookUpEntry(nwkHeader.GetDstAddr(), entry))
+    {
+        if (entry->GetStatus() == RouteStatus::ROUTE_VALIDATION_UNDERWAY)
+        {
+            entry->SetStatus(RouteStatus::ROUTE_ACTIVE);
+        }
+
+        if ((entry->GetStatus() == ROUTE_ACTIVE))
+        {
+            msdu->AddHeader(nwkHeader);
+            McpsDataRequestParams mcpsDataparams;
+            mcpsDataparams.m_dstPanId = m_nwkPanId;
+            mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
+            mcpsDataparams.m_txOptions = 0x01; // Acknowledment on for Non-Member Multicast
+            mcpsDataparams.m_srcAddrMode = SHORT_ADDR;
+            mcpsDataparams.m_dstAddrMode = SHORT_ADDR;
+            mcpsDataparams.m_dstAddr = entry->GetNextHopAddr();
+            m_macHandle++;
+            Simulator::ScheduleNow(&LrWpanMacBase::McpsDataRequest, m_mac, mcpsDataparams, msdu);
+        }
+    }
+}
+
 bool
 ZigbeeNwk::IsBroadcastAddress(Mac16Address address)
 {
@@ -714,8 +884,25 @@
 {
     NS_LOG_FUNCTION(this);
 
+    if (payload.GetMulticastField() &&
+        m_nwkGroupIdTable->IsGroupMember(payload.GetDstAddr().ConvertToInt()))
+    {
+        // If the destination is a group member, we can directly return the next hop
+        // as the destination address.
+        nextHop = payload.GetDstAddr();
+        return ROUTE_FOUND;
+    }
+
     // Mesh routing
 
+    // Check if I am the destination
+    if (payload.GetDstAddr() == m_nwkNetworkAddress)
+    {
+        // I am the destination, return myself as next hop
+        nextHop = m_nwkNetworkAddress;
+        return ROUTE_FOUND;
+    }
+
     // Check if the destination is our neighbor
     Ptr<NeighborTableEntry> neighborEntry;
     if (m_nwkNeighborTable.LookUpEntry(payload.GetDstAddr(), neighborEntry))
@@ -762,14 +949,14 @@
             }
         }
 
-        // Entry not found
+        // Entry not found, create a new routing entry
         Ptr<RoutingTableEntry> newRoutingEntry =
             Create<RoutingTableEntry>(payload.GetDstAddr(),
                                       ROUTE_DISCOVERY_UNDERWAY,
-                                      true,  // TODO no route cache
-                                      false, // TODO: Many to one
-                                      false, // TODO: Route record
-                                      false, // TODO: Group id
+                                      true,                        // TODO no route cache
+                                      false,                       // Many to one
+                                      false,                       // TODO: Route record
+                                      payload.GetMulticastField(), // Group id
                                       Mac16Address("FF:FF"));
         newRoutingEntry->SetLifeTime(Simulator::Now() + m_routeExpiryTime);
 
@@ -922,7 +1109,7 @@
                 Create<RoutingTableEntry>(nwkHeader.GetSrcAddr(),
                                           ROUTE_ACTIVE,
                                           true,        // TODO no route cache
-                                          true,        // TODO: Many to one
+                                          true,        // Many to one
                                           routeRecord, // TODO: Route record
                                           false,       // TODO: Group id
                                           macSrcAddr);
@@ -957,6 +1144,7 @@
     nwkHeaderRreq.SetDstAddr(Mac16Address("FF:FC"));
     nwkHeaderRreq.SetSrcAddr(m_nwkNetworkAddress);
     nwkHeaderRreq.SetSeqNum(m_nwkSequenceNumber.GetValue());
+
     // see Zigbee specification 3.2.2.33.3
     if (nwkHeaderData.GetRadius() == 0)
     {
@@ -972,6 +1160,15 @@
     payloadRreq.SetDstAddr(nwkHeaderData.GetDstAddr());
     payloadRreq.SetPathCost(0);
 
+    // If the original Data packet is marked as multicast,
+    // then set the multicast field in the RREQ payload
+    // In essence, this will initiate a multicast route discovery
+    // if necessary
+    if (nwkHeaderData.IsMulticast())
+    {
+        payloadRreq.SetMulticastField(true);
+    }
+
     Mac16Address nextHop;
     RouteDiscoveryStatus nextHopStatus =
         FindNextHop(m_nwkNetworkAddress, 0, nwkHeaderRreq, payloadRreq, nextHop);
@@ -1021,6 +1218,7 @@
     BufferTxPkt(packet->Copy(), m_macHandle.GetValue(), nwkHandle);
 
     // Parameters as described in Section 3.6.5
+    // TxOptions = 0 by default, i.e. no acknowledgment
     McpsDataRequestParams mcpsDataparams;
     mcpsDataparams.m_dstPanId = m_nwkPanId;
     mcpsDataparams.m_msduHandle = m_macHandle.GetValue();
@@ -1040,28 +1238,58 @@
         ZigbeeNwkHeader nwkHeader;
         bufferedElement->txPkt->PeekHeader(nwkHeader);
 
-        if (nwkHeader.GetFrameType() == DATA)
+        if (nwkHeader.GetFrameType() != NwkType::DATA)
         {
-            if (IsBroadcastAddress(nwkHeader.GetDstAddr()))
-            {
-            }
-            else if (nwkHeader.GetSrcAddr() == m_nwkNetworkAddress)
-            {
-                // Send the confirmation to next layer after the packet transmission,
-                // only if packet transmitted was in the initiator of the NLDE-DATA.request
+            NS_LOG_ERROR("Received DATA.confirm for a non-DATA packet");
+            return;
+        }
 
-                if (!m_nldeDataConfirmCallback.IsNull())
+        if (IsBroadcastAddress(nwkHeader.GetDstAddr()) || nwkHeader.IsMulticast())
+        {
+            if (params.m_status != MacStatus::SUCCESS)
+            {
+                // Broadcast or Multicast failed, retry sending the packet.
+                // Zigbee specification r22.1.0 Section 3.6.6.3
+                Ptr<BroadcastTransactionRecord> btr;
+                if (m_btt.LookUpEntry(nwkHeader.GetSeqNum(), btr))
                 {
-                    // Zigbee Specification r22.1.0, End of Section 3.2.1.1.3
-                    // Report the the results of a request to a transmission of a packet
-                    NldeDataConfirmParams nldeDataConfirmParams;
-                    // nldeDataConfirmParams.m_status =
-                    // static_cast<ZigbeeNwkStatus>(params.m_status);
-                    nldeDataConfirmParams.m_nsduHandle = bufferedElement->nwkHandle;
-                    m_nldeDataConfirmCallback(nldeDataConfirmParams);
+                    btr->SetBcstRetryCount(btr->GetBcstRetryCount() + 1);
+                    if (btr->GetBcstRetryCount() <= m_nwkMaxBroadcastRetries)
+                    {
+                        // Retry sending the Broadcast or Multicast packet
+
+                        Simulator::Schedule(MilliSeconds(m_nwkPassiveAckTimeout.GetMilliSeconds()),
+                                            &ZigbeeNwk::SendDataBcst,
+                                            this,
+                                            bufferedElement->txPkt,
+                                            bufferedElement->nwkHandle);
+                    }
+                    else
+                    {
+                        // Broadcast retries exhausted, silently discard the packet
+                        NS_LOG_WARN("Broadcast or Multicast packet retries exhausted for packet"
+                                    " with sequence number "
+                                    << nwkHeader.GetSeqNum());
+                    }
                 }
             }
         }
+        else if (nwkHeader.GetSrcAddr() == m_nwkNetworkAddress)
+        {
+            // Send the confirmation to next layer after the packet transmission,
+            // only if packet transmitted was in the initiator of the NLDE-DATA.request
+
+            if (!m_nldeDataConfirmCallback.IsNull())
+            {
+                // Zigbee Specification r22.1.0, End of Section 3.2.1.1.3
+                // Report the the results of a request to a transmission of a packet
+                NldeDataConfirmParams nldeDataConfirmParams;
+                // nldeDataConfirmParams.m_status =
+                // static_cast<ZigbeeNwkStatus>(params.m_status);
+                nldeDataConfirmParams.m_nsduHandle = bufferedElement->nwkHandle;
+                m_nldeDataConfirmCallback(nldeDataConfirmParams);
+            }
+        }
     }
 }
 
@@ -1970,7 +2198,7 @@
 
     if (params.m_dstAddr == m_nwkNetworkAddress)
     {
-        NS_LOG_DEBUG("The source and the destination of the route request are the same!");
+        NS_LOG_WARN("The source and the destination of the route request are the same!");
         return;
     }
 
@@ -1978,7 +2206,7 @@
     // check that we are associated
     if (m_nwkNetworkAddress == "FF:FF")
     {
-        NS_LOG_DEBUG("Cannot send data, the device is not currently associated");
+        NS_LOG_WARN("Cannot send data, the device is not currently associated");
 
         if (!m_nldeDataConfirmCallback.IsNull())
         {
@@ -1998,7 +2226,7 @@
     nwkHeader.SetDiscoverRoute(static_cast<DiscoverRouteType>(params.m_discoverRoute));
     nwkHeader.SetDstAddr(params.m_dstAddr);
 
-    if (params.m_useAlias)
+    if (params.m_useAlias && params.m_dstAddrMode != AddressMode::MCST)
     {
         nwkHeader.SetSrcAddr(params.m_aliasSrcAddr);
         nwkHeader.SetSeqNum(params.m_aliasSeqNumber.GetValue());
@@ -2028,32 +2256,93 @@
     CapabilityInformation capability;
     capability.SetCapability(m_nwkCapabilityInformation);
 
-    if (capability.GetDeviceType() == ENDDEVICE)
+    if (capability.GetDeviceType() == MacDeviceType::ENDDEVICE)
     {
         nwkHeader.SetEndDeviceInitiator();
     }
 
-    if (params.m_dstAddrMode == MCST)
+    // CASE 1: The destination is a multicast address (Group address)
+    // See Sections 3.6.6.2 and 3.2.1.1.3
+    if (params.m_dstAddrMode == AddressMode::MCST)
     {
+        if (nwkHeader.GetEndDeviceInitiator())
+        {
+            NS_LOG_WARN("EndDevices cannot send multicast packets, dropping the packet");
+            if (!m_nldeDataConfirmCallback.IsNull())
+            {
+                NldeDataConfirmParams confirmParams;
+                confirmParams.m_status = NwkStatus::INVALID_REQUEST;
+                confirmParams.m_txTime = Simulator::Now();
+                confirmParams.m_nsduHandle = params.m_nsduHandle;
+                m_nldeDataConfirmCallback(confirmParams);
+            }
+            return;
+            // TODO: Add trace here.
+        }
+
         nwkHeader.SetMulticast();
-        // TODO:
-        // set the nwkHeader multicast control according to
-        // the values of the non-member radios parameter
-        // See 3.2.1.1.3
+        nwkHeader.SetNonMemberRadius(params.m_nonMemberRadius);
+        nwkHeader.SetMaxNonMemberRadius(params.m_nonMemberRadius);
+
+        // Check if the current device is member of the multicast Group (dstAddr)
+        bool groupMember = m_nwkGroupIdTable->IsGroupMember(params.m_dstAddr.ConvertToInt());
+
+        if (groupMember)
+        {
+            nwkHeader.SetMulticastMode(MulticastMode::MEMBER);
+
+            // Add an entry to the Broadcast Transaction Table (BTT)
+            Ptr<BroadcastTransactionRecord> btr = Create<BroadcastTransactionRecord>(
+                nwkHeader.GetSrcAddr(),
+                nwkHeader.GetSeqNum(),
+                Simulator::Now() + m_nwkNetworkBroadcastDeliveryTime);
+
+            if (!m_btt.AddEntry(btr))
+            {
+                NS_LOG_DEBUG("Broadcast Transaction Table is full, dropping the packet");
+                // TODO: Add multicast packet trace here
+                if (!m_nldeDataConfirmCallback.IsNull())
+                {
+                    NldeDataConfirmParams confirmParams;
+                    confirmParams.m_status = NwkStatus::BT_TABLE_FULL;
+                    confirmParams.m_txTime = Simulator::Now();
+                    confirmParams.m_nsduHandle = params.m_nsduHandle;
+                    m_nldeDataConfirmCallback(confirmParams);
+                }
+                return;
+            }
+        }
+        else
+        {
+            nwkHeader.SetMulticastMode(MulticastMode::NONMEMBER);
+        }
+
+        packet->AddHeader(nwkHeader);
+
+        if (groupMember)
+        {
+            // See 3.6.6.2.1: Group Members initiate the transmission
+            // using a broadcast (MAC level)
+            SendDataBcst(packet, params.m_nsduHandle);
+        }
+        else
+        {
+            // See 3.6.6.2.2: Non-Group member initiate the transmission
+            // using a unicast (MAC level) and search for the next hop
+            // in its routing table if necessary.
+            SendDataUcst(packet, params.m_nsduHandle);
+        }
+        return;
     }
 
+    // CASE 2: The destination is a unicast address, a broadcast address
+    // or has no address (Many to one routing)
+
     packet->AddHeader(nwkHeader);
 
-    if (capability.GetDeviceType() == ROUTER)
+    if (capability.GetDeviceType() == MacDeviceType::ROUTER)
     {
-        if (params.m_dstAddrMode == MCST)
-        {
-            // The destination is MULTICAST (See 3.6.2)
-            NS_ABORT_MSG("Multicast is currently not supported");
-            // TODO
-            return;
-        }
-        else if (IsBroadcastAddress(params.m_dstAddr))
+        if (IsBroadcastAddress(params.m_dstAddr))
         {
             // The destination is BROADCAST (See 3.6.5)
             SendDataBcst(packet, params.m_nsduHandle);
@@ -2223,6 +2512,10 @@
             confirmParams.m_status = NwkStatus::INVALID_REQUEST;
             m_nlmeRouteDiscoveryConfirmCallback(confirmParams);
         }
+
+        NS_LOG_WARN("The destination address is a broadcast address, or the destination "
+                    "address mode is NO_ADDRESS, cannot send route discovery request");
+
         return;
     }
 
@@ -2234,8 +2527,12 @@
         {
             NlmeRouteDiscoveryConfirmParams confirmParams;
             confirmParams.m_status = NwkStatus::ROUTE_ERROR;
+            confirmParams.m_networkStatusCode = NetworkStatusCode::NO_ROUTING_CAPACITY;
             m_nlmeRouteDiscoveryConfirmCallback(confirmParams);
         }
+
+        NS_LOG_WARN("Device does not have routing capacity, cannot send route discovery request");
+
         return;
     }
 
@@ -2255,10 +2552,11 @@
     payload.SetRouteReqId(m_routeRequestId.GetValue());
     payload.SetPathCost(0);
 
-    if (params.m_dstAddrMode == UCST_BCST)
+    if (params.m_dstAddrMode == AddressMode::UCST_BCST || params.m_dstAddrMode == AddressMode::MCST)
     {
-        // Set the rest of the nwkHeader and command payload parameters
-        // as described in Zigbee specification, Section 3.2.2.33.3
+        // Set the rest of the nwkHeader and command payload (RREQ) parameters
+        // as described in Zigbee specification r22.1.0, Section 3.2.2.33.3
+
         if (params.m_radius == 0)
         {
             nwkHeader.SetRadius(m_nwkMaxDepth * 2);
@@ -2270,6 +2568,13 @@
 
         payload.SetDstAddr(params.m_dstAddr);
 
+        if (params.m_dstAddrMode == AddressMode::MCST)
+        {
+            // Set the Multicast flag and proceed with the
+            // multicast destination route discovery
+            payload.SetMulticastField(true);
+        }
+
         Mac16Address nextHop;
         RouteDiscoveryStatus routeStatus =
             FindNextHop(m_nwkNetworkAddress, 0, nwkHeader, payload, nextHop);
@@ -2298,10 +2603,6 @@
             m_routeRequestId++;
         }
     }
-    else if (params.m_dstAddrMode == MCST)
-    {
-        NS_ABORT_MSG("Multicast Route discovery not supported");
-    }
     else if (params.m_dstAddrMode == NO_ADDRESS)
     {
         // Many-to-one route discovery.
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk.h ns-3.46/src/zigbee/model/zigbee-nwk.h
--- ns-3.45/src/zigbee/model/zigbee-nwk.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk.h	2025-10-01 18:46:32.000000000 -0700
@@ -12,6 +12,7 @@
 #ifndef ZIGBEE_NWK_H
 #define ZIGBEE_NWK_H
 
+#include "zigbee-group-table.h"
 #include "zigbee-nwk-fields.h"
 #include "zigbee-nwk-header.h"
 #include "zigbee-nwk-payload-header.h"
@@ -49,7 +50,7 @@
                                                      //!< Page 0 in Zigbee (250kbps O-QPSK)
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * Indicates a pending NWK primitive
  */
@@ -67,7 +68,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * Table 3.2 (Address Mode) NLDE-DATA-Request parameters
  */
@@ -137,7 +138,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  *  Network layer status values
  *  Combines Zigbee Specification r22.1.0 Table 3-73 and
@@ -235,7 +236,7 @@
 std::ostream& operator<<(std::ostream& os, const uint8_t& num);
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  *  Status codes for network status command frame and route discovery failures.
  *
@@ -265,7 +266,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  Channel List Structure. See Zigbee Specification 3.2.2.2.1
  */
@@ -283,7 +284,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * NLDE-DATA.confirm params. See Zigbee Specification 3.2.1.2
  */
@@ -297,7 +298,7 @@
 };
 
 /**
- * @ingroup lr-wpan
+ * @ingroup Zigbee
  *
  * NLDE-DATA.indication params. See Zigbee Specification 3.2.1.3.1
  */
@@ -315,7 +316,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * NLDE-DATA.request params. See Zigbee Specification 3.2.1.1
  */
@@ -340,7 +341,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-NETWORK-FORMATION.request params. See Zigbee Specification 3.2.2.5.1
  */
@@ -372,7 +373,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * A group of pending parameters arranged into a structure during the execution of
  * a NLME-NETWORK-FORMATION.request primitive.
@@ -385,7 +386,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-NETWORK-FORMATION.confirm params. See Zigbee Specification 3.2.2.6.1
  */
@@ -396,14 +397,15 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-ROUTE-DISCOVERY.request params. See Zigbee Specification 3.2.2.33
  */
 struct NlmeRouteDiscoveryRequestParams
 {
     AddressMode m_dstAddrMode{UCST_BCST}; //!< Specifies the kind of destination address.
-    Mac16Address m_dstAddr;               //!< The destination of the route discovery.
+    Mac16Address m_dstAddr;    //!< The 16-bit destination address or Group ID (MCST destination)
+                               //!<  of the route discovery.
     uint16_t m_radius{0};      //!< Optional parameter that describes the number of hops that the
                                //!< route request will travel through the network.
     bool m_noRouteCache{true}; //!< This flag determines whether the NWK should establish a
@@ -411,7 +413,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-ROUTE-DISCOVERY.confirm params. See Zigbee Specification r22.1.0, 3.2.2.34
  */
@@ -425,7 +427,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-DIRECT-JOIN.request params.
  *  See Zigbee Specification r22.1.0, 3.2.2.16
@@ -438,7 +440,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-DIRECT-JOIN.confirm params.
  *  See Zigbee Specification r22.1.0, 3.2.2.17
@@ -452,7 +454,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-NETWORK-DISCOVERY.request params.
  *  See Zigbee Specification r22.1.0, 3.2.2.3
@@ -492,7 +494,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-NETWORK-DISCOVERY.confirm params. See Zigbee Specification r22.1.0, 3.2.2.4
  */
@@ -506,7 +508,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * NLME-JOIN.request params.
  * See Zigbee Specification r22.1.0, 3.2.2.13
@@ -528,7 +530,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-JOIN.confirm params.
  *  See Zigbee Specification r22.1.0, 3.2.2.15
@@ -560,7 +562,7 @@
 };
 
 /**
- *  @ingroup zigbee
+ *  @ingroup Zigbee
  *
  *  NLME-JOIN.indication params.
  *  See Zigbee Specification r22.1.0, 3.2.2.14
@@ -579,7 +581,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * NLME-START-ROUTER.request params.
  * See Zigbee Specification r22.1.0, 3.2.2.13
@@ -592,7 +594,7 @@
 };
 
 /**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * NLME-START-ROUTER.confirm params.
  * See Zigbee Specification r22.1.0, 3.2.2.10
@@ -603,86 +605,8 @@
                                                     //!< the corresponding request.
 };
 
-//////////////////////
-//     Callbacks    //
-//////////////////////
-
-/**
- * @ingroup zigbee
- *
- * This callback is called after a NSDU has successfully received and
- *  NWK push it to deliver it to the next higher layer.
- *
- */
-typedef Callback<void, NldeDataIndicationParams, Ptr<Packet>> NldeDataIndicationCallback;
-
-/**
- * @ingroup zigbee
- *
- * This callback is used to notify the next higher layer with a confirmation in response to
- * a previously issued NLDE-DATA.request.
- *
- */
-typedef Callback<void, NldeDataConfirmParams> NldeDataConfirmCallback;
-
-/**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with a confirmation in response to
- *  a previously issued NLME-NETWORK-FORMATION.request.
- */
-typedef Callback<void, NlmeNetworkFormationConfirmParams> NlmeNetworkFormationConfirmCallback;
-
-/**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with a confirmation in response to
- *  a previously issued NLME-NETWORK-DISCOVERY.request.
- */
-typedef Callback<void, NlmeNetworkDiscoveryConfirmParams> NlmeNetworkDiscoveryConfirmCallback;
-
 /**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with a confirmation in response to
- *  a previously issued NLME-ROUTE-DISCOVERY.request.
- */
-typedef Callback<void, NlmeRouteDiscoveryConfirmParams> NlmeRouteDiscoveryConfirmCallback;
-
-/**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with a confirmation in response to
- *  a previously issued NLME-DIRECT-JOIN.request.
- */
-typedef Callback<void, NlmeDirectJoinConfirmParams> NlmeDirectJoinConfirmCallback;
-
-/**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with a confirmation in response to
- *  a previously issued NLME-JOIN.request.
- */
-typedef Callback<void, NlmeJoinConfirmParams> NlmeJoinConfirmCallback;
-
-/**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with an indication that a new
- *  device has successfully joined its network by association or rejoining.
- */
-typedef Callback<void, NlmeJoinIndicationParams> NlmeJoinIndicationCallback;
-
-/**
- *  @ingroup zigbee
- *
- *  This callback is used to notify the next higher layer with a confirmation in response to
- *  a previously issued NLME-START-ROUTER.request.
- */
-typedef Callback<void, NlmeStartRouterConfirmParams> NlmeStartRouterConfirmCallback;
-
-/**
- * @ingroup zigbee
+ * @ingroup Zigbee
  *
  * Class that implements the Zigbee Specification Network Layer
  */
@@ -703,6 +627,60 @@
     ~ZigbeeNwk() override;
 
     /**
+     * This callback is called after a NSDU has successfully received and
+     *  NWK push it to deliver it to the next higher layer.
+     */
+    using NldeDataIndicationCallback = Callback<void, NldeDataIndicationParams, Ptr<Packet>>;
+
+    /**
+     * This callback is used to notify the next higher layer with a confirmation in response to
+     * a previously issued NLDE-DATA.request.
+     */
+    using NldeDataConfirmCallback = Callback<void, NldeDataConfirmParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with a confirmation in response to
+     *  a previously issued NLME-NETWORK-FORMATION.request.
+     */
+    using NlmeNetworkFormationConfirmCallback = Callback<void, NlmeNetworkFormationConfirmParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with a confirmation in response to
+     *  a previously issued NLME-NETWORK-DISCOVERY.request.
+     */
+    using NlmeNetworkDiscoveryConfirmCallback = Callback<void, NlmeNetworkDiscoveryConfirmParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with a confirmation in response to
+     *  a previously issued NLME-ROUTE-DISCOVERY.request.
+     */
+    using NlmeRouteDiscoveryConfirmCallback = Callback<void, NlmeRouteDiscoveryConfirmParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with a confirmation in response to
+     *  a previously issued NLME-DIRECT-JOIN.request.
+     */
+    using NlmeDirectJoinConfirmCallback = Callback<void, NlmeDirectJoinConfirmParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with a confirmation in response to
+     *  a previously issued NLME-JOIN.request.
+     */
+    using NlmeJoinConfirmCallback = Callback<void, NlmeJoinConfirmParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with an indication that a new
+     *  device has successfully joined its network by association or rejoining.
+     */
+    using NlmeJoinIndicationCallback = Callback<void, NlmeJoinIndicationParams>;
+
+    /**
+     *  This callback is used to notify the next higher layer with a confirmation in response to
+     *  a previously issued NLME-START-ROUTER.request.
+     */
+    using NlmeStartRouterConfirmCallback = Callback<void, NlmeStartRouterConfirmParams>;
+
+    /**
      * Set the underlying MAC to use in this Zigbee NWK
      *
      * @param mac The pointer to the underlying LrWpan MAC to set to this Zigbee NWK
@@ -710,6 +688,13 @@
     void SetMac(Ptr<lrwpan::LrWpanMacBase> mac);
 
     /**
+     * Get the group table used by this Zigbee NWK.
+     *
+     * @param groupTable The pointer to the group table to set.
+     */
+    void SetGroupTable(Ptr<ZigbeeGroupTable> groupTable);
+
+    /**
      * Get the underlying MAC used by the current Zigbee NWK.
      *
      * @return The pointer to the underlying MAC object currently connected to the Zigbee NWK.
@@ -1284,6 +1269,12 @@
     BroadcastTransactionTable m_btt;
 
     /**
+     *  The Group Table used by this Zigbee NWK.
+     *  See Zigbee specification r22.1.0, 3.6.3.2
+     */
+    Ptr<ZigbeeGroupTable> m_nwkGroupIdTable;
+
+    /**
      * Enqueue a packet in the pending transmission queue until
      * a route is discovered for its destination.
      *
@@ -1446,6 +1437,30 @@
                      ZigbeePayloadRouteReplyCommand payload);
 
     /**
+     *  Process a Multicast Frame received as a member of a multicast group.
+     *  See Zigbee specification r22.1.0 Section 3.6.6.3
+     *
+     * @param nwkHeader The network header of the received multicast frame.
+     * @param msdu The MSDU (MSDU = MAC Service Data Unit) received
+     * @param params The MCPS-DATA.indication parameters associated to the received frame.
+     */
+    void ReceiveMulticastMemberFrame(ZigbeeNwkHeader nwkHeader,
+                                     Ptr<Packet> msdu,
+                                     lrwpan::McpsDataIndicationParams params);
+
+    /**
+     *  Process a Multicast Frame received as a non member of a multicast group.
+     *  See Zigbee specification r22.1.0 Section 3.6.6.4
+     *
+     * @param nwkHeader The network header of the received multicast frame.
+     * @param msdu The MSDU (MSDU = MAC Service Data Unit) received
+     * @param params The MCPS-DATA.indication parameters associated to the received frame.
+     */
+    void ReceiveMulticastNonMemberFrame(ZigbeeNwkHeader nwkHeader,
+                                        Ptr<Packet> msdu,
+                                        lrwpan::McpsDataIndicationParams params);
+
+    /**
      *  Returns true if the address is a broadcast address according to
      *  Zigbee specification r22.1.0, Section 3.6.5, Table 3-69
      *
@@ -1481,6 +1496,18 @@
     void SendDataBcst(Ptr<Packet> packet, uint8_t nwkHandle);
 
     /**
+     * Send a data multicast packet to all the members of a multicast group.
+     *
+     * @param packet The NPDU (nwkHeader + data payload) to transmit.
+     * @param nwkHandle The NWK handle associated to this packet (nsdu handle).
+     *                  A handle of 0 implies that the unicast transmission is a
+     *                  retransmission and do not requires a handle which is
+     *                  used to identify a packet in confirmations to
+     *                  requests (NLDE-DATA.confirm).
+     */
+    void SendDataMcst(Ptr<Packet> packet, uint8_t nwkHandle);
+
+    /**
      * Find the next hop in route to a destination.
      *
      * See RouteDiscoveryStatus enumeration for full information on the returned status.
@@ -1527,6 +1554,11 @@
     Ptr<UniformRandomVariable> m_rreqJitter;
 
     /**
+     *  Provides uniform random values for the broadcast jitter
+     */
+    Ptr<UniformRandomVariable> m_bcstJitter;
+
+    /**
      * Temporarily store beacons information from POS routers and PAN coordinators
      * during a network-discovery process.
      */
@@ -1613,6 +1645,14 @@
      */
     double m_nwkcMaxRREQJitter;
 
+    /**
+     * Minimum Broadcast jitter time (msec).
+     * Zigbee Specification r22.1.0, Table 3-57. Defined as a constant
+     * in the specification but here is defined as variable to allow the selection of values
+     * per device.
+     */
+    double m_nwkcMaxBroadcastJitter;
+
     //////////////////////////////
     // Network layer attributes //
     //////////////////////////////
@@ -1763,6 +1803,7 @@
      * The maximum time duration in milliseconds allowed for the parent all the child devices to
      * retransmit a broadcast message.
      * See Zigbe Specification r22.1.0, Table 3-58 (NIB attributes)
+     * See Zigbee-2007 Layer PICS and Stack Profiles
      */
     Time m_nwkPassiveAckTimeout;
 
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk-header.cc ns-3.46/src/zigbee/model/zigbee-nwk-header.cc
--- ns-3.45/src/zigbee/model/zigbee-nwk-header.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk-header.cc	2025-10-01 18:46:32.000000000 -0700
@@ -175,6 +175,42 @@
 }
 
 void
+ZigbeeNwkHeader::SetMulticastMode(MulticastMode mode)
+{
+    m_mcstMode = mode;
+}
+
+MulticastMode
+ZigbeeNwkHeader::GetMulticastMode() const
+{
+    return m_mcstMode;
+}
+
+void
+ZigbeeNwkHeader::SetNonMemberRadius(uint8_t radius)
+{
+    m_nonMemberRadius = radius;
+}
+
+uint8_t
+ZigbeeNwkHeader::GetNonMemberRadius() const
+{
+    return m_nonMemberRadius;
+}
+
+void
+ZigbeeNwkHeader::SetMaxNonMemberRadius(uint8_t radius)
+{
+    m_maxNonMemberRadius = radius;
+}
+
+uint8_t
+ZigbeeNwkHeader::GetMaxNonMemberRadius() const
+{
+    return m_maxNonMemberRadius;
+}
+
+void
 ZigbeeNwkHeader::SetFrameControl(uint16_t frameControl)
 {
     m_fctrlFrmType = static_cast<NwkType>((frameControl) & (0x03));                  // Bit 0-1
@@ -217,13 +253,13 @@
 uint8_t
 ZigbeeNwkHeader::GetMulticastControl() const
 {
-    uint8_t val = 0;
+    uint8_t mcstCtrl = 0;
 
-    val = m_mcstMode & (0x03);                        // Bit 0-1
-    val |= (m_nonMemberRadius << 2) & (0x07 << 2);    // Bit 2-4
-    val |= (m_maxNonMemberRadius << 5) & (0x07 << 5); // Bit 5-7
+    mcstCtrl = m_mcstMode & (0x03);                        // Bit 0-1
+    mcstCtrl |= (m_nonMemberRadius << 2) & (0x07 << 2);    // Bit 2-4
+    mcstCtrl |= (m_maxNonMemberRadius << 5) & (0x07 << 5); // Bit 5-7
 
-    return val;
+    return mcstCtrl;
 }
 
 void
@@ -280,8 +316,8 @@
 
     if (m_fctrlMcst)
     {
-        uint8_t multicastControl = i.ReadU8();
-        SetMulticastControl(multicastControl);
+        uint8_t mcstCtrl = i.ReadU8();
+        SetMulticastControl(mcstCtrl);
     }
 
     // TODO: Add Source route subframe when supported
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk-header.h ns-3.46/src/zigbee/model/zigbee-nwk-header.h
--- ns-3.45/src/zigbee/model/zigbee-nwk-header.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk-header.h	2025-10-01 18:46:32.000000000 -0700
@@ -199,6 +199,48 @@
      */
     Mac64Address GetSrcIeeeAddr() const;
 
+    /**
+     * Set the multicast mode
+     *
+     * @param mode The multicast mode (member or non-member)
+     */
+    void SetMulticastMode(MulticastMode mode);
+
+    /**
+     * Get the multicast mode
+     *
+     * @return The multicast mode (member or non-member)
+     */
+    MulticastMode GetMulticastMode() const;
+
+    /**
+     * Set the non-member radius
+     *
+     * @param radius The non-member radius (0-7)
+     */
+    void SetNonMemberRadius(uint8_t radius);
+
+    /**
+     * Get the non-member radius
+     *
+     * @return The non-member radius (0-7)
+     */
+    uint8_t GetNonMemberRadius() const;
+
+    /**
+     * Set the maximum non-member radius
+     *
+     * @param radius The maximum non-member radius (0-7)
+     */
+    void SetMaxNonMemberRadius(uint8_t radius);
+
+    /**
+     * Get the maximum non-member radius
+     *
+     * @return The maximum non-member radius (0-7)
+     */
+    uint8_t GetMaxNonMemberRadius() const;
+
     void Serialize(Buffer::Iterator start) const override;
     uint32_t Deserialize(Buffer::Iterator start) override;
     uint32_t GetSerializedSize() const override;
@@ -223,7 +265,7 @@
      */
     uint16_t GetFrameControl() const;
     /**
-     * Set the Multicast control field
+     * Set the Multicast control field (mcstMode, nonMemberRadius, maxNonMemberRadius)
      * @param multicastControl 8 bits representing the multicast control field
      */
     void SetMulticastControl(uint8_t multicastControl);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk-payload-header.cc ns-3.46/src/zigbee/model/zigbee-nwk-payload-header.cc
--- ns-3.45/src/zigbee/model/zigbee-nwk-payload-header.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk-payload-header.cc	2025-10-01 18:46:32.000000000 -0700
@@ -301,6 +301,18 @@
 }
 
 void
+ZigbeePayloadRouteRequestCommand::SetMulticastField(bool mcst)
+{
+    m_cmdOptMcst = mcst;
+}
+
+bool
+ZigbeePayloadRouteRequestCommand::GetMulticastField() const
+{
+    return m_cmdOptMcst;
+}
+
+void
 ZigbeePayloadRouteRequestCommand::SetCmdOptionField(uint8_t cmdOptionField)
 {
     m_cmdOptManyToOne = static_cast<ManyToOne>((cmdOptionField >> 3) & (0x03)); // Bit 3-4
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk-payload-header.h ns-3.46/src/zigbee/model/zigbee-nwk-payload-header.h
--- ns-3.45/src/zigbee/model/zigbee-nwk-payload-header.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk-payload-header.h	2025-10-01 18:46:32.000000000 -0700
@@ -77,11 +77,14 @@
 
     /**
      * Set the command frame type
+     *
      * @param nwkCmd the command frame type
      */
     void SetCmdType(enum NwkCommandType nwkCmd);
+
     /**
      * Get the command frame type
+     *
      * @return The command type from the command payload header
      */
     NwkCommandType GetCmdType() const;
@@ -93,7 +96,8 @@
 /**
  * @ingroup zigbee
  * Represent a variable portion of the zigbee payload header that includes
- * the route request command
+ * the route request command.
+ * See Zigbee specification r22.1.0, Section 3.4.1
  */
 class ZigbeePayloadRouteRequestCommand : public Header
 {
@@ -126,36 +130,42 @@
 
     /**
      * Set the Route request identifier
+     *
      * @param id the route request identifier
      */
     void SetRouteReqId(uint8_t id);
 
     /**
      * Get the Route request identifier
+     *
      * @return the route request identifier
      */
     uint8_t GetRouteReqId() const;
 
     /**
      * Set Destination address
+     *
      * @param addr The destination address (16 bit)
      */
     void SetDstAddr(Mac16Address addr);
 
     /**
      * Get the Destination address
+     *
      * @return the Destination address (16bits)
      */
     Mac16Address GetDstAddr() const;
 
     /**
      * Set the path cost
+     *
      * @param cost the path cost
      */
     void SetPathCost(uint8_t cost);
 
     /**
      * Set the path cost
+     *
      * @return the path cost
      */
     uint8_t GetPathCost() const;
@@ -168,17 +178,35 @@
     bool IsDstIeeeAddressPresent() const;
 
     /**
-     *  Set the destination IEEE address
+     *  Set the destination IEEE address, also automatically
+     *  sets the command option DstIeeeAddr field
+     *
      *  @param dst The destination IEEE address (64 bits)
      */
     void SetDstIeeeAddr(Mac64Address dst);
 
     /**
-     * Get the destination IEEE address
+     * Get the destination IEEE address (64-bit) contained in the
+     * route request command.
+     *
      * @return The destination IEEE address (64bits)
      */
     Mac64Address GetDstIeeeAddr() const;
 
+    /**
+     * Set the command option multicast field
+     *
+     * @param mcst True if the command option multicast field is active
+     */
+    void SetMulticastField(bool mcst);
+
+    /**
+     * Get the command option multicast field
+     *
+     * @return True if the command option multicast field is active
+     */
+    bool GetMulticastField() const;
+
   private:
     /**
      * Set the complete command option field of the route request command.
@@ -208,7 +236,8 @@
 /**
  * @ingroup zigbee
  * Represent a variable portion of the zigbee payload header that includes
- * the route reply command
+ * the route reply command.
+ * See Zigbee specification r22.1.0, Section 3.4.2
  */
 class ZigbeePayloadRouteReplyCommand : public Header
 {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk-tables.cc ns-3.46/src/zigbee/model/zigbee-nwk-tables.cc
--- ns-3.45/src/zigbee/model/zigbee-nwk-tables.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk-tables.cc	2025-10-01 18:46:32.000000000 -0700
@@ -1327,6 +1327,14 @@
 }
 
 void
+BroadcastTransactionTable::Delete(uint8_t seq)
+{
+    std::erase_if(m_broadcastTransactionTable, [&seq](Ptr<BroadcastTransactionRecord> entry) {
+        return entry->GetSeqNum() == seq;
+    });
+}
+
+void
 BroadcastTransactionTable::Purge()
 {
     std::erase_if(m_broadcastTransactionTable, [](Ptr<BroadcastTransactionRecord> btr) {
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-nwk-tables.h ns-3.46/src/zigbee/model/zigbee-nwk-tables.h
--- ns-3.45/src/zigbee/model/zigbee-nwk-tables.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-nwk-tables.h	2025-10-01 18:46:32.000000000 -0700
@@ -8,8 +8,8 @@
  *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
  */
 
-#ifndef ZIGBEE_TABLES_H
-#define ZIGBEE_TABLES_H
+#ifndef ZIGBEE_NWK_TABLES_H
+#define ZIGBEE_NWK_TABLES_H
 
 #include "zigbee-nwk-fields.h"
 
@@ -924,10 +924,10 @@
     void Print(Ptr<OutputStreamWrapper> stream) const;
 
   private:
-    Mac16Address m_srcAddr;        //!< The 16-bit network address of the broadcast initiator.
-    uint8_t m_sequenceNumber;      //!< The RREQ sequence number of the initiator's broadcast.
-    Time m_expirationTime;         //!< An indicator of when the entry expires
-    uint8_t m_broadcastRetryCount; //!< The number of times this BCST has been retried.
+    Mac16Address m_srcAddr;           //!< The 16-bit network address of the broadcast initiator.
+    uint8_t m_sequenceNumber{0};      //!< The RREQ sequence number of the initiator's broadcast.
+    Time m_expirationTime;            //!< An indicator of when the entry expires
+    uint8_t m_broadcastRetryCount{1}; //!< The number of times this BCST has been retried.
 };
 
 /**
@@ -1298,6 +1298,13 @@
     bool LookUpEntry(uint8_t seq, Ptr<BroadcastTransactionRecord>& entryFound);
 
     /**
+     * Delete a broadcast transaction record (BTR) from the broadcast transaction table (BTT).
+     *
+     * @param seq The sequence number of the broadcasted frame to delete.
+     */
+    void Delete(uint8_t seq);
+
+    /**
      * Purge expired entries from the broadcast transaction table (BTT).
      */
     void Purge();
@@ -1324,4 +1331,4 @@
 } // namespace zigbee
 } // namespace ns3
 
-#endif /* ZIGBEE_TABLES_H */
+#endif /* ZIGBEE_NWK_TABLES_H */
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-stack.cc ns-3.46/src/zigbee/model/zigbee-stack.cc
--- ns-3.45/src/zigbee/model/zigbee-stack.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-stack.cc	2025-10-01 18:46:32.000000000 -0700
@@ -40,8 +40,10 @@
     NS_LOG_FUNCTION(this);
 
     m_nwk = CreateObject<zigbee::ZigbeeNwk>();
-    // TODO: Create  APS layer here.
-    //  m_aps = CreateObject<zigbee::ZigbeeAps> ();
+    m_aps = CreateObject<zigbee::ZigbeeAps>();
+    m_groupTable = Create<zigbee::ZigbeeGroupTable>();
+
+    m_nwkOnly = false;
 }
 
 ZigbeeStack::~ZigbeeStack()
@@ -56,7 +58,9 @@
 
     m_netDevice = nullptr;
     m_node = nullptr;
+    m_aps = nullptr;
     m_nwk = nullptr;
+    m_groupTable = nullptr;
     m_mac = nullptr;
     Object::DoDispose();
 }
@@ -66,18 +70,19 @@
 {
     NS_LOG_FUNCTION(this);
 
-    AggregateObject(m_nwk);
-
     NS_ABORT_MSG_UNLESS(m_netDevice,
                         "Invalid NetDevice found when attempting to install ZigbeeStack");
 
     // Make sure the NetDevice is previously initialized
-    // before using ZigbeeStack
+    // before using ZigbeeStack (PHY and MAC are initialized)
     m_netDevice->Initialize();
 
     m_mac = m_netDevice->GetObject<lrwpan::LrWpanMacBase>();
     NS_ABORT_MSG_UNLESS(m_mac,
-                        "No valid LrWpanMacBase found in this NetDevice, cannot use ZigbeeStack");
+                        "Invalid LrWpanMacBase found in this NetDevice, cannot use ZigbeeStack");
+
+    m_nwk->Initialize();
+    AggregateObject(m_nwk);
 
     // Set NWK callback hooks with the MAC
     m_nwk->SetMac(m_mac);
@@ -97,14 +102,27 @@
     m_mac->SetMlmeAssociateConfirmCallback(MakeCallback(&ZigbeeNwk::MlmeAssociateConfirm, m_nwk));
     // TODO: complete other callback hooks with the MAC
 
+    if (!m_nwkOnly)
+    {
+        // Set APS callback hooks with NWK (i.e., NLDE primitives only)
+        m_nwk->SetNldeDataConfirmCallback(MakeCallback(&ZigbeeAps::NldeDataConfirm, m_aps));
+        m_nwk->SetNldeDataIndicationCallback(MakeCallback(&ZigbeeAps::NldeDataIndication, m_aps));
+
+        m_nwk->SetGroupTable(m_groupTable);
+        m_aps->SetGroupTable(m_groupTable);
+
+        m_aps->Initialize();
+        m_aps->SetNwk(m_nwk);
+        AggregateObject(m_aps);
+    }
+    else
+    {
+        m_nwk->SetGroupTable(m_groupTable);
+    }
+
     // Obtain Extended address as soon as NWK is set to begin operations
     m_mac->MlmeGetRequest(MacPibAttributeIdentifier::macExtendedAddress);
 
-    // TODO: Set APS callback hooks with NWK when support for APS layer is added.
-    //       For example:
-    // m_aps->SetNwk (m_nwk);
-    // m_nwk->SetNldeDataIndicationCallback (MakeCallback (&ZigbeeAps::NldeDataIndication, m_aps));
-
     Object::DoInitialize();
 }
 
@@ -134,6 +152,12 @@
     m_node = m_netDevice->GetNode();
 }
 
+void
+ZigbeeStack::SetOnlyNwkLayer()
+{
+    m_nwkOnly = true;
+}
+
 Ptr<zigbee::ZigbeeNwk>
 ZigbeeStack::GetNwk() const
 {
@@ -148,5 +172,19 @@
     m_nwk = nwk;
 }
 
+Ptr<zigbee::ZigbeeAps>
+ZigbeeStack::GetAps() const
+{
+    return m_aps;
+}
+
+void
+ZigbeeStack::SetAps(Ptr<zigbee::ZigbeeAps> aps)
+{
+    NS_LOG_FUNCTION(this);
+    NS_ABORT_MSG_IF(ZigbeeStack::IsInitialized(), "APS layer cannot be set after initialization");
+    m_aps = aps;
+}
+
 } // namespace zigbee
 } // namespace ns3
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/model/zigbee-stack.h ns-3.46/src/zigbee/model/zigbee-stack.h
--- ns-3.45/src/zigbee/model/zigbee-stack.h	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/model/zigbee-stack.h	2025-10-01 18:46:32.000000000 -0700
@@ -10,6 +10,8 @@
 #ifndef ZIGBEE_STACK_H
 #define ZIGBEE_STACK_H
 
+#include "zigbee-aps.h"
+#include "zigbee-group-table.h"
 #include "zigbee-nwk.h"
 
 #include "ns3/lr-wpan-mac-base.h"
@@ -17,7 +19,6 @@
 #include "ns3/traced-callback.h"
 
 #include <stdint.h>
-#include <string>
 
 namespace ns3
 {
@@ -28,6 +29,7 @@
 {
 
 class ZigbeeNwk;
+class ZigbeeAps;
 
 /**
  * @ingroup zigbee
@@ -85,6 +87,20 @@
     void SetNwk(Ptr<ZigbeeNwk> nwk);
 
     /**
+     * Get the APS layer used by this ZigbeeStack.
+     *
+     * @return the APS object
+     */
+    Ptr<ZigbeeAps> GetAps() const;
+
+    /**
+     * Set the APS layer used by this ZigbeeStack.
+     *
+     * @param aps The APS layer object
+     */
+    void SetAps(Ptr<ZigbeeAps> aps);
+
+    /**
      *  Returns a smart pointer to the underlying NetDevice.
      *
      * @return A smart pointer to the underlying NetDevice.
@@ -100,6 +116,11 @@
      */
     void SetNetDevice(Ptr<NetDevice> netDevice);
 
+    /**
+     * Inticates to the Zigbee stack that only the NWK layer should be present.
+     */
+    void SetOnlyNwkLayer();
+
   protected:
     /**
      * Dispose of the Objects used by the ZigbeeStack
@@ -114,8 +135,11 @@
   private:
     Ptr<lrwpan::LrWpanMacBase> m_mac; //!< The underlying LrWpan MAC connected to this Zigbee Stack.
     Ptr<ZigbeeNwk> m_nwk;             //!< The Zigbee Network layer.
-    Ptr<Node> m_node;                 //!< The node associated with this NetDevice.
-    Ptr<NetDevice> m_netDevice;       //!< Smart pointer to the underlying NetDevice.
+    Ptr<ZigbeeAps> m_aps;             //!< The Zigbee Application Support Sub-layer
+    Ptr<ZigbeeGroupTable> m_groupTable; //!< The Zigbee Group Table used by both NWK and APS layers.
+    Ptr<Node> m_node;                   //!< The node associated with this NetDevice.
+    Ptr<NetDevice> m_netDevice;         //!< Smart pointer to the underlying NetDevice.
+    bool m_nwkOnly; //!< Indicates that only the NWK layer is present in the Zigbee stack
 };
 
 } // namespace zigbee
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/test/zigbee-aps-data-test.cc ns-3.46/src/zigbee/test/zigbee-aps-data-test.cc
--- ns-3.45/src/zigbee/test/zigbee-aps-data-test.cc	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/src/zigbee/test/zigbee-aps-data-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2025 Tokushima University, Tokushima, Japan
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Author:
+ *  Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
+ */
+
+#include "ns3/constant-position-mobility-model.h"
+#include "ns3/core-module.h"
+#include "ns3/log.h"
+#include "ns3/lr-wpan-module.h"
+#include "ns3/packet.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/rng-seed-manager.h"
+#include "ns3/simulator.h"
+#include "ns3/single-model-spectrum-channel.h"
+#include "ns3/zigbee-module.h"
+
+#include <iomanip>
+#include <iostream>
+
+using namespace ns3;
+using namespace ns3::lrwpan;
+using namespace ns3::zigbee;
+
+NS_LOG_COMPONENT_DEFINE("zigbee-aps-data-test");
+
+/**
+ * @ingroup zigbee-test
+ * @ingroup tests
+ *
+ * Zigbee RREQ transmission retries test case
+ */
+class ZigbeeApsDataTestCase : public TestCase
+{
+  public:
+    ZigbeeApsDataTestCase();
+    ~ZigbeeApsDataTestCase() override;
+
+  private:
+    /**
+     * Callback for APSDE-DATA.indication
+     * This callback is called when a data packet is received by the APS layer.
+     *
+     * @param testcase The ZigbeeApsDataTestCase instance
+     * @param stack The Zigbee stack that received the data
+     * @param params The parameters of the APSDE-DATA.indication
+     * @param asdu The received packet
+     */
+    static void ApsDataIndication(ZigbeeApsDataTestCase* testcase,
+                                  Ptr<ZigbeeStack> stack,
+                                  ApsdeDataIndicationParams params,
+                                  Ptr<Packet> asdu);
+
+    /**
+     * Callback for NLME-NETWORK-DISCOVERY.confirm
+     * This callback is called when a network discovery has been performed.
+     *
+     * @param testcase The ZigbeeApsDataTestCase instance
+     * @param stack The Zigbee stack that received the confirmation
+     * @param params The parameters of the NLME-NETWORK-DISCOVERY.confirm
+     */
+    static void NwkNetworkDiscoveryConfirm(ZigbeeApsDataTestCase* testcase,
+                                           Ptr<ZigbeeStack> stack,
+                                           NlmeNetworkDiscoveryConfirmParams params);
+
+    /**
+     * Send data to a unicast destination.
+     * This function sends a data packet from stackSrc to stackDst.
+     *
+     * @param stackSrc The source Zigbee stack
+     * @param stackDst The destination Zigbee stack
+     */
+    static void SendDataUcstDst(Ptr<ZigbeeStack> stackSrc, Ptr<ZigbeeStack> stackDst);
+
+    void DoRun() override;
+
+    uint16_t m_dstEndpoint; //!< The destination endpoint
+};
+
+ZigbeeApsDataTestCase::ZigbeeApsDataTestCase()
+    : TestCase("Zigbee: APS layer data test")
+{
+    m_dstEndpoint = 0;
+}
+
+ZigbeeApsDataTestCase::~ZigbeeApsDataTestCase()
+{
+}
+
+void
+ZigbeeApsDataTestCase::ApsDataIndication(ZigbeeApsDataTestCase* testcase,
+                                         Ptr<ZigbeeStack> stack,
+                                         ApsdeDataIndicationParams params,
+                                         Ptr<Packet> asdu)
+{
+    testcase->m_dstEndpoint = params.m_dstEndPoint;
+}
+
+void
+ZigbeeApsDataTestCase::NwkNetworkDiscoveryConfirm(ZigbeeApsDataTestCase* testcase,
+                                                  Ptr<ZigbeeStack> stack,
+                                                  NlmeNetworkDiscoveryConfirmParams params)
+{
+    if (params.m_status == NwkStatus::SUCCESS)
+    {
+        NlmeJoinRequestParams joinParams;
+
+        zigbee::CapabilityInformation capaInfo;
+        capaInfo.SetDeviceType(MacDeviceType::ENDDEVICE);
+        capaInfo.SetAllocateAddrOn(true);
+
+        joinParams.m_rejoinNetwork = JoiningMethod::ASSOCIATION;
+        joinParams.m_capabilityInfo = capaInfo.GetCapability();
+        joinParams.m_extendedPanId = params.m_netDescList[0].m_extPanId;
+
+        Simulator::ScheduleNow(&ZigbeeNwk::NlmeJoinRequest, stack->GetNwk(), joinParams);
+    }
+    else
+    {
+        NS_ABORT_MSG("Unable to discover networks | status: " << params.m_status);
+    }
+}
+
+void
+ZigbeeApsDataTestCase::SendDataUcstDst(Ptr<ZigbeeStack> stackSrc, Ptr<ZigbeeStack> stackDst)
+{
+    // UCST transmission to a single 16-bit address destination
+    // Data is transmitted from device stackSrc to device stackDst.
+
+    Ptr<Packet> p = Create<Packet>(5);
+
+    // Because we currently do not have ZDO or ZCL or AF, clusterId
+    // and profileId numbers are non-sensical.
+    ApsdeDataRequestParams dataReqParams;
+    // creates a BitMap with transmission options
+    // Default, use 16 bit address destination (No option), equivalent to bitmap 0x00
+    ZigbeeApsTxOptions txOptions;
+    dataReqParams.m_txOptions = txOptions.GetTxOptions();
+    dataReqParams.m_useAlias = false;
+    dataReqParams.m_srcEndPoint = 3;
+    dataReqParams.m_clusterId = 5; // Arbitrary value
+    dataReqParams.m_profileId = 2; // Arbitrary value
+    dataReqParams.m_dstAddrMode = ApsDstAddressMode::DST_ADDR16_DST_ENDPOINT_PRESENT;
+    dataReqParams.m_dstAddr16 = stackDst->GetNwk()->GetNetworkAddress();
+    dataReqParams.m_dstEndPoint = 4;
+
+    Simulator::ScheduleNow(&ZigbeeAps::ApsdeDataRequest, stackSrc->GetAps(), dataReqParams, p);
+}
+
+void
+ZigbeeApsDataTestCase::DoRun()
+{
+    // Transmit data using the APS layer.
+
+    // Zigbee Coordinator --------------> Zigbee EndDevice(destination endpoint:4)
+
+    // This test transmit a single packet to an enddevice with endpoint 4.
+    // The data transmission is done using the mode DST_ADDR16_DST_ENDPOINT_PRESENT (Mode 0x02).
+    // No fragmentations or Acknowledge is used
+    // Verification that the devices have join the network is performed
+    // (i.e., All devices have valid network addresses).
+
+    RngSeedManager::SetSeed(3);
+    RngSeedManager::SetRun(4);
+
+    NodeContainer nodes;
+    nodes.Create(3);
+
+    //// Add the PHY and MAC, configure the channel
+
+    LrWpanHelper lrWpanHelper;
+    NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(nodes);
+    Ptr<LrWpanNetDevice> dev0 = lrwpanDevices.Get(0)->GetObject<LrWpanNetDevice>();
+    Ptr<LrWpanNetDevice> dev1 = lrwpanDevices.Get(1)->GetObject<LrWpanNetDevice>();
+    Ptr<LrWpanNetDevice> dev2 = lrwpanDevices.Get(2)->GetObject<LrWpanNetDevice>();
+
+    dev0->GetMac()->SetExtendedAddress("00:00:00:00:00:00:CA:FE");
+    dev1->GetMac()->SetExtendedAddress("00:00:00:00:00:00:00:01");
+    dev2->GetMac()->SetExtendedAddress("00:00:00:00:00:00:00:02");
+
+    Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel>();
+    Ptr<LogDistancePropagationLossModel> propModel =
+        CreateObject<LogDistancePropagationLossModel>();
+
+    Ptr<ConstantSpeedPropagationDelayModel> delayModel =
+        CreateObject<ConstantSpeedPropagationDelayModel>();
+
+    channel->AddPropagationLossModel(propModel);
+    channel->SetPropagationDelayModel(delayModel);
+
+    dev0->SetChannel(channel);
+    dev1->SetChannel(channel);
+    dev2->SetChannel(channel);
+
+    // Add Zigbee stack with  NWK and APS
+
+    ZigbeeHelper zigbeeHelper;
+    ZigbeeStackContainer zigbeeStackContainer = zigbeeHelper.Install(lrwpanDevices);
+
+    Ptr<ZigbeeStack> zstack0 = zigbeeStackContainer.Get(0)->GetObject<ZigbeeStack>();
+    Ptr<ZigbeeStack> zstack1 = zigbeeStackContainer.Get(1)->GetObject<ZigbeeStack>();
+    Ptr<ZigbeeStack> zstack2 = zigbeeStackContainer.Get(2)->GetObject<ZigbeeStack>();
+
+    // reprodusable results from random events occurring inside the stack.
+    zstack0->GetNwk()->AssignStreams(0);
+    zstack1->GetNwk()->AssignStreams(10);
+    zstack2->GetNwk()->AssignStreams(20);
+
+    //// Configure Nodes Mobility
+
+    Ptr<ConstantPositionMobilityModel> dev0Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev0Mobility->SetPosition(Vector(0, 0, 0));
+    dev0->GetPhy()->SetMobility(dev0Mobility);
+
+    Ptr<ConstantPositionMobilityModel> dev1Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev1Mobility->SetPosition(Vector(50, 0, 0));
+    dev1->GetPhy()->SetMobility(dev1Mobility);
+
+    Ptr<ConstantPositionMobilityModel> dev2Mobility = CreateObject<ConstantPositionMobilityModel>();
+    dev2Mobility->SetPosition(Vector(0, 50, 0));
+    dev2->GetPhy()->SetMobility(dev2Mobility);
+
+    // Configure APS hooks
+    zstack1->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, this, zstack1));
+
+    zstack2->GetAps()->SetApsdeDataIndicationCallback(
+        MakeBoundCallback(&ApsDataIndication, this, zstack2));
+
+    // Configure NWK hooks
+    // We do not have ZDO, we are required to use the NWK
+    // directly to perform association.
+    zstack1->GetNwk()->SetNlmeNetworkDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkNetworkDiscoveryConfirm, this, zstack1));
+    zstack2->GetNwk()->SetNlmeNetworkDiscoveryConfirmCallback(
+        MakeBoundCallback(&NwkNetworkDiscoveryConfirm, this, zstack2));
+
+    // Configure NWK hooks (for managing Network Joining)
+
+    // 1 - Initiate the Zigbee coordinator on a channel
+    NlmeNetworkFormationRequestParams netFormParams;
+    netFormParams.m_scanChannelList.channelPageCount = 1;
+    netFormParams.m_scanChannelList.channelsField[0] = 0x00001800; // BitMap: channel 11 and 12
+    netFormParams.m_scanDuration = 0;
+    netFormParams.m_superFrameOrder = 15;
+    netFormParams.m_beaconOrder = 15;
+
+    Simulator::ScheduleWithContext(zstack0->GetNode()->GetId(),
+                                   Seconds(1),
+                                   &ZigbeeNwk::NlmeNetworkFormationRequest,
+                                   zstack0->GetNwk(),
+                                   netFormParams);
+
+    NlmeNetworkDiscoveryRequestParams netDiscParams;
+    netDiscParams.m_scanChannelList.channelPageCount = 1;
+    netDiscParams.m_scanChannelList.channelsField[0] = 0x00000800; // BitMap: Channels 11
+    netDiscParams.m_scanDuration = 2;
+    Simulator::ScheduleWithContext(zstack1->GetNode()->GetId(),
+                                   Seconds(2),
+                                   &ZigbeeNwk::NlmeNetworkDiscoveryRequest,
+                                   zstack1->GetNwk(),
+                                   netDiscParams);
+
+    NlmeNetworkDiscoveryRequestParams netDiscParams2;
+    netDiscParams.m_scanChannelList.channelPageCount = 1;
+    netDiscParams.m_scanChannelList.channelsField[0] = 0x00000800; // BitMap: Channels 11~14
+    netDiscParams.m_scanDuration = 2;
+    Simulator::ScheduleWithContext(zstack2->GetNode()->GetId(),
+                                   Seconds(3),
+                                   &ZigbeeNwk::NlmeNetworkDiscoveryRequest,
+                                   zstack2->GetNwk(),
+                                   netDiscParams2);
+
+    // Send data to a single UCST destination (16-bit address)
+    // The destination address is unknown until compilation, we extract
+    // it from the stack directly.
+    Simulator::Schedule(Seconds(4), &SendDataUcstDst, zstack0, zstack2);
+
+    Simulator::Run();
+
+    // Check that devices actually joined the network and have different 16-bit addresses.
+
+    NS_TEST_EXPECT_MSG_NE(zstack1->GetNwk()->GetNetworkAddress(),
+                          Mac16Address("FF:FF"),
+                          "The dev 1 was unable to join the network");
+
+    NS_TEST_EXPECT_MSG_NE(zstack2->GetNwk()->GetNetworkAddress(),
+                          Mac16Address("FF:FF"),
+                          "The dev 1 was unable to join the network");
+
+    NS_TEST_EXPECT_MSG_NE(zstack0->GetNwk()->GetNetworkAddress(),
+                          zstack1->GetNwk()->GetNetworkAddress(),
+                          "Error, devices 0 and 1 have the same 16 bit MAC address");
+
+    NS_TEST_EXPECT_MSG_NE(zstack1->GetNwk()->GetNetworkAddress(),
+                          zstack2->GetNwk()->GetNetworkAddress(),
+                          "Error, devices 1 and 2 have the same 16 bit MAC address");
+
+    // Check that the packet was received to the correct preconfigured destination endpoint.
+
+    NS_TEST_EXPECT_MSG_EQ(m_dstEndpoint,
+                          4,
+                          "Packet was not received in the correct destination endpoint");
+
+    zstack1->GetAps()->SetApsdeDataIndicationCallback(
+        MakeNullCallback<void, ApsdeDataIndicationParams, Ptr<Packet>>());
+    zstack2->GetAps()->SetApsdeDataIndicationCallback(
+        MakeNullCallback<void, ApsdeDataIndicationParams, Ptr<Packet>>());
+    Simulator::Destroy();
+}
+
+/**
+ * @ingroup zigbee-test
+ * @ingroup tests
+ *
+ * Zigbee APS Data TestSuite
+ */
+class ZigbeeApsDataTestSuite : public TestSuite
+{
+  public:
+    ZigbeeApsDataTestSuite();
+};
+
+ZigbeeApsDataTestSuite::ZigbeeApsDataTestSuite()
+    : TestSuite("zigbee-aps-data-test", Type::UNIT)
+{
+    AddTestCase(new ZigbeeApsDataTestCase, TestCase::Duration::QUICK);
+}
+
+static ZigbeeApsDataTestSuite zigbeeApsDataTestSuite; //!< Static variable for test initialization
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/src/zigbee/test/zigbee-rreq-test.cc ns-3.46/src/zigbee/test/zigbee-rreq-test.cc
--- ns-3.45/src/zigbee/test/zigbee-rreq-test.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/src/zigbee/test/zigbee-rreq-test.cc	2025-10-01 18:46:32.000000000 -0700
@@ -238,6 +238,7 @@
     //// Configure NWK
 
     ZigbeeHelper zigbee;
+    zigbee.SetNwkLayerOnly();
     ZigbeeStackContainer zigbeeStackContainer = zigbee.Install(lrwpanDevices);
 
     Ptr<ZigbeeStack> zstack0 = zigbeeStackContainer.Get(0)->GetObject<ZigbeeStack>();
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/test.py ns-3.46/test.py
--- ns-3.45/test.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/test.py	2025-10-01 18:46:32.000000000 -0700
@@ -8,6 +8,7 @@
 import fnmatch
 import os
 import queue
+import re
 import shutil
 import signal
 import subprocess
@@ -1248,7 +1249,7 @@
         # user wants to run everything.
         #
         if len(args.example):
-            build_cmd = "./ns3 build %s" % os.path.basename(args.example)
+            build_cmd = "./ns3 build %s" % os.path.basename(args.example.replace("*", ""))
         else:
             build_cmd = "./ns3"
 
@@ -1407,8 +1408,8 @@
                 standard_out = standard_out.decode()
             list_items = standard_out.split("\n")
             list_items.sort()
-        print("Test Type    Test Name")
-        print("---------    ---------")
+        print("Test Type            Test Name")
+        print("---------------      ---------")
         for item in list_items:
             if len(item.strip()):
                 print(item)
@@ -1424,7 +1425,7 @@
             python_examples_sorted.sort()
             examples_sorted.extend(python_examples_sorted)
         for item in examples_sorted:
-            print("example     ", item)
+            print("example             ", item)
         print()
 
     if args.kinds or args.list:
@@ -1656,11 +1657,15 @@
                 multiple = ""
             else:
                 multiple = " --stop-on-failure"
-            if len(args.fullness):
-                fullness = args.fullness.upper()
-                fullness = " --fullness=%s" % fullness
-            else:
-                fullness = " --fullness=QUICK"
+
+            if args.fullness:
+                if len(args.fullness):
+                    fullness = args.fullness.upper()
+                    fullness = " --fullness=%s" % fullness
+                else:
+                    fullness = " --fullness=QUICK"
+            elif args.only_fullness:
+                fullness = " --only-fullness=%s" % args.only_fullness.upper()
 
             path_cmd = os.path.join(
                 "utils", test_runner_name + " --test-name=%s%s%s" % (test, multiple, fullness)
@@ -1710,14 +1715,51 @@
     #  ./test.py:                                           run all of the examples
     #  ./test.py --constrain=unit                           run no examples
     #  ./test.py --constrain=example                        run all of the examples
-    #  ./test.py --suite=some-test-suite:                   run no examples
-    #  ./test.py --example=some-example:                    run the single example
-    #  ./test.py --suite=some-suite --example=some-example: run the single example
+    #  ./test.py --suite=some-test-suite                    run no examples
+    #  ./test.py --example=some-example                     run the single example with no parameters
+    #  ./test.py --example="some-example --args=2"          run the single example with custom parameters
+    #  ./test.py --example=some-example*                    run the all examples-to-run.py instances with said example
+    #  ./test.py --suite=some-suite --example=some-example  run the single example
     #
     #
-    if len(args.suite) == 0 and len(args.example) == 0 and len(args.pyexample) == 0:
+    if len(args.suite) == 0 and len(args.pyexample) == 0:
         if len(args.constrain) == 0 or args.constrain == "example":
             if ENABLE_EXAMPLES:
+                if args.example:
+                    if args.example.endswith("*"):
+                        # If an example name is passed without arguments, we filter all examples containing said program
+                        example_tests = list(
+                            filter(lambda x: args.example[:-1] in x[0], example_tests)
+                        )
+                        args.example_args = []
+                    else:
+                        example_tests = list(
+                            filter(
+                                lambda x: " ".join([args.example, *args.example_args])
+                                == x[0].split("/")[-1],
+                                example_tests,
+                            )
+                        )
+                        args.example_args = []
+
+                    if not example_tests or args.example_args:
+                        # If an example name is passed with arguments, we create an example entry for said example
+                        example_name = " ".join([args.example, *args.example_args])
+                        example_path = "%s%s-%s%s" % (
+                            APPNAME,
+                            VERSION,
+                            args.example,
+                            BUILD_PROFILE_SUFFIX,
+                        )
+                        if example_path in ns3_runnable_programs_dictionary:
+                            example_path = ns3_runnable_programs_dictionary[example_path]
+                            example_path += ".exe" if sys.platform == "win32" else ""
+                            example_path = " ".join([example_path, *args.example_args])
+                            example_tests = [(example_name, example_path, "True", "True", "QUICK")]
+                        else:
+                            print("No example matching the name %s" % example_name)
+                            example_tests = []
+
                 for name, test, do_run, do_valgrind_run, fullness in example_tests:
                     # Remove any arguments and directory names from test.
                     test_name = test.split(" ", 1)[0]
@@ -1772,44 +1814,6 @@
                             jobs = jobs + 1
                             total_tests = total_tests + 1
 
-    elif len(args.example):
-        # Add the proper prefix and suffix to the example name to
-        # match what is done in the CMakeLists.txt file.
-        example_name = "%s%s-%s%s" % (APPNAME, VERSION, args.example, BUILD_PROFILE_SUFFIX)
-
-        key_list = []
-        for key in ns3_runnable_programs_dictionary:
-            key_list.append(key)
-        example_name_key_list = fnmatch.filter(key_list, example_name)
-
-        if len(example_name_key_list) == 0:
-            print("No example matching the name %s" % args.example)
-        else:
-            #
-            # If you tell me to run an example, I will try and run the example
-            # irrespective of any condition.
-            #
-            for example_name_iter in example_name_key_list:
-                example_path = ns3_runnable_programs_dictionary[example_name_iter]
-                example_path = os.path.abspath(example_path)
-                job = Job()
-                job.set_is_example(True)
-                job.set_is_pyexample(False)
-                job.set_display_name(example_path)
-                job.set_tmp_file_name("")
-                job.set_cwd(testpy_output_dir)
-                job.set_basedir(os.getcwd())
-                job.set_tempdir(testpy_output_dir)
-                job.set_shell_command(example_path)
-                job.set_build_path(args.buildpath)
-
-                if args.verbose:
-                    print("Queue %s" % example_name_iter)
-
-                input_queue.put(job)
-                jobs = jobs + 1
-                total_tests = total_tests + 1
-
     #
     # Run some Python examples as smoke tests.  We have a list of all of
     # the example programs it makes sense to try and run.  Each example will
@@ -1994,7 +1998,7 @@
                 status = "CRASH"
                 status_print = colors.PINK + status + colors.NORMAL
 
-        print("[%d/%d] %s" % (i, total_tests, status_print), end="")
+        print("[%d/%d] %s" % (i + 1, total_tests, status_print), end="")
 
         if args.duration or args.constrain == "performance":
             print(" (%.3f)" % job.elapsed_time, end="")
@@ -2237,6 +2241,17 @@
         return 1  # catchall for general errors
 
 
+def split_program_and_arguments(argv):
+    split_argv = re.findall(r'(?:".*[|*]?"|\S)+', argv)
+    program = ""
+    program_args = []
+    if split_argv:
+        program = split_argv[0]
+    if len(split_argv) > 1:
+        program_args = split_argv[1:]
+    return program, program_args
+
+
 def main(argv):
     parser = argparse.ArgumentParser()
     parser.add_argument(
@@ -2281,8 +2296,9 @@
         default=False,
         help="If examples use reference data files, get them to re-generate them",
     )
+    fullness_group = parser.add_mutually_exclusive_group(required=False)
 
-    parser.add_argument(
+    fullness_group.add_argument(
         "-f",
         "--fullness",
         action="store",
@@ -2292,6 +2308,16 @@
         help="choose the duration of tests to run: QUICK, EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE includes QUICK and TAKES_FOREVER includes QUICK and EXTENSIVE (only QUICK tests are run by default)",
     )
 
+    fullness_group.add_argument(
+        "-of",
+        "--only-fullness",
+        action="store",
+        type=str,
+        default=None,
+        choices=["QUICK", "EXTENSIVE", "TAKES_FOREVER"],
+        help="choose the duration of tests to run: QUICK, EXTENSIVE, or TAKES_FOREVER (only tests marked with fullness will be executed)",
+    )
+
     parser.add_argument(
         "-g",
         "--grind",
@@ -2428,6 +2454,8 @@
 
     global args
     args = parser.parse_args()
+    args.example, exargs = split_program_and_arguments(args.example)
+    setattr(args, "example_args", exargs)
     signal.signal(signal.SIGINT, sigint_hook)
 
     # From waf/waflib/Options.py
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/bench-packets.cc ns-3.46/utils/bench-packets.cc
--- ns-3.45/utils/bench-packets.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/bench-packets.cc	2025-10-01 18:46:32.000000000 -0700
@@ -16,10 +16,10 @@
 #include "ns3/system-wall-clock-ms.h"
 
 #include <algorithm>
+#include <cstdlib> // for exit ()
 #include <iostream>
 #include <limits>
 #include <sstream>
-#include <stdlib.h> // for exit ()
 #include <string>
 
 using namespace ns3;
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/check-style-clang-format.py ns-3.46/utils/check-style-clang-format.py
--- ns-3.45/utils/check-style-clang-format.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/check-style-clang-format.py	2025-10-01 18:46:32.000000000 -0700
@@ -41,8 +41,8 @@
 ###########################################################
 # PARAMETERS
 ###########################################################
-CLANG_FORMAT_MAX_VERSION = 19
-CLANG_FORMAT_MIN_VERSION = 15
+CLANG_FORMAT_MAX_VERSION = 20
+CLANG_FORMAT_MIN_VERSION = 20
 
 FORMAT_GUARD_ON = [
     "// clang-format on",
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/codespell-ignored-lines ns-3.46/utils/codespell-ignored-lines
--- ns-3.45/utils/codespell-ignored-lines	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/codespell-ignored-lines	2025-10-01 18:46:32.000000000 -0700
@@ -82,6 +82,7 @@
  * Copyright (c) 2022 Universita' degli Studi di Napoli "Federico II"
  * Copyright (c) 2023 Universita' degli Studi di Napoli Federico II
  * Copyright (c) 2024 Universita' degli Studi di Napoli Federico II
+ * Copyright (c) 2025 Universita' degli Studi di Napoli Federico II
 
 ./src/core/examples/hash-example.cc
 6ed21de2  brand-newness       peripherial
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/print-introspected-doxygen.cc ns-3.46/utils/print-introspected-doxygen.cc
--- ns-3.45/utils/print-introspected-doxygen.cc	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/print-introspected-doxygen.cc	2025-10-01 18:46:32.000000000 -0700
@@ -44,27 +44,33 @@
  * Markup tokens.
  * @{
  */
-std::string anchor;        ///< hyperlink anchor
-std::string argument;      ///< function argument
-std::string boldStart;     ///< start of bold span
-std::string boldStop;      ///< end of bold span
-std::string breakBoth;     ///< linebreak
-std::string breakHtmlOnly; ///< linebreak for html output only
-std::string breakTextOnly; ///< linebreak for text output only
-std::string brief;         ///< brief tag
-std::string classStart;    ///< start of a class
-std::string classStop;     ///< end of a class
-std::string codeWord;      ///< format next word as source code
-std::string commentStart;  ///< start of code comment
-std::string commentStop;   ///< end of code comment
-std::string copyDoc;       ///< copy (or refer) to docs elsewhere
-std::string file;          ///< file
-std::string flagSpanStart; ///< start of Attribute flag value
-std::string flagSpanStop;  ///< end of Attribute flag value
-std::string functionStart; ///< start of a method/function
-std::string functionStop;  ///< end of a method/function
-std::string headingStart;  ///< start of section heading (h3)
-std::string headingStop;   ///< end of section heading (h3)
+std::string anchor;             ///< hyperlink anchor
+std::string argument;           ///< function argument
+std::string boldStart;          ///< start of bold span
+std::string boldStop;           ///< end of bold span
+std::string boldWithIdStart;    ///< start of bold with id
+std::string boldWithIdMid;      ///< middle of bold span with id
+std::string boldWithIdStop;     ///< end of bold span with id
+std::string breakBoth;          ///< linebreak
+std::string breakHtmlOnly;      ///< linebreak for html output only
+std::string breakTextOnly;      ///< linebreak for text output only
+std::string brief;              ///< brief tag
+std::string classStart;         ///< start of a class
+std::string classStop;          ///< end of a class
+std::string codeWord;           ///< format next word as source code
+std::string commentStart;       ///< start of code comment
+std::string commentStop;        ///< end of code comment
+std::string copyDoc;            ///< copy (or refer) to docs elsewhere
+std::string file;               ///< file
+std::string flagSpanStart;      ///< start of Attribute flag value
+std::string flagSpanStop;       ///< end of Attribute flag value
+std::string functionStart;      ///< start of a method/function
+std::string functionStop;       ///< end of a method/function
+std::string headingStart;       ///< start of section heading (h3)
+std::string headingStop;        ///< end of section heading (h3)
+std::string headingWithIdStart; ///< start of section heading with id (h3)
+std::string headingWithIdMid;   ///< middle of section heading with id (h3)
+std::string headingWithIdStop;  ///< end of section heading with id (h3)
 // Linking:  [The link text displayed](\ref TheTarget)
 std::string hrefStart;        ///< start of a link
 std::string hrefMid;          ///< middle part of a link
@@ -81,6 +87,9 @@
 std::string returns;          ///< the return value
 std::string sectionStart;     ///< start of a section or group
 std::string seeAlso;          ///< Reference to other docs
+std::string spanWithIdStart;  ///< start of span with id
+std::string spanWithIdMid;    ///< middle of span with id
+std::string spanWithIdStop;   ///< end of span with id
 std::string subSectionStart;  ///< start a new subsection
 std::string templArgDeduced;  ///< template argument deduced from function
 std::string templArgExplicit; ///< template argument required
@@ -124,6 +133,54 @@
     return index;
 }
 
+/**
+ * Generate bold (b) HTML markup with id if not generating text only.
+ * @param id The element id
+ * @param displayText The text to display
+ * @return The bold markup with id or just displayText if outputText is true
+ */
+std::string
+BoldWithId(const std::string id, const std::string displayText)
+{
+    if (outputText)
+    {
+        return displayText + " ";
+    }
+    return boldWithIdStart + id + boldWithIdMid + displayText + boldWithIdStop + " ";
+}
+
+/**
+ * Generate heading (h3) markup with id if not generating text only.
+ * @param id The element id
+ * @param displayText The text to display
+ * @return The heading markup with id or just displayText if outputText is true
+ */
+std::string
+HeadingWithId(const std::string id, const std::string displayText)
+{
+    if (outputText)
+    {
+        return displayText + " ";
+    }
+    return headingWithIdStart + id + headingWithIdMid + displayText + headingWithIdStop;
+}
+
+/**
+ * Generate span (span) HTML markup with id if not generating text only.
+ * @param id The element id
+ * @param displayText The text to display
+ * @return The span markup with id or just displayText if outputText is true
+ */
+std::string
+SpanWithId(const std::string id, const std::string displayText)
+{
+    if (outputText)
+    {
+        return displayText + " ";
+    }
+    return spanWithIdStart + id + spanWithIdMid + displayText + spanWithIdStop + " ";
+}
+
 } // unnamed namespace
 
 /**
@@ -139,6 +196,9 @@
         argument = "  Arg: ";
         boldStart = "";
         boldStop = "";
+        boldWithIdStart = "";
+        boldWithIdMid = "";
+        boldWithIdStop = "";
         breakBoth = "\n";
         breakHtmlOnly = "";
         breakTextOnly = "\n";
@@ -156,6 +216,9 @@
         functionStop = "\n\n";
         headingStart = "";
         headingStop = "";
+        headingWithIdStart = "";
+        headingWithIdMid = "";
+        headingWithIdStop = "";
         // Linking:  The link text displayed (see TheTarget)
         hrefStart = "";
         hrefMid = " (see ";
@@ -172,6 +235,9 @@
         returns = "  Returns: ";
         sectionStart = "Section:  ";
         seeAlso = "  See: ";
+        spanWithIdStart = "";
+        spanWithIdMid = "";
+        spanWithIdStop = "";
         subSectionStart = "Subsection ";
         templArgDeduced = "[deduced]  ";
         templArgExplicit = "[explicit] ";
@@ -184,6 +250,9 @@
         argument = "\\param ";
         boldStart = "<b>";
         boldStop = "</b>";
+        boldWithIdStart = "<b id=\"";
+        boldWithIdMid = "\">";
+        boldWithIdStop = "</b>";
         breakBoth = "<br>";
         breakHtmlOnly = "<br>";
         breakTextOnly = "";
@@ -201,6 +270,9 @@
         functionStop = "";
         headingStart = "<h3>";
         headingStop = "</h3>";
+        headingWithIdStart = "<h3 id=\"";
+        headingWithIdMid = "\">";
+        headingWithIdStop = "</h3>";
         // Linking:  [The link text displayed](\ref TheTarget)
         hrefStart = "[";
         hrefMid = "](\\ref ";
@@ -217,6 +289,9 @@
         returns = "\\returns ";
         sectionStart = "\\ingroup ";
         seeAlso = "\\see ";
+        spanWithIdStart = "<span id=\"";
+        spanWithIdMid = "\">";
+        spanWithIdStop = "</span>";
         subSectionStart = "\\addtogroup ";
         templArgDeduced = "\\deduced ";
         templArgExplicit = "\\explicit ";
@@ -453,7 +528,6 @@
             TypeId pointee = ptrChecker->GetPointeeTypeId();
 
             // See if this is a pointer to an Object.
-            Ptr<Object> object = CreateObject<Object>();
             TypeId objectTypeId = Object::GetTypeId();
             if (objectTypeId == pointee)
             {
@@ -718,11 +792,12 @@
     // Config --------------
     if (paths.empty())
     {
-        os << "Introspection did not find any typical Config paths." << breakBoth << std::endl;
+        os << SpanWithId("config-paths", "Introspection did not find any typical Config paths")
+           << breakBoth << std::endl;
     }
     else
     {
-        os << headingStart << "Config Paths" << headingStop << std::endl;
+        os << HeadingWithId("config-paths", "Config Paths") << std::endl;
         os << std::endl;
         os << tid.GetName() << " is accessible through the following paths"
            << " with Config::Set and Config::Connect:" << std::endl;
@@ -863,11 +938,12 @@
     NS_LOG_FUNCTION(tid);
     if (tid.GetAttributeN() == 0)
     {
-        os << "No Attributes are defined for this type." << breakBoth << std::endl;
+        os << SpanWithId("attributes", "No Attributes are defined for this type") << breakBoth
+           << std::endl;
     }
     else
     {
-        os << headingStart << "Attributes" << headingStop << std::endl;
+        os << HeadingWithId("attributes", "Attributes") << std::endl;
         PrintAttributesTid(os, tid);
     }
 
@@ -936,11 +1012,12 @@
     NS_LOG_FUNCTION(tid);
     if (tid.GetTraceSourceN() == 0)
     {
-        os << "No TraceSources are defined for this type." << breakBoth << std::endl;
+        os << SpanWithId("trace-sources", "No TraceSources are defined for this type") << breakBoth
+           << std::endl;
     }
     else
     {
-        os << headingStart << "TraceSources" << headingStop << std::endl;
+        os << HeadingWithId("trace-sources", "TraceSources") << std::endl;
         PrintTraceSourcesTid(os, tid);
     }
 
@@ -973,8 +1050,8 @@
 
     std::size_t arch = (sizeof(void*) * CHAR_BIT);
 
-    os << boldStart << "Size" << boldStop << " of this type is " << tid.GetSize() << " bytes (on a "
-       << arch << "-bit architecture)." << std::endl;
+    os << BoldWithId("size", "Size") << "of this type is " << tid.GetSize() << " bytes (on a "
+       << arch << "-bit architecture)." << breakBoth << std::endl;
 } // PrintSize()
 
 /**
@@ -999,9 +1076,13 @@
     PrintAttributes(os, tid);
     PrintTraceSources(os, tid);
 
-    if (!tid.GetGroupName().empty())
+    if (tid.GetGroupName().empty())
+    {
+        os << SpanWithId("group", name + " does not belong to a group") << breakBoth << std::endl;
+    }
+    else
     {
-        os << boldStart << "Group:" << boldStop << " " << tid.GetGroupName() << "\n" << std::endl;
+        os << BoldWithId("group", "Group:") << tid.GetGroupName() << breakBoth << std::endl;
     }
 
     PrintSize(os, tid);
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-build.yml ns-3.46/utils/tests/gitlab-ci-build.yml
--- ns-3.45/utils/tests/gitlab-ci-build.yml	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/utils/tests/gitlab-ci-build.yml	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,58 @@
+# ns-3 CI/CD script with the platform tests stage
+#
+# Contains jobs to check the ns-3 build system and test script are fully working.
+
+# Base platform test job
+.test-platform-job-base:
+  stage: test
+  image: ubuntu:rolling
+  rules:
+    - if: $RELEASE == "weekly"
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+      when: manual
+      allow_failure: true
+  before_script:
+    - apt update
+    - DEBIAN_FRONTEND=noninteractive apt install -y
+      cmake ccache g++ ninja-build python3 python3-venv pkg-config python3-pip docker.io lldb gdb imagemagick git
+    - python3 -m venv ns3env
+    - source ./ns3env/bin/activate
+    - python3 -m pip install python_on_whales GitPython cppyy django requests
+  script:
+    - mkdir -p $CCACHE_BASEDIR_VALUE
+    - export CCACHE_BASEDIR=${PWD}
+    - export CCACHE_DIR=${PWD}/$CCACHE_BASEDIR_VALUE
+    - ccache -M 3G # Set maximum cache size to 3GB
+    - ccache -F 0 # Remove the limit on number of files in the cache
+    - ./$TEST_SCRIPT
+  cache:
+    # Use separate key for each (debug/default/optimized) jobs because
+    # they run in parallel and will otherwise overwrite each other
+    # cache when they upload the cache archive at the end of the job,
+    # resulting in only the cache for the last finished configuration
+    # being stored.
+    #
+    # Do not distinguish between branches though to avoid
+    # recompilation of all the files when a new branch is created.
+    key: "ccache-$CI_JOB_NAME"
+    paths:
+      - $CCACHE_BASEDIR_VALUE/
+  timeout: 24h
+  interruptible: true
+  variables:
+    CCACHE_BASEDIR_VALUE: ns-3-ccache-storage
+  tags:
+    - nsnam
+    - linux
+
+weekly-test-py:
+  extends: .test-platform-job-base
+  variables:
+    TEST_SCRIPT: ./utils/tests/test-test.py
+
+weekly-test-ns3-py:
+  extends: .test-platform-job-base
+  variables:
+    TEST_SCRIPT: ./utils/tests/test-ns3.py
+  services:
+    - docker:dind-rootless
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-clang.yml ns-3.46/utils/tests/gitlab-ci-clang.yml
--- ns-3.45/utils/tests/gitlab-ci-clang.yml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/gitlab-ci-clang.yml	2025-10-01 18:46:32.000000000 -0700
@@ -4,8 +4,8 @@
 # "RELEASE", that has a value "weekly". Also, a variable "CLANG" should be set
 # to True.
 
-# We support CLANG versions 11 through 18
-# We test only CLANG 11 on Ubuntu 20.04 and CLANG 18 on Ubuntu 24.04
+# We support CLANG versions 17 through 20
+# We test only CLANG 17 and CLANG 18 on Ubuntu 24.04
 
 .weekly-clang-ubuntu:
   extends: .base-build
@@ -18,6 +18,7 @@
     - apt upgrade -y
     - DEBIAN_FRONTEND=noninteractive apt install -y
       clang-$CLANG cmake ninja-build ccache build-essential
+      lld-$CLANG libc++-$CLANG-dev libc++abi-$CLANG-dev
       libboost-all-dev
       libeigen3-dev
       libgtk-3-0 libgtk-3-dev
@@ -28,13 +29,12 @@
   variables:
     COMPILER: clang++-$CLANG
 
-.weekly-clang-ubuntu20.04:
-  image: ubuntu:20.04
+.weekly-clang-ubuntu24.04:
+  image: ubuntu:24.04
   extends: .weekly-clang-ubuntu
   variables:
-    LIBGSL: libgsl23
+    LIBGSL: libgsl27
     EXTRA_PACKAGES: libstdc++-10-dev
-    EXTRA_OPTIONS: --disable-eigen
 
 .weekly-clang-ubuntu24.04:
   image: ubuntu:24.04
@@ -52,49 +52,49 @@
   script:
     - echo "Starting clang jobs"
 
-# CLANG 11
-weekly-build-clang-11-debug:
-  extends: .weekly-clang-ubuntu20.04
+# CLANG 17
+weekly-build-clang-17-debug:
+  extends: .weekly-clang-ubuntu24.04
   needs: ["weekly-clang"]
   stage: build
   variables:
-    CLANG: 11
+    CLANG: 17
     MODE: debug
 
-weekly-build-clang-11-default:
-  extends: .weekly-clang-ubuntu20.04
+weekly-build-clang-17-default:
+  extends: .weekly-clang-ubuntu24.04
   needs: ["weekly-clang"]
   stage: build
   variables:
-    CLANG: 11
+    CLANG: 17
     MODE: default
 
-weekly-build-clang-11-optimized:
-  extends: .weekly-clang-ubuntu20.04
+weekly-build-clang-17-optimized:
+  extends: .weekly-clang-ubuntu24.04
   needs: ["weekly-clang"]
   stage: build
   variables:
-    CLANG: 11
+    CLANG: 17
     MODE: optimized
 
-weekly-test-clang-11-default:
-  extends: .weekly-clang-ubuntu20.04
+weekly-test-clang-17-default:
+  extends: .weekly-clang-ubuntu24.04
   stage: test
-  needs: ["weekly-build-clang-11-default"]
+  needs: ["weekly-build-clang-17-default"]
   dependencies:
-    - weekly-build-clang-11-default
+    - weekly-build-clang-17-default
   variables:
-    CLANG: 11
+    CLANG: 17
     MODE: default
 
-weekly-test-clang-11-optimized:
-  extends: .weekly-clang-ubuntu20.04
+weekly-test-clang-17-optimized:
+  extends: .weekly-clang-ubuntu24.04
   stage: test
-  needs: ["weekly-build-clang-11-optimized"]
+  needs: ["weekly-build-clang-17-optimized"]
   dependencies:
-    - weekly-build-clang-11-optimized
+    - weekly-build-clang-17-optimized
   variables:
-    CLANG: 11
+    CLANG: 17
     MODE: optimized
 
 # CLANG 18
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-code-linting.yml ns-3.46/utils/tests/gitlab-ci-code-linting.yml
--- ns-3.45/utils/tests/gitlab-ci-code-linting.yml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/gitlab-ci-code-linting.yml	2025-10-01 18:46:32.000000000 -0700
@@ -2,9 +2,15 @@
 #
 # Contains jobs to check the ns-3 coding style and perform lint checking.
 
+# Common settings
+.code-linting-base:
+  stage: .pre
+  timeout: 1h
+  interruptible: true
+
 # Clang-format
 .check-style-clang-format:
-  stage: .pre
+  extends: .code-linting-base
   image: ubuntu:rolling
   before_script:
     - apt update
@@ -13,21 +19,20 @@
       clang-format-$CLANG_FORMAT_VERSION
   script:
     - python3 utils/check-style-clang-format.py --verbose .
-  timeout: 1h
-  interruptible: true
 
-check-style-clang-format-19:
+check-style-clang-format-20:
   extends: .check-style-clang-format
   variables:
-    CLANG_FORMAT_VERSION: 19
+    CLANG_FORMAT_VERSION: 20
 
-check-style-clang-format-15:
-  extends: .check-style-clang-format
-  variables:
-    CLANG_FORMAT_VERSION: 15
+# check-style-clang-format-21:
+#   extends: .check-style-clang-format
+#   variables:
+#     CLANG_FORMAT_VERSION: 21
 
 # Clang-tidy
-clang-tidy-19:
+clang-tidy-20:
+  extends: .code-linting-base
   stage: code-linting
   image: ubuntu:rolling
   variables:
@@ -38,7 +43,7 @@
     - apt update
     - DEBIAN_FRONTEND=noninteractive apt install -y
       clang cmake
-      clang-tidy clang-tidy-19
+      clang-tidy clang-tidy-20
       libboost-all-dev libeigen3-dev libgtk-3-dev libopenmpi-dev libsqlite3-dev
       gsl-bin libgsl-dev libgsl28
       git ssh
@@ -65,7 +70,7 @@
         echo "Running clang-tidy on the following changed files:";
         echo $FILES_TO_CHECK;
       fi
-    - run-clang-tidy-19 -p cmake-cache/ -quiet $FILES_TO_CHECK
+    - run-clang-tidy-20 -p cmake-cache/ -quiet $FILES_TO_CHECK
       1> $CLANG_TIDY_OUTPUT
       2> /dev/null
 
@@ -80,12 +85,11 @@
     paths:
       - $CLANG_TIDY_OUTPUT
     when: on_failure
-  interruptible: true
   timeout: 3h
 
 # Spell checking
 spell-check:
-  stage: .pre
+  extends: .code-linting-base
   image: python:latest
   before_script:
     - pip install codespell
@@ -99,12 +103,10 @@
     - git log --pretty=%B HEAD...upstream/$CI_DEFAULT_BRANCH ^upstream/$CI_DEFAULT_BRANCH > git_messages.txt
     # Check source code and commit messages
     - codespell -f -C0 ./
-  timeout: 1h
-  interruptible: true
 
 # Check cmake format
 cmake-format:
-  stage: .pre
+  extends: .code-linting-base
   image: python:latest
   before_script:
     - pip install pyyaml cmake cmake-format ninja
@@ -119,19 +121,15 @@
         echo "You might need to run \"./ns3 configure\" after installing it.";
         exit 1;
       fi
-  timeout: 1h
-  interruptible: true
 
 # Check Python format
 .python-format:
-  stage: .pre
+  extends: .code-linting-base
   before_script:
     - pip install black isort
   script:
     - black --check .
     - isort --check .
-  timeout: 1h
-  interruptible: true
 
 python-format-latest:
   extends: .python-format
@@ -143,9 +141,9 @@
 
 # Markdown lint
 markdown-lint:
-  stage: .pre
-  image: ruby:slim
+  extends: .code-linting-base
+  image: node:slim
   before_script:
-    - gem install mdl
+    - npm install -g markdownlint-cli
   script:
-    - mdl -s .mdl_style.rb .
+    - markdownlint .
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-cppyy.yml ns-3.46/utils/tests/gitlab-ci-cppyy.yml
--- ns-3.45/utils/tests/gitlab-ci-cppyy.yml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/gitlab-ci-cppyy.yml	2025-10-01 18:46:32.000000000 -0700
@@ -46,28 +46,6 @@
     - ./ns3 run ./utils/python-unit-tests.py
   timeout: 9h
 
-cppyy-20.04:
-  stage: test
-  image: ubuntu:20.04 # python 3.8
-  rules:
-    - if: $RELEASE == "manual"
-  before_script:
-    - apt update
-    - DEBIAN_FRONTEND=noninteractive apt install -y
-      g++ cmake ninja-build ccache
-      python3 python3-pip
-      libboost-dev libgsl-dev libgtk-3-dev
-      git wget
-    - pip install cppyy==3.1.2
-  script:
-    - ./ns3 configure -G Ninja --enable-python-bindings
-    - ./ns3 build
-    - ./ns3 run first.py
-    - ./ns3 run second.py
-    - ./ns3 run third.py
-    - ./ns3 run ./utils/python-unit-tests.py
-  timeout: 9h
-
 .manylinux-pip-wheel:
   stage: test
   image: quay.io/pypa/manylinux_2_28_x86_64
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-gcc.yml ns-3.46/utils/tests/gitlab-ci-gcc.yml
--- ns-3.45/utils/tests/gitlab-ci-gcc.yml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/gitlab-ci-gcc.yml	2025-10-01 18:46:32.000000000 -0700
@@ -50,8 +50,6 @@
   script:
     - echo "Starting GCC jobs"
 
-# GCC 10 (not tested here since it is configured for Ubuntu 20.04)
-
 # GCC 13
 weekly-build-gcc-13-debug:
   extends: .weekly-gcc-base
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-macos.yml ns-3.46/utils/tests/gitlab-ci-macos.yml
--- ns-3.45/utils/tests/gitlab-ci-macos.yml	1969-12-31 16:00:00.000000000 -0800
+++ ns-3.46/utils/tests/gitlab-ci-macos.yml	2025-10-01 18:46:32.000000000 -0700
@@ -0,0 +1,86 @@
+# Copyright (c) 2025 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+#
+# SPDX-License-Identifier: GPL-2.0-only
+# NS3 CI script for MacOS
+# Check if everything builds fine under debug, default, and optimized, on MacOS.
+
+.build-macos-base:
+  extends: .base-build
+  #tags:
+  #  - saas-macos-medium-m1
+  #  - saas-macos-large-m2pro
+  #image: macos-14-xcode-15
+  tags:
+    - macOS
+    - nsnam
+  before_script:
+    - brew update
+    - brew upgrade
+    - brew install ninja cmake ccache libxml2 eigen git
+  rules:
+    - if: $RELEASE == "weekly"
+    - if: $RELEASE == "daily"
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+      allow_failure: true
+  variables:
+    EXTRA_OPTIONS: --disable-mpi
+    COMPILER: clang++
+
+daily-macos:
+  rules:
+    - if: $RELEASE == "weekly"
+    - if: $RELEASE == "daily"
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+      when: manual
+      allow_failure: true
+  stage: pre-build
+  script:
+    - echo "Starting MacOS jobs"
+
+daily-build-macos-debug:
+  extends: .build-macos-base
+  needs: [ "daily-macos" ]
+  stage: build
+  variables:
+    MODE: debug
+
+daily-build-macos-default:
+  extends: .build-macos-base
+  needs: [ "daily-macos" ]
+  stage: build
+  variables:
+    MODE: default
+
+daily-build-macos-optimized:
+  extends: .build-macos-base
+  needs: [ "daily-macos" ]
+  stage: build
+  variables:
+    MODE: optimized
+
+daily-test-macos-debug:
+  extends: .build-macos-base
+  stage: test
+  needs: ["daily-build-macos-debug"]
+  dependencies:
+    - daily-build-macos-debug
+  variables:
+    MODE: debug
+
+daily-test-macos-default:
+  extends: .build-macos-base
+  stage: test
+  needs: [ "daily-build-macos-default" ]
+  dependencies:
+    - daily-build-macos-default
+  variables:
+    MODE: default
+
+daily-test-macos-optimized:
+  extends: .build-macos-base
+  stage: test
+  needs: [ "daily-build-macos-optimized" ]
+  dependencies:
+    - daily-build-macos-optimized
+  variables:
+    MODE: optimized
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci-ubuntu.yml ns-3.46/utils/tests/gitlab-ci-ubuntu.yml
--- ns-3.45/utils/tests/gitlab-ci-ubuntu.yml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/gitlab-ci-ubuntu.yml	2025-10-01 18:46:32.000000000 -0700
@@ -40,111 +40,111 @@
   script:
     - echo "Starting Ubuntu jobs"
 
-# Ubuntu 20.04 (Until April 2025)
-weekly-build-ubuntu-20.04-debug:
+# Ubuntu 22.04 (Until April 2027)
+weekly-build-ubuntu-22.04-debug:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
-  image: ubuntu:20.04
+  image: ubuntu:22.04
   stage: build
   variables:
     MODE: debug
-    LIBGSL: libgsl23
-    COMPILER: g++-10
+    LIBGSL: libgsl27
+    COMPILER: g++
 
-weekly-build-ubuntu-20.04-default:
+weekly-build-ubuntu-22.04-default:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
-  image: ubuntu:20.04
+  image: ubuntu:22.04
   stage: build
   variables:
     MODE: default
-    LIBGSL: libgsl23
-    COMPILER: g++-10
+    LIBGSL: libgsl27
+    COMPILER: g++
 
-weekly-build-ubuntu-20.04-optimized:
+weekly-build-ubuntu-22.04-optimized:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
-  image: ubuntu:20.04
+  image: ubuntu:22.04
   stage: build
   variables:
     MODE: optimized
-    LIBGSL: libgsl23
-    COMPILER: g++-10
+    LIBGSL: libgsl27
+    COMPILER: g++
 
-weekly-test-ubuntu-20.04-default:
+weekly-test-ubuntu-22.04-default:
   extends: .weekly-base-ubuntu
-  image: ubuntu:20.04
+  image: ubuntu:22.04
   stage: test
-  needs: ["weekly-build-ubuntu-20.04-default"]
+  needs: ["weekly-build-ubuntu-22.04-default"]
   dependencies:
-    - weekly-build-ubuntu-20.04-default
+    - weekly-build-ubuntu-22.04-default
   variables:
     MODE: default
-    LIBGSL: libgsl23
-    COMPILER: g++-10
+    LIBGSL: libgsl27
+    COMPILER: g++
 
-weekly-test-ubuntu-20.04-optimized:
+weekly-test-ubuntu-22.04-optimized:
   extends: .weekly-base-ubuntu
-  image: ubuntu:20.04
+  image: ubuntu:22.04
   stage: test
-  needs: ["weekly-build-ubuntu-20.04-optimized"]
+  needs: ["weekly-build-ubuntu-22.04-optimized"]
   dependencies:
-    - weekly-build-ubuntu-20.04-optimized
+    - weekly-build-ubuntu-22.04-optimized
   variables:
     MODE: optimized
-    LIBGSL: libgsl23
-    COMPILER: g++-10
+    LIBGSL: libgsl27
+    COMPILER: g++
 
-# Ubuntu 22.04 (Until January 2032)
-weekly-build-ubuntu-22.04-debug:
+# Ubuntu 24.04 (Until April 2029)
+weekly-build-ubuntu-24.04-debug:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
-  image: ubuntu:22.04
+  image: ubuntu:24.04
   stage: build
   variables:
     MODE: debug
     LIBGSL: libgsl27
     COMPILER: g++
 
-weekly-build-ubuntu-22.04-default:
+weekly-build-ubuntu-24.04-default:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
-  image: ubuntu:22.04
+  image: ubuntu:24.04
   stage: build
   variables:
     MODE: default
     LIBGSL: libgsl27
     COMPILER: g++
 
-weekly-build-ubuntu-22.04-optimized:
+weekly-build-ubuntu-24.04-optimized:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
-  image: ubuntu:22.04
+  image: ubuntu:24.04
   stage: build
   variables:
     MODE: optimized
     LIBGSL: libgsl27
     COMPILER: g++
 
-weekly-test-ubuntu-22.04-default:
+weekly-test-ubuntu-24.04-default:
   extends: .weekly-base-ubuntu
-  image: ubuntu:22.04
+  image: ubuntu:24.04
   stage: test
-  needs: ["weekly-build-ubuntu-22.04-default"]
+  needs: ["weekly-build-ubuntu-24.04-default"]
   dependencies:
-    - weekly-build-ubuntu-22.04-default
+    - weekly-build-ubuntu-24.04-default
   variables:
     MODE: default
     LIBGSL: libgsl27
     COMPILER: g++
 
-weekly-test-ubuntu-22.04-optimized:
+weekly-test-ubuntu-24.04-optimized:
   extends: .weekly-base-ubuntu
-  image: ubuntu:22.04
+  image: ubuntu:24.04
   stage: test
-  needs: ["weekly-build-ubuntu-22.04-optimized"]
+  needs: ["weekly-build-ubuntu-24.04-optimized"]
   dependencies:
-    - weekly-build-ubuntu-22.04-optimized
+    - weekly-build-ubuntu-24.04-optimized
   variables:
     MODE: optimized
     LIBGSL: libgsl27
@@ -171,7 +171,6 @@
     LIBGSL: libgsl28
     COMPILER: g++
 
-# Aug. 26, 2023: --disable-eigen is needed to prevent a -Werror=unused-variable
 weekly-build-ubuntu-rolling-optimized:
   extends: .weekly-base-ubuntu
   needs: ["weekly-ubuntu"]
@@ -181,7 +180,6 @@
     MODE: optimized
     LIBGSL: libgsl28
     COMPILER: g++
-    EXTRA_OPTIONS: --disable-eigen
 
 weekly-test-ubuntu-rolling-default:
   extends: .weekly-base-ubuntu
@@ -195,7 +193,6 @@
     LIBGSL: libgsl28
     COMPILER: g++
 
-# Aug. 26, 2023: --disable-eigen is needed to prevent a -Werror=unused-variable
 weekly-test-ubuntu-rolling-optimized:
   extends: .weekly-base-ubuntu
   image: ubuntu:rolling
@@ -207,4 +204,3 @@
     MODE: optimized
     LIBGSL: libgsl28
     COMPILER: g++
-    EXTRA_OPTIONS: --disable-eigen
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/gitlab-ci.yml ns-3.46/utils/tests/gitlab-ci.yml
--- ns-3.45/utils/tests/gitlab-ci.yml	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/gitlab-ci.yml	2025-10-01 18:46:32.000000000 -0700
@@ -120,3 +120,5 @@
   - "utils/tests/gitlab-ci-doc.yml"
   - "utils/tests/gitlab-ci-cppyy.yml"
   - "utils/tests/gitlab-ci-release.yml"
+  - "utils/tests/gitlab-ci-build.yml"
+  - "utils/tests/gitlab-ci-macos.yml"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/test-ns3.py ns-3.46/utils/tests/test-ns3.py
--- ns-3.45/utils/tests/test-ns3.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/test-ns3.py	2025-10-01 18:46:32.000000000 -0700
@@ -214,6 +214,12 @@
                     os.environ[key] = value
                     del setting, key, value
 
+        # Check if we can use Docker (docker-on-docker is a pain)
+        try:
+            docker.ps()
+        except DockerException as e:
+            currentTestCase.skipTest(f"python-on-whales returned:{e.__str__()}")
+
         # Create Docker client instance and start it
         ## The Python-on-whales container instance
         self.container = docker.run(
@@ -933,7 +939,7 @@
         """
         # Try filtering disabled modules to disable lte and modules that depend on it.
         return_code, stdout, stderr = run_ns3(
-            "configure -G \"{generator}\" --disable-modules='lte;wimax'"
+            "configure -G \"{generator}\" --disable-modules='lte;wifi'"
         )
         self.config_ok(return_code, stdout, stderr)
 
@@ -941,7 +947,7 @@
         enabled_modules = get_enabled_modules()
         self.assertLess(len(enabled_modules), len(self.ns3_modules))
         self.assertNotIn("ns3-lte", enabled_modules)
-        self.assertNotIn("ns3-wimax", enabled_modules)
+        self.assertNotIn("ns3-wifi", enabled_modules)
 
         # Try cleaning the list of enabled modules to reset to the normal configuration.
         return_code, stdout, stderr = run_ns3("configure -G \"{generator}\" --disable-modules=''")
@@ -1121,7 +1127,7 @@
                     'lte',
                     #comment2,
                     #comment3
-                    'network', 'internet','wimax'""",
+                    'network', 'internet','wifi'""",
                             examples="True",
                             tests="True",
                         )
@@ -1129,7 +1135,7 @@
                 else:
                     f.write(
                         ns3rc_template.format(
-                            modules="'core', 'lte', 'network', 'internet', 'wimax'",
+                            modules="'core', 'lte', 'network', 'internet', 'wifi'",
                             examples="True",
                             tests="True",
                         )
@@ -1144,7 +1150,7 @@
             self.assertIn("ns3-core", enabled_modules)
             self.assertIn("ns3-internet", enabled_modules)
             self.assertIn("ns3-lte", enabled_modules)
-            self.assertIn("ns3-wimax", enabled_modules)
+            self.assertIn("ns3-wifi", enabled_modules)
             self.assertTrue(get_test_enabled())
             self.assertGreater(len(get_programs_list()), len(self.ns3_executables))
 
@@ -1801,7 +1807,7 @@
         """
 
         run_ns3("clean")
-        with DockerContainerManager(self, "gcc:12.1") as container:
+        with DockerContainerManager(self, "gcc:12") as container:
             # Install basic packages
             container.execute("apt-get update")
             container.execute("apt-get install -y python3 ninja-build cmake g++ lld")
@@ -1869,14 +1875,14 @@
         """
 
         run_ns3("clean")
-        with DockerContainerManager(self, "ubuntu:22.04") as container:
+        with DockerContainerManager(self, "ubuntu:24.04") as container:
             container.execute("apt-get update")
-            container.execute("apt-get install -y python3 ninja-build cmake clang-12")
+            container.execute("apt-get install -y python3 ninja-build cmake clang-18")
 
             # Enable ClangTimeTrace without git (it should fail)
             try:
                 container.execute(
-                    "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -DNS3_CLANG_TIMETRACE=ON"
+                    "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
                 )
             except DockerException as e:
                 self.assertIn("could not find git for clone of ClangBuildAnalyzer", e.stderr)
@@ -1886,7 +1892,7 @@
             # Enable ClangTimeTrace without git (it should succeed)
             try:
                 container.execute(
-                    "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -DNS3_CLANG_TIMETRACE=ON"
+                    "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
                 )
             except DockerException as e:
                 self.assertIn("could not find git for clone of ClangBuildAnalyzer", e.stderr)
@@ -1908,7 +1914,7 @@
             # Now try with GCC, which should fail during the configuration
             run_ns3("clean")
             container.execute("apt-get install -y g++")
-            container.execute("apt-get remove -y clang-12")
+            container.execute("apt-get remove -y clang-18")
 
             try:
                 container.execute(
@@ -1929,15 +1935,15 @@
         """
 
         run_ns3("clean")
-        with DockerContainerManager(self, "ubuntu:20.04") as container:
+        with DockerContainerManager(self, "ubuntu:24.04") as container:
             container.execute("apt-get update")
             container.execute("apt-get remove -y g++")
-            container.execute("apt-get install -y python3 cmake g++-10 clang-11")
+            container.execute("apt-get install -y python3 cmake g++-11 clang-18")
 
             # Enable Ninja tracing without using the Ninja generator
             try:
                 container.execute(
-                    "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11"
+                    "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
                 )
             except DockerException as e:
                 self.assertIn("Ninjatracing requires the Ninja generator", e.stderr)
@@ -1949,7 +1955,7 @@
             # Enable Ninjatracing support without git (should fail)
             try:
                 container.execute(
-                    "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11"
+                    "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
                 )
             except DockerException as e:
                 self.assertIn("could not find git for clone of NinjaTracing", e.stderr)
@@ -1958,7 +1964,7 @@
             # Enable Ninjatracing support with git (it should succeed)
             try:
                 container.execute(
-                    "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11"
+                    "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
                 )
             except DockerException as e:
                 self.assertTrue(False, "Failed to configure with Ninjatracing")
@@ -1987,7 +1993,7 @@
             # Enable Clang TimeTrace feature for more detailed traces
             try:
                 container.execute(
-                    "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11 -DNS3_CLANG_TIMETRACE=ON"
+                    "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
                 )
             except DockerException as e:
                 self.assertTrue(False, "Failed to configure Ninjatracing with Clang's TimeTrace")
@@ -2359,9 +2365,9 @@
             for import_method in ns3_import_methods:
                 test_cmake_project = (
                     """
-                                     cmake_minimum_required(VERSION 3.12..3.12)
+                                     cmake_minimum_required(VERSION 3.20..3.20)
                                      project(ns3_consumer CXX)
-                                     set(CMAKE_CXX_STANDARD 20)
+                                     set(CMAKE_CXX_STANDARD 23)
                                      set(CMAKE_CXX_STANDARD_REQUIRED ON)
                                      add_executable(test main.cpp)
                                      """
@@ -3189,8 +3195,68 @@
 
 class NS3QualityControlTestCase(unittest.TestCase):
     """!
-    ns-3 tests to control the quality of the repository over time,
-    by checking the state of URLs listed and more
+    ns-3 tests to control the quality of the repository over time
+    """
+
+    def test_01_CheckImageBrightness(self):
+        """!
+        Check if images in the docs are above a brightness threshold.
+        This should prevent screenshots with dark UI themes.
+        @return None
+        """
+        if shutil.which("convert") is None:
+            self.skipTest("Imagemagick was not found")
+
+        from pathlib import Path
+
+        # Scan for images
+        image_extensions = ["png", "jpg"]
+        images = []
+        for extension in image_extensions:
+            images += list(Path("./doc").glob("**/figures/*.{ext}".format(ext=extension)))
+            images += list(Path("./doc").glob("**/figures/**/*.{ext}".format(ext=extension)))
+
+        # Get the brightness of an image on a scale of 0-100%
+        imagemagick_get_image_brightness = 'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
+
+        # We could invert colors of target image to increase its brightness
+        # convert source.png -channel RGB -negate target.png
+        brightness_threshold = 50
+        for image in images:
+            brightness = subprocess.check_output(
+                imagemagick_get_image_brightness.format(image=image).split()
+            )
+            brightness = float(brightness.decode().strip("'\""))
+            self.assertGreater(
+                brightness,
+                brightness_threshold,
+                "Image darker than threshold (%d < %d): %s"
+                % (brightness, brightness_threshold, image),
+            )
+
+    def test_02_CheckForBrokenLogs(self):
+        """!
+        Check if one of the log statements of examples/tests contains/exposes a bug.
+        @return None
+        """
+        # First enable examples and tests with sanitizers
+        return_code, stdout, stderr = run_ns3(
+            'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
+        )
+        self.assertEqual(return_code, 0)
+
+        # Then build and run tests setting the environment variable
+        return_code, stdout, stderr = run_program(
+            "test.py", "", python=True, env={"TEST_LOGS": "1"}
+        )
+        self.assertEqual(return_code, 0)
+
+
+class NS3QualityControlThatCanFailTestCase(unittest.TestCase):
+    """!
+    ns-3 complementary tests, allowed to fail, to help control
+    the quality of the repository over time, by checking the
+    state of URLs listed and more
     """
 
     def test_01_CheckForDeadLinksInSources(self):
@@ -3237,6 +3303,8 @@
             "http://en.wikipedia.org/wiki/Namespace_(computer_science",
             "http://en.wikipedia.org/wiki/Bonobo_(component_model",
             "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
+            "https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch",
+            "http://www.nsnam.org/bugzilla/show_bug.cgi?id=",
             # historical links
             "http://www.research.att.com/info/kpv/",
             "http://www.research.att.com/~gsf/",
@@ -3386,59 +3454,6 @@
         test_return_code, stdout, stderr = run_program("test.py", "", python=True)
         self.assertEqual(test_return_code, 0)
 
-    def test_03_CheckImageBrightness(self):
-        """!
-        Check if images in the docs are above a brightness threshold.
-        This should prevent screenshots with dark UI themes.
-        @return None
-        """
-        if shutil.which("convert") is None:
-            self.skipTest("Imagemagick was not found")
-
-        from pathlib import Path
-
-        # Scan for images
-        image_extensions = ["png", "jpg"]
-        images = []
-        for extension in image_extensions:
-            images += list(Path("./doc").glob("**/figures/*.{ext}".format(ext=extension)))
-            images += list(Path("./doc").glob("**/figures/**/*.{ext}".format(ext=extension)))
-
-        # Get the brightness of an image on a scale of 0-100%
-        imagemagick_get_image_brightness = 'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
-
-        # We could invert colors of target image to increase its brightness
-        # convert source.png -channel RGB -negate target.png
-        brightness_threshold = 50
-        for image in images:
-            brightness = subprocess.check_output(
-                imagemagick_get_image_brightness.format(image=image).split()
-            )
-            brightness = float(brightness.decode().strip("'\""))
-            self.assertGreater(
-                brightness,
-                brightness_threshold,
-                "Image darker than threshold (%d < %d): %s"
-                % (brightness, brightness_threshold, image),
-            )
-
-    def test_04_CheckForBrokenLogs(self):
-        """!
-        Check if one of the log statements of examples/tests contains/exposes a bug.
-        @return None
-        """
-        # First enable examples and tests with sanitizers
-        return_code, stdout, stderr = run_ns3(
-            'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
-        )
-        self.assertEqual(return_code, 0)
-
-        # Then build and run tests setting the environment variable
-        return_code, stdout, stderr = run_program(
-            "test.py", "", python=True, env={"TEST_LOGS": "1"}
-        )
-        self.assertEqual(return_code, 0)
-
 
 def main():
     """!
@@ -3470,6 +3485,7 @@
         ],
         "extras": [
             NS3DependenciesTestCase,
+            NS3QualityControlThatCanFailTestCase,
         ],
     }
 
@@ -3482,6 +3498,7 @@
     parser.add_argument("-tn", "--test-name", action="store", default=None, type=str)
     parser.add_argument("-rtn", "--resume-from-test-name", action="store", default=None, type=str)
     parser.add_argument("-q", "--quiet", action="store_true", default=False)
+    parser.add_argument("-f", "--failfast", action="store_true", default=False)
     args = parser.parse_args(sys.argv[1:])
 
     loader = unittest.TestLoader()
@@ -3517,7 +3534,7 @@
         shutil.move(ns3rc_script, ns3rc_script_bak)
 
     # Run tests and fail as fast as possible
-    runner = unittest.TextTestRunner(failfast=True, verbosity=1 if args.quiet else 2)
+    runner = unittest.TextTestRunner(failfast=args.failfast, verbosity=1 if args.quiet else 2)
     runner.run(suite)
 
     # After completing the tests successfully, restore the ns3rc file
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/utils/tests/test-test.py ns-3.46/utils/tests/test-test.py
--- ns-3.45/utils/tests/test-test.py	2025-06-01 20:34:45.000000000 -0700
+++ ns-3.46/utils/tests/test-test.py	2025-10-01 18:46:32.000000000 -0700
@@ -100,6 +100,9 @@
         "--html=t_opt.html && rm t_opt.html",
         "-x t_opt.xml && rm t_opt.xml",
         "--xml=t_opt.xml && rm t_opt.xml",
+        "--example=wifi-phy-configuration",
+        "--example=wifi-phy-configuration*",
+        '--example="wifi-phy-configuration --testCase=0"',
     ]
 
     configure_string = sys.executable + " ns3 configure --enable-tests --enable-examples"
diff -Naur -x '*.dia' -x '*.pcap' -x '*.png' ns-3.45/VERSION ns-3.46/VERSION
--- ns-3.45/VERSION	2025-06-01 20:35:04.000000000 -0700
+++ ns-3.46/VERSION	2025-10-01 18:46:49.000000000 -0700
@@ -1 +1 @@
-3.45
+3.46
