主要结构体

 原来的注释就挺全的,就不多废话了,无非就是通过指针相互指,通过全局的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. */
};


Logo

更多推荐