summaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2019-06-20 07:03:41 -0400
committerDavid S. Miller <davem@davemloft.net>2019-06-28 01:36:57 -0400
commite9c1a793210f29f32ee4cf048e04d7d9bb3221cc (patch)
treec210981a6790a78bd55d46ff126d8d8db3e983ef /net/tipc
parentd96ff269a04be286989ead13bf8b4be55bdee8ee (diff)
tipc: add dst_cache support for udp media
As other udp/ip tunnels do, tipc udp media should also have a lockless dst_cache supported on its tx path. Here we add dst_cache into udp_replicast to support dst cache for both rmcast and rcast, and rmcast uses ub->rcast and each rcast uses its own node in ub->rcast.list. Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/udp_media.c72
1 files changed, 47 insertions, 25 deletions
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 1405ccc9101c..b8962df07d36 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -76,6 +76,7 @@ struct udp_media_addr {
76/* struct udp_replicast - container for UDP remote addresses */ 76/* struct udp_replicast - container for UDP remote addresses */
77struct udp_replicast { 77struct udp_replicast {
78 struct udp_media_addr addr; 78 struct udp_media_addr addr;
79 struct dst_cache dst_cache;
79 struct rcu_head rcu; 80 struct rcu_head rcu;
80 struct list_head list; 81 struct list_head list;
81}; 82};
@@ -158,22 +159,27 @@ static int tipc_udp_addr2msg(char *msg, struct tipc_media_addr *a)
158/* tipc_send_msg - enqueue a send request */ 159/* tipc_send_msg - enqueue a send request */
159static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, 160static int tipc_udp_xmit(struct net *net, struct sk_buff *skb,
160 struct udp_bearer *ub, struct udp_media_addr *src, 161 struct udp_bearer *ub, struct udp_media_addr *src,
161 struct udp_media_addr *dst) 162 struct udp_media_addr *dst, struct dst_cache *cache)
162{ 163{
164 struct dst_entry *ndst = dst_cache_get(cache);
163 int ttl, err = 0; 165 int ttl, err = 0;
164 struct rtable *rt;
165 166
166 if (dst->proto == htons(ETH_P_IP)) { 167 if (dst->proto == htons(ETH_P_IP)) {
167 struct flowi4 fl = { 168 struct rtable *rt = (struct rtable *)ndst;
168 .daddr = dst->ipv4.s_addr, 169
169 .saddr = src->ipv4.s_addr, 170 if (!rt) {
170 .flowi4_mark = skb->mark, 171 struct flowi4 fl = {
171 .flowi4_proto = IPPROTO_UDP 172 .daddr = dst->ipv4.s_addr,
172 }; 173 .saddr = src->ipv4.s_addr,
173 rt = ip_route_output_key(net, &fl); 174 .flowi4_mark = skb->mark,
174 if (IS_ERR(rt)) { 175 .flowi4_proto = IPPROTO_UDP
175 err = PTR_ERR(rt); 176 };
176 goto tx_error; 177 rt = ip_route_output_key(net, &fl);
178 if (IS_ERR(rt)) {
179 err = PTR_ERR(rt);
180 goto tx_error;
181 }
182 dst_cache_set_ip4(cache, &rt->dst, fl.saddr);
177 } 183 }
178 184
179 ttl = ip4_dst_hoplimit(&rt->dst); 185 ttl = ip4_dst_hoplimit(&rt->dst);
@@ -182,17 +188,19 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb,
182 dst->port, false, true); 188 dst->port, false, true);
183#if IS_ENABLED(CONFIG_IPV6) 189#if IS_ENABLED(CONFIG_IPV6)
184 } else { 190 } else {
185 struct dst_entry *ndst; 191 if (!ndst) {
186 struct flowi6 fl6 = { 192 struct flowi6 fl6 = {
187 .flowi6_oif = ub->ifindex, 193 .flowi6_oif = ub->ifindex,
188 .daddr = dst->ipv6, 194 .daddr = dst->ipv6,
189 .saddr = src->ipv6, 195 .saddr = src->ipv6,
190 .flowi6_proto = IPPROTO_UDP 196 .flowi6_proto = IPPROTO_UDP
191 }; 197 };
192 err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, &ndst, 198 err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk,
193 &fl6); 199 &ndst, &fl6);
194 if (err) 200 if (err)
195 goto tx_error; 201 goto tx_error;
202 dst_cache_set_ip6(cache, ndst, &fl6.saddr);
203 }
196 ttl = ip6_dst_hoplimit(ndst); 204 ttl = ip6_dst_hoplimit(ndst);
197 err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL, 205 err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL,
198 &src->ipv6, &dst->ipv6, 0, ttl, 0, 206 &src->ipv6, &dst->ipv6, 0, ttl, 0,
@@ -230,7 +238,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
230 } 238 }
231 239
232 if (addr->broadcast != TIPC_REPLICAST_SUPPORT) 240 if (addr->broadcast != TIPC_REPLICAST_SUPPORT)
233 return tipc_udp_xmit(net, skb, ub, src, dst); 241 return tipc_udp_xmit(net, skb, ub, src, dst,
242 &ub->rcast.dst_cache);
234 243
235 /* Replicast, send an skb to each configured IP address */ 244 /* Replicast, send an skb to each configured IP address */
236 list_for_each_entry_rcu(rcast, &ub->rcast.list, list) { 245 list_for_each_entry_rcu(rcast, &ub->rcast.list, list) {
@@ -242,7 +251,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
242 goto out; 251 goto out;
243 } 252 }
244 253
245 err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr); 254 err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr,
255 &rcast->dst_cache);
246 if (err) 256 if (err)
247 goto out; 257 goto out;
248 } 258 }
@@ -286,6 +296,11 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b,
286 if (!rcast) 296 if (!rcast)
287 return -ENOMEM; 297 return -ENOMEM;
288 298
299 if (dst_cache_init(&rcast->dst_cache, GFP_ATOMIC)) {
300 kfree(rcast);
301 return -ENOMEM;
302 }
303
289 memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr)); 304 memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr));
290 305
291 if (ntohs(addr->proto) == ETH_P_IP) 306 if (ntohs(addr->proto) == ETH_P_IP)
@@ -742,6 +757,10 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
742 tuncfg.encap_destroy = NULL; 757 tuncfg.encap_destroy = NULL;
743 setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg); 758 setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg);
744 759
760 err = dst_cache_init(&ub->rcast.dst_cache, GFP_ATOMIC);
761 if (err)
762 goto err;
763
745 /** 764 /**
746 * The bcast media address port is used for all peers and the ip 765 * The bcast media address port is used for all peers and the ip
747 * is used if it's a multicast address. 766 * is used if it's a multicast address.
@@ -756,6 +775,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
756 775
757 return 0; 776 return 0;
758err: 777err:
778 dst_cache_destroy(&ub->rcast.dst_cache);
759 if (ub->ubsock) 779 if (ub->ubsock)
760 udp_tunnel_sock_release(ub->ubsock); 780 udp_tunnel_sock_release(ub->ubsock);
761 kfree(ub); 781 kfree(ub);
@@ -769,10 +789,12 @@ static void cleanup_bearer(struct work_struct *work)
769 struct udp_replicast *rcast, *tmp; 789 struct udp_replicast *rcast, *tmp;
770 790
771 list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) { 791 list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
792 dst_cache_destroy(&rcast->dst_cache);
772 list_del_rcu(&rcast->list); 793 list_del_rcu(&rcast->list);
773 kfree_rcu(rcast, rcu); 794 kfree_rcu(rcast, rcu);
774 } 795 }
775 796
797 dst_cache_destroy(&ub->rcast.dst_cache);
776 if (ub->ubsock) 798 if (ub->ubsock)
777 udp_tunnel_sock_release(ub->ubsock); 799 udp_tunnel_sock_release(ub->ubsock);
778 synchronize_net(); 800 synchronize_net();