@@ -443,6 +443,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/net/checksum.h], [csum_replace4])
OVS_GREP_IFELSE([$KSRC/include/net/checksum.h], [csum_unfold])
+ OVS_GREP_IFELSE([$KSRC/include/net/dst.h], [dst_discard_sk])
+
OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [genl_has_listeners])
OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [mcgrp_offset])
OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [parallel_ops])
@@ -22,4 +22,82 @@ static inline void skb_dst_drop(struct sk_buff *skb)
#endif
+#ifndef DST_OBSOLETE_NONE
+#define DST_OBSOLETE_NONE 0
+#endif
+
+#ifndef DST_NOCOUNT
+#define DST_NOCOUNT 0
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst)
+{
+ nskb->_skb_dst = refdst;
+ dst_clone(skb_dst(nskb));
+}
+
+static inline void refdst_drop(unsigned long refdst) { }
+static inline void skb_dst_set_noref(struct sk_buff *skb,
+ struct dst_entry *dst) { }
+static inline void dst_init_metrics(struct dst_entry *dst, const u32 *metrics,
+ bool read_only) { }
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
+static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst)
+{
+ nskb->_skb_refdst = refdst;
+ if (!(nskb->_skb_refdst & SKB_DST_NOREF))
+ dst_clone(skb_dst(nskb));
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
+static inline void dst_entries_add(struct dst_ops *ops, int count)
+{
+ atomic_add(count, &ops->entries);
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
+static const u32 rpl_dst_default_metrics[RTAX_MAX + 1] = {
+ /* This initializer is needed to force linker to place this variable
+ * into const section. Otherwise it might end into bss section.
+ * We really want to avoid false sharing on this variable, and catch
+ * any writes on it.
+ */
+ [RTAX_MAX] = 0xdeadbeef,
+};
+#define dst_default_metrics rpl_dst_default_metrics
+
+static inline void rpl_dst_init(struct dst_entry *dst, struct dst_ops *ops,
+ struct net_device *dev, int initial_ref,
+ int initial_obsolete, unsigned short flags)
+{
+ /* XXX: It's easier to handle compatibility by zeroing, as we can
+ * refer to fewer fields. Do that here.
+ */
+ memset(dst, 0, sizeof *dst);
+
+ dst->dev = dev;
+ if (dev)
+ dev_hold(dev);
+ dst->ops = ops;
+ dst_init_metrics(dst, dst_default_metrics, true);
+ dst->path = dst;
+ dst->input = dst_discard;
+#ifndef HAVE_DST_DISCARD_SK
+ dst->output = dst_discard;
+#else
+ dst->output = dst_discard_sk;
+#endif
+ dst->obsolete = initial_obsolete;
+ atomic_set(&dst->__refcnt, initial_ref);
+ dst->lastuse = jiffies;
+ dst->flags = flags;
+ if (!(flags & DST_NOCOUNT))
+ dst_entries_add(ops, 1);
+}
+#define dst_init rpl_dst_init
+#endif
+
#endif
Signed-off-by: Joe Stringer <joestringer@nicira.com> --- acinclude.m4 | 2 + datapath/linux/compat/include/net/dst.h | 78 +++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+)