linux l2tp kernel(包含了L2TPv3的版本)主要數據結構理解

主要結構體

 原來的註釋就挺全的,就不多廢話了,無非就是通過指針相互指,通過全局的hash保存。

1

struct l2tp_net {
	struct list_head l2tp_tunnel_list; //保存了所有tunnel的雙向列表的表頭
	spinlock_t l2tp_tunnel_list_lock;
	struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2]; /*保存了所有的session的hash列表的表頭偏移量由hash_32計算,此處的size(1<<8)更大,hash衝突比tunnel結構體裏的小(1<<4)(不過一個tunnel基本上也不會包含很多個session,具體請參考hash_32的實現),通過調用RCU的api方式訪問*/
	spinlock_t l2tp_session_hlist_lock;
};

2

struct l2tp_tunnel {
	int			magic;		/* Should be L2TP_TUNNEL_MAGIC */
	rwlock_t		hlist_lock;	/* protect session_hlist */
	struct hlist_head	session_hlist[L2TP_HASH_SIZE]; //size比較下,是1<<4
						/* hashed list of sessions,
						 * hashed by id */
	u32			tunnel_id;
	u32			peer_tunnel_id;
	int			version;	/* 2=>L2TPv2, 3=>L2TPv3 */

	char			name[20];	/* for logging */ //"tunl %u"
	int			debug;		/* bitmask of debug message
						 * categories */
	enum l2tp_encap_type	encap;
	struct l2tp_stats	stats;

	struct list_head	list;		/* Keep a list of all tunnels */ //雙向鏈接到l2tp_net結構體的l2tp_tunnel_list列表中,見上
	struct net		*l2tp_net;	/* the net we belong to */

	atomic_t		ref_count;
#ifdef CONFIG_DEBUG_FS
	void (*show)(struct seq_file *m, void *arg);
#endif
	int (*recv_payload_hook)(struct sk_buff *skb);
	void (*old_sk_destruct)(struct sock *);
	struct sock		*sock;		/* Parent socket */
	int			fd;

	uint8_t			priv[0];	/* private data */
};
3
struct l2tp_session {
	int			magic;		/* should be
						 * L2TP_SESSION_MAGIC */

	struct l2tp_tunnel	*tunnel;	/* back pointer to tunnel
						 * context */ //指向所屬tunnel
	u32			session_id;
	u32			peer_session_id;
	u8			cookie[8];
	int			cookie_len;
	u8			peer_cookie[8];
	int			peer_cookie_len;
	u16			offset;		/* offset from end of L2TP header
						   to beginning of data */
	u16			l2specific_len;
	u16			l2specific_type;
	u16			hdr_len;
	u32			nr;		/* session NR state (receive) */
	u32			ns;		/* session NR state (send) */
	struct sk_buff_head	reorder_q;	/* receive reorder queue */
	struct hlist_node	hlist;		/* Hash list node */ //鏈接到l2tp_tunnel結構體的sesson_hlist中,見上
	atomic_t		ref_count;

	char			name[32];	/* for logging */
	char			ifname[IFNAMSIZ];
	unsigned		data_seq:2;	/* data sequencing level
						 * 0 => none, 1 => IP only,
						 * 2 => all
						 */
	unsigned		recv_seq:1;	/* expect receive packets with
						 * sequence numbers? */
	unsigned		send_seq:1;	/* send packets with sequence
						 * numbers? */
	unsigned		lns_mode:1;	/* behave as LNS? LAC enables
						 * sequence numbers under
						 * control of LNS. */
	int			debug;		/* bitmask of debug message
						 * categories */
	int			reorder_timeout; /* configured reorder timeout
						  * (in jiffies) */
	int			mtu;
	int			mru;
	enum l2tp_pwtype	pwtype;
	struct l2tp_stats	stats;
	struct hlist_node	global_hlist;	/* Global hash list node */ //鏈接到l2tp_net結構體的l2tp_session_hlist中,見上

	int (*build_header)(struct l2tp_session *session, void *buf);
	void (*recv_skb)(struct l2tp_session *session, struct sk_buff *skb, int data_len);
	void (*session_close)(struct l2tp_session *session);
	void (*ref)(struct l2tp_session *session);
	void (*deref)(struct l2tp_session *session);
#if defined(CONFIG_L2TP_DEBUGFS) || defined(CONFIG_L2TP_DEBUGFS_MODULE)
	void (*show)(struct seq_file *m, void *priv);
#endif
	uint8_t			priv[0];	/* private data */
};
4
/* Private data of each session. This data lives at the end of struct
 * l2tp_session, referenced via session->priv[]. 即處於上面結構體l2tp_session的最後部分,通過l2tp_session_priv(struct l2tp_session session)返回相應的地址指針,這裏是上層承載ppp的包
 */
struct pppol2tp_session {
	int			owner;		/* pid that opened the socket */

	struct sock		*sock;		/* Pointer to the session
						 * PPPoX socket */
	struct sock		*tunnel_sock;	/* Pointer to the tunnel UDP
						 * socket */
	int			flags;		/* accessed by PPPIOCGFLAGS.
						 * Unused. */
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章