手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

linux的网络设计和实现

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

struct net_proto
{
const char *name; /* Protocol name */
void (*init_func)(struct net_proto *); /* Bootstrap */
} protocols[];
每一个协议提供了一个自己的init_func. 如IP提供了ip_init.

dev_add_pack完成了实际的协议添加过程. 系统维护了两个协议表. 一个是单向链表,
另一个是hash表(使用了桶形的hash表).

每一个协议用一个struct packet_type来描述, 其中的func是其入口函数. 当系统从
读到一个报文就会调用相应协议的func来完成实际的处理工作.

struct packet_type
{
unsigned short type; /* This is really htons(ether_type). */
struct device *dev; /* NULL is wildcarded here */
int (*func) (struct sk_buff *, struct device *,
struct packet_type *);
void *data; /* Private to the packet type */
struct packet_type *next;
};

// 协议的hash表
struct packet_type *ptype_base[16]; /* Hashed types */
// 协议的单向链表的头指针
struct packet_type *ptype_all = NULL; /* Taps */

dev_add_pack完成的工作其实很简单, 他将一个struct packet_type指针加入到相应
的链表中. 请看源码:
void dev_add_pack(struct packet_type *pt)
{
int hash;

//由pt->type来判断加到那一个链表中
if(pt->type == htons(ETH_P_ALL))
{

netdev_nit ;
// 添加到单向链表中
pt->next = ptype_all;
ptype_all = pt;
}
else
{
// 添加到hash表中
hash = ntohs(pt->type)&15;
~~~~~~~~~~~~~~~~~~~~~~~~~~
//这是他的hash算法, 简单的只取低4位
pt->next = ptype_base[hash];
ptype_base[hash] = pt;
}
}
ip_init使用dev_add_pack完成了实际的添加过程.

下面是核心数据结构sk_buff
struct sk_buff {
struct sk_buff * next; /* Next buffer in list */
struct sk_buff * prev; /* Previous buffer in list */
struct sk_buff_head * list; /* List we are on */
struct sock *sk; /* Socket we are owned by */
struct timeval stamp; /* Time we arrived */
struct device *dev; /* Device we arrived on/are leaving by */

/* Transport layer header */
union
{
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct spxhdr *spxh;
unsigned char *raw;
} h;

/* Network layer header */
union
{
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
struct ipxhdr *ipxh;
unsigned char *raw;
} nh;

/* Link layer header */
union
{
struct ethhdr *ethernet;
unsigned char *raw;
} mac;

struct dst_entry *dst;

char cb[48];

unsigned int len; /* Length of actual data */
unsigned int csum; /* Checksum */
volatile char used; /* Data moved to user and not MSG_PEEK */
unsigned char is_clone, /* We are a clone */
cloned, /* head may be cloned(check refcnt to be sure)*/
pkt_type, /* Packet class */
pkt_bridged, /* Tracker for bridging */
ip_summed; /* Driver fed us an IP checksum */
__u32 priority; /* Packet queueing priority */
atomic_t users; /* User count - see datagram.c,tcp.c */
unsigned short protocol; /* Packet protocol from driver. */
unsigned short security; /* Security level of packet */
unsigned int truesize; /* Buffer size */

unsigned char *head; /* Head of buffer */
unsigned char *data; /* Data head pointer */
unsigned char *tail; /* Tail pointer */
unsigned char *end; /* End pointer */
void (*destructor)(struct sk_buff *); /* Destruct function */
#ifdef CONFIG_IP_FIREWALL
__u32 fwmark; /* Label made by fwchains, used by pktsched */
#endif
#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
__u32 shapelatency; /* Latency on frame */
__u32 shapeclock; /* Time it should go out */
__u32 shapelen; /* Frame length in clocks */
__u32 shapestamp; /* Stamp for shaper */
__u16 shapepend; /* Pending */
#endif

#if defined(CONFIG_HIPPI)
union{
__u32 ifield;
} private;
#endif
};

* arch/i386/kernel/irq.c

void do_IRQ(unsigned int irq, struct pt_regs *regs)
{
int cpu = smp_processor_id();

kstat.irqs[cpu][irq] ;
irq_desc[irq].handler->handle(irq, regs);

/*
* This should be conditional: we should really get
* a return code from the irq handler to tell us
* whether the handler wants us to do software bottom
* half handling or not..
*/
//每次处理中断, 都会进行底半处理. 现在还不符合底半的原意.
if (1) {
if (bh_active & bh_mask)
do_bottom_half();

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!