/************************************************************************ * 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); } }
/************************************************************************ * 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; }