免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1512 | 回复: 0
打印 上一主题 下一主题

struct net_device 详解1 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-25 15:19 |只看该作者 |倒序浏览

                结构体net_device代表了一个网络设备接口,它是我们理解网络设备驱动程序的关键。这里,我们选择其中的一些重要成员,一一作详细分析,并结合以太网设备,看看Linux内核是如何为以太网设备提供结构体中某些成员的缺省值的。
   
在Linux内核源代码中是这样为这个结构体作注释的:实际上,这个结构体是一个很大的错误,它把I/O数据和更高层的数据混合在一起,而且它几乎必须知道INET模块中的每个数据结构。
   
毫无疑问,这是一个巨型结构体。但我们为编写网络设备驱动程序,只需要了解其中的一部分,下面选择其中的一些作分析,并给出以太网设备的缺省值。
   
unsigned short  flags;void
(*set_multicast_list)(struct net_device *dev);
   
这是一个接口标志,包含了很多值的位掩码。在以太网的缺省初始化函数中,该标志被设置为:IFF_BROADCAST|IFF_MULTICAST,表示以太网卡是可广播的,并且是能够进行组播发送的。另外,该标志接口还有一些只读标志,如IFF_UP,当接口被激活并可以开始传输数据包时,内核设置该标志。而IFF_PROMISC被设置或清除时,会调用set_multicast_list函数通知板卡上的硬件过滤器。
unsigned short hard_header_len;unsigned short
type;
   
hard_header_len是硬件头的长度,在以太网设备的初始化函数中,该成员被赋为ETH_HLEN,即以太网头的长度,该值为14,下面是以太网头的定义:
struct
ethhdr {
    unsigned char   h_dest[ETH_ALEN];   /* destination eth addr
*/
    unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
   
unsigned short  h_proto;        /* packet type ID field */
}
__attribute__((packed));
   
ETH_ALEN被定义为6,即以太网MAC地址的长度。h_proto保存type的值。type是接口的硬件类型,以太网设备的初始化函数中将其赋值为ARPHRD_ETHER,即10Mb以太网。
int (*hard_header) (struct sk_buff *skb, struct
net_device *dev,                unsigned short type, void *daddr,void
*saddr,                unsigned len);
   
该函数在数据被传输之前被调用,它根据先前检索到的源和目标地址建立硬件头。以太网设备的默认函数是eth_header:
int
eth_header(struct sk_buff *skb, struct net_device *dev,
               
unsigned short type, void *daddr,
                void *saddr, unsigned
len)
{
    struct ethhdr *eth = (struct ethhdr
*)skb_push(skb,ETH_HLEN);
    /*
     *  Set the protocol type. For a
packet of
     *  type ETH_P_802_3 we put the length
     *  in here
instead. It is up to the 802.2
     *  layer to carry protocol
information.
     */
    if(type!=ETH_P_802_3)
        eth->h_proto
= htons(type);
    else
        eth->h_proto = htons(len);
   
//Set the source hardware address.
    if(!saddr)
        saddr =
dev->dev_addr;
    memcpy(eth->h_source,saddr,dev->addr_len);
   
//Anyway, the loopback-device should never
    //use this function...
   
if (dev->flags & (IFF_LOOPBACK|IFF_NOARP)){
        
memset(eth->h_dest, 0, dev->addr_len);
        return ETH_HLEN;
   
}
    if(daddr){
        
memcpy(eth->h_dest,daddr,dev->addr_len);
        return
ETH_HLEN;
    }
    return -ETH_HLEN;
}
   
它根据传入的参数建立以太网头,如果传入的源地址为空,则使用设备的地址作为源地址。与之相关的还有一个int (*rebuild_header)(struct
sk_buff *skb)函数,在以太网设备中,它是用于在ARP地址解析完成以后,重新建立以太网头,主要是更新目标MAC地址,因为在前一次建立时,由于没有经过
ARP协议,有可能目标MAC地址是错误的。
int (*set_mac_address)(struct net_device *dev, void *addr);
   
改变网卡的mac地址。实际上,许多硬件设备接口根本不支持这种功能,就算支持,也需要硬件厂商提供的工具修改EPROM中的硬件地址。一般我们在某一操作系统下所谓的修改MAC地址,只是修改了操作系统在安装网卡时从网卡EPROM中读出来的值,如果系统被重装,则MAC地址又恢复为原来的值。以太网设备的默认函数是eth_mac_addr,它只是简单地修改了dev->dev_addr的值。
int
(*hard_header_cache)(struct neighbour *neigh,struct hh_cache *hh);
void
(*header_cache_update)(struct hh_cache *hh,struct net_device
*dev,
                            unsigned char *  haddr);
int
(*hard_header_parse)(struct sk_buff *skb,unsigned char *haddr);
   
这三个函数在以太网设备接口中都有默认的值,hard_header_cache把硬件地址缓存到struct
hh_cache中;header_cache_update在地址发生变化中,更新hh_cache结构中的目标地址;而
hard_header_parse则从skb中的数据包中获得源地址,并将其复制到位于haddr的缓冲区。
int
(*change_mtu)(struct net_device *dev, int new_mtu);
   
下面是以太网设备接口的change_mtu的实现:
    static int eth_change_mtu(struct net_device
*dev, int new_mtu)
    {
        if ((new_mtu  
1500))
            return -EINVAL;
        dev->mtu =
new_mtu;
        return 0;
    }
   
在net_device中,还有很多网络驱动程序必须涉及的重要成员,随着我们的8139too网卡驱动程序的进一步深入,在涉及时再作详细分析。
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/98073/showart_1977195.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP