Acked-by: Jon Maloy <jon.ma...@ericsson.com>

> -----Original Message-----
> From: netdev-ow...@vger.kernel.org <netdev-ow...@vger.kernel.org> On
> Behalf Of Xin Long
> Sent: 20-Jun-19 07:04
> To: network dev <netdev@vger.kernel.org>
> Cc: da...@davemloft.net; Jon Maloy <jon.ma...@ericsson.com>; Ying Xue
> <ying....@windriver.com>; tipc-discuss...@lists.sourceforge.net; Paolo
> Abeni <pab...@redhat.com>
> 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 <lucien....@gmail.com>
> ---
>  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

Reply via email to