Chinaunix首页 | 论坛 | 博客
  • 博客访问: 585405
  • 博文数量: 146
  • 博客积分: 5251
  • 博客等级: 大校
  • 技术积分: 1767
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-10 15:58
文章分类
文章存档

2010年(12)

2008年(129)

2007年(5)

我的朋友

分类: LINUX

2008-02-01 11:55:59

LOOPBACK网络回送设备
====================

(1) 当从主机内部发送一个目标地址为本机地址的IP包时,
ip_route_output()将IP包的输出路由定向到回送设备.
回送设备的驱动程序可看成是最简单的以太网设备驱动程序, 它的硬件地址为零,
IP地址一般设定为标准回送地址127.0.0.1.

当包调度器启动回送设备的硬件发射操作(hard_start_xmit)时, 驱动程序将发送包作为接收包,
交给一般的接收过程(netif_rx)进行排队处理.

(2) 对回送设备来说, 根本无需硬件地址解析(ARP)过程来解析IP包的帧头目的地址.
所有指向回送设备的缓冲路由将共享同一邻居结构,
该邻居结构在ARP邻居缓冲表中以零地址来标识, 它的状态为NUD_NOARP, 属于NUD_CONNECT状态,
即为永久连接状态. 路由缓冲的输出口一开始仍指向邻居解析输出口(neigh_resolve_output),
当传送第一个包时, 解析口将绕过ARP过程立接建立路由的帧头缓冲结构,
使输出通过帧头缓冲直接指向包发射器(dev_queue_xmit), 该帧头缓冲结构将一直有效.

#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)

/*
* The higher levels take care of making this non-reentrant (it's
* called with bh's disabled).
*/
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *stats = (struct net_device_stats *)dev->priv;

/*
* Optimise so buffers with skb->free=1 are not copied but
* instead are lobbed from tx queue to rx queue
*/

if(atomic_read(&skb->users) != 1)
{
  struct sk_buff *skb2=skb; 继承包的复制特性
  skb=skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */
  if(skb==NULL) {
kfree_skb(skb2);
return 0;
}
  kfree_skb(skb2);
}
else
skb_orphan(skb); 释放源套接字对该包的拥有

skb->protocol=eth_type_trans(skb,dev); 识别并去除硬件帧头
skb->dev=dev;
#ifndef LOOPBACK_MUST_CHECKSUM
skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif
netif_rx(skb);

stats->rx_bytes+=skb->len; 对回送设备来说, 发送的字节数就是接收的字节数
stats->tx_bytes+=skb->len; 发送包的数量就是接收包的数量
stats->rx_packets++;
stats->tx_packets++;

return(0);
}

static struct net_device_stats *get_stats(struct net_device *dev)
{
return (struct net_device_stats *)dev->priv;
}

/* Initialize the rest of the LOOPBACK device. */
int __init loopback_init(struct net_device *dev)
{
dev->mtu = PAGE_SIZE - LOOPBACK_OVERHEAD; 使得包数据缓冲区不超过1页
dev->hard_start_xmit = loopback_xmit;
dev->hard_header = eth_header;
dev->hard_header_cache = eth_header_cache;
dev->header_cache_update= eth_header_cache_update;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->tx_queue_len = 0;
dev->type = ARPHRD_LOOPBACK; /* 0x0001 */
dev->rebuild_header = eth_rebuild_header;
dev->flags = IFF_LOOPBACK;
dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
if (dev->priv == NULL)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct net_device_stats));
dev->get_stats = get_stats;

if (num_physpages >= ((128*1024*1024)>>PAGE_SHIFT)) 如果物理内存达到128M
dev->mtu = 4096*4 - LOOPBACK_OVERHEAD; 增大包数据缓冲区,使包缓冲区不超过4页

/*
* Fill in the generic fields of the device structure.
*/
  
dev_init_buffers(dev);
 
return(0);
};
阅读(814) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~