FreeBSD/sys/netinet6/ip6_output.c
/*
 * Calculates IPv6 path MTU for @dst based on transmit @ifp,
 * and cached data in @ro_pmtu.
 * MTU from (successful) route lookup is saved (along with dst)
 * inside @ro_pmtu to avoid subsequent route lookups after packet
 * filter processing.
 *
 * Stores mtu and always-frag value into @mtup and @alwaysfragp.
 * Returns 0 on success.
 */
Calculates IPv6 path MTU for @dst based on transmit @ifp,
and cached data in @ro_pmtu.
MTU from (successful) route lookup is saved (along with dst)
inside @ro_pmtu to avoid subsequent route lookups after packet
filter processing.

Stores mtu and always-frag value into @mtup and @alwaysfragp.
Returns 0 on success.
Calculates IPv6 path MTU for @dst based on transmit @ifp and cached data in @ro_pmtu . MTU from ( successful ) route lookup is saved ( along with dst ) inside @ro_pmtu to avoid subsequent route lookups after packet filter processing . Stores mtu and always - frag value into @mtup and @alwaysfragp . Returns 0 on success .
static int
ip6_getpmtu(struct route_in6 *ro_pmtu, int do_lookup,
    struct ifnet *ifp, const struct in6_addr *dst, u_long *mtup,
    int *alwaysfragp, u_int fibnum)
{
	struct nhop6_basic nh6;
	struct in6_addr kdst;
	uint32_t scopeid;
	struct sockaddr_in6 *sa6_dst;
	u_long mtu;
	mtu = 0;
	if (do_lookup) {
		sa6_dst = (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
		if (!IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))
			ro_pmtu->ro_mtu = 0;
		if (ro_pmtu->ro_mtu == 0) {
			bzero(sa6_dst, sizeof(*sa6_dst));
			sa6_dst->sin6_family = AF_INET6;
			sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
			sa6_dst->sin6_addr = *dst;
			in6_splitscope(dst, &kdst, &scopeid);
			if (fib6_lookup_nh_basic(fibnum, &kdst, scopeid, 0, 0,
			    &nh6) == 0)
				ro_pmtu->ro_mtu = nh6.nh_mtu;
		}
		mtu = ro_pmtu->ro_mtu;
	}
	if (ro_pmtu->ro_rt)
		mtu = ro_pmtu->ro_rt->rt_mtu;
	return (ip6_calcmtu(ifp, dst, mtu, mtup, alwaysfragp));
}
static int ip6_getpmtu ( struct route_in6 * ro_pmtu , int do_lookup , struct ifnet * ifp , const struct in6_addr * dst , u_long * mtup , int * alwaysfragp , u_int fibnum ) { struct nhop6_basic nh6 ; struct in6_addr kdst ; uint32_t scopeid ; struct sockaddr_in6 * sa6_dst ; u_long mtu ; mtu = 0 ; if ( do_lookup ) { sa6_dst = ( struct sockaddr_in6 * ) & ro_pmtu -> ro_dst ; if ( ! IN6_ARE_ADDR_EQUAL ( & sa6_dst -> sin6_addr , dst ) ) ro_pmtu -> ro_mtu = 0 ; if ( ro_pmtu -> ro_mtu == 0 ) { bzero ( sa6_dst , sizeof ( * sa6_dst ) ) ; sa6_dst -> sin6_family = AF_INET6 ; sa6_dst -> sin6_len = sizeof ( struct sockaddr_in6 ) ; sa6_dst -> sin6_addr = * dst ; in6_splitscope ( dst , & kdst , & scopeid ) ; if ( fib6_lookup_nh_basic ( fibnum , & kdst , scopeid , 0 , 0 , & nh6 ) == 0 ) ro_pmtu -> ro_mtu = nh6 . nh_mtu ; } mtu = ro_pmtu -> ro_mtu ; } if ( ro_pmtu -> ro_rt ) mtu = ro_pmtu -> ro_rt -> rt_mtu ; return ( ip6_calcmtu ( ifp , dst , mtu , mtup , alwaysfragp ) ) ; }
Calculates IPv6 path MTU for @dst based on transmit @ifp,
 and cached data in @ro_pmtu.
Calculates IPv6 path MTU for @dst based on transmit @ifp and cached data in @ro_pmtu .
/*
		 * Here ro_pmtu has final destination address, while
		 * ro might represent immediate destination.
		 * Use ro_pmtu destination since mtu might differ.
		 */