static void ip6_link_failure(struct sk_buff *skb) { struct rt6_info *rt; icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); rt = (struct rt6_info *) skb->dst; if (rt) { if (rt->rt6i_flags&RTF_CACHE) { dst_set_expires(&rt->u.dst, 0); rt->rt6i_flags |= RTF_EXPIRES; } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) rt->rt6i_node->fn_sernum = -1; } }
/* * The decnet standards don't impose a particular minimum mtu, what they * do insist on is that the routing layer accepts a datagram of at least * 230 bytes long. Here we have to subtract the routing header length from * 230 to get the minimum acceptable mtu. If there is no neighbour, then we * assume the worst and use a long header size. * * We update both the mtu and the advertised mss (i.e. the segment size we * advertise to the other end). */ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) { u32 min_mtu = 230; struct dn_dev *dn = dst->neighbour ? (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL; if (dn && dn->use_long == 0) min_mtu -= 6; else min_mtu -= 21; if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= min_mtu) { if (!(dst_metric_locked(dst, RTAX_MTU))) { dst->metrics[RTAX_MTU-1] = mtu; dst_set_expires(dst, dn_rt_mtu_expires); } if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; if (dst->metrics[RTAX_ADVMSS-1] > mss) dst->metrics[RTAX_ADVMSS-1] = mss; } } }
void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, struct net_device *dev, u32 pmtu) { struct rt6_info *rt, *nrt; if (pmtu < IPV6_MIN_MTU) { if (net_ratelimit()) printk(KERN_DEBUG "rt6_pmtu_discovery: invalid MTU value %d\n", pmtu); /* According to RFC1981, the PMTU is set to the IPv6 minimum link MTU if the node receives a Packet Too Big message reporting next-hop MTU that is less than the IPv6 minimum MTU. */ pmtu = IPV6_MIN_MTU; } rt = rt6_lookup(daddr, saddr, dev->ifindex, 0); if (rt == NULL) return; if (pmtu >= rt->u.dst.pmtu) goto out; /* New mtu received -> path was valid. They are sent only in response to data packets, so that this nexthop apparently is reachable. --ANK */ dst_confirm(&rt->u.dst); /* Host route. If it is static, it would be better not to override it, but add new one, so that when cache entry will expire old pmtu would return automatically. */ if (rt->rt6i_flags & RTF_CACHE) { rt->u.dst.pmtu = pmtu; dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires); rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; goto out; } /* Network route. Two cases are possible: 1. It is connected route. Action: COW 2. It is gatewayed route or NONEXTHOP route. Action: clone it. */ if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { nrt = rt6_cow(rt, daddr, saddr); if (!nrt->u.dst.error) { nrt->u.dst.pmtu = pmtu; /* According to RFC 1981, detecting PMTU increase shouldn't be happened within 5 mins, the recommended timer is 10 mins. Here this route expiration time is set to ip6_rt_mtu_expires which is 10 mins. After 10 mins the decreased pmtu is expired and detecting PMTU increase will be automatically happened. */ dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; dst_release(&nrt->u.dst); } } else { nrt = ip6_rt_copy(rt); if (nrt == NULL) goto out; ipv6_addr_copy(&nrt->rt6i_dst.addr, daddr); nrt->rt6i_dst.plen = 128; nrt->u.dst.flags |= DST_HOST; nrt->rt6i_nexthop = neigh_clone(rt->rt6i_nexthop); dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES; nrt->u.dst.pmtu = pmtu; rt6_ins(nrt, NULL); } out: dst_release(&rt->u.dst); }