我是靠谱客的博主 糟糕万宝路,最近开发中收集的这篇文章主要介绍ovs视频流转发实验,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 本实验实用平台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 here
            root /usr/local/nginx-rtmp-module;
        }

        location /hls {
            # Serve HLS fragments
            types {
                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

#绑定四个物理端口,每个真机的物理端口名称不太一样,这里用eth1234代替
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

#绑定四个物理端口,每个真机的物理端口名称不太一样,这里用eth1234代替
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*****对应的绑定到br1br2时br1br2发给它的port-number,可以用ovs-ofctl show br1br2来查看

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 random

class 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.ip
        v2e, s2s = self.v2e, self.s2s
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = 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.id
        print("******setting features for s" + str(dpid) + "******")
        self.send_set_config(datapath)
        if dpid == 1:
            #icmp:
            #client -> server
            inport, 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 -> client
            inport, 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 -> client
            inport, 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 -> server
            inport, 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 -> client
            inport, 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.ofproto
        parser = 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-h1
    def add_icmp_rules(self, datapath, in_port, out_port, ips, ipd, macs, macd):
        priority = 20
        parser = datapath.ofproto_parser
        actions = [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 = 20
        parser = datapath.ofproto_parser
        actions = [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先安装给datapath
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = 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.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = datapath.id
        msg = ev.msg
        print("****** 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.ethertype
        if not eth_pkt:
            return
        pkt_arp = pkt.get_protocol(arp.arp)

        if ethertype == ether.ETH_TYPE_ARP:
            self.handle_arp(datapath, in_port, pkt)
            return
        if ethertype == ether.ETH_TYPE_IP:
            self.handle_ip(datapath, in_port, pkt)
            return

    def handle_arp(self, datapath, in_port, pkt):
        print("*************** handling arp packet in  from "+str(datapath.id)+" ****************")
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # parse out the ethernet and arp packet
        eth_pkt = pkt.get_protocol(ethernet.ethernet)
        arp_pkt = pkt.get_protocol(arp.arp)
        # obtain the MAC of dst IP  
        dpid = datapath.id

        if 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 Msg
        ether_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 ARP
        actions = [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.ofproto
        parser = datapath.ofproto_parser
        mac = self.mac
        v2e, s2s = self.v2e, self.s2s
        ipv4_pkt = pkt.get_protocol(ipv4.ipv4)
        src_ip = ipv4_pkt.src
        dst_ip = ipv4_pkt.dst
        tcp_pkt = pkt.get_protocol(tcp.tcp)
        src_port, dst_port = tcp_pkt.src_port, tcp_pkt.dst_port
        self.counter += 1
        rand = self.counter % 3
        inp = in_port
        if 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:
            return

        match = 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.ofproto
        parser = datapath.ofproto_parser
        ipv4_pkt = pkt.get_protocol(ipv4.ipv4)
        src_ip, dst_ip = ipv4_pkt.src, ipv4_pkt.dst
        eth_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节点

在node123上同时开启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

此时观察node123上dump的包,发现它们转发了tcp_src不同的packet

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

最后

以上就是糟糕万宝路为你收集整理的ovs视频流转发实验的全部内容,希望文章能够帮你解决ovs视频流转发实验所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部