#ifndef _NET_DST_H
#define _NET_DST_H
-#include <linux/config.h>
+#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#include <linux/jiffies.h>
int __use;
struct dst_entry *child;
struct net_device *dev;
- int obsolete;
+ short error;
+ short obsolete;
int flags;
#define DST_HOST 1
#define DST_NOXFRM 2
#define DST_NOPOLICY 4
#define DST_NOHASH 8
+#define DST_BALANCED 0x10
unsigned long lastuse;
unsigned long expires;
unsigned short header_len; /* more space at head required */
+ unsigned short nfheader_len; /* more non-fragment space at head required */
unsigned short trailer_len; /* space to reserve at tail */
u32 metrics[RTAX_MAX];
unsigned long rate_last; /* rate limiting for ICMP */
unsigned long rate_tokens;
- int error;
-
struct neighbour *neighbour;
struct hh_cache *hh;
struct xfrm_state *xfrm;
int (*input)(struct sk_buff*);
- int (*output)(struct sk_buff**);
+ int (*output)(struct sk_buff*);
#ifdef CONFIG_NET_CLS_ROUTE
__u32 tclassid;
struct dst_ops
{
unsigned short family;
- unsigned short protocol;
+ __be16 protocol;
unsigned gc_thresh;
int (*gc)(void);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
void (*destroy)(struct dst_entry *);
- void (*ifdown)(struct dst_entry *, int how);
+ void (*ifdown)(struct dst_entry *,
+ struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
- int (*get_mss)(struct dst_entry *dst, u32 mtu);
int entry_size;
atomic_t entries;
- kmem_cache_t *kmem_cachep;
+ struct kmem_cache *kmem_cachep;
};
#ifdef __KERNEL__
static inline u32
-dst_metric(struct dst_entry *dst, int metric)
+dst_metric(const struct dst_entry *dst, int metric)
{
return dst->metrics[metric-1];
}
-static inline u32
-dst_path_metric(struct dst_entry *dst, int metric)
+static inline u32 dst_mtu(const struct dst_entry *dst)
{
- return dst->path->metrics[metric-1];
+ u32 mtu = dst_metric(dst, RTAX_MTU);
+ /*
+ * Alexey put it here, so ask him about it :)
+ */
+ barrier();
+ return mtu;
}
static inline u32
-dst_pmtu(struct dst_entry *dst)
+dst_allfrag(const struct dst_entry *dst)
{
- u32 mtu = dst_path_metric(dst, RTAX_MTU);
+ int ret = dst_metric(dst, RTAX_FEATURES) & RTAX_FEATURE_ALLFRAG;
/* Yes, _exactly_. This is paranoia. */
barrier();
- return mtu;
+ return ret;
}
static inline int
void dst_release(struct dst_entry * dst)
{
if (dst) {
- if (atomic_read(&dst->__refcnt) < 1) {
- printk("BUG: dst underflow %d: %p\n",
- atomic_read(&dst->__refcnt),
- current_text_addr());
- }
+ WARN_ON(atomic_read(&dst->__refcnt) < 1);
+ smp_mb__before_atomic_dec();
atomic_dec(&dst->__refcnt);
}
}
__dst_free(dst);
}
+static inline void dst_rcu_free(struct rcu_head *head)
+{
+ struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head);
+ dst_free(dst);
+}
+
static inline void dst_confirm(struct dst_entry *dst)
{
if (dst)
/* Output packet to network from transport. */
static inline int dst_output(struct sk_buff *skb)
{
- int err;
-
- for (;;) {
- err = skb->dst->output(&skb);
-
- if (likely(err == 0))
- return err;
- if (unlikely(err != NET_XMIT_BYPASS))
- return err;
- }
+ return skb->dst->output(skb);
}
/* Input packet from network to transport. */
}
}
+static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
+{
+ if (dst->obsolete)
+ dst = dst->ops->check(dst, cookie);
+ return dst;
+}
+
extern void dst_init(void);
struct flowi;