summaryrefslogtreecommitdiff
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-06-09 22:36:36 -0700
committerDavid S. Miller <davem@davemloft.net>2012-06-11 02:08:47 -0700
commit97bab73f987e2781129cd6f4b6379bf44d808cc6 (patch)
tree40b10c4c021c8b5524c19f79fcfe4b0799b59952 /net/ipv4/route.c
parentc0efc887dcadbdbfe171f028acfab9c7c00e9dde (diff)
inet: Hide route peer accesses behind helpers.
We encode the pointer(s) into an unsigned long with one state bit. The state bit is used so we can store the inetpeer tree root to use when resolving the peer later. Later the peer roots will be per-FIB table, and this change works to facilitate that. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2aa663a6ae9e..03e5b614370e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -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;