>From 3.1 kernel, struct dst_entry no longer has direct ref to hh_cache.
Following patch handles this case.

Signed-off-by: Pravin Shelar <[email protected]>
---
 datapath/tunnel.c |   45 ++++++++++++++++++++++++++++++---------------
 1 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 8edff06..c7e9814 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -93,6 +93,12 @@ static unsigned int remote_ports __read_mostly;
 #define rt_dst(rt) (rt->u.dst)
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
+#define rt_hh(rt) (&dst_get_neighbour(&rt_dst(rt))->hh)
+#else
+#define rt_hh(rt) (rt_dst(rt).hh)
+#endif
+
 static inline struct vport *tnl_vport_to_vport(const struct tnl_vport 
*tnl_vport)
 {
        return vport_from_priv(tnl_vport);
@@ -751,7 +757,7 @@ static inline bool check_cache_valid(const struct tnl_cache 
*cache,
                atomic_read(&init_net.ipv4.rt_genid) == cache->rt->rt_genid &&
 #endif
 #ifdef HAVE_HH_SEQ
-               rt_dst(cache->rt).hh->hh_lock.sequence == cache->hh_seq &&
+               rt_hh(cache->rt)->hh_lock.sequence == cache->hh_seq &&
 #endif
                mutable->seq == cache->mutable_seq &&
                (!is_internal_dev(rt_dst(cache->rt).dev) ||
@@ -791,25 +797,26 @@ static void cache_cleaner(struct work_struct *work)
 }
 
 static inline void create_eth_hdr(struct tnl_cache *cache,
-                                 const struct rtable *rt)
+                                 struct rtable *rt)
 {
        void *cache_data = get_cached_header(cache);
-       int hh_len = rt_dst(rt).hh->hh_len;
-       int hh_off = HH_DATA_ALIGN(rt_dst(rt).hh->hh_len) - hh_len;
+       struct hh_cache *hh = rt_hh(rt);
+       int hh_len = hh->hh_len;
+       int hh_off = HH_DATA_ALIGN(hh_len) - hh_len;
 
 #ifdef HAVE_HH_SEQ
        unsigned hh_seq;
 
        do {
-               hh_seq = read_seqbegin(&rt_dst(rt).hh->hh_lock);
-               memcpy(cache_data, (void *)rt_dst(rt).hh->hh_data + hh_off, 
hh_len);
-       } while (read_seqretry(&rt_dst(rt).hh->hh_lock, hh_seq));
+               hh_seq = read_seqbegin(&hh->hh_lock);
+               memcpy(cache_data, (void *)hh->hh_data + hh_off, hh_len);
+       } while (read_seqretry(&hh->hh_lock, hh_seq));
 
        cache->hh_seq = hh_seq;
 #else
-       read_lock(&rt_dst(rt).hh->hh_lock);
-       memcpy(cache_data, (void *)rt_dst(rt).hh->hh_data + hh_off, hh_len);
-       read_unlock(&rt_dst(rt).hh->hh_lock);
+       read_lock(&hh->hh_lock);
+       memcpy(cache_data, (void *)hh->hh_data + hh_off, hh_len);
+       read_unlock(&hh->hh_lock);
 #endif
 }
 
@@ -829,9 +836,17 @@ static struct tnl_cache *build_cache(struct vport *vport,
         * If there is no entry in the ARP cache or if this device does not
         * support hard header caching just fall back to the IP stack.
         */
-       if (!rt_dst(rt).hh)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
+       {
+               struct neighbour *neigh = dst_get_neighbour(&rt->dst);
+               if (!neigh || !(neigh->nud_state & NUD_CONNECTED) ||
+                              !neigh->hh.hh_len)
+                       return NULL;
+       }
+#else
+       if (!rt_hh(rt))
                return NULL;
-
+#endif
        /*
         * If lock is contended fall back to directly building the header.
         * We're not going to help performance by sitting here spinning.
@@ -845,7 +860,7 @@ static struct tnl_cache *build_cache(struct vport *vport,
        else
                cache = NULL;
 
-       cache_len = rt_dst(rt).hh->hh_len + mutable->tunnel_hlen;
+       cache_len = rt_hh(rt)->hh_len + mutable->tunnel_hlen;
 
        cache = kzalloc(ALIGN(sizeof(struct tnl_cache), CACHE_DATA_ALIGN) +
                        cache_len, GFP_ATOMIC);
@@ -855,7 +870,7 @@ static struct tnl_cache *build_cache(struct vport *vport,
        cache->len = cache_len;
 
        create_eth_hdr(cache, rt);
-       cache_data = get_cached_header(cache) + rt_dst(rt).hh->hh_len;
+       cache_data = get_cached_header(cache) + rt_hh(rt)->hh_len;
 
        create_tunnel_header(vport, mutable, rt, cache_data);
 
@@ -1181,7 +1196,7 @@ int tnl_send(struct vport *vport, struct sk_buff *skb)
                        skb_push(skb, cache->len);
                        memcpy(skb->data, get_cached_header(cache), cache->len);
                        skb_reset_mac_header(skb);
-                       skb_set_network_header(skb, rt_dst(rt).hh->hh_len);
+                       skb_set_network_header(skb, rt_hh(rt)->hh_len);
 
                } else {
                        skb_push(skb, mutable->tunnel_hlen);
-- 
1.7.1

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to