net: UDP tunnel encapsulation module for tunnelling different protocols like MPLS...
[platform/kernel/linux-starfive.git] / net / ipv4 / route.c
index ebe7060..042599c 100644 (file)
@@ -2774,6 +2774,54 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
 }
 EXPORT_SYMBOL_GPL(ip_route_output_flow);
 
+struct rtable *ip_route_output_tunnel(struct sk_buff *skb,
+                                     struct net_device *dev,
+                                     struct net *net, __be32 *saddr,
+                                     const struct ip_tunnel_info *info,
+                                     u8 protocol, bool use_cache)
+{
+#ifdef CONFIG_DST_CACHE
+       struct dst_cache *dst_cache;
+#endif
+       struct rtable *rt = NULL;
+       struct flowi4 fl4;
+       __u8 tos;
+
+#ifdef CONFIG_DST_CACHE
+       dst_cache = (struct dst_cache *)&info->dst_cache;
+       if (use_cache) {
+               rt = dst_cache_get_ip4(dst_cache, saddr);
+               if (rt)
+                       return rt;
+       }
+#endif
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.flowi4_mark = skb->mark;
+       fl4.flowi4_proto = protocol;
+       fl4.daddr = info->key.u.ipv4.dst;
+       fl4.saddr = info->key.u.ipv4.src;
+       tos = info->key.tos;
+       fl4.flowi4_tos = RT_TOS(tos);
+
+       rt = ip_route_output_key(net, &fl4);
+       if (IS_ERR(rt)) {
+               netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr);
+               return ERR_PTR(-ENETUNREACH);
+       }
+       if (rt->dst.dev == dev) { /* is this necessary? */
+               netdev_dbg(dev, "circular route to %pI4\n", &fl4.daddr);
+               ip_rt_put(rt);
+               return ERR_PTR(-ELOOP);
+       }
+#ifdef CONFIG_DST_CACHE
+       if (use_cache)
+               dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr);
+#endif
+       *saddr = fl4.saddr;
+       return rt;
+}
+EXPORT_SYMBOL_GPL(ip_route_output_tunnel);
+
 /* called with rcu_read_lock held */
 static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
                        struct rtable *rt, u32 table_id, struct flowi4 *fl4,