Skip to content

Commit e9c1a79

Browse files
lxindavem330
authored andcommitted
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>
1 parent d96ff26 commit e9c1a79

File tree

1 file changed

+47
-25
lines changed

1 file changed

+47
-25
lines changed

net/tipc/udp_media.c

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct udp_media_addr {
7676
/* struct udp_replicast - container for UDP remote addresses */
7777
struct udp_replicast {
7878
struct udp_media_addr addr;
79+
struct dst_cache dst_cache;
7980
struct rcu_head rcu;
8081
struct list_head list;
8182
};
@@ -158,22 +159,27 @@ static int tipc_udp_addr2msg(char *msg, struct tipc_media_addr *a)
158159
/* tipc_send_msg - enqueue a send request */
159160
static int tipc_udp_xmit(struct net *net, struct sk_buff *skb,
160161
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)
162163
{
164+
struct dst_entry *ndst = dst_cache_get(cache);
163165
int ttl, err = 0;
164-
struct rtable *rt;
165166

166167
if (dst->proto == htons(ETH_P_IP)) {
167-
struct flowi4 fl = {
168-
.daddr = dst->ipv4.s_addr,
169-
.saddr = src->ipv4.s_addr,
170-
.flowi4_mark = skb->mark,
171-
.flowi4_proto = IPPROTO_UDP
172-
};
173-
rt = ip_route_output_key(net, &fl);
174-
if (IS_ERR(rt)) {
175-
err = PTR_ERR(rt);
176-
goto tx_error;
168+
struct rtable *rt = (struct rtable *)ndst;
169+
170+
if (!rt) {
171+
struct flowi4 fl = {
172+
.daddr = dst->ipv4.s_addr,
173+
.saddr = src->ipv4.s_addr,
174+
.flowi4_mark = skb->mark,
175+
.flowi4_proto = IPPROTO_UDP
176+
};
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);
177183
}
178184

179185
ttl = ip4_dst_hoplimit(&rt->dst);
@@ -182,17 +188,19 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb,
182188
dst->port, false, true);
183189
#if IS_ENABLED(CONFIG_IPV6)
184190
} else {
185-
struct dst_entry *ndst;
186-
struct flowi6 fl6 = {
187-
.flowi6_oif = ub->ifindex,
188-
.daddr = dst->ipv6,
189-
.saddr = src->ipv6,
190-
.flowi6_proto = IPPROTO_UDP
191-
};
192-
err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, &ndst,
193-
&fl6);
194-
if (err)
195-
goto tx_error;
191+
if (!ndst) {
192+
struct flowi6 fl6 = {
193+
.flowi6_oif = ub->ifindex,
194+
.daddr = dst->ipv6,
195+
.saddr = src->ipv6,
196+
.flowi6_proto = IPPROTO_UDP
197+
};
198+
err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk,
199+
&ndst, &fl6);
200+
if (err)
201+
goto tx_error;
202+
dst_cache_set_ip6(cache, ndst, &fl6.saddr);
203+
}
196204
ttl = ip6_dst_hoplimit(ndst);
197205
err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL,
198206
&src->ipv6, &dst->ipv6, 0, ttl, 0,
@@ -230,7 +238,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
230238
}
231239

232240
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);
234243

235244
/* Replicast, send an skb to each configured IP address */
236245
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,
242251
goto out;
243252
}
244253

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);
246256
if (err)
247257
goto out;
248258
}
@@ -286,6 +296,11 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b,
286296
if (!rcast)
287297
return -ENOMEM;
288298

299+
if (dst_cache_init(&rcast->dst_cache, GFP_ATOMIC)) {
300+
kfree(rcast);
301+
return -ENOMEM;
302+
}
303+
289304
memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr));
290305

291306
if (ntohs(addr->proto) == ETH_P_IP)
@@ -742,6 +757,10 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
742757
tuncfg.encap_destroy = NULL;
743758
setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg);
744759

760+
err = dst_cache_init(&ub->rcast.dst_cache, GFP_ATOMIC);
761+
if (err)
762+
goto err;
763+
745764
/**
746765
* The bcast media address port is used for all peers and the ip
747766
* is used if it's a multicast address.
@@ -756,6 +775,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
756775

757776
return 0;
758777
err:
778+
dst_cache_destroy(&ub->rcast.dst_cache);
759779
if (ub->ubsock)
760780
udp_tunnel_sock_release(ub->ubsock);
761781
kfree(ub);
@@ -769,10 +789,12 @@ static void cleanup_bearer(struct work_struct *work)
769789
struct udp_replicast *rcast, *tmp;
770790

771791
list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
792+
dst_cache_destroy(&rcast->dst_cache);
772793
list_del_rcu(&rcast->list);
773794
kfree_rcu(rcast, rcu);
774795
}
775796

797+
dst_cache_destroy(&ub->rcast.dst_cache);
776798
if (ub->ubsock)
777799
udp_tunnel_sock_release(ub->ubsock);
778800
synchronize_net();

0 commit comments

Comments
 (0)