dst_entry() is one of the important Linux Kernel Networking subsystem data-structure which is used while navigating the packet flow within the IPv4 stack. It contains function pointers one for input and one for output.
For example a dst_entry instance (net/ipv4/ip_input.c) for a locally received packet would have an input function pointer to a local ip receiving function. A packet which was not intended for the local host, would have a dst_entry with an input function pointer to a packet forwarding function (net/ipv4/ip_forward.c).
For more details refer Linux Source:
Network_data_flow_through_kernel API Map ↗
http://lxr.free-electrons.com/source/include/net/dst.h ↗
http://lxr.free-electrons.com/source/net/core/dst.c ↗
http://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L396 ↗
http://lxr.free-electrons.com/source/include/linux/skbuff.h ↗
http://lxr.free-electrons.com/source/include/linux/skbuff.h#L665 ↗
skb_dst() – http://lxr.free-electrons.com/source/include/linux/skbuff.h#L845 ↗
skb_dst_set() – http://lxr.free-electrons.com/source/include/linux/skbuff.h#L864 ↗
And here is the copy paste of struct dst_entry data-structure (/include/net/dst.h) from the Kernel-source version 4.13 for quick reference:
struct dst_entry {
struct net_device *dev;
struct rcu_head rcu_head;
struct dst_entry *child;
struct dst_ops *ops;
unsigned long _metrics;
unsigned long expires;
struct dst_entry *path;
struct dst_entry *from;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
#else
void *__pad1;
#endif
int (*input)(struct sk_buff *);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
unsigned short flags;
#define DST_HOST 0x0001
#define DST_NOXFRM 0x0002
#define DST_NOPOLICY 0x0004
#define DST_NOCOUNT 0x0008
#define DST_FAKE_RTABLE 0x0010
#define DST_XFRM_TUNNEL 0x0020
#define DST_XFRM_QUEUE 0x0040
#define DST_METADATA 0x0080
short error;
/* A non-zero value of dst->obsolete forces by-hand validation
* of the route entry. Positive values are set by the generic
* dst layer to indicate that the entry has been forcefully
* destroyed.
*
* Negative values are used by the implementation layer code to
* force invocation of the dst_ops->check() method.
*/
short obsolete;
#define DST_OBSOLETE_NONE 0
#define DST_OBSOLETE_DEAD 2
#define DST_OBSOLETE_FORCE_CHK -1
#define DST_OBSOLETE_KILL -2
unsigned short header_len; /* more space at head required */
unsigned short trailer_len; /* space to reserve at tail */
unsigned short __pad3;
#ifdef CONFIG_IP_ROUTE_CLASSID
__u32 tclassid;
#else
__u32 __pad2;
#endif
#ifdef CONFIG_64BIT
/*
* Align __refcnt to a 64 bytes alignment
* (L1_CACHE_SIZE would be too much)
*/
long __pad_to_align_refcnt[2];
#endif
/*
* __refcnt wants to be on a different cache line from
* input/output/ops or performance tanks badly
*/
atomic_t __refcnt; /* client references */
int __use;
unsigned long lastuse;
struct lwtunnel_state *lwtstate;
union {
struct dst_entry *next;
struct rtable __rcu *rt_next;
struct rt6_info *rt6_next;
struct dn_route __rcu *dn_next;
};
};
And here is the copy paste of API skb_dst() which returns the dst_entry linked to the corresponding skbuff instance (include/linux/skbuff.h) from the Kernel-source version 4.13 for quick reference:
/**
* skb_dst - returns skb dst_entry
* @skb: buffer
*
* Returns skb dst_entry, regardless of reference taken or not.
*/
static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
{
/* If refdst was not refcounted, check we still are in a
* rcu_read_lock section
*/
WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) &&
!rcu_read_lock_held() &&
!rcu_read_lock_bh_held());
return (struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK);
}
So here is my detailed YouTube video on the same and overall various aspects of Kernel network subsystem development and architecture.
I also conduct sessions/classes on Systems and Network Software Programming, Linux Kernel Programming and Architecture. If you are interested, click HERE for more details.
If you have any queries or anything to discuss further kindly feel free to contact me.