linux协议栈之网桥实现之一.docx

上传人:b****6 文档编号:5918796 上传时间:2023-01-02 格式:DOCX 页数:9 大小:17.95KB
下载 相关 举报
linux协议栈之网桥实现之一.docx_第1页
第1页 / 共9页
linux协议栈之网桥实现之一.docx_第2页
第2页 / 共9页
linux协议栈之网桥实现之一.docx_第3页
第3页 / 共9页
linux协议栈之网桥实现之一.docx_第4页
第4页 / 共9页
linux协议栈之网桥实现之一.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

linux协议栈之网桥实现之一.docx

《linux协议栈之网桥实现之一.docx》由会员分享,可在线阅读,更多相关《linux协议栈之网桥实现之一.docx(9页珍藏版)》请在冰豆网上搜索。

linux协议栈之网桥实现之一.docx

linux协议栈之网桥实现之一

linux协议栈之网桥实现之一

网卡驱动最个函数netif_receive_skb.就从说起。

简单起见,去掉里面预编译代码intnetif_receive_skb(structsk_buff*skb)    (net/core/dev.c)

{

    structpacket_type*ptype,*pt_prev;

    intret=NET_RX_DROP;

    unsignedshorttype;

    //打接收时间戳

    if(!

skb->stamp.tv_sec)

         net_timestamp(&skb->stamp);

    //如果存dev->master。

则更新相应指针

    skb_bond(skb);

    //更新CPU接收统计数据

    __get_cpu_var(netdev_rx_stat).total++;

    skb->h.raw=skb->nh.raw=skb->data;

    skb->mac_len=skb->nh.raw-skb->mac.raw;

    pt_prev=NULL;

    rcu_read_lock();

    //处理所有协议模块

    list_for_each_entry_rcu(ptype,&ptype_all,list){

         if(!

ptype->dev||ptype->dev==skb->dev){

              if(pt_prev)

                  ret=deliver_skb(skb,pt_prev);

              pt_prev=ptype;

         }

    }

    //分片处理

    handle_diverter(skb);

    //网桥处理

    if(handle_bridge(&skb,&pt_prev,&ret))

         gotoout;

    type=skb->protocol;

    //协议调相应模块处理。

    list_for_each_entry_rcu(ptype,&ptype_base[ntohs(type)&15],list){

         if(ptype->type==type&&

           (!

ptype->dev||ptype->dev==skb->dev)){

              if(pt_prev)

                  ret=deliver_skb(skb,pt_prev);

              pt_prev=ptype;

         }

    }

    if(pt_prev){

         ret=pt_prev->func(skb,skb->dev,pt_prev);

    }else{

         kfree_skb(skb);

         /*Jamal,nowyouwillnotabletoescapeexplaining

         *mehowyouweregoingtousethis.:

-)

         */

         ret=NET_RX_DROP;

    }

out:

    rcu_read_unlock();

    returnret;

}此函数主完成分片重组,网桥处理,根据不同协议调不同传输层处理模块。

本节重点概述linux网桥实现处理。

传输层协议分层续章节陆续给出。

进入网桥处理代码:

#ifdefined(CONFIG_BRIDGE)||defined(CONFIG_BRIDGE_MODULE)        (net/core/dev.c)

int(*br_handle_frame_hook)(structnet_bridge_port*p,structsk_buff**pskb);

static__inline__inthandle_bridge(structsk_buff**pskb,

                    structpacket_type**pt_prev,int*ret)

{

    structnet_bridge_port*port;

    //回环接口?

非以太网接口?

    if((*pskb)->pkt_type==PACKET_LOOPBACK||

      (port=rcu_dereference((*pskb)->dev->br_port))==NULL)

         return0;

    if(*pt_prev){

         *ret=deliver_skb(*pskb,*pt_prev);

         *pt_prev=NULL;

    }

    //br_handle_frame_hook个全局函数指针

    returnbr_handle_frame_hook(port,pskb);

}

#else

#definehandle_bridge(skb,pt_prev,ret)(0)

#endif

  从此以看出。

