|
@@ -677,7 +677,7 @@ static inline int rt_fast_clean(struct rtable *rth)
|
|
|
static inline int rt_valuable(struct rtable *rth)
|
|
|
{
|
|
|
return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
|
|
|
- (rth->peer && rth->peer->pmtu_expires);
|
|
|
+ (rt_has_peer(rth) && rt_peer_ptr(rth)->pmtu_expires);
|
|
|
}
|
|
|
|
|
|
static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
|
|
@@ -1325,12 +1325,16 @@ static u32 rt_peer_genid(void)
|
|
|
|
|
|
void rt_bind_peer(struct rtable *rt, __be32 daddr, int create)
|
|
|
{
|
|
|
- struct net *net = dev_net(rt->dst.dev);
|
|
|
+ struct inet_peer_base *base;
|
|
|
struct inet_peer *peer;
|
|
|
|
|
|
- peer = inet_getpeer_v4(net->ipv4.peers, daddr, create);
|
|
|
+ base = inetpeer_base_ptr(rt->_peer);
|
|
|
+ if (!base)
|
|
|
+ return;
|
|
|
+
|
|
|
+ peer = inet_getpeer_v4(base, daddr, create);
|
|
|
|
|
|
- if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL)
|
|
|
+ if (!rt_set_peer(rt, peer))
|
|
|
inet_putpeer(peer);
|
|
|
else
|
|
|
rt->rt_peer_genid = rt_peer_genid();
|
|
@@ -1533,8 +1537,10 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
|
|
|
rt_genid(dev_net(dst->dev)));
|
|
|
rt_del(hash, rt);
|
|
|
ret = NULL;
|
|
|
- } else if (rt->peer && peer_pmtu_expired(rt->peer)) {
|
|
|
- dst_metric_set(dst, RTAX_MTU, rt->peer->pmtu_orig);
|
|
|
+ } else if (rt_has_peer(rt)) {
|
|
|
+ struct inet_peer *peer = rt_peer_ptr(rt);
|
|
|
+ if (peer_pmtu_expired(peer))
|
|
|
+ dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig);
|
|
|
}
|
|
|
}
|
|
|
return ret;
|
|
@@ -1796,14 +1802,13 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
|
|
|
static void ipv4_dst_destroy(struct dst_entry *dst)
|
|
|
{
|
|
|
struct rtable *rt = (struct rtable *) dst;
|
|
|
- struct inet_peer *peer = rt->peer;
|
|
|
|
|
|
if (rt->fi) {
|
|
|
fib_info_put(rt->fi);
|
|
|
rt->fi = NULL;
|
|
|
}
|
|
|
- if (peer) {
|
|
|
- rt->peer = NULL;
|
|
|
+ if (rt_has_peer(rt)) {
|
|
|
+ struct inet_peer *peer = rt_peer_ptr(rt);
|
|
|
inet_putpeer(peer);
|
|
|
}
|
|
|
}
|
|
@@ -1816,8 +1821,11 @@ static void ipv4_link_failure(struct sk_buff *skb)
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
|
|
|
|
|
|
rt = skb_rtable(skb);
|
|
|
- if (rt && rt->peer && peer_pmtu_cleaned(rt->peer))
|
|
|
- dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig);
|
|
|
+ if (rt && rt_has_peer(rt)) {
|
|
|
+ struct inet_peer *peer = rt_peer_ptr(rt);
|
|
|
+ if (peer_pmtu_cleaned(peer))
|
|
|
+ dst_metric_set(&rt->dst, RTAX_MTU, peer->pmtu_orig);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int ip_rt_bug(struct sk_buff *skb)
|
|
@@ -1919,7 +1927,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
|
|
static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
|
|
|
struct fib_info *fi)
|
|
|
{
|
|
|
- struct net *net = dev_net(rt->dst.dev);
|
|
|
+ struct inet_peer_base *base;
|
|
|
struct inet_peer *peer;
|
|
|
int create = 0;
|
|
|
|
|
@@ -1929,8 +1937,12 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
|
|
|
if (fl4 && (fl4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS))
|
|
|
create = 1;
|
|
|
|
|
|
- rt->peer = peer = inet_getpeer_v4(net->ipv4.peers, rt->rt_dst, create);
|
|
|
+ base = inetpeer_base_ptr(rt->_peer);
|
|
|
+ BUG_ON(!base);
|
|
|
+
|
|
|
+ peer = inet_getpeer_v4(base, rt->rt_dst, create);
|
|
|
if (peer) {
|
|
|
+ __rt_set_peer(rt, peer);
|
|
|
rt->rt_peer_genid = rt_peer_genid();
|
|
|
if (inet_metrics_new(peer))
|
|
|
memcpy(peer->metrics, fi->fib_metrics,
|
|
@@ -2046,7 +2058,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
|
|
|
rth->rt_gateway = daddr;
|
|
|
rth->rt_spec_dst= spec_dst;
|
|
|
rth->rt_peer_genid = 0;
|
|
|
- rth->peer = NULL;
|
|
|
+ rt_init_peer(rth, dev_net(dev)->ipv4.peers);
|
|
|
rth->fi = NULL;
|
|
|
if (our) {
|
|
|
rth->dst.input= ip_local_deliver;
|
|
@@ -2174,7 +2186,7 @@ static int __mkroute_input(struct sk_buff *skb,
|
|
|
rth->rt_gateway = daddr;
|
|
|
rth->rt_spec_dst= spec_dst;
|
|
|
rth->rt_peer_genid = 0;
|
|
|
- rth->peer = NULL;
|
|
|
+ rt_init_peer(rth, dev_net(rth->dst.dev)->ipv4.peers);
|
|
|
rth->fi = NULL;
|
|
|
|
|
|
rth->dst.input = ip_forward;
|
|
@@ -2357,7 +2369,7 @@ local_input:
|
|
|
rth->rt_gateway = daddr;
|
|
|
rth->rt_spec_dst= spec_dst;
|
|
|
rth->rt_peer_genid = 0;
|
|
|
- rth->peer = NULL;
|
|
|
+ rt_init_peer(rth, net->ipv4.peers);
|
|
|
rth->fi = NULL;
|
|
|
if (res.type == RTN_UNREACHABLE) {
|
|
|
rth->dst.input= ip_error;
|
|
@@ -2561,7 +2573,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
|
|
|
rth->rt_gateway = fl4->daddr;
|
|
|
rth->rt_spec_dst= fl4->saddr;
|
|
|
rth->rt_peer_genid = 0;
|
|
|
- rth->peer = NULL;
|
|
|
+ rt_init_peer(rth, dev_net(dev_out)->ipv4.peers);
|
|
|
rth->fi = NULL;
|
|
|
|
|
|
RT_CACHE_STAT_INC(out_slow_tot);
|
|
@@ -2898,9 +2910,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
|
|
|
rt->rt_src = ort->rt_src;
|
|
|
rt->rt_gateway = ort->rt_gateway;
|
|
|
rt->rt_spec_dst = ort->rt_spec_dst;
|
|
|
- rt->peer = ort->peer;
|
|
|
- if (rt->peer)
|
|
|
- atomic_inc(&rt->peer->refcnt);
|
|
|
+ rt_transfer_peer(rt, ort);
|
|
|
rt->fi = ort->fi;
|
|
|
if (rt->fi)
|
|
|
atomic_inc(&rt->fi->fib_clntref);
|
|
@@ -2938,7 +2948,6 @@ static int rt_fill_info(struct net *net,
|
|
|
struct rtmsg *r;
|
|
|
struct nlmsghdr *nlh;
|
|
|
unsigned long expires = 0;
|
|
|
- const struct inet_peer *peer = rt->peer;
|
|
|
u32 id = 0, ts = 0, tsage = 0, error;
|
|
|
|
|
|
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
|
|
@@ -2994,8 +3003,9 @@ static int rt_fill_info(struct net *net,
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
error = rt->dst.error;
|
|
|
- if (peer) {
|
|
|
- inet_peer_refcheck(rt->peer);
|
|
|
+ if (rt_has_peer(rt)) {
|
|
|
+ const struct inet_peer *peer = rt_peer_ptr(rt);
|
|
|
+ inet_peer_refcheck(peer);
|
|
|
id = atomic_read(&peer->ip_id_count) & 0xffff;
|
|
|
if (peer->tcp_ts_stamp) {
|
|
|
ts = peer->tcp_ts;
|