摄像机IP是.0怎么设置网桥的ip地址IP是.1能不能实现传

developerWorks 社区
本文分析了linux 2.4.x内核的网桥的实现方法,并且描述了如何使用2.4中的网桥。网桥,类似于中继器,连接局域网中两个或者多个网段。它与中继器的不同之处就在于它能够解析它收发的数据,读取目标地址信息(MAC),并决定是否向所连接网络的其他网段转发数据包。为了能够决策向那个网段发送数据包,网桥学习接收到数据包的源MAC地址,在本地建立一个以MAC和端口为记录项的信息数据库。
()XML error:
Please enter a value for the author element's jobtitle attribute, or the company-name element, or both.
祝顺民,网名:getmoon。目前从事防火墙开发,致力于网络的研究和开发,分析linux内核。经常出没于
的内核板块。希望于爱好者们共同探讨。email:
一、Linux内核网桥的实现分析Linux 内核分别在2.2 和 2.4内核中实现了网桥。但是2.2 内核和 2.4内核的实现有很大的区别,2.4中的实现几乎是全部重写了所有的实现代码。本文以2.4.0内核版本为例进行分析。
在分析具体的实现之前,先描述几个概念,有助于对网桥的功能及实现有更深的理解。冲突域
一个冲突域由所有能够看到同一个冲突或者被该冲突涉及到的设备组成。以太网使用C S M A / C D(Carrier Sense Multiple Access with Collision Detection,带有冲突监测的载波侦听多址访问)技术来保证同一时刻,只有一个节点能够在冲突域内传送数据。网桥或者交换机,构成了一个冲突域的边界。缺省情况下,网桥中的每个端口实际上就是一个冲突域的结束点。广播域
一个广播域由所有能够看到一个广播数据包的设备组成。一个路由器,构成一个广播域的边界。网桥能够延伸到的最大范围就是一个广播域。缺省的情况下,一个网桥或交换机的所有端口在同一个广播域中。VLAN技术可以把交换机或者网桥的不同端口分割成不同的广播域。一般情况下, 一个广播域代表一个逻辑网段。网桥中的CAM表
网桥和交换机一样,为了能够实现对数据包的转发,网桥保存着许多(MAC,端口)项。所有的这些项组成一个表,叫做CAM表。每个项有超时机制,如果一定时间内未接收到以这个MAC为源MAC地址的数据包,这个项就会被删除。图1:一个交换网络的逻辑图在Linux内核网桥的实现中,一个逻辑网段用net_bridge结构体表示。一个逻辑网段需要保留的信息有:本逻辑网段中所有的端口(port_list)
每个端口用net_bridge_port结构体来表示,从net_bridge_port结构体中可以看出,它主要有:逻辑网段中的下一个端口(next)本端口所属的逻辑网段(br)本端口所指向的物理网卡(dev)本端口在网桥中的编号(port_no)用于生成树管理的信息一个逻辑网段中可以具有很多个端口,所有的端口都挂在以port_list为链表头的链表上。本网段中CAM表(hash[BR_HASH_SIZE])
CAM表中的每个项用net_bridge_fdb_entry结构体代表,每项中有:用于CAM表连接的链表指针(next_hash,pprev_hash)此项当前的引用计数(use_count)MAC地址(addr)此项所对应的端口(dst)处理MAC超时(ageing_timer)是否是本机的MAC地址(is_local)是否是静态MAC地址(is_static)一个逻辑网段中的所有表项形成一个CAM表,他们之间的组织关系是一个HASH链表。HASH链的个数为BR_HASH_SIZE(256)。本逻辑网段用于和外部通信的虚拟网络设备(dev)
Linux网桥可以在网桥上为每个逻辑网段配置一个IP,用于和外部通信。实际上这个IP不是配置在一个特定的物理网卡上面, 而是建立一个虚拟的网卡,虚拟网卡可以附在每个同一逻辑网段的物理网卡上,让这个网卡可以象所有的物理网卡一样工作。从而使网桥可以和外部通信。本逻辑网段虚拟网卡的统计数据(statistics)
按照Linux网卡驱动的接口,一个网卡的统计信息是由每个网卡的私有数据处理的。一般的写法是用dev-&priv来指向每个网卡的统计数据。网卡的get_stats方法就是用来读取统计数据。用户一个网段的生成树(STP)信息以上对几个结构体的描述和分析可以通过下图来表示:图2:Linux网桥数据结构描述图描述了网桥的数据结构后,就可以开始数据包处理流程的分析。网桥处理包遵循着以下几条原则:在一个接口上接收到的包不会再在那个接口上发送这个数据包。每个接收到的数据包都要学习其源MAC地址。如果数据包是多播包或广播包,则要在同一个网段中除了接收端口外的其他所有端口发送这个数据包,如果上层协议栈对多播包感兴趣,则需要把数据包提交给上层协议栈。如果数据包的目的MAC地址不能在CAM表中找到,则要在同一个网段中除了接收端口外的其他所有端口发送这个数据包。如果能够在CAM表中查询到目的MAC地址,则在特定的端口上发送这个数据包,如果发送端口和接收端口是同一端口,则不发送。在网络软中断处理函数net_rx_action中,嵌入了handle_bridge用于把数据包skb送入网桥模块处理。#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
if (skb-&dev-&br_port != NULL &&
br_handle_frame_hook != NULL) {
handle_bridge(skb, pt_prev);
dev_put(rx_dev);
#endifbr_handle_frame_hook是网桥处理接收到数据包的中入口,网桥初始化(br_init)的时候,把br_handle_frame_hook赋值为br_handle_frame。skb-&dev-&br_port用于判断接收到这个数据包的接口是否是网桥中的一个端口,如果是,skb-&dev-&br_port不为NULL,那么数据包应该由网桥处理。反之,数据包由上层协议栈处理。网桥中虚拟网卡对应的数据包就是在这个判断点时不再进入网桥。(实际上虚拟网卡并不会自己主动接收数据包,而是在网桥处理中把数据包向本地上层协议栈提交,并且修改了skb-&dev,使得数据包不会多次进入桥处理代码)。前面提到,网桥处理接收包的入口是br_handle_frame(net/bridge/br_input.c)函数。br_handle_frame函数首先从skb中获得这个包属于的逻辑网段。然后调用__br_handle_frame进行转发处理。 br_handle_frame函数里有一个值得了解的地方,里面有一个加读锁。因为在转发中需要读CAM表,所以必须加读锁,避免在这个过程中另外的内核控制路径(如多处理机上另外一个CPU上的系统调用)修改CAM表。对输入包的转发决策都是在__br_handle_frame函数中。这个函数的处理可以分为以下几个部分:如果网桥的虚拟网卡处于混杂模式,那么每个接收到的数据包都需要克隆一份送到AF_PACKET协议处理体(网络软中断函数net_rx_action中ptype_all链的处理)。
if (br-&dev.flags & IFF_PROMISC) {
struct sk_buff *skb2;
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) {
passedup = 1;
br_pass_frame_up(br, skb2);
}如果源MAC地址是多播或者是广播地址,那么这个包格式是错误的,简单的丢弃。
if (skb-&mac.ethernet-&h_source[0] & 1)
如果是一个多播包,则需要向本机的上层协议栈传送这个数据包(如果在之前没有向上提交的话,即passedup为0。如果为1,则前面已经发送了,现在就不需要提交了,在后面中的处理都是一样的)。
if (!passedup &&
(dest[0] & 1) &&
(br-&dev.flags & IFF_ALLMULTI || br-&dev.mc_list != NULL)) {
struct sk_buff *skb2;
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) {
passedup = 1;
br_pass_frame_up(br, skb2);
}如果启动了生成树协议,一个生成树包需要由生成树协议处理模块单独处理。如果不支持,则这个包的目的MAC肯定在CAM中查询不到,所以是向所有的端口发送(除接收口)。这样才不会影响整个网络的生成树协议运行。
if (br-&stp_enabled &&
!memcmp(dest, bridge_ula, 5) &&
!(dest[5] & 0xF0))
goto handle_special_如果接收端口不是处于LEARNING或者FORWARDING,那么就学习这个包的源MAC地址,或者更新CAM表中相应项的定时器。
if (p-&state == BR_STATE_LEARNING ||
p-&state == BR_STATE_FORWARDING)
br_fdb_insert(br, p, skb-&mac.ethernet-&h_source, 0);如果是一个多播包或广播包,则调用br_flood函数向每个口发送(除接收口)这个数据包。如果之前没有提交上层协议,则需要克隆一个包提交上层协议。
if (dest[0] & 1) {
br_flood(br, skb, 1);
if (!passedup)
br_pass_frame_up(br, skb);
kfree_skb(skb);
}用接收到数据包的目的MAC地址查询CAM表。
dst = br_fdb_get(br, dest);查询CAM表后,如果能够找到表项,并且目的MAC是到本机的虚拟网卡的,那么就需要把这个包提交给上层协议。网桥就是通过这个地方的处理和外部通信,实现远程管理的目的。
if (dst != NULL && dst-&is_local) {
if (!passedup)
br_pass_frame_up(br, skb);
kfree_skb(skb);
br_fdb_put(dst);
}如果查询CAM表有结果,并且目的MAC不是到本地的,那么就通过调用br_forward发送到特定的端口。
if (dst != NULL) {
br_forward(dst-&dst, skb);
br_fdb_put(dst);
}如果在CAM表中查询不到数据包的目的MAC地址,那么就需要向别的每个端口发送这个数据包。调用br_flood来进行这个处理。
br_flood(br, skb, 0);
在br_forward和br_flood函数中都必须判断源接口和目的接口是否是同一个,如果是同一端口,就不发送这个数据包。数据包的最后发送都是通过统一的发送接口dev_queue_xmit函数来完成的。以下就是数据包的处理流程:图3:数据包处理流程图前面多次提到网桥的虚拟网卡,实际上在网桥中,这个网卡存在着一个net_device结构(在net_bridge里),但是不存在着实际的物理设备,而是附在网桥中每个物理网卡上面。这个虚拟网卡的支持函数在(br_device.c)。因为是虚拟的网卡,所以没有物理中断产生,每个需要发送到这个设备的数据包都是靠判断数据包的目的MAC地址来决定是否需要提交到本地上层协议栈(在__br_handle_frame判断)。如果数据包需要向上层协议提交,都调用br_pass_frame_up函数来处理。在这个函数中,首先把skb-&dev设置成br-&dev。然后再模拟在中断中处理数据包一样,进行相应的处理, 然后调用netif_rx放入接收队列。这里有一个要十分注意的地方,这个数据包的skb-&dev已经变成br-&dev。所以在网络接收软中断处理函数net_rx_action中不会再次进入handle_bridge了。static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
br-&statistics.rx_packets++;
br-&statistics.rx_bytes += skb-&
skb-&dev = &br-&
skb-&pkt_type = PACKET_HOST;
skb_pull(skb, skb-&mac.raw - skb-&data);
skb-&protocol = eth_type_trans(skb, &br-&dev);
netif_rx(skb);
}二、配置内核 2.4 Linux 网桥要配置网桥,首先需要网桥的配置工具bridge-utils。这个配置程序的源代码可以在
下载。编译成功之后,就可以生成网桥配置的主要工具brctl。
下面,我们将用brctl对以下网络拓扑配置网桥,使Linux能够对数据包进行交换。上图中,有五台主机。其中中间那台主机装有linux ,安装了网桥模块,而且有四块物理网卡,分别连接同一网段的其他主机。我们希望其成为一个网桥,为其他四台主机(IP分别为192.168.1.2 ,192.168.1.3,192.168.1.4,192.168.1.5) 之间转发数据包。同时,为了方便管理,希望网桥能够有一个IP(192.168.1.1),那样管理员就可以在192.168.1.0/24网段内的主机上telnet到网桥,对其进行配置,实现远程管理。前一节中提到,网桥在同一个逻辑网段转发数据包。针对上面的拓扑,这个逻辑网段就是192.168.1.0/24网段。我们为这个逻辑网段一个名称,br_192。首先需要配置这样一个逻辑网段。# brctl addbr br_192
(建立一个逻辑网段,名称为br_192)实际上,我们可以把逻辑网段192.168.1.0/24看作使一个VLAN ,而br_192则是这个VLAN的名称。建立一个逻辑网段之后,我们还需要为这个网段分配特定的端口。在Linux中,一个端口实际上就是一个物理网卡。而每个物理网卡的名称则分别为eth0,eth1,eth2,eth3。我们需要把每个网卡一一和br_192这个网段联系起来,作为br_192中的一个端口。# brctl addif br_192 eth0
(让eth0成为br_192的一个端口)
# brctl addif br_192 eth1
(让eth1成为br_192的一个端口)
# brctl addif br_192 eth0
(让eth2成为br_192的一个端口)
# brctl addif br_192 eth3
(让eth3成为br_192的一个端口)网桥的每个物理网卡作为一个端口,运行于混杂模式,而且是在链路层工作,所以就不需要IP了。# ifconfig eth0 0.0.0.0
# ifconfig eth1 0.0.0.0
# ifconfig eth2 0.0.0.0
# ifconfig eth3 0.0.0.0然后给br_192的虚拟网卡配置IP:192.168.1.1。那样就能远程管理网桥。# ifconfig br_192 192.168.1.1给br_192配置了IP之后,网桥就能够工作了。192.168.1.0/24网段内的主机都可以telnet到网桥上对其进行配置。以上配置的是一个逻辑网段,实际上Linux网桥也能配置成多个逻辑网段(相当于交换机中划分多个VLAN)。具体的方法可以参考bridge-util中的HOWTO。三、总结本文分析了Linux网桥的实现,并且举例说明如何配置网桥。 通过学习网桥的实现,就能够了解网络中二层交换的原理。
网桥和交换机的功能非常相似,所以在分析网桥的时候,绝大多数情况下可以用交换机的处理方法来分析网桥的动作。
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
文章、教程、演示,帮助您构建、部署和管理云应用。
立即加入来自 IBM 的专业 IT 社交网络。
免费下载、试用软件产品,构建应用并提升技能。
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=LinuxArticleID=22004ArticleTitle=ALinux网桥的实现分析与使用publish-date=Docker 配置固定IP及桥接的实现方法
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Docker 配置固定IP和桥接的实现方法的相关资料,这里详细介绍了Docker 的四种网络模式及如何实现桥接的案例,需要的朋友可以参考下
docker默认使用bridge模式,通过网桥连接到宿主机,而容器内部的ip则从网桥所在的ip段取未用的ip。这样做一个不方便的地方在于容器内部的ip不是固定的,想要连接容器时只能通过映射到宿主机的端口,因而有很多项目使用overlay来为docker提供网络的配置,比如Pipework、Flannel、Kubernetes、Weave、opencontrail等。
想要使用overlay来为docker配置网络,需要首先了解下docker的网络模式:
一、Docker的四种网络模式
Docker在创建容器时有四种网络模式,bridge为默认不需要用--net去指定,其他三种模式需要在创建容器时使用--net去指定。
bridge模式,使用--net=bridge指定,默认设置。
none模式,使用--net=none指定。
host模式,使用--net=host指定。
container模式,使用--net=container:容器名称或ID指定。(如:--net=container:30b668ccb630)
bridge模式:docker网络隔离基于网络命名空间&Network Namespace&,在物理机上创建docker容器时会为每一个docker容器分配网络命名空间,并且把容器IP桥接到物理机的虚拟网桥上。
none模式:此模式下创建容器是不会为容器配置任何网络参数的,如:容器网卡、IP、通信路由等,全部需要自己去配置。
host模式:此模式创建的容器没有自己独立的网络命名空间,是和物理机共享一个Network Namespace,并且共享物理机的所有端口与IP,并且这个模式认为是不安全的。
container模式:此模式和host模式很类似,只是此模式创建容器共享的是其他容器的IP和端口而不是物理机,此模式容器自身是不会配置网络和端口,创建此模式容器进去后,你会发现里边的IP是你所指定的那个容器IP并且端口也是共享的,而且其它还是互相隔离的,如进程等。
二、Docker配置自己的网桥
1)、自定义新网桥
root@Docker:~# dpkg -l | grep bridge*
#查看是否有安装brctl命令包
ii bridge-utils 1.5-6Ubuntu2
Utilities for configuring the Linux Ethernet bridge
root@Docker:~# apt-get install bridge-utils #安装brctl命令包
root@Docker:~# docker -v
#docker版本
Docker version 1.5.0, build a8a31ef
root@Docker:~# ps -ef | grep docker
16:28 ?
00:00:00 /usr/bin/docker -d
root@Docker:~# service docker stop
root@Docker:~# ifconfig | grep docker0
#docker默认网桥
docker0 Link encap:以太网 硬件地址 56:84:7a:fe:97:99
root@Docker:~# ifconfig docker0 down
#停止docker默认网桥
root@Docker:~# brctl show
#查看物理机上有哪些网桥
root@Docker:~# brctl delbr docker0
#删除docker默认网桥
root@Docker:~# brctl addbr docker_new0
#自定义网桥
root@Docker:~# ifconfig docker_new0 192.168.6.1 netmask 255.255.255.0
#给自定义网桥指定IP和子网
root@Docker:~# ifconfig | grep docker_new0 #查看发现自定义网桥已经启动
docker_new0 Link encap:以太网 硬件地址 0a:5b:26:48:dc:04
inet 地址:192.168.6.1 广播:192.168.6.255 掩码:255.255.255.0
root@Docker:~# echo 'DOCKER_OPTS="-b=docker_new0"' && /etc/default/docker #指定网桥写入docker配置文件
root@Docker:~# service docker start
#启动docker
root@Docker:~# ps -ef | grep docker
#成功启动,并且成功加载了docker_new0
2 18:44 ?
00:00:00 /usr/bin/docker -d -b=docker_new0
root@Docker:~# brctl show
#查看当前网桥下是否有容器连接
bridge name
STP enabled
interfaces
docker_new0
8000.fa3ce276c3b9
root@Docker:~# docker run -itd CentOS:centos6 /bin/bash
#创建容器测试
root@Docker:~# docker attach 7f8ff622237f
[root@7f8ff622237f /]# ifconfig eth0 | grep addr
#容器IP已经和自定义网桥一个网段,该容器IP为DHCP自动分配,不属于指定固定IP
Link encap:Ethernet HWaddr 02:42:C0:A8:06:02
inet addr:192.168.6.2 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:c0ff:fea8:602/64 Scope:Link
root@Docker:~# brctl show
#该网桥上已经连接着一个网络设备了
bridge name
STP enabled
interfaces
docker_new0
8000.fa3ce276c3b9
veth17f560a
注:veth设备是成双成对出现的,一端是容器内部命名eth0,一端是加入到网桥并命名的veth17f560a(通常命名为veth*),他们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备&&& 并实现了数据通信。
root@Docker:~# wget /jpetazzo/pipework/archive/master.zip #下载 pipework
root@Docker:~# unzip master.zip
root@Docker:~# cp pipework-master/pipework /usr/bin/
#拷贝pipework到 /usr/bin/下
root@Docker:~# chmod +x /usr/bin/pipework
#赋予该命令执行权限
root@Docker:~# pipework docker_new0 -i eth1 $(docker run -itd -p 9197:80 centos:centos6 /bin/bash) 192.168.6.27/24@192.168.6.1 #创建容器,并指定固定IP
格式:pipework 网桥名 -i 指定在那块网卡上配置 &容器名or容器ID& 指定容器内IP/子网@网关 注:容器内网关就是物理机网桥的IP
root@Docker:~# docker attach dbe
#进入新容器
[root@dbe /]# ifconfig
#容器内IP为指定的IP 192.168.6.27
Link encap:Ethernet HWaddr 02:42:C0:A8:06:05
inet addr:192.168.6.7 Bcast:0.0.0.0 Mask:255.255.255.0
#docker_new0网桥创建容器时DHCP分配的IP
Link encap:Ethernet HWaddr 82:DB:F7:A3:33:92
inet addr:192.168.6.27 Bcast:0.0.0.0 Mask:255.255.255.0
#pipework指定的固定IP,网桥还是docker_new0
[root@dbe /]# route -n
#查看路由路径
Kernel IP routing table
Destination
Flags Metric Ref
192.168.6.1
192.168.6.0
255.255.255.0 U
192.168.6.0
255.255.255.0 U
[root@dbe /]# ping
(119.75.218.70) 56(84) bytes of data.
64 bytes from 119.75.218.70: icmp_seq=1 ttl=127 time=3.98 ms
64 bytes from 119.75.218.70: icmp_seq=2 ttl=127 time=2.98 ms
[root@dbe /]# netstat -anptu | grep 80
#容器内80端口已经开启
root@Docker:~# telnet 192.168.6.27 80
#物理机上测试指定的IP是否和映射的端口等通信正常
Trying 192.168.6.27...
Connected to 192.168.6.27.
Escape character is '^]'.
root@Docker:~# iptables-save & iptables-rules #拷贝防火墙规则到本地文件
root@Docker:~# vi iptables-rules
#打开规则文件查看你会发现你物理机的防火墙自动添加了很多条规则,这个是容器到网桥到本地网卡到公网的地址转换通信规则
首先,配置一个用于创建container interface的网桥,可以使用ovs,也可以使用Linux bridge,以Linux bridge为例:
br_name=docker
brctl addbr $br_name
ip addr add 192.168.33.2/24 dev $br_name
ip addr del 192.168.33.2/24 dev em1
ip link set $br_name up
brctl addif $br_name eth0
接着,可以启动容器了,注意用--net=none方式启动:
# start new container
hostname=''
cid=$(docker run -d -i -h $hostname --net=none -t centos)
pid=$(docker inspect -f '{{.State.Pid}}' $cid)
下面,为该容器配置网络namespace,并设置固定ip:
# set up netns
mkdir -p /var/run/netns
ln -s /proc/$pid/ns/net /var/run/netns/$pid
# set up bridge
ip link add q$pid type veth peer name r$pid
brctl addif $br_name q$pid
ip link set q$pid up
# set up docker interface
fixed_ip='192.168.33.3/24'
gateway='192.168.33.1'
ip link set r$pid netns $pid
ip netns exec $pid ip link set dev r$pid name eth0
ip netns exec $pid ip link set eth0 up
ip netns exec $pid ip addr add $fixed_ip dev eth0
ip netns exec $pid ip route add default via 192.168.33.1
这样,容器的网络就配置好了,如果容器内部开启了sshd服务,通过192.168.33.3就可以直接ssh连接到容器,非常方便。上面的步骤比较长,可以借助pipework来为容器设置固定ip(除了设置IP,还封装了配置网关、macvlan、vlan、dhcp等功能):
pipework docker0 be4 10.88.88.8/24
那么,当容器需要删除的时候,怎么清理网络呢,其实也很简单:
# stop and delete container
docker stop $cid
docker rm $cid
# delete docker's net namespace (also delete veth pair)
ip netns delete $pid
更多docker网络的配置,可以参考官方手册。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 ovs 网桥 ip 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信