如果编译时候选择网桥模式,则进入网桥处理模块,否则,只个空函数,直接返回。

br_handle_frame_hook代表函数什么呢?

网桥数据处理框架又什么样呢?

关于网桥:

  网桥个二层设备,深入以当成个二层交换机。

二层协议转发数据。

网桥转发数据,维持个端口MAC应表,通常通CAM表。

根据这张表以数据送往相应端口进行发送.网桥转发过程:

1:

接收个包。

判断自己CAM表否含包此包源地址.如果没有,则源地址端口更新至于CAM表.2:

判断包否送给本机,如果,则送往本机层协议栈处理。

如果不,则查寻CAM表。

找相应出口。

3:

如果找出口,则此包送至出口。

如果不存,各端口发送。

4:

如果CAM表应表项规定时间没有得更新,则除此项。

网桥配置:

Brctl个比较好配置网桥工具。

源代码配置极其简单。

们从网桥配置流程说起,看linux核怎样步步管理。

首先,创建个网桥:

brctladdbrbr0      (建立个br0网桥)然,接口添加进网桥:

brctladdif br0eth0 (eth0eth1添加进网桥br0)                       brctladdif broeth1OK,网桥现就配置好。

这台linux主机以当作交换机使,从eth0包都以转发eth1。

现,们看代码进行处理首先brctladdbr。

查看brctl代码调:

ioctl(br_socket_fd,SIOCBRADDBR,brname);然brctladdif  brctl代码调:

ioctl(br_socket_fd,SIOCBRADDIF,&ifr);呵呵。

Brctl代码简单吧,只调户空间配置工具ioctl.Linux网桥分析:

好,现就以进入核分析网桥模式:

staticint__initbr_init(void)                        (net/brige/br.c)

{

    //分配slab缓冲区

    br_fdb_init();

//网桥netfiter处理,以章节分析

#ifdefCONFIG_BRIDGE_NETFILTER

    if(br_netfilter_init())

         return1;

#endif

    //户空间ioctl调函数

    brioctl_set(br_ioctl_deviceless_stub);

    //接收数据包处理,就们面netif_receive_skb函数看br_handle_frame_hook

    br_handle_frame_hook=br_handle_frame;

#ifdefined(CONFIG_ATM_LANE)||defined(CONFIG_ATM_LANE_MODULE)

    br_fdb_get_hook=br_fdb_get;

    br_fdb_put_hook=br_fdb_put;

#endif

    //netdev_chain通知链表注册。

关于通知链表,面已经介绍过,这里不再讨论

    register_netdevice_notifier(&br_device_notifier);

    return0;

}新建网桥:

从面分析以知道,户空间调ioctl(br_socket_fd,SIOCBRADDBR,brname).进入br_ioctl_deviceless_stub,以看相关处理:

intbr_ioctl_deviceless_stub(unsignedintcmd,void__user*uarg)

{

    switch(cmd){

    caseSIOCGIFBR:

    caseSIOCSIFBR:

         returnold_deviceless(uarg);

    //新建网桥

    caseSIOCBRADDBR:

    //除网桥

    caseSIOCBRDELBR:

    {

         charbuf[IFNAMSIZ];

         if(!

capable(CAP_NET_ADMIN))

              return-EPERM;

         //copy_from_user:

户空间数据拷入核空间

         if(copy_from_user(buf,uarg,IFNAMSIZ))

              return-EFAULT;

         buf[IFNAMSIZ-1]=0;

         if(cmd==SIOCBRADDBR)

              returnbr_add_bridge(buf);

         returnbr_del_bridge(buf);

    }

    }

    return-EOPNOTSUPP;}

这里,们传入cmdSIOCBRADDBR.转入br_add_bridge(buf)进行:

intbr_add_bridge(constchar*name)

{

    structnet_device*dev;

    intret;

    //虚拟桥新建个net_device

    //面“网络设备管理”经讲述此结构

    dev=new_bridge_dev(name);

    if(!

dev)

         return-ENOMEM;

//sysfs建立相关信息

    ret=br_sysfs_addbr(dev);

    dev_put(dev);

    if(ret)

         unregister_netdev(dev);

out:

    returnret;

err2:

    free_netdev(dev);

err1:

    rtnl_unlock();

    gotoout;}

  网桥注册跟们以看物理网络设备注册样。

