/************************************************************************
* NAME: fnet_netif_set_pmtu
* RETURS: None.
* DESCRIPTION: Sets PMTU of the interface.
*************************************************************************/
void fnet_netif_set_pmtu(fnet_netif_t *netif, unsigned long pmtu)
{
    /* Set Path MTU for the link. */
    netif->pmtu = pmtu;
            
    netif->pmtu_timestamp = fnet_timer_ms();
}
/************************************************************************
* NAME: fnet_nd6_dad_timer
* RETURS: None.
* DESCRIPTION: Timer routine used to detect increase of PMTU
*************************************************************************/
static void fnet_netif_pmtu_timer( void *cookie )
{
    fnet_netif_t    *netif = (fnet_netif_t *)cookie;
    
    if( fnet_timer_get_interval(netif->pmtu_timestamp, fnet_timer_ms()) > FNET_NETIF_PMTU_TIMEOUT)
    {
        fnet_netif_set_pmtu(netif, netif->mtu);
    }
}
Esempio n. 3
0
/************************************************************************
* NAME: fnet_eth_output_ip6
*
* DESCRIPTION: Ethernet IPv6 output function.
*************************************************************************/
void fnet_eth_output_ip6(fnet_netif_t *netif, const fnet_ip6_addr_t *src_ip_addr,  const fnet_ip6_addr_t *dest_ip_addr, fnet_netbuf_t *nb)
{
    fnet_mac_addr_t dest_mac_addr; /* 48-bit destination address */
    fnet_uint8_t *dest_mac_addr_ptr;

    /********************************************
    * Multicast.
    ********************************************/
    if (FNET_IP6_ADDR_IS_MULTICAST(dest_ip_addr))
    {
        FNET_ETH_MULTICAST_IP6_TO_MAC(dest_ip_addr, dest_mac_addr);

        dest_mac_addr_ptr = (fnet_uint8_t *)dest_mac_addr;
    }
    /********************************************
    * Unicast.
    ********************************************/
    else
    {
        fnet_nd6_neighbor_entry_t *neighbor;

        /* Possible redirection.*/
        fnet_nd6_redirect_addr(netif, &dest_ip_addr);

        /* Check Neigbor cache.*/
        neighbor = fnet_nd6_neighbor_cache_get(netif, dest_ip_addr);

        /* RFC4861 7.2.2: When a node has a unicast packet to send to a neighbor, but does not
         * know the neighbor’s link-layer address, it performs address resolution.
         * For multicast-capable interfaces, this entails creating a
         * Neighbor Cache entry in the INCOMPLETE state and transmitting a
         * Neighbor Solicitation message targeted at the neighbor. The
         * solicitation is sent to the solicited-node multicast address
         * corresponding to the target address.
         */
        if(neighbor == FNET_NULL)
        {
            /* RFC4861 7.2.Address resolution is performed only on addresses that are determined to be
             * on-link and for which the sender does not know the corresponding link-layer address.
             * Address resolution is never performed on multicast addresses.*/

            if(fnet_nd6_addr_is_onlink(netif, dest_ip_addr) == FNET_TRUE)
                /* Destimnation is ON local-link.*/
            {
                /* Creating a Neighbor Cache entry in the INCOMPLETE state. */
                neighbor = fnet_nd6_neighbor_cache_add(netif, dest_ip_addr, FNET_NULL, FNET_ND6_NEIGHBOR_STATE_INCOMPLETE);

                neighbor->state_time = fnet_timer_ms();
                neighbor->solicitation_send_counter = 0u;
                FNET_IP6_ADDR_COPY(src_ip_addr, &neighbor->solicitation_src_ip_addr); /* Save src address for later usage.*/

                /* AR: Transmitting a Neighbor Solicitation message targeted at the neighbor.*/
                fnet_nd6_neighbor_solicitation_send(netif, src_ip_addr, FNET_NULL /* NULL for AR */, dest_ip_addr);
            }
            /* Destination is OFF local-link.*/
            else
            {
                /* Try to use the router, if exists.*/
                neighbor = fnet_nd6_default_router_get(netif);

                if(neighbor == FNET_NULL)
                    /* No Router exists.*/
                {
                    fnet_netbuf_free_chain(nb); /* Discard datagram */
                    goto EXIT;
                }

                dest_ip_addr = &neighbor->ip_addr;   /* Chage destination address to the router one */
            }
        }

        /* Link -layer address is not initialized.*/
        if((neighbor->state != FNET_ND6_NEIGHBOR_STATE_INCOMPLETE)
           && (neighbor->ll_addr[0] == 0U) && (neighbor->ll_addr[1] == 0U) && (neighbor->ll_addr[2] == 0U)
           && (neighbor->ll_addr[3] == 0U) && (neighbor->ll_addr[4] == 0U) && (neighbor->ll_addr[5] == 0U) )
        {
            neighbor->state = FNET_ND6_NEIGHBOR_STATE_INCOMPLETE;
            neighbor->state_time = fnet_timer_ms();
            neighbor->solicitation_send_counter = 0u;
            FNET_IP6_ADDR_COPY(src_ip_addr, &neighbor->solicitation_src_ip_addr); /* Save src address for later usage.*/
            /* AR: Transmitting a Neighbor Solicitation message targeted at the neighbor.*/
            fnet_nd6_neighbor_solicitation_send(netif, src_ip_addr, FNET_NULL /* NULL for AR */, dest_ip_addr);
        }

        if(neighbor->state == FNET_ND6_NEIGHBOR_STATE_INCOMPLETE)
            /* Queue packet for later transmit.
             */
        {
            fnet_nd6_neighbor_enqueue_waiting_netbuf(neighbor, nb);
            goto EXIT;
        }

        if(neighbor->state == FNET_ND6_NEIGHBOR_STATE_STALE)
            /* RFC4861 7.3.3: The first time a node sends a packet to a neighbor whose entry is
             * STALE, the sender changes the state to DELAY and sets a timer to
             * expire in DELAY_FIRST_PROBE_TIME seconds.
             */
        {
            neighbor->state = FNET_ND6_NEIGHBOR_STATE_DELAY;
            neighbor->state_time = fnet_timer_ms();
        }

        /* Get destination MAC/HW address.*/
        dest_mac_addr_ptr = (fnet_uint8_t *)(&neighbor->ll_addr[0]);
    }

    /* Send Ethernet frame. */
    fnet_eth_output(netif, FNET_ETH_TYPE_IP6, dest_mac_addr_ptr, nb);

EXIT:
    return;
}