Commit 0580e4e8 authored by Alexey Kuznetsov's avatar Alexey Kuznetsov Committed by Hideaki Yoshifuji

[NET]: Cleanup DST metrics and abstract MSS/PMTU further.

- Changed dst named metrics, to RTAX_MAX metrics array.
- Add inline shorthands to access them
- Add update_pmtu and get_mss to DST ops.
- Add path component to DST, it is DST itself by default.
parent 145c04ec
......@@ -9,6 +9,7 @@
#define _NET_DST_H
#include <linux/config.h>
#include <linux/rtnetlink.h>
#include <net/neighbour.h>
/*
......@@ -22,6 +23,13 @@
#define DST_GC_INC (5*HZ)
#define DST_GC_MAX (120*HZ)
/* Each dst_entry has reference count and sits in some parent list(s).
* When it is removed from parent list, it is "freed" (dst_free).
* After this it enters dead state (dst->obsolete > 0) and if its refcnt
* is zero, it can be destroyed immediately, otherwise it is added
* to gc list and garbage collector periodically checks the refcnt.
*/
struct sk_buff;
struct dst_entry
......@@ -39,15 +47,8 @@ struct dst_entry
unsigned header_len; /* more space at head required */
unsigned mxlock;
unsigned pmtu;
unsigned window;
unsigned rtt;
unsigned rttvar;
unsigned ssthresh;
unsigned cwnd;
unsigned advmss;
unsigned reordering;
u32 metrics[RTAX_MAX];
struct dst_entry *path;
unsigned long rate_last; /* rate limiting for ICMP */
unsigned long rate_tokens;
......@@ -81,6 +82,8 @@ struct dst_ops
void (*destroy)(struct dst_entry *);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
int (*get_mss)(struct dst_entry *dst, u32 mtu);
int entry_size;
atomic_t entries;
......@@ -89,6 +92,33 @@ struct dst_ops
#ifdef __KERNEL__
static inline u32
dst_metric(struct dst_entry *dst, int metric)
{
return dst->metrics[metric-1];
}
static inline u32
dst_path_metric(struct dst_entry *dst, int metric)
{
return dst->path->metrics[metric-1];
}
static inline u32
dst_pmtu(struct dst_entry *dst)
{
u32 mtu = dst_path_metric(dst, RTAX_MTU);
/* Yes, _exactly_. This is paranoia. */
barrier();
return mtu;
}
static inline int
dst_metric_locked(struct dst_entry *dst, int metric)
{
return dst_metric(dst, RTAX_LOCK) & (1<<metric);
}
static inline void dst_hold(struct dst_entry * dst)
{
atomic_inc(&dst->__refcnt);
......
......@@ -178,7 +178,7 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
{
return (inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
(inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&
!(dst->mxlock&(1<<RTAX_MTU))));
!(dst_metric(dst, RTAX_LOCK)&(1<<RTAX_MTU))));
}
extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
......
......@@ -67,7 +67,7 @@ struct fib_info
int fib_protocol;
u32 fib_prefsrc;
u32 fib_priority;
unsigned fib_metrics[RTAX_MAX];
u32 fib_metrics[RTAX_MAX];
#define fib_mtu fib_metrics[RTAX_MTU-1]
#define fib_window fib_metrics[RTAX_WINDOW-1]
#define fib_rtt fib_metrics[RTAX_RTT-1]
......
......@@ -115,7 +115,6 @@ extern void rt_cache_flush(int how);
extern int ip_route_output_key(struct rtable **, const struct flowi *flp);
extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu);
extern void ip_rt_send_redirect(struct sk_buff *skb);
extern unsigned inet_addr_type(u32 addr);
......
......@@ -921,9 +921,11 @@ static __inline__ unsigned int tcp_current_mss(struct sock *sk, int large)
int mss_now = large && (sk->route_caps&NETIF_F_TSO) && !tp->urg_mode ?
tp->mss_cache : tp->mss_cache_std;
if (dst && dst->pmtu != tp->pmtu_cookie)
mss_now = tcp_sync_mss(sk, dst->pmtu);
if (dst) {
u32 mtu = dst_pmtu(dst);
if (mtu != tp->pmtu_cookie)
mss_now = tcp_sync_mss(sk, mtu);
}
if (tp->eff_sacks)
mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
(tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
......
......@@ -110,6 +110,7 @@ void * dst_alloc(struct dst_ops * ops)
memset(dst, 0, ops->entry_size);
dst->ops = ops;
dst->lastuse = jiffies;
dst->path = dst;
dst->input = dst_discard;
dst->output = dst_blackhole;
#if RT_CACHE_DEBUG >= 2
......
......@@ -1058,10 +1058,12 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int
RTA_PUT(skb, RTA_SRC, 2, &rt->rt_saddr);
if (rt->u.dst.dev)
RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);
if (rt->u.dst.window)
RTA_PUT(skb, RTAX_WINDOW, sizeof(unsigned), &rt->u.dst.window);
if (rt->u.dst.rtt)
RTA_PUT(skb, RTAX_RTT, sizeof(unsigned), &rt->u.dst.rtt);
if (dst_metric(&rt->u.dst, RTAX_WINDOW))
RTA_PUT(skb, RTAX_WINDOW, sizeof(unsigned),
&rt->u.dst.metrics[RTAX_WINDOW - 1]);
if (dst_metric(&rt->u.dst, RTAX_RTT))
RTA_PUT(skb, RTAX_RTT, sizeof(unsigned),
&rt->u.dst.metrics[RTAX_RTT]);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
......@@ -1217,7 +1219,7 @@ static int decnet_cache_get_info(char *buffer, char **start, off_t offset, int l
dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2),
atomic_read(&rt->u.dst.__refcnt),
rt->u.dst.__use,
(int)rt->u.dst.rtt
(int) dst_metric(&rt->u.dst, RTAX_RTT)
);
......
......@@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
/* RFC says return as much as we can without exceeding 576 bytes. */
room = rt->u.dst.pmtu;
room = dst_pmtu(&rt->u.dst);
if (room > 576)
room = 576;
room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen;
......
......@@ -40,6 +40,9 @@
#include <net/checksum.h>
#include <linux/route.h>
#include <net/route.h>
#if 0
#include <net/xfrm.h>
#endif
static inline int ip_forward_finish(struct sk_buff *skb)
{
......@@ -55,12 +58,14 @@ static inline int ip_forward_finish(struct sk_buff *skb)
int ip_forward(struct sk_buff *skb)
{
struct net_device *dev2; /* Output device */
struct iphdr *iph; /* Our header */
struct rtable *rt; /* Route we use */
struct ip_options * opt = &(IPCB(skb)->opt);
unsigned short mtu;
#if 0
if (!xfrm_policy_check(XFRM_POLICY_FWD, skb))
goto drop;
#endif
if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
return NET_RX_SUCCESS;
......@@ -76,32 +81,23 @@ int ip_forward(struct sk_buff *skb)
*/
iph = skb->nh.iph;
rt = (struct rtable*)skb->dst;
if (iph->ttl <= 1)
goto too_many_hops;
if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
goto sr_failed;
/*
* Having picked a route we can now send the frame out
* after asking the firewall permission to do so.
*/
#if 0
if (!xfrm_route_forward(skb))
goto drop;
#endif
skb->priority = rt_tos2priority(iph->tos);
dev2 = rt->u.dst.dev;
mtu = rt->u.dst.pmtu;
iph = skb->nh.iph;
rt = (struct rtable*)skb->dst;
/*
* We now generate an ICMP HOST REDIRECT giving the route
* we calculated.
*/
if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
ip_rt_send_redirect(skb);
if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
goto sr_failed;
/* We are about to mangle packet. Copy it! */
if (skb_cow(skb, dev2->hard_header_len))
if (skb_cow(skb, rt->u.dst.dev->hard_header_len+rt->u.dst.header_len))
goto drop;
iph = skb->nh.iph;
......@@ -109,30 +105,17 @@ int ip_forward(struct sk_buff *skb)
ip_decrease_ttl(iph);
/*
* We now may allocate a new buffer, and copy the datagram into it.
* If the indicated interface is up and running, kick it.
* We now generate an ICMP HOST REDIRECT giving the route
* we calculated.
*/
if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
ip_rt_send_redirect(skb);
if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF))
goto frag_needed;
#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags & RTCF_NAT) {
if (ip_do_nat(skb)) {
kfree_skb(skb);
return NET_RX_BAD;
}
}
#endif
skb->priority = rt_tos2priority(iph->tos);
return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2,
return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,
ip_forward_finish);
frag_needed:
IP_INC_STATS_BH(IpFragFails);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
goto drop;
sr_failed:
/*
* Strict routing permits no gatewaying
......
......@@ -773,13 +773,16 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
df = tiph->frag_off;
if (df)
mtu = rt->u.dst.pmtu - tunnel->hlen;
mtu = dst_pmtu(&rt->u.dst) - tunnel->hlen;
else
mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
if (skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
if (skb->protocol == htons(ETH_P_IP)) {
if (skb->dst && mtu < skb->dst->pmtu && mtu >= 68)
skb->dst->pmtu = mtu;
if (skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
df |= (old_iph->frag_off&htons(IP_DF));
......@@ -794,11 +797,11 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
else if (skb->protocol == htons(ETH_P_IPV6)) {
struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
if (rt6 && mtu < rt6->u.dst.pmtu && mtu >= IPV6_MIN_MTU) {
if (rt6 && mtu < dst_pmtu(skb->dst) && mtu >= IPV6_MIN_MTU) {
if ((tunnel->parms.iph.daddr && !MULTICAST(tunnel->parms.iph.daddr)) ||
rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
skb->dst->pmtu = mtu;
skb->dst->metrics[RTAX_MTU-1] = mtu;
}
}
......
......@@ -287,6 +287,7 @@ int ip_queue_xmit(struct sk_buff *skb)
struct ip_options *opt = inet->opt;
struct rtable *rt;
struct iphdr *iph;
u32 mtu;
/* Skip all of this if the packet is already routed,
* f.e. by something like SCTP.
......@@ -352,12 +353,13 @@ int ip_queue_xmit(struct sk_buff *skb)
ip_options_build(skb, opt, inet->daddr, rt, 0);
}
if (skb->len > rt->u.dst.pmtu && (sk->route_caps&NETIF_F_TSO)) {
mtu = dst_pmtu(&rt->u.dst);
if (skb->len > mtu && (sk->route_caps&NETIF_F_TSO)) {
unsigned int hlen;
/* Hack zone: all this must be done by TCP. */
hlen = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
skb_shinfo(skb)->tso_size = rt->u.dst.pmtu - hlen;
skb_shinfo(skb)->tso_size = mtu - hlen;
skb_shinfo(skb)->tso_segs =
(skb->len - hlen + skb_shinfo(skb)->tso_size - 1)/
skb_shinfo(skb)->tso_size - 1;
......@@ -436,7 +438,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
if (unlikely(iph->frag_off & htons(IP_DF))) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(rt->u.dst.pmtu));
htonl(dst_pmtu(&rt->u.dst)));
kfree_skb(skb);
return -EMSGSIZE;
}
......@@ -446,7 +448,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
*/
hlen = iph->ihl * 4;
mtu = rt->u.dst.pmtu - hlen; /* Size of data space */
mtu = dst_pmtu(&rt->u.dst) - hlen; /* Size of data space */
/* When frag_list is given, use it. First, check its validity:
* some transformers could create wrong frag_list or break existing
......@@ -747,7 +749,7 @@ int ip_append_data(struct sock *sk,
inet->cork.addr = ipc->addr;
}
dst_hold(&rt->u.dst);
inet->cork.fragsize = mtu = rt->u.dst.pmtu;
inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
inet->cork.rt = rt;
inet->cork.length = 0;
inet->sndmsg_page = NULL;
......@@ -834,7 +836,7 @@ int ip_append_data(struct sock *sk,
* Find where to start putting bytes.
*/
data = skb_put(skb, fraglen);
skb->nh.raw = __skb_pull(skb, exthdrlen);
skb->nh.raw = data + exthdrlen;
data += fragheaderlen;
skb->h.raw = data + exthdrlen;
......@@ -1063,6 +1065,9 @@ int ip_push_pending_frames(struct sock *sk)
goto out;
tail_skb = &(skb_shinfo(skb)->frag_list);
/* move skb->data to ip header from ext header */
if (skb->data < skb->nh.raw)
__skb_pull(skb, skb->nh.raw - skb->data);
while ((tmp_skb = __skb_dequeue(&sk->write_queue)) != NULL) {
__skb_pull(tmp_skb, skb->h.raw - skb->nh.raw);
*tail_skb = tmp_skb;
......
......@@ -726,7 +726,7 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
val = 0;
dst = sk_dst_get(sk);
if (dst) {
val = dst->pmtu;
val = dst_pmtu(dst) - dst->header_len;
dst_release(dst);
}
if (!val) {
......
......@@ -583,17 +583,17 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (tiph->frag_off)
mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
mtu = dst_pmtu(&rt->u.dst) - sizeof(struct iphdr);
else
mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
if (mtu < 68) {
tunnel->stat.collisions++;
ip_rt_put(rt);
goto tx_error;
}
if (skb->dst && mtu < skb->dst->pmtu)
skb->dst->pmtu = mtu;
if (skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
df |= (old_iph->frag_off&htons(IP_DF));
......
......@@ -133,6 +133,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static void ipv4_dst_destroy(struct dst_entry *dst);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
static int rt_garbage_collect(void);
......@@ -144,6 +145,7 @@ struct dst_ops ipv4_dst_ops = {
.destroy = ipv4_dst_destroy,
.negative_advice = ipv4_negative_advice,
.link_failure = ipv4_link_failure,
.update_pmtu = ip_rt_update_pmtu,
.entry_size = sizeof(struct rtable),
};
......@@ -245,10 +247,11 @@ static int rt_cache_get_info(char *buffer, char **start, off_t offset,
r->u.dst.__use,
0,
(unsigned long)r->rt_src,
(r->u.dst.advmss ?
(int) r->u.dst.advmss + 40 : 0),
r->u.dst.window,
(int)((r->u.dst.rtt >> 3) + r->u.dst.rttvar),
(dst_metric(&r->u.dst, RTAX_ADVMSS) ?
(int) dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0),
dst_metric(&r->u.dst, RTAX_WINDOW),
(int)((dst_metric(&r->u.dst, RTAX_RTT) >> 3)
+ dst_metric(&r->u.dst, RTAX_RTTVAR)),
r->fl.fl4_tos,
r->u.dst.hh ?
atomic_read(&r->u.dst.hh->hh_refcnt) :
......@@ -1056,28 +1059,28 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
rth->rt_src == iph->saddr &&
rth->fl.fl4_tos == tos &&
rth->fl.iif == 0 &&
!(rth->u.dst.mxlock & (1 << RTAX_MTU))) {
!(dst_metric_locked(&rth->u.dst, RTAX_MTU))) {
unsigned short mtu = new_mtu;
if (new_mtu < 68 || new_mtu >= old_mtu) {
/* BSD 4.2 compatibility hack :-( */
if (mtu == 0 &&
old_mtu >= rth->u.dst.pmtu &&
old_mtu >= rth->u.dst.metrics[RTAX_MTU-1] &&
old_mtu >= 68 + (iph->ihl << 2))
old_mtu -= iph->ihl << 2;
mtu = guess_mtu(old_mtu);
}
if (mtu <= rth->u.dst.pmtu) {
if (mtu < rth->u.dst.pmtu) {
if (mtu <= rth->u.dst.metrics[RTAX_MTU-1]) {
if (mtu < rth->u.dst.metrics[RTAX_MTU-1]) {
dst_confirm(&rth->u.dst);
if (mtu < ip_rt_min_pmtu) {
mtu = ip_rt_min_pmtu;
rth->u.dst.mxlock |=
rth->u.dst.metrics[RTAX_LOCK-1] |=
(1 << RTAX_MTU);
}
rth->u.dst.pmtu = mtu;
rth->u.dst.metrics[RTAX_MTU-1] = mtu;
dst_set_expires(&rth->u.dst,
ip_rt_mtu_expires);
}
......@@ -1090,15 +1093,15 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
return est_mtu ? : new_mtu;
}
void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu)
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
{
if (dst->pmtu > mtu && mtu >= 68 &&
!(dst->mxlock & (1 << RTAX_MTU))) {
if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= 68 &&
!(dst_metric_locked(dst, RTAX_MTU))) {
if (mtu < ip_rt_min_pmtu) {
mtu = ip_rt_min_pmtu;
dst->mxlock |= (1 << RTAX_MTU);
dst->metrics[RTAX_LOCK-1] |= (1 << RTAX_MTU);
}
dst->pmtu = mtu;
dst->metrics[RTAX_MTU-1] = mtu;
dst_set_expires(dst, ip_rt_mtu_expires);
}
}
......@@ -1189,28 +1192,28 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
if (FIB_RES_GW(*res) &&
FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
rt->rt_gateway = FIB_RES_GW(*res);
memcpy(&rt->u.dst.mxlock, fi->fib_metrics,
sizeof(fi->fib_metrics));
memcpy(rt->u.dst.metrics, fi->fib_metrics,
sizeof(rt->u.dst.metrics));
if (fi->fib_mtu == 0) {
rt->u.dst.pmtu = rt->u.dst.dev->mtu;
if (rt->u.dst.mxlock & (1 << RTAX_MTU) &&
rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
if (rt->u.dst.metrics[RTAX_LOCK-1] & (1 << RTAX_MTU) &&
rt->rt_gateway != rt->rt_dst &&
rt->u.dst.pmtu > 576)
rt->u.dst.pmtu = 576;
rt->u.dst.dev->mtu > 576)
rt->u.dst.metrics[RTAX_MTU-1] = 576;
}
#ifdef CONFIG_NET_CLS_ROUTE
rt->u.dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
#endif
} else
rt->u.dst.pmtu = rt->u.dst.dev->mtu;
rt->u.dst.metrics[RTAX_MTU-1]= rt->u.dst.dev->mtu;
if (rt->u.dst.pmtu > IP_MAX_MTU)
rt->u.dst.pmtu = IP_MAX_MTU;
if (rt->u.dst.advmss == 0)
rt->u.dst.advmss = max_t(unsigned int, rt->u.dst.dev->mtu - 40,
if (rt->u.dst.metrics[RTAX_MTU-1] > IP_MAX_MTU)
rt->u.dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0)
rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->u.dst.dev->mtu - 40,
ip_rt_min_advmss);
if (rt->u.dst.advmss > 65535 - 40)
rt->u.dst.advmss = 65535 - 40;
if (rt->u.dst.metrics[RTAX_ADVMSS-1] > 65535 - 40)
rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535 - 40;
#ifdef CONFIG_NET_CLS_ROUTE
#ifdef CONFIG_IP_MULTIPLE_TABLES
......@@ -2057,7 +2060,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src);
if (rt->rt_dst != rt->rt_gateway)
RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);
if (rtnetlink_put_metrics(skb, &rt->u.dst.mxlock) < 0)
if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
goto rtattr_failure;
ci.rta_lastuse = jiffies - rt->u.dst.lastuse;
ci.rta_used = rt->u.dst.__use;
......
......@@ -526,25 +526,25 @@ void tcp_update_metrics(struct sock *sk)
* Probably, no packets returned in time.
* Reset our results.
*/
if (!(dst->mxlock&(1<<RTAX_RTT)))
dst->rtt = 0;
if (!(dst_metric_locked(dst, RTAX_RTT)))
dst->metrics[RTAX_RTT-1] = 0;
return;
}
m = dst->rtt - tp->srtt;
m = dst_metric(dst, RTAX_RTT) - tp->srtt;
/* If newly calculated rtt larger than stored one,
* store new one. Otherwise, use EWMA. Remember,
* rtt overestimation is always better than underestimation.
*/
if (!(dst->mxlock&(1<<RTAX_RTT))) {
if (!(dst_metric_locked(dst, RTAX_RTT))) {
if (m <= 0)
dst->rtt = tp->srtt;
dst->metrics[RTAX_RTT-1] = tp->srtt;
else
dst->rtt -= (m>>3);
dst->metrics[RTAX_RTT-1] -= (m>>3);
}
if (!(dst->mxlock&(1<<RTAX_RTTVAR))) {
if (!(dst_metric_locked(dst, RTAX_RTTVAR))) {
if (m < 0)
m = -m;
......@@ -553,45 +553,46 @@ void tcp_update_metrics(struct sock *sk)
if (m < tp->mdev)
m = tp->mdev;
if (m >= dst->rttvar)
dst->rttvar = m;
if (m >= dst_metric(dst, RTAX_RTTVAR))
dst->metrics[RTAX_RTTVAR-1] = m;
else
dst->rttvar -= (dst->rttvar - m)>>2;
dst->metrics[RTAX_RTT-1] -=
(dst->metrics[RTAX_RTT-1] - m)>>2;
}
if (tp->snd_ssthresh >= 0xFFFF) {
/* Slow start still did not finish. */
if (dst->ssthresh &&
!(dst->mxlock&(1<<RTAX_SSTHRESH)) &&
(tp->snd_cwnd >> 1) > dst->ssthresh)
dst->ssthresh = tp->snd_cwnd >> 1;
if (!(dst->mxlock&(1<<RTAX_CWND)) &&
tp->snd_cwnd > dst->cwnd)
dst->cwnd = tp->snd_cwnd;
if (dst_metric(dst, RTAX_SSTHRESH) &&
!dst_metric_locked(dst, RTAX_SSTHRESH) &&
(tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH))
dst->metrics[RTAX_SSTHRESH-1] = tp->snd_cwnd >> 1;
if (!dst_metric_locked(dst, RTAX_CWND) &&
tp->snd_cwnd > dst_metric(dst, RTAX_CWND))
dst->metrics[RTAX_CWND-1] = tp->snd_cwnd;
} else if (tp->snd_cwnd > tp->snd_ssthresh &&
tp->ca_state == TCP_CA_Open) {
/* Cong. avoidance phase, cwnd is reliable. */
if (!(dst->mxlock&(1<<RTAX_SSTHRESH)))
dst->ssthresh = max(tp->snd_cwnd >> 1,
tp->snd_ssthresh);
if (!(dst->mxlock&(1<<RTAX_CWND)))
dst->cwnd = (dst->cwnd + tp->snd_cwnd) >> 1;
if (!dst_metric_locked(dst, RTAX_SSTHRESH))
dst->metrics[RTAX_SSTHRESH-1] =
max(tp->snd_cwnd >> 1, tp->snd_ssthresh);
if (!dst_metric_locked(dst, RTAX_CWND))
dst->metrics[RTAX_CWND-1] = (dst->metrics[RTAX_CWND-1] + tp->snd_cwnd) >> 1;
} else {
/* Else slow start did not finish, cwnd is non-sense,
ssthresh may be also invalid.
*/
if (!(dst->mxlock&(1<<RTAX_CWND)))
dst->cwnd = (dst->cwnd + tp->snd_ssthresh) >> 1;
if (dst->ssthresh &&
!(dst->mxlock&(1<<RTAX_SSTHRESH)) &&
tp->snd_ssthresh > dst->ssthresh)
dst->ssthresh = tp->snd_ssthresh;
if (!dst_metric_locked(dst, RTAX_CWND))
dst->metrics[RTAX_CWND-1] = (dst->metrics[RTAX_CWND-1] + tp->snd_ssthresh) >> 1;
if (dst->metrics[RTAX_SSTHRESH-1] &&
!dst_metric_locked(dst, RTAX_SSTHRESH) &&
tp->snd_ssthresh > dst->metrics[RTAX_SSTHRESH-1])
dst->metrics[RTAX_SSTHRESH-1] = tp->snd_ssthresh;
}
if (!(dst->mxlock&(1<<RTAX_REORDERING))) {
if (dst->reordering < tp->reordering &&
if (!dst_metric_locked(dst, RTAX_REORDERING)) {
if (dst->metrics[RTAX_REORDERING-1] < tp->reordering &&
tp->reordering != sysctl_tcp_reordering)
dst->reordering = tp->reordering;
dst->metrics[RTAX_REORDERING-1] = tp->reordering;
}
}
}
......@@ -630,22 +631,23 @@ static void tcp_init_metrics(struct sock *sk)
dst_confirm(dst);
if (dst->mxlock&(1<<RTAX_CWND))
tp->snd_cwnd_clamp = dst->cwnd;
if (dst->ssthresh) {
tp->snd_ssthresh = dst->ssthresh;
if (dst_metric_locked(dst, RTAX_CWND))
tp->snd_cwnd_clamp = dst_metric(dst, RTAX_CWND);
if (dst_metric(dst, RTAX_SSTHRESH)) {
tp->snd_ssthresh = dst_metric(dst, RTAX_SSTHRESH);
if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
tp->snd_ssthresh = tp->snd_cwnd_clamp;
}
if (dst->reordering && tp->reordering != dst->reordering) {
if (dst_metric(dst, RTAX_REORDERING) &&
tp->reordering != dst_metric(dst, RTAX_REORDERING)) {
tp->sack_ok &= ~2;
tp->reordering = dst->reordering;
tp->reordering = dst_metric(dst, RTAX_REORDERING);
}
if (dst->rtt == 0)
if (dst_metric(dst, RTAX_RTT) == 0)
goto reset;
if (!tp->srtt && dst->rtt < (TCP_TIMEOUT_INIT << 3))
if (!tp->srtt && dst_metric(dst, RTAX_RTT) < (TCP_TIMEOUT_INIT << 3))
goto reset;
/* Initial rtt is determined from SYN,SYN-ACK.
......@@ -662,10 +664,10 @@ static void tcp_init_metrics(struct sock *sk)
* to low value, and then abruptly stops to do it and starts to delay
* ACKs, wait for troubles.
*/
if (dst->rtt > tp->srtt)
tp->srtt = dst->rtt;
if (dst->rttvar > tp->mdev) {
tp->mdev = dst->rttvar;
if (dst_metric(dst, RTAX_RTT) > tp->srtt)
tp->srtt = dst_metric(dst, RTAX_RTT);
if (dst_metric(dst, RTAX_RTTVAR) > tp->mdev) {
tp->mdev = dst_metric(dst, RTAX_RTTVAR);
tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
}
tcp_set_rto(tp);
......
......@@ -933,7 +933,7 @@ static void tcp_v4_synq_add(struct sock *sk, struct open_request *req)
* This routine does path mtu discovery as defined in RFC1191.
*/
static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph,
unsigned mtu)
u32 mtu)
{
struct dst_entry *dst;
struct inet_opt *inet = inet_sk(sk);
......@@ -955,17 +955,19 @@ static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph,
if ((dst = __sk_dst_check(sk, 0)) == NULL)
return;
ip_rt_update_pmtu(dst, mtu);
dst->ops->update_pmtu(dst, mtu);
/* Something is about to be wrong... Remember soft error
* for the case, if this connection will not able to recover.
*/
if (mtu < dst->pmtu && ip_dont_fragment(sk, dst))
if (mtu < dst_pmtu(dst) && ip_dont_fragment(sk, dst))
sk->err_soft = EMSGSIZE;
mtu = dst_pmtu(dst);
if (inet->pmtudisc != IP_PMTUDISC_DONT &&
tp->pmtu_cookie > dst->pmtu) {
tcp_sync_mss(sk, dst->pmtu);
tp->pmtu_cookie > mtu) {
tcp_sync_mss(sk, mtu);
/* Resend the TCP packet because it's
* clear that the old packet has been
......@@ -1523,7 +1525,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
(sysctl_max_syn_backlog - tcp_synq_len(sk) <
(sysctl_max_syn_backlog >> 2)) &&
(!peer || !peer->tcp_ts_stamp) &&
(!dst || !dst->rtt)) {
(!dst || !dst_metric(dst, RTAX_RTT))) {
/* Without syncookies last quarter of
* backlog is filled with destinations,
* proven to be alive.
......@@ -1603,8 +1605,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newtp->ext_header_len += dst->header_len;
newinet->id = newtp->write_seq ^ jiffies;
tcp_sync_mss(newsk, dst->pmtu);
newtp->advmss = dst->advmss;
tcp_sync_mss(newsk, dst_pmtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);;
tcp_initialize_rcv_mss(newsk);
__tcp_v4_hash(newsk, 0);
......
......@@ -89,8 +89,8 @@ static __u16 tcp_advertise_mss(struct sock *sk)
struct dst_entry *dst = __sk_dst_get(sk);
int mss = tp->advmss;
if (dst && dst->advmss < mss) {
mss = dst->advmss;
if (dst && dst_metric(dst, RTAX_ADVMSS) < mss) {
mss = dst_metric(dst, RTAX_ADVMSS);
tp->advmss = mss;
}
......@@ -554,13 +554,17 @@ static int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
int tcp_sync_mss(struct sock *sk, u32 pmtu)
{
struct tcp_opt *tp = tcp_sk(sk);
struct dst_entry *dst = __sk_dst_get(sk);
int mss_now;
if (dst && dst->ops->get_mss)
pmtu = dst->ops->get_mss(dst, pmtu);
/* Calculate base mss without TCP options:
It is MMS_S - sizeof(tcphdr) of rfc1122
*/
mss_now = pmtu - tp->af_specific->net_header_len - sizeof(struct tcphdr);
/* Clamp it (mss_clamp does not include tcp options) */
if (mss_now > tp->mss_clamp)
mss_now = tp->mss_clamp;
......@@ -1211,10 +1215,10 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
__u8 rcv_wscale;
/* Set this up on the first call only */
req->window_clamp = tp->window_clamp ? : dst->window;
req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW);
/* tcp_full_space because it is guaranteed to be the first packet */
tcp_select_initial_window(tcp_full_space(sk),
dst->advmss - (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
dst_metric(dst, RTAX_ADVMSS) - (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
&req->rcv_wnd,
&req->window_clamp,
req->wscale_ok,
......@@ -1226,7 +1230,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
th->window = htons(req->rcv_wnd);
TCP_SKB_CB(skb)->when = tcp_time_stamp;
tcp_syn_build_options((__u32 *)(th + 1), dst->advmss, req->tstamp_ok,
tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), req->tstamp_ok,
req->sack_ok, req->wscale_ok, req->rcv_wscale,
TCP_SKB_CB(skb)->when,
req->ts_recent);
......@@ -1255,11 +1259,11 @@ static inline void tcp_connect_init(struct sock *sk)
if (tp->user_mss)
tp->mss_clamp = tp->user_mss;
tp->max_window = 0;
tcp_sync_mss(sk, dst->pmtu);
tcp_sync_mss(sk, dst_pmtu(dst));
if (!tp->window_clamp)
tp->window_clamp = dst->window;
tp->advmss = dst->advmss;
tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
tp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(sk);
tcp_select_initial_window(tcp_full_space(sk),
......
......@@ -191,6 +191,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
u8 proto = fl->proto;
int seg_len = skb->len;
int hlimit;
u32 mtu;
if (opt) {
int head_room;
......@@ -237,14 +238,15 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
ipv6_addr_copy(&hdr->saddr, fl->nl_u.ip6_u.saddr);
ipv6_addr_copy(&hdr->daddr, first_hop);
if (skb->len <= dst->pmtu) {
mtu = dst_pmtu(dst);
if (skb->len <= mtu) {
IP6_INC_STATS(Ip6OutRequests);
return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
}
if (net_ratelimit())
printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
kfree_skb(skb);
return -EMSGSIZE;
}
......@@ -600,7 +602,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
}
}
mtu = dst->pmtu;
mtu = dst_pmtu(dst);
if (np->frag_size < mtu) {
if (np->frag_size)
mtu = np->frag_size;
......@@ -796,10 +798,10 @@ int ip6_forward(struct sk_buff *skb)
goto error;
}
if (skb->len > dst->pmtu) {
if (skb->len > dst_pmtu(dst)) {
/* Again, force OUTPUT device used as source address */
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_pmtu(dst), skb->dev);
IP6_INC_STATS_BH(Ip6InTooBigErrors);
kfree_skb(skb);
return -EMSGSIZE;
......
......@@ -474,7 +474,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, char *optval,
lock_sock(sk);
dst = sk_dst_get(sk);
if (dst) {
val = dst->pmtu;
val = dst_pmtu(dst) - dst->header_len;
dst_release(dst);
}
release_sock(sk);
......
......@@ -759,7 +759,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
in6_dev->cnf.mtu6 = mtu;
if (rt)
rt->u.dst.pmtu = mtu;
rt->u.dst.metrics[RTAX_MTU-1] = mtu;
rt6_mtu_change(skb->dev, mtu);
}
......
......@@ -83,18 +83,18 @@ static int ip6_dst_gc(void);
static int ip6_pkt_discard(struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
static struct dst_ops ip6_dst_ops = {
AF_INET6,
__constant_htons(ETH_P_IPV6),
1024,
ip6_dst_gc,
ip6_dst_check,
NULL,
ip6_negative_advice,
ip6_link_failure,
sizeof(struct rt6_info),
.family = AF_INET6,
.protocol = __constant_htons(ETH_P_IPV6),
.gc = ip6_dst_gc,
.gc_thresh = 1024,
.check = ip6_dst_check,
.negative_advice = ip6_negative_advice,
.link_failure = ip6_link_failure,
.update_pmtu = ip6_rt_update_pmtu,
.entry_size = sizeof(struct rt6_info),
};
struct rt6_info ip6_null_entry = {
......@@ -536,6 +536,16 @@ static void ip6_link_failure(struct sk_buff *skb)
}
}
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
{
struct rt6_info *rt6 = (struct rt6_info*)dst;
if (mtu < dst_pmtu(dst) && rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
dst->metrics[RTAX_MTU-1] = mtu;
}
}
static int ip6_dst_gc()
{
static unsigned expire = 30*HZ;
......@@ -742,14 +752,14 @@ int ip6_route_add(struct in6_rtmsg *rtmsg)
rt->rt6i_flags = rtmsg->rtmsg_flags;
install_route:
rt->u.dst.pmtu = ipv6_get_mtu(dev);
rt->u.dst.advmss = max_t(unsigned int, rt->u.dst.pmtu - 60, ip6_rt_min_advmss);
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, dst_pmtu(&rt->u.dst) - 60, ip6_rt_min_advmss);
/* Maximal non-jumbo IPv6 payload is 65535 and corresponding
MSS is 65535 - tcp_header_size. 65535 is also valid and
means: "any MSS, rely only on pmtu discovery"
*/
if (rt->u.dst.advmss > 65535-20)
rt->u.dst.advmss = 65535;
if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535-20)
rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
rt->u.dst.dev = dev;
return rt6_ins(rt);
......@@ -901,10 +911,10 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
nrt->rt6i_nexthop = neigh_clone(neigh);
/* Reset pmtu, it may be better */
nrt->u.dst.pmtu = ipv6_get_mtu(neigh->dev);
nrt->u.dst.advmss = max_t(unsigned int, nrt->u.dst.pmtu - 60, ip6_rt_min_advmss);
if (rt->u.dst.advmss > 65535-20)
rt->u.dst.advmss = 65535;
nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
nrt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, dst_pmtu(&nrt->u.dst) - 60, ip6_rt_min_advmss);
if (nrt->u.dst.metrics[RTAX_ADVMSS-1] > 65535-20)
nrt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev);
if (rt6_ins(nrt))
......@@ -942,7 +952,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
if (rt == NULL)
return;
if (pmtu >= rt->u.dst.pmtu)
if (pmtu >= dst_pmtu(&rt->u.dst))
goto out;
/* New mtu received -> path was valid.
......@@ -957,7 +967,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
would return automatically.
*/
if (rt->rt6i_flags & RTF_CACHE) {
rt->u.dst.pmtu = pmtu;
rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires);
rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
goto out;
......@@ -971,7 +981,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
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;
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires);
nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
dst_release(&nrt->u.dst);
......@@ -986,7 +996,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
nrt->rt6i_nexthop = neigh_clone(rt->rt6i_nexthop);
dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires);
nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
nrt->u.dst.pmtu = pmtu;
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
rt6_ins(nrt);
}
......@@ -1008,7 +1018,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
rt->u.dst.input = ort->u.dst.input;
rt->u.dst.output = ort->u.dst.output;
memcpy(&rt->u.dst.mxlock, &ort->u.dst.mxlock, RTAX_MAX*sizeof(unsigned));
memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
rt->u.dst.dev = ort->u.dst.dev;
if (rt->u.dst.dev)
dev_hold(rt->u.dst.dev);
......@@ -1156,10 +1166,10 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
rt->u.dst.input = ip6_input;
rt->u.dst.output = ip6_output;
rt->rt6i_dev = dev_get_by_name("lo");
rt->u.dst.pmtu = ipv6_get_mtu(rt->rt6i_dev);
rt->u.dst.advmss = max_t(unsigned int, rt->u.dst.pmtu - 60, ip6_rt_min_advmss);
if (rt->u.dst.advmss > 65535-20)
rt->u.dst.advmss = 65535;
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, dst_pmtu(&rt->u.dst) - 60, ip6_rt_min_advmss);
if (rt->u.dst.metrics[RTAX_ADVMSS-1] > 65535-20)
rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
rt->rt6i_hoplimit = ipv6_get_hoplimit(rt->rt6i_dev);
rt->u.dst.obsolete = -1;
......@@ -1230,12 +1240,12 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
caused by addrconf/ndisc.
*/
if (rt->rt6i_dev == arg->dev &&
rt->u.dst.pmtu > arg->mtu &&
!(rt->u.dst.mxlock&(1<<RTAX_MTU)))
rt->u.dst.pmtu = arg->mtu;
rt->u.dst.advmss = max_t(unsigned int, arg->mtu - 60, ip6_rt_min_advmss);
if (rt->u.dst.advmss > 65535-20)
rt->u.dst.advmss = 65535;
rt->u.dst.metrics[RTAX_MTU-1] > arg->mtu &&
!dst_metric_locked(&rt->u.dst, RTAX_MTU))
rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, arg->mtu - 60, ip6_rt_min_advmss);
if (rt->u.dst.metrics[RTAX_ADVMSS-1] > 65535-20)
rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
return 0;
}
......@@ -1372,7 +1382,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
}
if (rtnetlink_put_metrics(skb, &rt->u.dst.mxlock) < 0)
if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
goto rtattr_failure;
if (rt->u.dst.neighbour)
RTA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key);
......
......@@ -519,9 +519,9 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (tiph->frag_off)
mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
mtu = dst_pmtu(&rt->u.dst) - sizeof(struct iphdr);
else
mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
if (mtu < 68) {
tunnel->stat.collisions++;
......@@ -530,15 +530,9 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU;
if (skb->dst && mtu < skb->dst->pmtu) {
struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
if (mtu < rt6->u.dst.pmtu) {
if (tunnel->parms.iph.daddr || rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
rt6->u.dst.pmtu = mtu;
}
}
}
if (tunnel->parms.iph.daddr && skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
if (skb->len > mtu) {
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
ip_rt_put(rt);
......
......@@ -805,8 +805,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (dst->error) {
sk->err_soft = -dst->error;
} else if (tp->pmtu_cookie > dst->pmtu) {
tcp_sync_mss(sk, dst->pmtu);
} else if (tp->pmtu_cookie > dst_pmtu(dst)) {
tcp_sync_mss(sk, dst_pmtu(dst));
tcp_simple_retransmit(sk);
} /* else let the usual retransmit timer handle it */
dst_release(dst);
......@@ -1416,8 +1416,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newtp->ext_header_len = newnp->opt->opt_nflen +
newnp->opt->opt_flen;
tcp_sync_mss(newsk, dst->pmtu);
newtp->advmss = dst->advmss;
tcp_sync_mss(newsk, dst_pmtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(newsk);
newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
......
......@@ -175,7 +175,7 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address)
dst = ip6_route_output(NULL, &fl);
if (dst) {
dst_mtu = dst->pmtu;
dst_mtu = dst_pmtu(dst);
SCTP_DEBUG_PRINTK("sctp_v6_get_dst_mtu: "
"ip6_route_output: dev:%s pmtu:%d\n",
dst->dev->name, dst_mtu);
......
......@@ -268,7 +268,7 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address)
" failed, returning %d as dst_mtu\n",
dst_mtu);
} else {
dst_mtu = rt->u.dst.pmtu;
dst_mtu = dst_pmtu(&rt->u.dst);
SCTP_DEBUG_PRINTK("sctp_v4_get_dst_mtu: "
"ip_route_output_key: dev:%s pmtu:%d\n",
rt->u.dst.dev->name, dst_mtu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment