本实验实用平台cloudlab,cloudlab可以提供多台虚拟机/真机,是实验的物理载体

实验目的是让不同的tcp视频流通过switch1和switch2时被分流到不同的路径上(via node1/node2/node3)

实验前,我调查了收发/处理视频流的一些常用的工具,并看了前人做的一些实验,发现rtmp-nginx很适合本实验

表格一:linux处理视频流的相关软件:

名称

描述

是否适用

ffmpeg

多媒体视频处理工具,用于视频采集、视频格式处理、视频流化

后面会用

vlc

简单、快速、强大的流媒体播放器,无需安装解码器包的媒体播放器

不用

WebRTC

网页即时通信,支持网页浏览器进行实时语音对话或视频对话的api,google发起的实时通信解决方案,包括音视频采集、编解码、数据传输、音视频展示等功能,基于udp,可以代替rtmp,提供了一套api,可能需要二次开发,不支持cdn

不用

rtmp

主流的流媒体传输协议,基于tcp,协议简单,在各平台上容易实现,比较容易找到教程,支持cdn

适用

nginx

web-server,和rtmp配套使用

适用

(1)cloudlab上搭起topo

#每个节点在每个link上各有一个ip,switch节点有4个网卡,4个ip,node节点有两个网卡,两个ip

#client的ip是唯一的,是10.10.1.1

#server的ip是唯一的,是10.10.8.2

client(10.10.1.1) ————— switch1(10.10.1.2)

switch1(10.10.2.1) ————— node1(10.10.2.2)

switch1(10.10.3.1) ————— node2(10.10.3.2)

switch1(10.10.4.1) ————— node3(10.10.4.2)

node1(10.10.5.1) ————— switch2(10.10.5.2)

node2(10.10.6.2) ————— switch2(10.10.6.1)

node3(10.10.7.1) ————— switch2(10.10.7.2)

switch2(10.10.8.1) ————— server(10.10.8.2)

(2)登陆"server"节点,把它设置为rtmp server

wget http://nginx.org/download/nginx-1.17.3.tar.gz
git clone https://github.com/arut/nginx-rtmp-module
tar -zxf nginx-1.17.3.tar.gz
cd nginx-1.17.3
./configure --add-module=/root/nginx-rtmp-module#此时发生缺少pcre library错误
#需要:
apt-get update
apt-get install libpcre3 libpcre3-dev
apt-get install openssl libssl-dev
sudo apt-get install zlib1g-dev#再重新执行configure文件
./configure --add-module=/root/nginx-rtmp-module
make
make install
cd /usr/local/nginx
cd conf
#在本地写好nginx.conf文件(代码见后面),并上传到server上,覆盖掉原来的nginx.conf文件
scp ~/Desktop/nginx.conf root@155.98.36.44:/usr/local/nginx/conf
cd ..
./sbin/nginx -c conf/nginx.conf
cd html
mkdir play

#nginx.conf:

worker_processes  1;
events {worker_connections  1024;
}
rtmp {server {listen 1935;chunk_size 4000;application play {play /usr/local/nginx/html/play;}application hls {live on;hls on;hls_path /usr/local/nginx/html/hls;hls_fragment 1s;hls_playlist_length 4s;}application live {live on;}}
}http {include       mime.types;default_type  application/octet-stream;sendfile        on;keepalive_timeout  65;server {listen       8000;server_name  localhost;location /stat {rtmp_stat all;rtmp_stat_stylesheet stat.xsl;}location /stat.xsl {# XML stylesheet to view RTMP stats.# Copy stat.xsl wherever you want# and put the full directory path hereroot /usr/local/nginx-rtmp-module;}location /hls {# Serve HLS fragmentstypes {application/vnd.apple.mpegurl m3u8;video/mp2t ts;}root /usr/local/nginx/html;add_header Cache-Control no-cache;}}
}

打开本地shell,将本地的mp4文件上传到rtmp server,作为视频流的视频

scp ~/Desktop/6mins.mp4 root@155.98.36.44:/usr/local/nginx/html/play
scp ~/Desktop/3mins.mp4 root@155.98.36.44:/usr/local/nginx/html/play

至此,rtmp server设置完成

(3) 登陆client节点,设置rtmp client

apt-get update
apt install rtmpdump
#设置完测试一下:
rtmpdump -r rtmp://10.10.8.1:1935/play/3mins.mp4
rtmpdump -r rtmp://10.10.8.1:1935/play/3mins.mp4

使用rtmpdump测试一下能不能顺利接收到视频流

可以接收到:(可以在shell里看到乱码)

此时,有关rtmp的设置已经设置完成了,接下来设置ovs

(3)登陆switch1,switch2两个节点,在上面下载、安装software ovs

这里略,前面的博客里有写怎么安装

在switch1上搭起br1

#搭起switch(bridge)
ovs-vsctl add-br br1#绑定四个物理端口,每个真机的物理端口名称不太一样,这里用eth1\2\3\4代替
ovs-vsctl add-port br1 eth1
ovs-vsctl add-port br1 eth2
ovs-vsctl add-port br1 eth3
ovs-vsctl add-port br1 eth4#物理网卡绑定到bridge后,它的ip会失效,即无法再使用ip地址访问到四个物理网卡
#绑定四个虚拟端口,作为ip地址的载体:
ovs-vsctl add-port br1 vp1 -- set Interface vp1 type=internal
ovs-vsctl add-port br1 vp2 -- set Interface vp2 type=internal
ovs-vsctl add-port br1 vp3 -- set Interface vp3 type=internal
ovs-vsctl add-port br1 vp4 -- set Interface vp4 type=internal#给四个虚拟网卡设置ip地址
ifconfig vp1 10.10.1.2
ifconfig vp2 10.10.2.1
ifconfig vp3 10.10.3.1
ifconfig vp4 10.10.4.1#给四个物理网卡的ip设置为0
#在进行此步骤之前务必先记录下哪个物理网卡对应哪个虚拟网卡,后面会用到
#记录的方式可以参照后面的表格2
ifconfig eth1 0.0.0.0
ifconfig eth2 0.0.0.0
ifconfig eth3 0.0.0.0
ifconfig eth4 0.0.0.0#将br1的dpid设置为1(方便写controller文件)
ovs-vsctl set bridge br1 other-config:datapath-id=0000000000000001

在switch2上搭起br2,步骤和switch1上的完全一样

#搭起switch(bridge)
ovs-vsctl add-br br2#绑定四个物理端口,每个真机的物理端口名称不太一样,这里用eth1\2\3\4代替
ovs-vsctl add-port br2 eth1
ovs-vsctl add-port br2 eth2
ovs-vsctl add-port br2 eth3
ovs-vsctl add-port br2 eth4#物理网卡绑定到bridge后,它的ip会失效,即无法再使用ip地址访问到四个物理网卡
#绑定四个虚拟端口,作为ip地址的载体:
ovs-vsctl add-port br2 vp1 -- set Interface vp1 type=internal
ovs-vsctl add-port br2 vp2 -- set Interface vp2 type=internal
ovs-vsctl add-port br2 vp3 -- set Interface vp3 type=internal
ovs-vsctl add-port br2 vp4 -- set Interface vp4 type=internal#给四个虚拟网卡设置ip地址
ifconfig vp1 10.10.5.2
ifconfig vp2 10.10.6.1
ifconfig vp3 10.10.7.2
ifconfig vp4 10.10.8.2#给四个物理网卡的ip设置为0
#在进行此步骤之前务必先记录下哪个物理网卡对应哪个虚拟网卡,后面会用到
#记录的方式可以参照后面的表格2
ifconfig eth1 0.0.0.0
ifconfig eth2 0.0.0.0
ifconfig eth3 0.0.0.0
ifconfig eth4 0.0.0.0#将br1的dpid设置为1(方便写controller文件)
ovs-vsctl set bridge br2 other-config:datapath-id=0000000000000002

两个switch基本搭起了,现在两个switch上没有任何流表项,可能会出一些环路上的问题,先不管,先把controller搭一下

表格2:

#第一列是物理网卡名字

#第二列是物理网课的mac

#第三列是在没修改之前物理网课对应的ip

#第四列是我们设置的每个物理网课对应的虚拟网卡

#第五列是虚拟网卡vp*对应的mac地址

#第六列是物理网卡enp*****对应的绑定到br1\br2时br1\br2发给它的port-number,可以用ovs-ofctl show br1\br2来查看

switch1

enp6s0f1

3c:fd:fe:05:8f:e2

10.10.1.2

vp1

26:91:67:e5:fc:90

1

enp4s0f0

a0:36:9f:96:45:12

10.10.2.1

vp2

2a:09:31:bd:fc:8a

2

enp6s0f2

3c:fd:fe:05:8f:e4

10.10.3.1

vp3

22:57:c4:79:4c:e6

3

enp6s0f0

3c:fd:fe:05:8f:e0

10.10.4.1

vp4

e6:cc:13:b9:9a:34

4

switch2

enp6s0f1

3c:fd:fe:05:ac:42

10.10.5.2

vp1

42:57:e5:32:e3:38

1

enp6s0f0

3c:fd:fe:05:ac:40

10.10.6.1

vp2

86:76:4f:20:ba:a5

2

enp6s0f2

3c:fd:fe:05:ac:44

10.10.7.2

vp3

7e:79:7f:dc:ab:b7

3

enp6s0f3

3c:fd:fe:05:ac:46

10.10.8.2

vp4

ae:87:88:0a:b7:83

4

(4)登陆controller节点,搭起ryu controller

ryu环境的搭建过程在前面安装ovs的那个博客里有,略

写controller文件:

这个文件里把tcp流发向不同的link的主要逻辑在handle_tcp里,这里设置了一句计数器,每次增加1,再经过mod操作,把流分往不同的link

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.ofproto import ether
from ryu.ofproto import inet
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib.packet import icmp
from ryu.lib.packet import tcp
import randomclass ExampleSwitch13(app_manager.RyuApp):OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]def __init__(self, *args, **kwargs):super(ExampleSwitch13, self).__init__(*args, **kwargs)self.mac = {"client":"3c:fd:fe:05:ce:c2","server":"3c:fd:fe:05:94:c2","s1v1":"26:91:67:e5:fc:90","s1v2":"2a:09:31:bd:fc:8a","s1v3":"22:57:c4:79:4c:e6","s1v4":"e6:cc:13:b9:9a:34","s2v1":"42:57:e5:32:e3:38","s2v2":"86:76:4f:20:ba:a5","s2v3":"7e:79:7f:dc:ab:b7","s2v4":"ae:87:88:0a:b7:83","node1l":"a0:36:9f:6b:fd:4c","node1r":"3c:fd:fe:05:7b:02","node2l":"3c:fd:fe:05:de:82","node2r":"3c:fd:fe:05:de:80","node3l":"3c:fd:fe:05:49:62","node3r":"3c:fd:fe:05:49:60"}self.ip = {"client":"10.10.1.1","server":"10.10.8.1","s1v1":"10.10.1.2","s1v2":"10.10.2.1","s1v3":"10.10.3.1","s1v4":"10.10.4.1","s2v1":"10.10.5.2","s2v2":"10.10.6.1","s2v3":"10.10.7.2","s2v4":"10.10.8.2"}self.v2e = {"s1v1":1,"s1v2":2,"s1v3":3,"s1v4":4,"s2v1":1,"s2v2":2,"s2v3":3,"s2v4":4}self.s2s = {"s1":{"client":"s1v1","node1":"s1v2","node2":"s1v3","node3":"s1v4"},"s2":{"server":"s2v4","node1":"s2v1","node2":"s2v2","node3":"s2v3"}}self.counter = 0@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)def switch_features_handler(self, ev):mac, ip = self.mac, self.ipv2e, s2s = self.v2e, self.s2sdatapath = ev.msg.datapathofproto = datapath.ofprotoparser = datapath.ofproto_parser# install the table-miss flow entry.match = parser.OFPMatch()actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]self.add_flow(datapath, 0, match, actions)dpid = datapath.idprint("******setting features for s" + str(dpid) + "******")self.send_set_config(datapath)if dpid == 1:#icmp:#client -> serverinport, outport, toport = s2s["s1"]["client"], s2s["s1"]["node1"], "node1l"self.add_icmp_rules(datapath,v2e[inport],v2e[outport] ,ip["client"],ip["server"], mac[outport], mac[toport])#server -> clientinport, outport, toport = s2s["s1"]["node3"], s2s["s1"]["client"], "client"self.add_icmp_rules(datapath,v2e[inport],v2e[outport] ,ip["server"],ip["client"], mac[outport], mac[toport])#tcp:#server -> clientinport, outport, toport = s2s["s1"]["node1"], s2s["s1"]["client"], "client"self.add_tcp_rules(datapath,v2e[inport],v2e[outport] ,ip["server"],ip["client"], mac[outport], mac[toport])inport, outport, toport = s2s["s1"]["node2"], s2s["s1"]["client"], "client"self.add_tcp_rules(datapath,v2e[inport],v2e[outport] ,ip["server"],ip["client"], mac[outport], mac[toport])inport, outport, toport = s2s["s1"]["node3"], s2s["s1"]["client"], "client"self.add_tcp_rules(datapath,v2e[inport],v2e[outport] ,ip["server"],ip["client"], mac[outport], mac[toport])elif dpid == 2:#icmp:#client -> serverinport, outport, toport = s2s["s2"]["node1"], s2s["s2"]["server"], "server"self.add_icmp_rules(datapath,v2e[inport],v2e[outport] ,ip["client"],ip["server"], mac[outport], mac[toport])#server -> clientinport, outport, toport = s2s["s2"]["server"], s2s["s2"]["node3"], "node3r"self.add_icmp_rules(datapath,v2e[inport],v2e[outport] ,ip["server"],ip["client"], mac[outport], mac[toport])#tcp:#client -> server:inport, outport, toport = s2s["s2"]["node1"], s2s["s2"]["server"], "server"self.add_tcp_rules(datapath,v2e[inport],v2e[outport] ,ip["client"],ip["server"], mac[outport], mac[toport])inport, outport, toport = s2s["s2"]["node2"], s2s["s2"]["server"], "server"self.add_tcp_rules(datapath,v2e[inport],v2e[outport] ,ip["client"],ip["server"], mac[outport], mac[toport])inport, outport, toport = s2s["s2"]["node3"], s2s["s2"]["server"], "server"self.add_tcp_rules(datapath,v2e[inport],v2e[outport] ,ip["client"],ip["server"], mac[outport], mac[toport])#下发流表逻辑def add_flow(self, datapath, priority, match, actions):ofproto = datapath.ofprotoparser = datapath.ofproto_parser# construct flow_mod message and send it.inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst)datapath.send_msg(mod)#对icmp单独的转发规则:h1-s1-s3-s4-h2/h2-s4-s3-s1-h1def add_icmp_rules(self, datapath, in_port, out_port, ips, ipd, macs, macd):priority = 20parser = datapath.ofproto_parseractions = [parser.OFPActionSetField(eth_src=macs),parser.OFPActionSetField(eth_dst=macd), parser.OFPActionOutput(out_port)]match = parser.OFPMatch(eth_type =ether.ETH_TYPE_IP,ip_proto=inet.IPPROTO_ICMP, in_port= in_port, ipv4_src=ips, ipv4_dst=ipd)self.add_flow(datapath, priority, match, actions)def add_tcp_rules(self, datapath, in_port, out_port, ips, ipd, macs, macd):priority = 20parser = datapath.ofproto_parseractions = [parser.OFPActionSetField(eth_src=macs),parser.OFPActionSetField(eth_dst=macd), parser.OFPActionOutput(out_port)]match = parser.OFPMatch(eth_type =ether.ETH_TYPE_IP,ip_proto=inet.IPPROTO_TCP, in_port= in_port, ipv4_src=ips, ipv4_dst=ipd)self.add_flow(datapath, priority, match, actions)def send_set_config(self, datapath):#把Normal先安装给datapathofp = datapath.ofprotoofp_parser = datapath.ofproto_parserreq = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)datapath.send_msg(req)@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)def _pakcet_in_handler(self, ev):#如果发生了table-miss,就把对应的default forwarding安装上#如果miss的是icmp,就把对应的icmp forwarding安装上datapath = ev.msg.datapathofproto = datapath.ofprotoparser = datapath.ofproto_parserdpid = datapath.idmsg = ev.msgprint("****** receiving a packet in from " + str(dpid) + " ******")pkt = packet.Packet(msg.data)eth_pkt = pkt.get_protocol(ethernet.ethernet)in_port = msg.match["in_port"]ethertype = eth_pkt.ethertypeif not eth_pkt:returnpkt_arp = pkt.get_protocol(arp.arp)if ethertype == ether.ETH_TYPE_ARP:self.handle_arp(datapath, in_port, pkt)returnif ethertype == ether.ETH_TYPE_IP:self.handle_ip(datapath, in_port, pkt)returndef handle_arp(self, datapath, in_port, pkt):print("*************** handling arp packet in  from "+str(datapath.id)+" ****************")ofproto = datapath.ofprotoparser = datapath.ofproto_parser# parse out the ethernet and arp packeteth_pkt = pkt.get_protocol(ethernet.ethernet)arp_pkt = pkt.get_protocol(arp.arp)# obtain the MAC of dst IP  dpid = datapath.idif dpid == 1:#sw1上的arp请求            arp_resolv_mac = self.mac["s1v1"]elif dpid == 2:#sw2上的arp请求arp_resolv_mac = self.mac["s2v4"]else:print("*** require handling arp on switch: dpid="+str(dpid)+" *****")return### generate the ARP reply msg, please refer RYU documentation### the packet library section# ARP Reply Msgether_hd = ethernet.ethernet(dst = eth_pkt.src, src = arp_resolv_mac, ethertype = ether.ETH_TYPE_ARP);arp_hd = arp.arp(hwtype=1, proto = 2048, hlen = 6, plen = 4,opcode = 2, src_mac = arp_resolv_mac, src_ip = arp_pkt.dst_ip, dst_mac = eth_pkt.src,dst_ip = arp_pkt.src_ip);arp_reply = packet.Packet()arp_reply.add_protocol(ether_hd)arp_reply.add_protocol(arp_hd)arp_reply.serialize()# send the Packet Out mst to back to the host who is initilaizing the ARPactions = [parser.OFPActionOutput(in_port)];out = parser.OFPPacketOut(datapath, ofproto.OFP_NO_BUFFER, ofproto.OFPP_CONTROLLER, actions,arp_reply.data)print("************** sending arp packet out **************")datapath.send_msg(out)def handle_ip(self, datapath, in_port, pkt):ipv4_pkt = pkt.get_protocol(ipv4.ipv4)if ipv4_pkt.proto == inet.IPPROTO_ICMP:self.handle_icmp(datapath, in_port, pkt)elif ipv4_pkt.proto == inet.IPPROTO_TCP:self.handle_tcp(datapath, in_port, pkt)def handle_tcp(self, datapath, in_port, pkt):print("************* handling tcp packet in ****************")ofproto = datapath.ofprotoparser = datapath.ofproto_parsermac = self.macv2e, s2s = self.v2e, self.s2sipv4_pkt = pkt.get_protocol(ipv4.ipv4)src_ip = ipv4_pkt.srcdst_ip = ipv4_pkt.dsttcp_pkt = pkt.get_protocol(tcp.tcp)src_port, dst_port = tcp_pkt.src_port, tcp_pkt.dst_portself.counter += 1rand = self.counter % 3inp = in_portif datapath.id == 1:if inp != v2e[s2s["s1"]["client"]]:macs = mac[s2s["s1"]["client"]]macd = mac["client"]oup = v2e[s2s["s1"]["client"]]elif rand == 0:macs = mac[s2s["s1"]["node1"]]macd = mac["node1l"]oup = v2e[s2s["s1"]["node1"]]elif rand == 1:macs = mac[s2s["s1"]["node2"]]macd = mac["node2l"]oup = v2e[s2s["s1"]["node2"]]else:macs = mac[s2s["s1"]["node3"]]macd = mac["node3l"]oup = v2e[s2s["s1"]["node3"]]elif datapath.id == 2:if inp != v2e[s2s["s2"]["server"]]:macs = mac[s2s["s2"]["server"]]macd = mac["server"]oup = v2e[s2s["s2"]["server"]]elif rand == 0:macs = mac[s2s["s2"]["node1"]]macd = mac["node1r"]oup = v2e[s2s["s2"]["node1"]]elif rand == 1:macs = mac[s2s["s2"]["node2"]]macd = mac["node2r"]oup = v2e[s2s["s2"]["node2"]]else:macs = mac[s2s["s2"]["node3"]]macd = mac["node3r"]oup = v2e[s2s["s2"]["node3"]]else:returnmatch = parser.OFPMatch(eth_type = ether.ETH_TYPE_IP,ipv4_src = src_ip,ipv4_dst = dst_ip,tcp_dst = dst_port,tcp_src = src_port,ip_proto = inet.IPPROTO_TCP)actions = [parser.OFPActionSetField(eth_src=macs),parser.OFPActionSetField(eth_dst=macd),parser.OFPActionOutput(oup)]self.add_flow(datapath, 50, match, actions)def handle_icmp(self, datapath, in_port, pkt):print("************* handling icmp packet in ****************")#对于任意不是h1/h2互相传的icmp,这里的处理是switch一旦拿到这样的match不到的icmp packet,controller直接给一个回复(有时间想想是不是有更好的方法)ofproto = datapath.ofprotoparser = datapath.ofproto_parseripv4_pkt = pkt.get_protocol(ipv4.ipv4)src_ip, dst_ip = ipv4_pkt.src, ipv4_pkt.dsteth_pkt = pkt.get_protocol(ethernet.ethernet)icmp_pkt = pkt.get_protocol(icmp.icmp)#ethernet源和目的互换ether_hd = ethernet.ethernet(dst = eth_pkt.src, src = eth_pkt.dst, ethertype = ether.ETH_TYPE_IP)ipv4_hd = ipv4.ipv4(proto = 1, src = dst_ip, dst = src_ip)#icmp源和目的互换icmp_hd = icmp.icmp(type_=icmp.ICMP_ECHO_REPLY,code=icmp.ICMP_ECHO_REPLY_CODE,csum=0,data=icmp_pkt.data)icmp_reply = packet.Packet()icmp_reply.add_protocol(ether_hd)icmp_reply.add_protocol(ipv4_hd)icmp_reply.add_protocol(icmp_hd)icmp_reply.serialize()#从inport把包发出去actions = [parser.OFPActionOutput(in_port)];out = parser.OFPPacketOut(datapath, ofproto.OFP_NO_BUFFER, ofproto.OFPP_CONTROLLER, actions, icmp_reply.data)print("************* sending icmp packet out ***************")datapath.send_msg(out)

