Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2374228
  • 博文数量: 145
  • 博客积分: 8668
  • 博客等级: 中将
  • 技术积分: 3922
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-09 21:21
个人简介

work hard

文章分类

全部博文(145)

文章存档

2016年(1)

2015年(1)

2014年(1)

2013年(12)

2012年(3)

2011年(9)

2010年(34)

2009年(55)

2008年(20)

2007年(9)

分类: LINUX

2008-10-07 16:54:52

本文并不是系统的比较2.4和2.6内核的区别,而只是单纯从程序设计的角度,并且仅是本人在阅读代码过程中的一个点感受,没有任何系统性。

这里比较的函数是位于内核源码下net/etherne/eth.c中的eth_type_trans函数的设计。

以下分别是2.4和2.6中该函数的源代码:

2.4中的代码:

/*
 *    Determine the packet's protocol ID. The rule here is that we
 *    assume 802.3 if the type field is short enough to be a length.
 *    This is normal practice and works for any 'now in use' protocol.
 */

 
unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
    struct ethhdr *eth;
    unsigned char *rawp;
    
    skb->mac.raw=skb->data;
    skb_pull(skb,dev->hard_header_len);
    eth= skb->mac.ethernet;
    
    if(*eth->h_dest&1)
    {
        if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
            skb->pkt_type=PACKET_BROADCAST;
        else
            skb->pkt_type=PACKET_MULTICAST;
    }
    
    /*
     *    This ALLMULTI check should be redundant by 1.4
     *    so don't forget to remove it.
     *
     *    Seems, you forgot to remove it. All silly devices
     *    seems to set IFF_PROMISC.
     */

    
    else if(1 /*dev->flags&IFF_PROMISC*/)
    {
        if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
            skb->pkt_type=PACKET_OTHERHOST;
    }
    
    if (ntohs(eth->h_proto) >= 1536)
        return eth->h_proto;
        
    rawp = skb->data;
    
    /*
     *    This is a magic hack to spot IPX packets. Older Novell breaks
     *    the protocol design and runs IPX over 802.3 without an 802.2 LLC
     *    layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
     *    won't work for fault tolerant netware but does for the rest.
     */

    if (*(unsigned short *)rawp == 0xFFFF)
        return htons(ETH_P_802_3);
        
    /*
     *    Real 802.2 LLC
     */

    return htons(ETH_P_802_2);
}

2.6中的代码:

/**
 * eth_type_trans - determine the packet's protocol ID.
 * @skb: received socket data
 * @dev: receiving network device
 *
 * The rule here is that we
 * assume 802.3 if the type field is short enough to be a length.
 * This is normal practice and works for any 'now in use' protocol.
 */

__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
    struct ethhdr *eth;
    unsigned char *rawp;

    skb->mac.raw = skb->data;
    skb_pull(skb, ETH_HLEN);
    eth = eth_hdr(skb);

    if (is_multicast_ether_addr(eth->h_dest)) {
        if (!compare_ether_addr(eth->h_dest, dev->broadcast))
            skb->pkt_type = PACKET_BROADCAST;
        else
            skb->pkt_type = PACKET_MULTICAST;
    }

    /*
     * This ALLMULTI check should be redundant by 1.4
     * so don't forget to remove it.
     *
     * Seems, you forgot to remove it. All silly devices
     * seems to set IFF_PROMISC.
     */


    else if (1 /*dev->flags&IFF_PROMISC */ ) {
        if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr)))
            skb->pkt_type = PACKET_OTHERHOST;
    }

    if (ntohs(eth->h_proto) >= 1536)
        return eth->h_proto;

    rawp = skb->data;

    /*
     * This is a magic hack to spot IPX packets. Older Novell breaks
     * the protocol design and runs IPX over 802.3 without an 802.2 LLC
     * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
     * won't work for fault tolerant netware but does for the rest.
     */

    if (*(unsigned short *)rawp == 0xFFFF)
        return htons(ETH_P_802_3);

    /*
     * Real 802.2 LLC
     */

    return htons(ETH_P_802_2);
}


这两部分代码所做的工作都是要判断一下数据包是否属于多播类型,以及网卡是否设置为混杂模式。但通过两部分代码的比较就可以看出:
(1)在判断是否属于多播的时候,2.4内核直接进行了判断,并且进行MAC的比较,然后得出是否属于多播并且对skb->pkt_type进行赋值。而2.6中则将这些具体的操作封装到一个函数is_multicast_ether_addr里实现。这样做的效果很明显,别人一看就知道这段代码是干什么的,所谓见名之义。
(2)在比较MAC地址方面,2.4内核也是直接使用memcmp进行比较,而2.6内核则同样通过一个函数compare_ether_addr来实现。相同地,2.6中的实现更容易被接受和理解。

从这个简单的比较中,可以看出,2.6内核中对很多功能比较单一的代码进行了有效的封装。实现某个小的功能,进行相应的函数调用即可。如果具体功能的实现方法随着技术的发展有所调整的话,只要函数借口不变,那么调用该函数的代码就不需要做什么改变,而只修改具体实现功能的函数即可。

像这样的情况,在2.6内核中比较多。因此,这样的做法也给了我们在设计程序中一些提醒和建议,在保证代码效率或者代码效率不是问题的时候,要充分的利用函数模块化的思想,将功能单一的一些代码通过函数封装起来,对外提供一个接口即可。这样,不管以后是别人接受自己的代码,或者长时间之后再次阅读自己的代码,应该都很容易的得到一个清晰的结构。
                                                               
                                                                 Godbach记.
                                                                 Oct 7, 2008

阅读(3462) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~