diff options
author | David Ahern <dsa@cumulusnetworks.com> | 2015-08-27 19:07:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-28 16:32:36 -0400 |
commit | 192132b9a034d87566294be0fba5f8f75c2cf16b (patch) | |
tree | c4d7126eb3cd4eb84effc223fb98fdf8e0b80658 | |
parent | 5345c2e12d41f815c1009c9dee72f3d5fcfd4282 (diff) |
net: Add support for VRFs to inetpeer cache
inetpeer caches based on address only, so duplicate IP addresses within
a namespace return the same cached entry. Enhance the ipv4 address key
to contain both the IPv4 address and VRF device index.
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/inetpeer.h | 17 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 3 | ||||
-rw-r--r-- | net/ipv4/route.c | 7 |
4 files changed, 21 insertions, 9 deletions
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index e34f98aa93b1..4a6009d4486b 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h | |||
@@ -15,11 +15,17 @@ | |||
15 | #include <net/ipv6.h> | 15 | #include <net/ipv6.h> |
16 | #include <linux/atomic.h> | 16 | #include <linux/atomic.h> |
17 | 17 | ||
18 | /* IPv4 address key for cache lookups */ | ||
19 | struct ipv4_addr_key { | ||
20 | __be32 addr; | ||
21 | int vif; | ||
22 | }; | ||
23 | |||
18 | #define INETPEER_MAXKEYSZ (sizeof(struct in6_addr) / sizeof(u32)) | 24 | #define INETPEER_MAXKEYSZ (sizeof(struct in6_addr) / sizeof(u32)) |
19 | 25 | ||
20 | struct inetpeer_addr { | 26 | struct inetpeer_addr { |
21 | union { | 27 | union { |
22 | __be32 a4; | 28 | struct ipv4_addr_key a4; |
23 | struct in6_addr a6; | 29 | struct in6_addr a6; |
24 | u32 key[INETPEER_MAXKEYSZ]; | 30 | u32 key[INETPEER_MAXKEYSZ]; |
25 | }; | 31 | }; |
@@ -71,13 +77,13 @@ void inet_initpeers(void) __init; | |||
71 | 77 | ||
72 | static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip) | 78 | static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip) |
73 | { | 79 | { |
74 | iaddr->a4 = ip; | 80 | iaddr->a4.addr = ip; |
75 | iaddr->family = AF_INET; | 81 | iaddr->family = AF_INET; |
76 | } | 82 | } |
77 | 83 | ||
78 | static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr) | 84 | static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr) |
79 | { | 85 | { |
80 | return iaddr->a4; | 86 | return iaddr->a4.addr; |
81 | } | 87 | } |
82 | 88 | ||
83 | static inline void inetpeer_set_addr_v6(struct inetpeer_addr *iaddr, | 89 | static inline void inetpeer_set_addr_v6(struct inetpeer_addr *iaddr, |
@@ -99,11 +105,12 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base, | |||
99 | 105 | ||
100 | static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, | 106 | static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, |
101 | __be32 v4daddr, | 107 | __be32 v4daddr, |
102 | int create) | 108 | int vif, int create) |
103 | { | 109 | { |
104 | struct inetpeer_addr daddr; | 110 | struct inetpeer_addr daddr; |
105 | 111 | ||
106 | daddr.a4 = v4daddr; | 112 | daddr.a4.addr = v4daddr; |
113 | daddr.a4.vif = vif; | ||
107 | daddr.family = AF_INET; | 114 | daddr.family = AF_INET; |
108 | return inet_getpeer(base, &daddr, create); | 115 | return inet_getpeer(base, &daddr, create); |
109 | } | 116 | } |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index f16488efa1c8..79fe05befcae 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -309,9 +309,10 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, | |||
309 | 309 | ||
310 | rc = false; | 310 | rc = false; |
311 | if (icmp_global_allow()) { | 311 | if (icmp_global_allow()) { |
312 | int vif = vrf_master_ifindex(dst->dev); | ||
312 | struct inet_peer *peer; | 313 | struct inet_peer *peer; |
313 | 314 | ||
314 | peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1); | 315 | peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, vif, 1); |
315 | rc = inet_peer_xrlim_allow(peer, | 316 | rc = inet_peer_xrlim_allow(peer, |
316 | net->ipv4.sysctl_icmp_ratelimit); | 317 | net->ipv4.sysctl_icmp_ratelimit); |
317 | if (peer) | 318 | if (peer) |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 15762e758861..fa7f15305f9a 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -151,7 +151,8 @@ static void ip4_frag_init(struct inet_frag_queue *q, const void *a) | |||
151 | qp->vif = arg->vif; | 151 | qp->vif = arg->vif; |
152 | qp->user = arg->user; | 152 | qp->user = arg->user; |
153 | qp->peer = sysctl_ipfrag_max_dist ? | 153 | qp->peer = sysctl_ipfrag_max_dist ? |
154 | inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, 1) : NULL; | 154 | inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, arg->vif, 1) : |
155 | NULL; | ||
155 | } | 156 | } |
156 | 157 | ||
157 | static void ip4_frag_free(struct inet_frag_queue *q) | 158 | static void ip4_frag_free(struct inet_frag_queue *q) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f3087aaa6dd8..6b91879e9cbe 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -838,6 +838,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
838 | struct inet_peer *peer; | 838 | struct inet_peer *peer; |
839 | struct net *net; | 839 | struct net *net; |
840 | int log_martians; | 840 | int log_martians; |
841 | int vif; | ||
841 | 842 | ||
842 | rcu_read_lock(); | 843 | rcu_read_lock(); |
843 | in_dev = __in_dev_get_rcu(rt->dst.dev); | 844 | in_dev = __in_dev_get_rcu(rt->dst.dev); |
@@ -846,10 +847,11 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
846 | return; | 847 | return; |
847 | } | 848 | } |
848 | log_martians = IN_DEV_LOG_MARTIANS(in_dev); | 849 | log_martians = IN_DEV_LOG_MARTIANS(in_dev); |
850 | vif = vrf_master_ifindex_rcu(rt->dst.dev); | ||
849 | rcu_read_unlock(); | 851 | rcu_read_unlock(); |
850 | 852 | ||
851 | net = dev_net(rt->dst.dev); | 853 | net = dev_net(rt->dst.dev); |
852 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); | 854 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, vif, 1); |
853 | if (!peer) { | 855 | if (!peer) { |
854 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, | 856 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, |
855 | rt_nexthop(rt, ip_hdr(skb)->daddr)); | 857 | rt_nexthop(rt, ip_hdr(skb)->daddr)); |
@@ -938,7 +940,8 @@ static int ip_error(struct sk_buff *skb) | |||
938 | break; | 940 | break; |
939 | } | 941 | } |
940 | 942 | ||
941 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); | 943 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, |
944 | vrf_master_ifindex(skb->dev), 1); | ||
942 | 945 | ||
943 | send = true; | 946 | send = true; |
944 | if (peer) { | 947 | if (peer) { |