可能不太完善,但能用

将在本地写好的controller文件scp到controller上

scp /Users/yujin/Desktop/sw2_h5_ctrl.py root@155.98.36.38:/usr/local/lib/python3.6/dist-packages/ryu/app

把controller文件运行起来

#在/usr/local/lib/python3.6/dist-packages/ryu/app路径下运行:
ryu-manager sw2_h5_ctrl.py --verbose

如果遇到这个问题:ImportError: cannot import name 'ALREADY_HANDLED':

需要在controller上执行:

pip3 install eventlet==0.30.2

然后再重新运行ryu-manager命令,亲测有效

此时,controller已经成功启动

(5)登陆两个switch节点,将switch1和switch2连入controller:

在switch1上执行:

ovs-vsctl set-controller br1 tcp:155.98.36.38:6633

在switch2上执行:

ovs-vsctl set-controller br2 tcp:155.98.36.38:6633

此时,网络已经全部搭建完毕

(6)登陆三个node节点

在node1\2\3上同时开启tcpdump对每条link上的packet进行监听,以观察packet是否从这个link上被转发

-i : tcpdump的参数,用于指定网卡,下面的命令中的网卡需要根据实际情况进行修改

#node1:
tcpdump -i enp4s0f0
#node2:
tcpdump -i enp6s0f1
#node3
tcpdump -i enp6s0f1

