| <!-- |
| Documentation/_templates/layout.html |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. The |
| ASF licenses this file to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance with the |
| License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| License for the specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| |
| |
| <!DOCTYPE html> |
| <html class="writer-html5" lang="en"> |
| <head> |
| <meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> |
| |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>IPv6 — NuttX latest documentation</title> |
| <link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/css/theme.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/copybutton.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" /> |
| <link rel="stylesheet" type="text/css" href="../_static/custom.css" /> |
| |
| |
| <link rel="shortcut icon" href="../_static/favicon.ico"/> |
| <script src="../_static/jquery.js"></script> |
| <script src="../_static/_sphinx_javascript_frameworks_compat.js"></script> |
| <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script> |
| <script src="../_static/doctools.js"></script> |
| <script src="../_static/sphinx_highlight.js"></script> |
| <script src="../_static/clipboard.min.js"></script> |
| <script src="../_static/copybutton.js"></script> |
| <script src="../_static/design-tabs.js"></script> |
| <script src="../_static/js/theme.js"></script> |
| <link rel="index" title="Index" href="../genindex.html" /> |
| <link rel="search" title="Search" href="../search.html" /> |
| <link rel="next" title="Integrating with Newlib" href="integrate_newlib.html" /> |
| <link rel="prev" title="Logging to a RAM Buffer" href="logging_rambuffer.html" /> |
| </head> |
| |
| <body class="wy-body-for-nav"> |
| <div class="wy-grid-for-nav"> |
| <nav data-toggle="wy-nav-shift" class="wy-nav-side"> |
| <div class="wy-side-scroll"> |
| <div class="wy-side-nav-search" > |
| |
| <a href="../index.html" class="icon icon-home"> NuttX |
| |
| |
| |
| </a> |
| |
| <!-- this version selector is quite ugly, should be probably replaced by something |
| more modern --> |
| |
| <div class="version-selector"> |
| <select onchange="javascript:location.href = this.value;"> |
| |
| <option value="../../latest" selected="selected">latest</option> |
| |
| <option value="../../10.0.0" >10.0.0</option> |
| |
| <option value="../../10.0.1" >10.0.1</option> |
| |
| <option value="../../10.1.0" >10.1.0</option> |
| |
| <option value="../../10.2.0" >10.2.0</option> |
| |
| <option value="../../10.3.0" >10.3.0</option> |
| |
| <option value="../../11.0.0" >11.0.0</option> |
| |
| <option value="../../12.0.0" >12.0.0</option> |
| |
| <option value="../../12.1.0" >12.1.0</option> |
| |
| <option value="../../12.2.0" >12.2.0</option> |
| |
| <option value="../../12.2.1" >12.2.1</option> |
| |
| <option value="../../12.3.0" >12.3.0</option> |
| |
| <option value="../../12.4.0" >12.4.0</option> |
| |
| <option value="../../12.5.0" >12.5.0</option> |
| |
| <option value="../../12.5.1" >12.5.1</option> |
| |
| <option value="../../12.6.0" >12.6.0</option> |
| |
| <option value="../../12.7.0" >12.7.0</option> |
| |
| <option value="../../12.8.0" >12.8.0</option> |
| |
| <option value="../../12.9.0" >12.9.0</option> |
| |
| <option value="../../12.10.0" >12.10.0</option> |
| |
| <option value="../../12.11.0" >12.11.0</option> |
| |
| </select> |
| </div> |
| |
| |
| <div role="search"> |
| <form id="rtd-search-form" class="wy-form" action="../search.html" method="get"> |
| <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" /> |
| <input type="hidden" name="check_keywords" value="yes" /> |
| <input type="hidden" name="area" value="default" /> |
| </form> |
| </div> |
| |
| </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> |
| <p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p> |
| <ul class="current"> |
| <li class="toctree-l1"><a class="reference internal" href="../index.html">Home</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../introduction/index.html">Introduction</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../quickstart/index.html">Getting Started</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../contributing/index.html">Contributing</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../platforms/index.html">Supported Platforms</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../components/index.html">OS Components</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../applications/index.html">Applications</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../implementation/index.html">Implementation Details</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../reference/index.html">API Reference</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../debugging/index.html">Debugging</a></li> |
| <li class="toctree-l1 current"><a class="reference internal" href="index.html">Guides</a><ul class="current"> |
| <li class="toctree-l2"><a class="reference internal" href="nfs.html">NFS Client How-To</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="usbtrace.html">USB Device Trace</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="simulator.html">Simulator</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="rndis.html">How to use RNDIS</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="drivers.html">Drivers</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="cpp_cmake.html">C++ Example using CMake</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="pysimcoder.html">pysimCoder integration with NuttX</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="customboards.html">Custom Boards How-To</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="customapps.html">Custom Apps How-to</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="citests.html">Running CI Test Locally</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="zerolatencyinterrupts.html">High Performance: Zero Latency Interrupts, Maskable Nested Interrupts</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="fortify.html">Fortify</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="nestedinterrupts.html">Nested Interrupts</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="ofloader.html">Open Flash Loader</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="testingtcpip.html">Testing TCP/IP Network Stacks</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="automounter.html">Auto-Mounter</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="stm32nullpointer.html">STM32 Null Pointer Detection</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="stm32ccm.html">STM32 CCM Allocator</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="etcromfs.html">etc romfs</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="devicetree.html">Device Tree</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="changing_systemclockconfig.html">Changing the System Clock Configuration</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="usingkernelthreads.html">Using Kernel Threads</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="armv7m_runtimestackcheck.html">ARMv7-M Run Time Stack Checking</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="include_files_board_h.html">Including Files in board.h</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="specialstuff_in_nuttxheaderfiles.html">Why can’t I put my special stuff in NuttX header files?</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="kernel_threads_with_custom_stacks.html">Kernel Threads with Custom Stacks</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="versioning_and_task_names.html">Versioning and Task Names</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="logging_rambuffer.html">Logging to a RAM Buffer</a></li> |
| <li class="toctree-l2 current"><a class="current reference internal" href="#">IPv6</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#ethernet-driver-requirements">Ethernet Driver Requirements</a><ul> |
| <li class="toctree-l4"><a class="reference internal" href="#basic-driver-requirements">Basic Driver Requirements</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#multicast-address-filtering">Multicast Address Filtering</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#icmpv6-neighbor-discovery-protocol">ICMPv6 Neighbor Discovery Protocol</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l3"><a class="reference internal" href="#board-configurations">Board Configurations</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#ping">Ping</a><ul> |
| <li class="toctree-l4"><a class="reference internal" href="#ping-from-host-pc">Ping from Host PC</a><ul> |
| <li class="toctree-l5"><a class="reference internal" href="#ping-from-windows-cmd-terminal">Ping from Windows cmd Terminal</a></li> |
| <li class="toctree-l5"><a class="reference internal" href="#ping-from-linux-shell">Ping From Linux shell</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l4"><a class="reference internal" href="#ping-from-the-nuttshell-nsh">Ping from the NuttShell (NSH)</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l3"><a class="reference internal" href="#nsh-ifconfig">NSH ifconfig</a><ul> |
| <li class="toctree-l4"><a class="reference internal" href="#ipv4-only">IPv4 Only</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#ipv6-only">IPv6 Only</a></li> |
| <li class="toctree-l4"><a class="reference internal" href="#both-ipv4-and-ipv6">Both IPv4 and IPv6</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l3"><a class="reference internal" href="#tests-applications-and-network-utilities">Tests, Applications, and Network Utilities</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="integrate_newlib.html">Integrating with Newlib</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="protected_build.html">NuttX Protected Build</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="platform_directories.html">Platform Directories</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="port_drivers_to_stm32f7.html">Porting Drivers to the STM32 F7</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="semihosting.html">Semihosting</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="renode.html">Run NuttX on Renode</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="signal_events_interrupt_handlers.html">Signaling Events from Interrupt Handlers</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="signaling_sem_priority_inheritance.html">Signaling Semaphores and Priority Inheritance</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="smaller_vector_tables.html">Smaller Vector Tables</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="port.html">How to port</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="updating_release_system_elf.html">Updating a Release System with ELF Programs</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="partially_linked_elf.html">ELF Programs – With Symbol Tables</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="fully_linked_elf.html">ELF Programs – No Symbol Tables</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="building_nuttx_with_app_out_of_src_tree.html">Building NuttX with Applications Outside the Source Tree</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="building_uclibcpp.html">Building uClibc++</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="custom_app_directories.html">Custom Application Directories</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="multiple_nsh_sessions.html">Multiple NSH Sessions</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="nsh_network_link_management.html">NSH Network Link Management</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="ram_rom_disks.html">RAM Disks and ROM Disks</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="reading_can_msgs.html">Reading CAN Messages</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="remove_device_drivers_nsh.html">Removing Device Drivers with NSH</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="rust.html">Rust in NuttX</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="optee.html">Interfacing with OP-TEE</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../logos/index.html">NuttX Logos</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="../_tags/tagsindex.html">Tags</a></li> |
| </ul> |
| |
| </div> |
| </div> |
| </nav> |
| |
| <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" > |
| <i data-toggle="wy-nav-top" class="fa fa-bars"></i> |
| <a href="../index.html">NuttX</a> |
| </nav> |
| |
| <div class="wy-nav-content"> |
| <div class="rst-content"> |
| <div role="navigation" aria-label="Page navigation"> |
| <ul class="wy-breadcrumbs"> |
| <li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li> |
| <li class="breadcrumb-item"><a href="index.html">Guides</a></li> |
| <li class="breadcrumb-item active">IPv6</li> |
| <li class="wy-breadcrumbs-aside"> |
| <a href="https://github.com/apache/nuttx/blob/master/Documentation/guides/ipv6.rst" class="fa fa-github"> Edit on GitHub</a> |
| </li> |
| </ul> |
| <hr/> |
| </div> |
| <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> |
| <div itemprop="articleBody"> |
| |
| <section id="ipv6"> |
| <h1>IPv6<a class="headerlink" href="#ipv6" title="Permalink to this heading"></a></h1> |
| <div class="admonition warning"> |
| <p class="admonition-title">Warning</p> |
| <p>Migrated from: <a class="reference external" href="https://cwiki.apache.org/confluence/display/NUTTX/IPv6">https://cwiki.apache.org/confluence/display/NUTTX/IPv6</a></p> |
| </div> |
| <p>NuttX has supported the Internet Protocol Version 4 (IPv4) for many years. |
| There have been fragments of IPv6 in the code base for many years as well, |
| but these fragments were not more than place markers and not functional.</p> |
| <p>But recently, post NuttX-7.6, I have focused some effort into completing the |
| IPv6 implementation. This Wiki page contains notes from that integration |
| effort and will, hopefully, evolve to provide full documentation for NuttX |
| IPv6 support.</p> |
| <p>Current status: Basic functionality is complete and verified. That includes |
| ICMPPv6 Neighbor Discover Protocol, IPCMPv6 Echo Request/Response |
| (for <code class="docutils literal notranslate"><span class="pre">ping6</span></code>), TCP/IPv6, and UDP/IPv6. It has also been proven that you |
| can support a platform with <cite>both</cite> IPv4 and IPv6 enabled.</p> |
| <section id="ethernet-driver-requirements"> |
| <h2>Ethernet Driver Requirements<a class="headerlink" href="#ethernet-driver-requirements" title="Permalink to this heading"></a></h2> |
| <section id="basic-driver-requirements"> |
| <h3>Basic Driver Requirements<a class="headerlink" href="#basic-driver-requirements" title="Permalink to this heading"></a></h3> |
| <p>In order to support IPv6, Ethernet drivers must do the following:</p> |
| <ul class="simple"> |
| <li><p>They must recognize IPv6 packets and call <code class="docutils literal notranslate"><span class="pre">ipv6_input</span></code> in order to pass the |
| packets into the network stack. This is equivalent to calling <code class="docutils literal notranslate"><span class="pre">ipv4_input</span></code> |
| when an IPv4 pack is received.</p></li> |
| <li><p>When sending an IPv6, the drivers must call <code class="docutils literal notranslate"><span class="pre">neighbor_out()</span></code> in order to add |
| the MAC address of the destination into the link layer header. IPv6’s |
| <cite>ICMPv6 Neighbor Discovery Protocol</cite> is the moral equivalent of the |
| <cite>Address Resolution Protocol</cite> (ARP) used with IPv6. And the IPv6 |
| <code class="docutils literal notranslate"><span class="pre">neighbor_out()</span></code> performs a similar function to the IPv4 <code class="docutils literal notranslate"><span class="pre">arp_out()</span></code> |
| function.</p></li> |
| <li><p>Ethernet drivers must also support some additional address filtering. |
| For IPv4 support, most Ethernet drivers are configured to accept only |
| Ethernet packets with matching MAC addresses and broadcast packets (or |
| selected multicast packets if IGMP support is enabled). Additional |
| filtering support is needed to support IPv6.</p></li> |
| </ul> |
| <p>All existing NuttX Ethernet drivers have already been modified to support |
| the requirements of the first two bullets. However, additional logic must |
| be added to most of the existing Ethernet drivers to support the final |
| requirement.</p> |
| </section> |
| <section id="multicast-address-filtering"> |
| <h3>Multicast Address Filtering<a class="headerlink" href="#multicast-address-filtering" title="Permalink to this heading"></a></h3> |
| <p>Each Ethernet device connects to the Ethernet wire via a PHY and so |
| potentially has access to every packet that passes on the wire. In |
| <cite>promiscuous</cite> mode, that is the behavior that is desired but normally |
| it is not: The amount of traffic that appears on the wire would swamp |
| most modest MCUs in promiscuous mode. So instead, the Ethernet MAC |
| hardware will support address filtering. That is, the hardware will |
| look at the Ethernet header at the beginning of each packet and will |
| ignore packets that do not have the desired information in the Ethernet |
| header. The software will see only those filtered packets that are desired.</p> |
| <p>Typically, the Ethernet MAC is set-up for <cite>unicast</cite> address filtering: The |
| hardware is programmed so that that only packets whose destination Ethernet |
| MAC address matches the MAC address programmed into the hardware are accepted. |
| In addition, special <cite>broadcast</cite> Ethernet addresses will also be accepted. |
| In this way, the volume of Ethernet data received by the MCU is greatly |
| reduced.</p> |
| <p><cite>Multicast</cite> addresses are a little different. Unlike broadcast addresses, |
| there are many possible multicast addresses and so the Ethernet MAC hardware |
| must support some special capability to match the destination Ethernet |
| address in an incoming packet with a variety of multicast addresses. |
| Usually this involves <cite>hashing</cite> the Ethernet address and performing a <cite>hash |
| table lookup</cite> to check for an address match.</p> |
| <p>Each Ethernet driver uses a common interface that is defined in |
| <code class="docutils literal notranslate"><span class="pre">nuttx/include/nuttx/net/netdev.h</span></code>. That interface defines, among other |
| things, a set of calls into the Ethernet driver to perform a variety of |
| functions. One of those functions is multicast address filtering:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifdef CONFIG_NET_IGMP</span> |
| <span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">d_addmac</span><span class="p">)(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">net_driver_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">mac</span><span class="p">);</span> |
| <span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">d_rmmac</span><span class="p">)(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">net_driver_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">FAR</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="o">*</span><span class="n">mac</span><span class="p">);</span> |
| <span class="cp">#endif</span> |
| </pre></div> |
| </div> |
| <p>The <code class="docutils literal notranslate"><span class="pre">d_addmac()</span></code> interface adds a multicast address to the hash |
| table; <code class="docutils literal notranslate"><span class="pre">d_rmmac()</span></code> removes a multicast address from the hash table.</p> |
| <p>These interface is only required if IGMP is supported, but the underlying |
| ability to program multicast address filtered is required for full IPv6 |
| support. This interface exists in all Ethernet drivers but most are |
| currently place holders and are <cite>to-be-provided</cite>. At present, only the |
| STMicro STM32, the TI Tiva TM4C, and the Atmel SAM3/4 and SAMA5D3/4 |
| Ethernet drivers support multicast hash tables. This capability will |
| have to be added to any additional Ethernet drivers that are modified |
| to support IPv6.</p> |
| </section> |
| <section id="icmpv6-neighbor-discovery-protocol"> |
| <h3>ICMPv6 Neighbor Discovery Protocol<a class="headerlink" href="#icmpv6-neighbor-discovery-protocol" title="Permalink to this heading"></a></h3> |
| <p>The ICMPv6 Neighbor Discover protocol is the reason for this additional |
| address filtering. The ICMPv6 Neighbor Discovery Protocol is the |
| replacement for IPv4’s ARP. It different from ARP in the it is |
| implemented not at the Ethernet link layer, but within the IPv6 layer. |
| In order to receive broadcast packets to ICMPv6, the IPv6 Multicast |
| address of 33.33.ff.xx.xx.xx is used, where the xx.xx.xx part derives |
| from the IPv6 address. The Ethernet driver filtering logic must be modified |
| so that it accepts packets directed to the that MAC address.</p> |
| <p>At present, this additional support is only implemented for the TI Tiva |
| TM4C129X Ethernet driver. Below is a snippet of code from that drier |
| showing how this is implemented:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/* Set the MAC address */</span> |
| |
| <span class="n">tiva_macaddress</span><span class="p">(</span><span class="n">priv</span><span class="p">);</span> |
| |
| <span class="cp">#ifdef CONFIG_NET_ICMPv6</span> |
| <span class="cm">/* Set up the IPv6 multicast address */</span> |
| |
| <span class="n">tiva_ipv6multicast</span><span class="p">(</span><span class="n">priv</span><span class="p">);</span> |
| <span class="cp">#endif</span> |
| </pre></div> |
| </div> |
| <p>Where <cite>tiva_macaddress()</cite> sets up the normal MAC address filtering and |
| <cite>tiva_ipv6multicast()</cite> sets up the special filtering needed by IPv6:</p> |
| <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="cm">/****************************************************************************</span> |
| <span class="cm">* Function: tiva_ipv6multicast</span> |
| <span class="cm">*</span> |
| <span class="cm">* Description:</span> |
| <span class="cm">* Configure the IPv6 multicast MAC address.</span> |
| <span class="cm">*</span> |
| <span class="cm">* Parameters:</span> |
| <span class="cm">* priv - A reference to the private driver state structure</span> |
| <span class="cm">*</span> |
| <span class="cm">* Returned Value:</span> |
| <span class="cm">* OK on success; Negated errno on failure.</span> |
| <span class="cm">*</span> |
| <span class="cm">* Assumptions:</span> |
| <span class="cm">***************************************************************************/</span> |
| |
| <span class="w"> </span><span class="cp">#ifdef CONFIG_NET_ICMPv6</span> |
| <span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">tiva_ipv6multicast</span><span class="p">(</span><span class="n">FAR</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">tiva_ethmac_s</span><span class="w"> </span><span class="o">*</span><span class="n">priv</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">net_driver_s</span><span class="w"> </span><span class="o">*</span><span class="n">dev</span><span class="p">;</span> |
| <span class="w"> </span><span class="kt">uint16_t</span><span class="w"> </span><span class="n">tmp16</span><span class="p">;</span> |
| <span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span> |
| |
| <span class="w"> </span><span class="cm">/* For ICMPv6, we need to add the IPv6 multicast address</span> |
| <span class="cm"> * For IPv6 multicast addresses, the Ethernet MAC is derived by</span> |
| <span class="cm"> * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00,</span> |
| <span class="cm"> * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map</span> |
| <span class="cm"> * to the Ethernet MAC address 33:33:00:01:00:03.</span> |
| <span class="cm"> * NOTES: This appears correct for the ICMPv6 Router Solicitation</span> |
| <span class="cm"> * Message, but the ICMPv6 Neighbor Solicitation message seems to</span> |
| <span class="cm"> * use 33:33:ff:01:00:03.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mh">0x33</span><span class="p">;</span> |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mh">0x33</span><span class="p">;</span> |
| |
| <span class="w"> </span><span class="n">dev</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&</span><span class="n">priv</span><span class="o">-></span><span class="n">dev</span><span class="p">;</span> |
| <span class="w"> </span><span class="n">tmp16</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dev</span><span class="o">-></span><span class="n">d_ipv6addr</span><span class="p">[</span><span class="mi">6</span><span class="p">];</span> |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mh">0xff</span><span class="p">;</span> |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp16</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mi">8</span><span class="p">;</span> |
| |
| <span class="w"> </span><span class="n">tmp16</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dev</span><span class="o">-></span><span class="n">d_ipv6addr</span><span class="p">[</span><span class="mi">7</span><span class="p">];</span> |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp16</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="mh">0xff</span><span class="p">;</span> |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tmp16</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="mi">8</span><span class="p">;</span> |
| |
| <span class="w"> </span><span class="n">nvdbg</span><span class="p">(</span><span class="s">"IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span><span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span><span class="w"> </span><span class="n">mac</span><span class="p">[</span><span class="mi">5</span><span class="p">]);</span> |
| |
| <span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">tiva_addmac</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">mac</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="cp">#ifdef CONFIG_NET_ICMPv6_AUTOCONF</span> |
| <span class="w"> </span><span class="cm">/* Add the IPv6 all link-local nodes Ethernet address. This is the</span> |
| <span class="cm"> * address that we expect to receive ICMPv6 Router Advertisement</span> |
| <span class="cm"> * packets.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">tiva_addmac</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">g_ipv6_ethallnodes</span><span class="p">.</span><span class="n">ether_addr_octet</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="cp">#endif </span><span class="cm">/* CONFIG_NET_ICMPv6_AUTOCONF */</span> |
| <span class="w"> </span><span class="cp">#ifdef CONFIG_NET_ICMPv6_ROUTER</span> |
| <span class="w"> </span><span class="cm">/* Add the IPv6 all link-local routers Ethernet address. This is the</span> |
| <span class="cm"> * address that we expect to receive ICMPv6 Router Solicitation</span> |
| <span class="cm"> * packets.</span> |
| <span class="cm"> */</span> |
| |
| <span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">tiva_addmac</span><span class="p">(</span><span class="n">dev</span><span class="p">,</span><span class="w"> </span><span class="n">g_ipv6_ethallrouters</span><span class="p">.</span><span class="n">ether_addr_octet</span><span class="p">);</span> |
| |
| <span class="w"> </span><span class="cp">#endif </span><span class="cm">/* CONFIG_NET_ICMPv6_ROUTER */</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="cp">#endif </span><span class="cm">/* CONFIG_NET_ICMPv6 */</span> |
| </pre></div> |
| </div> |
| <p>The following Ethernet drivers are complete and IPv6 ready. All others |
| Ethernet drivers have all required IPv6 support <cite>except</cite> that they are |
| missing (1) the required ICMPv6 addressing filtering described above |
| and/or (2) support for multi-cast address filtering.</p> |
| <ul class="simple"> |
| <li><p>STMicro STM32</p></li> |
| <li><p>TI Tiva TM4C</p></li> |
| <li><p>Atmel SAMA5D4</p></li> |
| <li><p>NXP LPC17xx</p></li> |
| </ul> |
| </section> |
| </section> |
| <section id="board-configurations"> |
| <h2>Board Configurations<a class="headerlink" href="#board-configurations" title="Permalink to this heading"></a></h2> |
| <p>At present, there are three board configuration that are pre-configured to |
| use IPv6: <code class="docutils literal notranslate"><span class="pre">nuttx/boards/arm/tiva/dk-tm4c129x/configs/ipv6</span></code>, |
| <code class="docutils literal notranslate"><span class="pre">nuttx/boards/arm/stm32/stm32f4discovery/ipv6</span></code>, and |
| <code class="docutils literal notranslate"><span class="pre">nuttx/boards/arm/tiva/tm4c1294-launchpad/configs/ipv6</span></code>. These default |
| configurations have only IPv6 enabled. But the <cite>README</cite> files at in those |
| board directories describes how to enable <cite>both</cite> IPv4 and IPv6 simultaneously.</p> |
| </section> |
| <section id="ping"> |
| <h2>Ping<a class="headerlink" href="#ping" title="Permalink to this heading"></a></h2> |
| <section id="ping-from-host-pc"> |
| <h3>Ping from Host PC<a class="headerlink" href="#ping-from-host-pc" title="Permalink to this heading"></a></h3> |
| <section id="ping-from-windows-cmd-terminal"> |
| <h4>Ping from Windows cmd Terminal<a class="headerlink" href="#ping-from-windows-cmd-terminal" title="Permalink to this heading"></a></h4> |
| <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>ping<span class="w"> </span>-6<span class="w"> </span>fc00::2 |
| </pre></div> |
| </div> |
| </section> |
| <section id="ping-from-linux-shell"> |
| <h4>Ping From Linux shell<a class="headerlink" href="#ping-from-linux-shell" title="Permalink to this heading"></a></h4> |
| <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>ping6<span class="w"> </span>fc00::2 |
| </pre></div> |
| </div> |
| </section> |
| </section> |
| <section id="ping-from-the-nuttshell-nsh"> |
| <h3>Ping from the NuttShell (NSH)<a class="headerlink" href="#ping-from-the-nuttshell-nsh" title="Permalink to this heading"></a></h3> |
| <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>nsh><span class="w"> </span>ping6<span class="w"> </span>fc00::2 |
| </pre></div> |
| </div> |
| </section> |
| </section> |
| <section id="nsh-ifconfig"> |
| <h2>NSH ifconfig<a class="headerlink" href="#nsh-ifconfig" title="Permalink to this heading"></a></h2> |
| <section id="ipv4-only"> |
| <h3>IPv4 Only<a class="headerlink" href="#ipv4-only" title="Permalink to this heading"></a></h3> |
| <p><code class="docutils literal notranslate"><span class="pre">CONFIG_NET_IPv4=y</span></code> and <code class="docutils literal notranslate"><span class="pre">CONFIG_NET_IPv6=n</span></code></p> |
| <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>nsh><span class="w"> </span>ifconfig |
| eth0<span class="w"> </span>Link<span class="w"> </span>encap:<span class="w"> </span>Ethernet<span class="w"> </span>HWaddr<span class="w"> </span><span class="m">00</span>:1a:b6:02:81:14<span class="w"> </span>at<span class="w"> </span>UP |
| <span class="w"> </span>inet<span class="w"> </span>addr:10.0.0.2<span class="w"> </span>DRaddr:10.0.0.1<span class="w"> </span>Mask:255.255.255.0 |
| |
| <span class="w"> </span>IPv4<span class="w"> </span>TCP<span class="w"> </span>UDP<span class="w"> </span>ICMP |
| Received<span class="w"> </span>003b<span class="w"> </span>001c<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0004</span> |
| Dropped<span class="w"> </span>001b<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>IPv4<span class="w"> </span>VHL:<span class="w"> </span><span class="m">0000</span><span class="w"> </span>Frg:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>Checksum<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span>---- |
| <span class="w"> </span>TCP<span class="w"> </span>ACK:<span class="w"> </span><span class="m">0000</span><span class="w"> </span>SYN:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>RST:<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>Type<span class="w"> </span><span class="m">0000</span><span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span> |
| Sent<span class="w"> </span><span class="m">0031</span><span class="w"> </span>002d<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0004</span> |
| <span class="w"> </span>Rexmit<span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span><span class="w"> </span>---- |
| </pre></div> |
| </div> |
| <p>NOTE: The detailed packet statistics only appear if |
| <code class="docutils literal notranslate"><span class="pre">CONFIG_NET_STATISTICS</span></code> is enabled.</p> |
| </section> |
| <section id="ipv6-only"> |
| <h3>IPv6 Only<a class="headerlink" href="#ipv6-only" title="Permalink to this heading"></a></h3> |
| <p><code class="docutils literal notranslate"><span class="pre">CONFIG_NET_IPv4=n</span></code> and <code class="docutils literal notranslate"><span class="pre">CONFIG_NET_IPv6=y</span></code></p> |
| <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>nsh><span class="w"> </span>ifconfig |
| eth0<span class="w"> </span>Link<span class="w"> </span>encap:<span class="w"> </span>Ethernet<span class="w"> </span>HWaddr<span class="w"> </span><span class="m">00</span>:1a:b6:02:81:14<span class="w"> </span>at<span class="w"> </span>UP |
| <span class="w"> </span>inet6<span class="w"> </span>addr:fc00::2 |
| <span class="w"> </span>inet6<span class="w"> </span>DRaddr:fc00::1 |
| <span class="w"> </span>inet6<span class="w"> </span>Mask:ffff:ffff:ffff::ffff:ffff:ffff:ff80 |
| |
| <span class="w"> </span>IPv6<span class="w"> </span>TCP<span class="w"> </span>UDP<span class="w"> </span>ICMPv6 |
| Received<span class="w"> </span><span class="m">0007</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0007</span> |
| Dropped<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>IPv6<span class="w"> </span>VHL:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>Checksum<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span>---- |
| <span class="w"> </span>TCP<span class="w"> </span>ACK:<span class="w"> </span><span class="m">0000</span><span class="w"> </span>SYN:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>RST:<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>Type<span class="w"> </span><span class="m">0000</span><span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span> |
| Sent<span class="w"> </span><span class="m">0011</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0011</span> |
| <span class="w"> </span>Rexmit<span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span><span class="w"> </span>---- |
| </pre></div> |
| </div> |
| </section> |
| <section id="both-ipv4-and-ipv6"> |
| <h3>Both IPv4 and IPv6<a class="headerlink" href="#both-ipv4-and-ipv6" title="Permalink to this heading"></a></h3> |
| <p><code class="docutils literal notranslate"><span class="pre">CONFIG_NET_IPv4=y</span></code> and <code class="docutils literal notranslate"><span class="pre">CONFIG_NET_IPv6=y</span></code></p> |
| <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>nsh><span class="w"> </span>ifconfig |
| eth0<span class="w"> </span>Link<span class="w"> </span>encap:<span class="w"> </span>Ethernet<span class="w"> </span>HWaddr<span class="w"> </span><span class="m">00</span>:1a:b6:02:81:14<span class="w"> </span>at<span class="w"> </span>UP |
| <span class="w"> </span>inet<span class="w"> </span>addr:10.0.0.2<span class="w"> </span>DRaddr:10.0.0.1<span class="w"> </span>Mask:255.255.255.0 |
| <span class="w"> </span>inet6<span class="w"> </span>addr:fc00::2 |
| <span class="w"> </span>inet6<span class="w"> </span>DRaddr:fc00::1 |
| <span class="w"> </span>inet6<span class="w"> </span>Mask:ffff:ffff:ffff::ffff:ffff:ffff:ff80 |
| |
| <span class="w"> </span>IPv4<span class="w"> </span>IPv6<span class="w"> </span>TCP<span class="w"> </span>UDP<span class="w"> </span>ICMP<span class="w"> </span>ICMPv6 |
| Received<span class="w"> </span><span class="m">0047</span><span class="w"> </span>000a<span class="w"> </span>001c<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0004</span><span class="w"> </span>000a |
| Dropped<span class="w"> </span><span class="m">0027</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>IPv4<span class="w"> </span>VHL:<span class="w"> </span><span class="m">0000</span><span class="w"> </span>Frg:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>IPv6<span class="w"> </span>VHL:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>Checksum<span class="w"> </span><span class="m">0000</span><span class="w"> </span>----<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span>----<span class="w"> </span>---- |
| <span class="w"> </span>TCP<span class="w"> </span>ACK:<span class="w"> </span><span class="m">0000</span><span class="w"> </span>SYN:<span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>RST:<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| <span class="w"> </span>Type<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span><span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0000</span> |
| Sent<span class="w"> </span><span class="m">0033</span><span class="w"> </span>000a<span class="w"> </span>002f<span class="w"> </span><span class="m">0000</span><span class="w"> </span><span class="m">0004</span><span class="w"> </span>000a |
| <span class="w"> </span>Rexmit<span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span>----<span class="w"> </span><span class="m">0000</span><span class="w"> </span>----<span class="w"> </span>---- |
| </pre></div> |
| </div> |
| </section> |
| </section> |
| <section id="tests-applications-and-network-utilities"> |
| <h2>Tests, Applications, and Network Utilities<a class="headerlink" href="#tests-applications-and-network-utilities" title="Permalink to this heading"></a></h2> |
| <p>In addition to the core RTOS support IPv6, changes are also required to |
| networking tests, to networking aware applications, and, of course, to all of |
| the network utils (<code class="docutils literal notranslate"><span class="pre">netutils</span></code>).</p> |
| <ul class="simple"> |
| <li><p>NuttShell (NSH): IPv6 support is partially available. NSH is capable of |
| initializing the IPv6 domain and some of the NSH commands have been adapted |
| to support IPv6. A ping6 command has been added. But there are many commands |
| that still require updating.</p></li> |
| <li><p>Tests: There are several networking tests in <code class="docutils literal notranslate"><span class="pre">apps/examples</span></code>. The |
| <code class="docutils literal notranslate"><span class="pre">nettest</span></code> test and the <code class="docutils literal notranslate"><span class="pre">udp</span></code> test have been adapted to work in the IPv6 |
| domain, but none of the others have yet been adapted.</p></li> |
| <li><p>Netutils: The network utilities in <code class="docutils literal notranslate"><span class="pre">apps/netutils</span></code> have been adapted to |
| work with IPv6: DHCP, FTP, TFTP, Telnet, etc. Support for managing IPv6 |
| address have been included in the <code class="docutils literal notranslate"><span class="pre">netlib</span></code>, but nothing else has yet been |
| updated.</p></li> |
| </ul> |
| </section> |
| </section> |
| |
| |
| </div> |
| </div> |
| <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer"> |
| <a href="logging_rambuffer.html" class="btn btn-neutral float-left" title="Logging to a RAM Buffer" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> |
| <a href="integrate_newlib.html" class="btn btn-neutral float-right" title="Integrating with Newlib" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> |
| </div> |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <p>© Copyright 2023, The Apache Software Foundation.</p> |
| </div> |
| |
| |
| |
| </footer> |
| </div> |
| </div> |
| </section> |
| </div> |
| <script> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| </body> |
| </html> |