linux loopback驱动分析,LOOPBACK网络回送设备分析

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);

};

阅读(675) | 评论(0) | 转发(0) |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值