们关心网桥应net_device结构什么样,继续跟踪进new_bridge_dev:

staticstructnet_device*new_bridge_dev(constchar*name)

{

    structnet_bridge*br;

    structnet_device*dev;

    //分配net_device

    dev=alloc_netdev(sizeof(structnet_bridge),name,

               br_dev_setup);

    if(!

dev)

         returnNULL;    网桥私区结构net_bridge    br=netdev_priv(dev);

    //私区结构dev字段指向本身

    br->dev=dev;

    br->lock=SPIN_LOCK_UNLOCKED;

    //队列始化。

port_list保存这个桥端口列表

    INIT_LIST_HEAD(&br->port_list);

    br->hash_lock=SPIN_LOCK_UNLOCKED;

    //面这部份代码跟stp协议相关,们暂不关心

    br->bridge_id.prio[0]=0x80;

    br->bridge_id.prio[1]=0x00;

    memset(br->bridge_id.addr,0,ETH_ALEN);

    dev->open=br_dev_open;

    dev->set_multicast_list=br_dev_set_multicast_list;

    dev->change_mtu=br_change_mtu;

    dev->destructor=free_netdev;

    SET_MODULE_OWNER(dev);

    dev->stop=br_dev_stop;

    dev->accept_fastpath=br_dev_accept_fastpath;

    dev->tx_queue_len=0;

    dev->set_mac_address=NULL;

    dev->priv_flags=IFF_EBRIDGE;

}这部份,桥设备私区空间进行始化。

这里,有必给桥net_device应私区结构:

structnet_bridge

{

    //读锁

    spinlock_t          lock;

    //端口列表

    structlist_head      port_list;

    //网桥应虚拟设备

    structnet_device     *dev;

    //网桥应虚拟网卡统计数据

    structnet_device_stats         statistics;

    //hash表锁

    spinlock_t          hash_lock;

    //MACPORT应表,即CAM

    structhlist_head     hash[BR_HASH_SIZE];

    structlist_head      age_list;

/*STP*/

u16               root_port;

rtnl_lock();

br->stp_enabled=0;

br_stp_timer_init(br);

returndev;

//stp协议应数据

unsignedchar            stp_enabled;

//由核确定接口名字,例如eth0eth1等

br->designated_root=br->bridge_id;

}

bridge_id           designated_root;

unsignedchar            topology_change;

if(strchr(dev->name,'%')){

br->root_path_cost=0;

  br_dev_setup还做些另函数指针始化:

bridge_id   bridge_id;

ret=dev_alloc_name(dev,dev->name);

br->root_port=0;

voidbr_dev_setup(structnet_device*dev)

u32               root_path_cost;

if(ret<0)

br->bridge_max_age=br->max_age=20*HZ;

{

unsignedlong            max_age;

gotoerr1;

br->bridge_hello_time=br->hello_time=2*HZ;

//桥MAC地址设零

unsignedlong            hello_time;

}

br->bridge_forward_delay=br->forward_delay=15*HZ;

memset(dev->dev_addr,0,ETH_ALEN);

unsignedlong            forward_delay;

//向核注册此网络设备

br->topology_change=0;

//以太网结构始化

unsignedlong            bridge_max_age;

ret=register_netdevice(dev);

br->topology_change_detected=0;

ether_setup(dev);

unsignedlong            ageing_time;

if(ret)

br->ageing_time=300*HZ;

//系列函数指针始化

unsignedlong            bridge_hello_time;

gotoerr2;

INIT_LIST_HEAD(&br->age_list);

dev->do_ioctl=br_dev_ioctl;

unsignedlong            bridge_forward_delay;

dev_hold(dev);

dev->get_stats=br_dev_get_stats;

    rtnl_unlock();    dev->hard_start_xmit=br_dev_xmit;

    unsignedchar            topology_change_detected;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1