ryu学习---利用socket

一 实验目的

本实验仅学习控制器与应用层如何通信,利用ryu实现hub,然后获取每次通信的dpid和port传输给应用层。拓扑结构如下:
在这里插入图片描述
记得都要关闭防火墙。

二 实验代码

本次实验,数据转发层面和控制层面都是在一台Ubuntu系统下面的mininet进行拓扑仿真的,在ryu运行编写好的程序,在另一台windows下运行编写好的server端程序。

(1)server程序

server端主要用于接收控制器的连接,并接收由控制器发送过来的信息,这里主要是dpid和port信息,也就是当主机h1、h2进行通信时,控制器收集通信时经过的端口和交换机id。

import socket
import re


def main():
    server1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # TCP

    host = ''
    port = 12345
    server1.bind((host, port))

    server1.listen(5)
    while True:
        conn, addr = server1.accept()
        print("----------------------------")
        print("Success connect from ", addr)

        try:
            count = 0
            while True:
                data = conn.recv(1024)
                data = re.split(r'[, :]', data.decode('utf-8'))  # 对收到的信息进行解析,包括dpid和port
                count += 1
                print("from {0}:dpid={1}, in_port={2}".format(addr, data[0], data[1]))
            conn.close()
        except Exception as error:  # 当控制器和应用层断开连接后,输出统计信息
            print('共接收{}条信息。'.format(count - 1))
            print(error)
            exit()


if __name__ == '__main__':
    main()

(1)client程序

该实验以简单的hub为基础,在hub中写入client端程序实现控制器和应用层的通信。

from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER
from ryu.controller import ofp_event
from ryu.ofproto import ofproto_v1_3
import socket
 
 
class L2Switch(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
 
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.dp_id = '0'
        self.in_port = '0'
        
        # 开启client,并连接server
        self.client1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dst_host = '192.168.0.100'
        dst_port = 12345
        # 防止server端连接不上影响hub的使用
        try:
            self.client1.connect((dst_host, dst_port))
        except Exception as error:
            print('Connect error:', error)
 
    def add_flow(self, datapath, command, priority, match, actions):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser
        inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)]
        req = ofp_parser.OFPFlowMod(datapath=datapath, command=command,
                                    priority=priority, match=match, instructions=inst)
        datapath.send_msg(req)
    
    # 控制器和交换机握手时,向交换机下发默认流表项
    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser
 
        # add table-miss
        command = ofp.OFPFC_ADD
        match = ofp_parser.OFPMatch()
        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_CONTROLLER, ofp.OFPCML_NO_BUFFER)]
        self.add_flow(datapath, command, 0, match, actions)
 
    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto
        ofp_parser = dp.ofproto_parser
        self.dp_id = dp.id
 
        # 计算出in_port
        start = str(msg).index('oxm_fields') + 11
        end = str(msg).index('),reason')
        inport_str = str(msg)[start:end]
        instr = eval(inport_str)
        self.in_port = instr['in_port']
 
        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
 
        data = None
        if msg.buffer_id == ofp.OFP_NO_BUFFER:
             data = msg.data
        print('id:{0}     in_port:{1}'.format(self.dp_id, self.in_port))
        # 每次有信息经过交换机时,控制器就将获取的dpid和port发送给server
        info = str(self.dp_id) + ',' + str(self.in_port)
        self.client1.send(info.encode())
 
        out = ofp_parser.OFPPacketOut(
            datapath=dp, buffer_id=msg.buffer_id, in_port=self.in_port,
            actions=actions, data=data)
        dp.send_msg(out)

三 运行实验

(1)在mininet中创建拓扑

$ sudo mn --controller=remote --topo=single,2 --mac

(2)运行server端程序

在这里插入图片描述

(3)启动ryu程序

sudo ryu-manager hub_client.py --observe-links

ryu启动后,可以在server端控制台看见输出连接成功。
在这里插入图片描述

(4)h1 ping h2,观察输出信息

server端:
在这里插入图片描述
client端:
在这里插入图片描述
server与client断开通信:
在这里插入图片描述
打印共接收到多少条信息。

代码来源:ryu–北向接口(流表的操作以及多控制器流表信息互通)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值