(7)登陆client

开多个client的shell窗口,分别在多个窗口执行rtmpdump:

#client窗口1里执行
rtmpdump -r rtmp://10.10.8.1:1935/play/3mins.mp4
#client窗口2里执行
rtmpdump -r rtmp://10.10.8.1:1935/play/3mins.mp4

此时观察node1\2\3上dump的包,发现它们转发了tcp_src不同的packet

到这里,实验就结束了,可以写博客总结一下了

ovs视频流转发实验相关推荐

  1. 利用Mininet环境-交换机转发实验整个过程

    目录 1.写在前面 2.安装工作 2.1.mininet安装 2.2 cmake安装 2.3 xterm安装 2.4 wireshark安装 3.作业要求:(交换机转发实验) ​ 4.C语言完成函数编 ...

  2. 基于HDMI的视频流输入输出实验

    本实验基于ECE-CV K7-75T FPGA开发板实现. 软件使用Vivado 2018.1. 欢迎添加QQ:2639406604一起交流 原文链接: 基于HDMI的视频流输入输出实验 基于HDMI ...

  3. 【计网实验——prj9】路由器转发实验

    [计网实验--prj9]路由器转发实验 实验要求 实验内容一 运行给定网络拓扑(router_topo.py) 在r1上执行路由器程序./router,进行数据包的处理 在h1上进行ping实验 Pi ...

  4. 交换机转发实验(回顾哈希表实现)

    交换机转发实验(回顾哈希表实现) 哈希表的C语言实现 哈希函数为对哈希表长取余 哈希表算法实现 # include <stdio.h> # include <stdlib.h> ...

  5. Open vSwitch---流表控制主机数据转发实验(四)---meter表实践

    一.meter表介绍 meter表是openflow协议的内容,meter表是openflow1.3版本以后才支持,所以所有命令需要指定OpenFlow1.3版本以上.此外,在openvswitch- ...

  6. 通过nginx-rtmp server进行视频流转发的几种方法

    1.接收流: 在需要接收流的节点上进行类似以下的配置: application live{live on;} 只要有这一项,就可以通过在浏览器等位置输入下面这个url来点播了 rtmp://127.0 ...

  7. 【FFmpeg】ffmpeg+nginx-rtmp实现视频流转发

    1.应用场景 目前的摄像头厂家能提供出来的视频流格式有限,且chrome已经禁止了对flash的支持,导致像硬盘录像机这种只能提供rtsp格式流地址的摄像头无法接入Web应用,所以不得不对视频的流地址 ...

  8. 单域MPLS ***数据转发实验分析

    MPLS ×××数据详细转发流程示意图: 配置思路: 在自治系统AS100中配置IGP,使得两台PE路由器的lo 0接口路由可达: 两台PE路由器路由可达后,在两台PE路由器之间建立MP-iBGP邻居 ...

  9. bind简单转发实验

    2019独角兽企业重金招聘Python工程师标准>>> *主配置文件内容// [root@localhost /]# cat /etc/named.conf  // // named ...

