Signed-off-by: Andreas Schultz <aschu...@tpip.net>
---
 drivers/net/gtp.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 4637ce7..c3e40cc 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -61,6 +61,10 @@ struct pdp_ctx {
        struct net_device       *dev;
        struct sock             *sk;
 
+#ifdef CONFIG_DST_CACHE
+       struct dst_cache        dst_cache;
+#endif
+
        atomic_t                tx_seq;
        struct rcu_head         rcu_head;
 };
@@ -485,12 +489,18 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct 
net_device *dev,
        }
        netdev_dbg(dev, "found PDP context %p\n", pctx);
 
-       rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr_ip4.s_addr);
-       if (IS_ERR(rt)) {
-               netdev_dbg(dev, "no route to SSGN %pI4\n",
-                          &pctx->sgsn_addr_ip4.s_addr);
-               dev->stats.tx_carrier_errors++;
-               goto err;
+       rt = dst_cache_get_ip4(&pctx->dst_cache, &pctx->sgsn_addr_ip4.s_addr);
+       if (!rt) {
+               rt = ip4_route_output_gtp(&fl4, pctx->sk, 
pctx->sgsn_addr_ip4.s_addr);
+               if (IS_ERR(rt)) {
+                       netdev_dbg(dev, "no route to SSGN %pI4\n",
+                                  &pctx->sgsn_addr_ip4.s_addr);
+                       dev->stats.tx_carrier_errors++;
+                       goto err;
+               }
+
+               dst_cache_set_ip4(&pctx->dst_cache, &rt->dst,
+                                 pctx->sgsn_addr_ip4.s_addr);
        }
 
        if (rt->dst.dev == dev) {
@@ -883,6 +893,8 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct 
genl_info *info)
        pctx->ms_addr_ip4.s_addr =
                nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
 
+       dst_cache_reset(&pctx->dst_cache);
+
        switch (pctx->gtp_version) {
        case GTP_V0:
                /* According to TS 09.60, sections 7.5.1 and 7.5.2, the flow
@@ -910,6 +922,7 @@ static int ipv4_pdp_add(struct net_device *dev, struct sock 
*sk,
        struct pdp_ctx *pctx;
        bool found = false;
        __be32 ms_addr;
+       int err;
 
        gsk = rcu_dereference_sk_user_data(sk);
        if (!gsk)
@@ -948,6 +961,12 @@ static int ipv4_pdp_add(struct net_device *dev, struct 
sock *sk,
        if (pctx == NULL)
                return -ENOMEM;
 
+       err = dst_cache_init(&pctx->dst_cache, GFP_KERNEL);
+       if (err) {
+               kfree(pctx);
+               return err;
+       }
+
        sock_hold(sk);
        pctx->sk = sk;
        pctx->dev = dev;
@@ -992,6 +1011,7 @@ static void pdp_context_free(struct rcu_head *head)
        struct pdp_ctx *pctx = container_of(head, struct pdp_ctx, rcu_head);
 
        sock_put(pctx->sk);
+       dst_cache_destroy(&pctx->dst_cache);
        kfree(pctx);
 }
 
-- 
2.10.2

Reply via email to