vxlan: consolidate output route calculation
authorJiri Benc <jbenc@redhat.com>
Tue, 2 Feb 2016 17:09:14 +0000 (18:09 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 7 Feb 2016 18:51:00 +0000 (13:51 -0500)
The code for output route lookup is duplicated for ndo_start_xmit and
ndo_fill_metadata_dst. Move it to a common function.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxlan.c

index 6543918..d0f7723 100644 (file)
@@ -1847,6 +1847,27 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
        return 0;
 }
 
+static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
+                                     struct sk_buff *skb, int oif, u8 tos,
+                                     __be32 daddr, __be32 *saddr)
+{
+       struct rtable *rt = NULL;
+       struct flowi4 fl4;
+
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.flowi4_oif = oif;
+       fl4.flowi4_tos = RT_TOS(tos);
+       fl4.flowi4_mark = skb->mark;
+       fl4.flowi4_proto = IPPROTO_UDP;
+       fl4.daddr = daddr;
+       fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr;
+
+       rt = ip_route_output_key(vxlan->net, &fl4);
+       if (!IS_ERR(rt))
+               *saddr = fl4.saddr;
+       return rt;
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
                                          struct sk_buff *skb, int oif,
@@ -1928,7 +1949,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
        struct sock *sk;
        struct rtable *rt = NULL;
        const struct iphdr *old_iph;
-       struct flowi4 fl4;
        union vxlan_addr *dst;
        union vxlan_addr remote_ip;
        struct vxlan_metadata _md;
@@ -1995,6 +2015,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
        }
 
        if (dst->sa.sa_family == AF_INET) {
+               __be32 saddr;
+
                if (!vxlan->vn4_sock)
                        goto drop;
                sk = vxlan->vn4_sock->sock->sk;
@@ -2009,15 +2031,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                                flags &= ~VXLAN_F_UDP_CSUM;
                }
 
-               memset(&fl4, 0, sizeof(fl4));
-               fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0;
-               fl4.flowi4_tos = RT_TOS(tos);
-               fl4.flowi4_mark = skb->mark;
-               fl4.flowi4_proto = IPPROTO_UDP;
-               fl4.daddr = dst->sin.sin_addr.s_addr;
-               fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr;
-
-               rt = ip_route_output_key(vxlan->net, &fl4);
+               rt = vxlan_get_route(vxlan, skb,
+                                    rdst ? rdst->remote_ifindex : 0, tos,
+                                    dst->sin.sin_addr.s_addr, &saddr);
                if (IS_ERR(rt)) {
                        netdev_dbg(dev, "no route to %pI4\n",
                                   &dst->sin.sin_addr.s_addr);
@@ -2049,7 +2065,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 
                tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
                ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
-               err = vxlan_xmit_skb(rt, sk, skb, fl4.saddr,
+               err = vxlan_xmit_skb(rt, sk, skb, saddr,
                                     dst->sin.sin_addr.s_addr, tos, ttl, df,
                                     src_port, dst_port, htonl(vni << 8), md,
                                     !net_eq(vxlan->net, dev_net(vxlan->dev)),
@@ -2390,31 +2406,6 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
-                               struct ip_tunnel_info *info,
-                               __be16 sport, __be16 dport)
-{
-       struct vxlan_dev *vxlan = netdev_priv(dev);
-       struct rtable *rt;
-       struct flowi4 fl4;
-
-       memset(&fl4, 0, sizeof(fl4));
-       fl4.flowi4_tos = RT_TOS(info->key.tos);
-       fl4.flowi4_mark = skb->mark;
-       fl4.flowi4_proto = IPPROTO_UDP;
-       fl4.daddr = info->key.u.ipv4.dst;
-
-       rt = ip_route_output_key(vxlan->net, &fl4);
-       if (IS_ERR(rt))
-               return PTR_ERR(rt);
-       ip_rt_put(rt);
-
-       info->key.u.ipv4.src = fl4.saddr;
-       info->key.tp_src = sport;
-       info->key.tp_dst = dport;
-       return 0;
-}
-
 static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
@@ -2426,9 +2417,16 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
        dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
 
        if (ip_tunnel_info_af(info) == AF_INET) {
+               struct rtable *rt;
+
                if (!vxlan->vn4_sock)
                        return -EINVAL;
-               return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+               rt = vxlan_get_route(vxlan, skb, 0, info->key.tos,
+                                    info->key.u.ipv4.dst,
+                                    &info->key.u.ipv4.src);
+               if (IS_ERR(rt))
+                       return PTR_ERR(rt);
+               ip_rt_put(rt);
        } else {
 #if IS_ENABLED(CONFIG_IPV6)
                struct dst_entry *ndst;
@@ -2441,13 +2439,12 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
                if (IS_ERR(ndst))
                        return PTR_ERR(ndst);
                dst_release(ndst);
-
-               info->key.tp_src = sport;
-               info->key.tp_dst = dport;
 #else /* !CONFIG_IPV6 */
                return -EPFNOSUPPORT;
 #endif
        }
+       info->key.tp_src = sport;
+       info->key.tp_dst = dport;
        return 0;
 }