最新文章

  1. mysql 定时计划_MYSQL定时任务
  2. 【转载】用开源软件搭建企业内部协作平台, Kill QQ MSN
  3. 快学Scala习题解答—第一章 基础
  4. unity mysql增删改查,XML的使用,增删改查(Unity中的)
  5. 按照这个步骤来刷题,迷茫的你两个月亦能成为王者
  6. 云服务器CentOS7上安装Mysql,并使用Navicat连接的最简便快速方法
  7. x550网卡linux驱动,Intel英特尔X520/X540/X550/82599系列万兆网卡驱动5.10.2版For Linux(2021年2月1日发布)...
  8. 【西汉文学】之《贾谊·过秦论》
  9. 怎样在word表格中快速输入序号?
  10. pacman 查询_pacman命令
  11. Unity3D的3D音效的实现
  12. MTK 6737 android6.0 user版本打开root权限(adb root权限和 apk root权限)
  13. 计算机基础应用在线模拟考试,计算机应用基础模拟试卷一与答案.pdf
  14. mysql 查询字母集合_使用MySQL查询查找所有以字母“ a”,“ b”或“ c”开头的名称?...
  15. iPhone手机在Apple启动logo处卡住,无法开机该怎么办?
  16. linux安装java(zz)
  17. ecb里使用自定义快捷键切换窗口
  18. 数据流角度看DSO(一)
  19. 计算机在金融领域的,计算机在金融领域中的应用
  20. webstorm 2018 激活破解方法大全 亲测第三个有用

热门文章

  1. 松下FP7大型plc程序,一共三十多个电机,轴控制程序模块化
  2. 02智慧城市分层架构
  3. linux重启shutdown命令,linux重启命令 reboot与shutdown -r now的区别与联系
  4. C# Stopwatch实现精确计时
  5. 如何在Windows中使用“ shutdown r”命令重新启动和关闭计算机?
  6. SpringBoot(一)
  7. 古琴禅曲《崖下栖心》:听琴如修禅,飘渺闲云中
  8. 周信东c语言实验二实验报告,周信东主编最新版-C语言程序设计基础实验一实验报告...
  9. 美国最值得关注十大创业孵化器:TechStars居首
  10. 达梦单机数据库安装(for linux)