From: Xin L. <luc...@gm...> - 2019-06-20 11:03:55
|
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 <luc...@gm...> --- net/tipc/udp_media.c | 72 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index 1405ccc..b8962df 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -76,6 +76,7 @@ struct udp_media_addr { /* struct udp_replicast - container for UDP remote addresses */ struct udp_replicast { struct udp_media_addr addr; + struct dst_cache dst_cache; struct rcu_head rcu; struct list_head list; }; @@ -158,22 +159,27 @@ static int tipc_udp_addr2msg(char *msg, struct tipc_media_addr *a) /* tipc_send_msg - enqueue a send request */ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, struct udp_bearer *ub, struct udp_media_addr *src, - struct udp_media_addr *dst) + struct udp_media_addr *dst, struct dst_cache *cache) { + struct dst_entry *ndst = dst_cache_get(cache); int ttl, err = 0; - struct rtable *rt; if (dst->proto == htons(ETH_P_IP)) { - struct flowi4 fl = { - .daddr = dst->ipv4.s_addr, - .saddr = src->ipv4.s_addr, - .flowi4_mark = skb->mark, - .flowi4_proto = IPPROTO_UDP - }; - rt = ip_route_output_key(net, &fl); - if (IS_ERR(rt)) { - err = PTR_ERR(rt); - goto tx_error; + struct rtable *rt = (struct rtable *)ndst; + + if (!rt) { + struct flowi4 fl = { + .daddr = dst->ipv4.s_addr, + .saddr = src->ipv4.s_addr, + .flowi4_mark = skb->mark, + .flowi4_proto = IPPROTO_UDP + }; + rt = ip_route_output_key(net, &fl); + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + goto tx_error; + } + dst_cache_set_ip4(cache, &rt->dst, fl.saddr); } ttl = ip4_dst_hoplimit(&rt->dst); @@ -182,17 +188,19 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, dst->port, false, true); #if IS_ENABLED(CONFIG_IPV6) } else { - struct dst_entry *ndst; - struct flowi6 fl6 = { - .flowi6_oif = ub->ifindex, - .daddr = dst->ipv6, - .saddr = src->ipv6, - .flowi6_proto = IPPROTO_UDP - }; - err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, &ndst, - &fl6); - if (err) - goto tx_error; + if (!ndst) { + struct flowi6 fl6 = { + .flowi6_oif = ub->ifindex, + .daddr = dst->ipv6, + .saddr = src->ipv6, + .flowi6_proto = IPPROTO_UDP + }; + err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, + &ndst, &fl6); + if (err) + goto tx_error; + dst_cache_set_ip6(cache, ndst, &fl6.saddr); + } ttl = ip6_dst_hoplimit(ndst); err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL, &src->ipv6, &dst->ipv6, 0, ttl, 0, @@ -230,7 +238,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, } if (addr->broadcast != TIPC_REPLICAST_SUPPORT) - return tipc_udp_xmit(net, skb, ub, src, dst); + return tipc_udp_xmit(net, skb, ub, src, dst, + &ub->rcast.dst_cache); /* Replicast, send an skb to each configured IP address */ 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, goto out; } - err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr); + err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr, + &rcast->dst_cache); if (err) goto out; } @@ -286,6 +296,11 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b, if (!rcast) return -ENOMEM; + if (dst_cache_init(&rcast->dst_cache, GFP_ATOMIC)) { + kfree(rcast); + return -ENOMEM; + } + memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr)); if (ntohs(addr->proto) == ETH_P_IP) @@ -742,6 +757,10 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, tuncfg.encap_destroy = NULL; setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg); + err = dst_cache_init(&ub->rcast.dst_cache, GFP_ATOMIC); + if (err) + goto err; + /** * The bcast media address port is used for all peers and the ip * is used if it's a multicast address. @@ -756,6 +775,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, return 0; err: + dst_cache_destroy(&ub->rcast.dst_cache); if (ub->ubsock) udp_tunnel_sock_release(ub->ubsock); kfree(ub); @@ -769,10 +789,12 @@ static void cleanup_bearer(struct work_struct *work) struct udp_replicast *rcast, *tmp; list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) { + dst_cache_destroy(&rcast->dst_cache); list_del_rcu(&rcast->list); kfree_rcu(rcast, rcu); } + dst_cache_destroy(&ub->rcast.dst_cache); if (ub->ubsock) udp_tunnel_sock_release(ub->ubsock); synchronize_net(); -- 2.1.0 |
From: Jon M. <jon...@er...> - 2019-06-20 13:09:34
|
Acked-by: Jon Maloy <jon...@er...> > -----Original Message----- > From: net...@vg... <net...@vg...> On > Behalf Of Xin Long > Sent: 20-Jun-19 07:04 > To: network dev <ne...@vg...> > Cc: da...@da...; Jon Maloy <jon...@er...>; Ying Xue > <yin...@wi...>; tip...@li...; Paolo > Abeni <pa...@re...> > Subject: [PATCH net] 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 <luc...@gm...> > --- > net/tipc/udp_media.c | 72 ++++++++++++++++++++++++++++++++++------- > ----------- > 1 file changed, 47 insertions(+), 25 deletions(-) > > diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index > 1405ccc..b8962df 100644 > --- a/net/tipc/udp_media.c > +++ b/net/tipc/udp_media.c > @@ -76,6 +76,7 @@ struct udp_media_addr { > /* struct udp_replicast - container for UDP remote addresses */ struct > udp_replicast { > struct udp_media_addr addr; > + struct dst_cache dst_cache; > struct rcu_head rcu; > struct list_head list; > }; > @@ -158,22 +159,27 @@ static int tipc_udp_addr2msg(char *msg, struct > tipc_media_addr *a) > /* tipc_send_msg - enqueue a send request */ static int tipc_udp_xmit(struct > net *net, struct sk_buff *skb, > struct udp_bearer *ub, struct udp_media_addr *src, > - struct udp_media_addr *dst) > + struct udp_media_addr *dst, struct dst_cache *cache) > { > + struct dst_entry *ndst = dst_cache_get(cache); > int ttl, err = 0; > - struct rtable *rt; > > if (dst->proto == htons(ETH_P_IP)) { > - struct flowi4 fl = { > - .daddr = dst->ipv4.s_addr, > - .saddr = src->ipv4.s_addr, > - .flowi4_mark = skb->mark, > - .flowi4_proto = IPPROTO_UDP > - }; > - rt = ip_route_output_key(net, &fl); > - if (IS_ERR(rt)) { > - err = PTR_ERR(rt); > - goto tx_error; > + struct rtable *rt = (struct rtable *)ndst; > + > + if (!rt) { > + struct flowi4 fl = { > + .daddr = dst->ipv4.s_addr, > + .saddr = src->ipv4.s_addr, > + .flowi4_mark = skb->mark, > + .flowi4_proto = IPPROTO_UDP > + }; > + rt = ip_route_output_key(net, &fl); > + if (IS_ERR(rt)) { > + err = PTR_ERR(rt); > + goto tx_error; > + } > + dst_cache_set_ip4(cache, &rt->dst, fl.saddr); > } > > ttl = ip4_dst_hoplimit(&rt->dst); > @@ -182,17 +188,19 @@ static int tipc_udp_xmit(struct net *net, struct > sk_buff *skb, > dst->port, false, true); > #if IS_ENABLED(CONFIG_IPV6) > } else { > - struct dst_entry *ndst; > - struct flowi6 fl6 = { > - .flowi6_oif = ub->ifindex, > - .daddr = dst->ipv6, > - .saddr = src->ipv6, > - .flowi6_proto = IPPROTO_UDP > - }; > - err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, &ndst, > - &fl6); > - if (err) > - goto tx_error; > + if (!ndst) { > + struct flowi6 fl6 = { > + .flowi6_oif = ub->ifindex, > + .daddr = dst->ipv6, > + .saddr = src->ipv6, > + .flowi6_proto = IPPROTO_UDP > + }; > + err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, > + &ndst, &fl6); > + if (err) > + goto tx_error; > + dst_cache_set_ip6(cache, ndst, &fl6.saddr); > + } > ttl = ip6_dst_hoplimit(ndst); > err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL, > &src->ipv6, &dst->ipv6, 0, ttl, 0, @@ -230,7 > +238,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, > } > > if (addr->broadcast != TIPC_REPLICAST_SUPPORT) > - return tipc_udp_xmit(net, skb, ub, src, dst); > + return tipc_udp_xmit(net, skb, ub, src, dst, > + &ub->rcast.dst_cache); > > /* Replicast, send an skb to each configured IP address */ > 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, > goto out; > } > > - err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr); > + err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr, > + &rcast->dst_cache); > if (err) > goto out; > } > @@ -286,6 +296,11 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b, > if (!rcast) > return -ENOMEM; > > + if (dst_cache_init(&rcast->dst_cache, GFP_ATOMIC)) { > + kfree(rcast); > + return -ENOMEM; > + } > + > memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr)); > > if (ntohs(addr->proto) == ETH_P_IP) > @@ -742,6 +757,10 @@ static int tipc_udp_enable(struct net *net, struct > tipc_bearer *b, > tuncfg.encap_destroy = NULL; > setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg); > > + err = dst_cache_init(&ub->rcast.dst_cache, GFP_ATOMIC); > + if (err) > + goto err; > + > /** > * The bcast media address port is used for all peers and the ip > * is used if it's a multicast address. > @@ -756,6 +775,7 @@ static int tipc_udp_enable(struct net *net, struct > tipc_bearer *b, > > return 0; > err: > + dst_cache_destroy(&ub->rcast.dst_cache); > if (ub->ubsock) > udp_tunnel_sock_release(ub->ubsock); > kfree(ub); > @@ -769,10 +789,12 @@ static void cleanup_bearer(struct work_struct > *work) > struct udp_replicast *rcast, *tmp; > > list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) { > + dst_cache_destroy(&rcast->dst_cache); > list_del_rcu(&rcast->list); > kfree_rcu(rcast, rcu); > } > > + dst_cache_destroy(&ub->rcast.dst_cache); > if (ub->ubsock) > udp_tunnel_sock_release(ub->ubsock); > synchronize_net(); > -- > 2.1.0 |
From: David M. <da...@da...> - 2019-06-22 23:54:57
|
From: Xin Long <luc...@gm...> Date: Thu, 20 Jun 2019 19:03:41 +0800 > 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 <luc...@gm...> I'll apply this to net-next after the next net --> net-next marge since it depends upon the register_pernet_device change. |
From: David M. <da...@da...> - 2019-06-28 05:37:23
|
From: Xin Long <luc...@gm...> Date: Thu, 20 Jun 2019 19:03:41 +0800 > 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 <luc...@gm...> Applied to net-next. |