主要結構體
原來的註釋就挺全的,就不多廢話了,無非就是通過指針相互指,通過全局的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 */
};
3struct 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. */
};