|
@@ -40,24 +40,10 @@ struct dst_entry {
|
|
|
struct rcu_head rcu_head;
|
|
|
struct dst_entry *child;
|
|
|
struct net_device *dev;
|
|
|
- short error;
|
|
|
- short obsolete;
|
|
|
- int flags;
|
|
|
-#define DST_HOST 0x0001
|
|
|
-#define DST_NOXFRM 0x0002
|
|
|
-#define DST_NOPOLICY 0x0004
|
|
|
-#define DST_NOHASH 0x0008
|
|
|
-#define DST_NOCACHE 0x0010
|
|
|
+ struct dst_ops *ops;
|
|
|
+ unsigned long _metrics;
|
|
|
unsigned long expires;
|
|
|
-
|
|
|
- unsigned short header_len; /* more space at head required */
|
|
|
- unsigned short trailer_len; /* space to reserve at tail */
|
|
|
-
|
|
|
- unsigned int rate_tokens;
|
|
|
- unsigned long rate_last; /* rate limiting for ICMP */
|
|
|
-
|
|
|
struct dst_entry *path;
|
|
|
-
|
|
|
struct neighbour *neighbour;
|
|
|
struct hh_cache *hh;
|
|
|
#ifdef CONFIG_XFRM
|
|
@@ -68,17 +54,16 @@ struct dst_entry {
|
|
|
int (*input)(struct sk_buff*);
|
|
|
int (*output)(struct sk_buff*);
|
|
|
|
|
|
- struct dst_ops *ops;
|
|
|
-
|
|
|
- u32 _metrics[RTAX_MAX];
|
|
|
-
|
|
|
+ short error;
|
|
|
+ short obsolete;
|
|
|
+ unsigned short header_len; /* more space at head required */
|
|
|
+ unsigned short trailer_len; /* space to reserve at tail */
|
|
|
#ifdef CONFIG_IP_ROUTE_CLASSID
|
|
|
__u32 tclassid;
|
|
|
#else
|
|
|
__u32 __pad2;
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
* Align __refcnt to a 64 bytes alignment
|
|
|
* (L1_CACHE_SIZE would be too much)
|
|
@@ -93,6 +78,14 @@ struct dst_entry {
|
|
|
atomic_t __refcnt; /* client references */
|
|
|
int __use;
|
|
|
unsigned long lastuse;
|
|
|
+ unsigned long rate_last; /* rate limiting for ICMP */
|
|
|
+ unsigned int rate_tokens;
|
|
|
+ int flags;
|
|
|
+#define DST_HOST 0x0001
|
|
|
+#define DST_NOXFRM 0x0002
|
|
|
+#define DST_NOPOLICY 0x0004
|
|
|
+#define DST_NOHASH 0x0008
|
|
|
+#define DST_NOCACHE 0x0010
|
|
|
union {
|
|
|
struct dst_entry *next;
|
|
|
struct rtable __rcu *rt_next;
|
|
@@ -103,10 +96,69 @@ struct dst_entry {
|
|
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
|
|
+extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
|
|
|
+
|
|
|
+#define DST_METRICS_READ_ONLY 0x1UL
|
|
|
+#define __DST_METRICS_PTR(Y) \
|
|
|
+ ((u32 *)((Y) & ~DST_METRICS_READ_ONLY))
|
|
|
+#define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics)
|
|
|
+
|
|
|
+static inline bool dst_metrics_read_only(const struct dst_entry *dst)
|
|
|
+{
|
|
|
+ return dst->_metrics & DST_METRICS_READ_ONLY;
|
|
|
+}
|
|
|
+
|
|
|
+extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
|
|
|
+
|
|
|
+static inline void dst_destroy_metrics_generic(struct dst_entry *dst)
|
|
|
+{
|
|
|
+ unsigned long val = dst->_metrics;
|
|
|
+ if (!(val & DST_METRICS_READ_ONLY))
|
|
|
+ __dst_destroy_metrics_generic(dst, val);
|
|
|
+}
|
|
|
+
|
|
|
+static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst)
|
|
|
+{
|
|
|
+ unsigned long p = dst->_metrics;
|
|
|
+
|
|
|
+ if (p & DST_METRICS_READ_ONLY)
|
|
|
+ return dst->ops->cow_metrics(dst, p);
|
|
|
+ return __DST_METRICS_PTR(p);
|
|
|
+}
|
|
|
+
|
|
|
+/* This may only be invoked before the entry has reached global
|
|
|
+ * visibility.
|
|
|
+ */
|
|
|
+static inline void dst_init_metrics(struct dst_entry *dst,
|
|
|
+ const u32 *src_metrics,
|
|
|
+ bool read_only)
|
|
|
+{
|
|
|
+ dst->_metrics = ((unsigned long) src_metrics) |
|
|
|
+ (read_only ? DST_METRICS_READ_ONLY : 0);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
|
|
|
+{
|
|
|
+ u32 *dst_metrics = dst_metrics_write_ptr(dest);
|
|
|
+
|
|
|
+ if (dst_metrics) {
|
|
|
+ u32 *src_metrics = DST_METRICS_PTR(src);
|
|
|
+
|
|
|
+ memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
|
|
|
+{
|
|
|
+ return DST_METRICS_PTR(dst);
|
|
|
+}
|
|
|
+
|
|
|
static inline u32
|
|
|
dst_metric_raw(const struct dst_entry *dst, const int metric)
|
|
|
{
|
|
|
- return dst->_metrics[metric-1];
|
|
|
+ u32 *p = DST_METRICS_PTR(dst);
|
|
|
+
|
|
|
+ return p[metric-1];
|
|
|
}
|
|
|
|
|
|
static inline u32
|
|
@@ -131,22 +183,10 @@ dst_metric_advmss(const struct dst_entry *dst)
|
|
|
|
|
|
static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
|
|
|
{
|
|
|
- dst->_metrics[metric-1] = val;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void dst_import_metrics(struct dst_entry *dst, const u32 *src_metrics)
|
|
|
-{
|
|
|
- memcpy(dst->_metrics, src_metrics, RTAX_MAX * sizeof(u32));
|
|
|
-}
|
|
|
+ u32 *p = dst_metrics_write_ptr(dst);
|
|
|
|
|
|
-static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
|
|
|
-{
|
|
|
- dst_import_metrics(dest, src->_metrics);
|
|
|
-}
|
|
|
-
|
|
|
-static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
|
|
|
-{
|
|
|
- return dst->_metrics;
|
|
|
+ if (p)
|
|
|
+ p[metric-1] = val;
|
|
|
}
|
|
|
|
|
|
static inline u32
|