SDN实验---Ryu的应用开发(四)修改Ryu源码,实现openflow1.3自定义action

13 篇文章 4 订阅
12 篇文章 1 订阅

(一)定义action,修改ofproto_v1_3.py

# enum ofp_action_type
OFPAT_OUTPUT = 0                # Output to switch port.
OFPAT_COPY_TTL_OUT = 11         # Copy TTL "outwards" -- from
                                # next-to-outermost to outermost
OFPAT_COPY_TTL_IN = 12          # Copy TTL "inwards" -- from outermost to
                                # next-to-outermost
OFPAT_SET_MPLS_TTL = 15         # MPLS TTL.
OFPAT_DEC_MPLS_TTL = 16         # Decrement MPLS TTL
OFPAT_PUSH_VLAN = 17            # Push a new VLAN tag
OFPAT_POP_VLAN = 18             # Pop the outer VLAN tag
OFPAT_PUSH_MPLS = 19            # Push a new MPLS tag
OFPAT_POP_MPLS = 20             # Pop the outer MPLS tag
OFPAT_SET_QUEUE = 21            # Set queue id when outputting to a port
OFPAT_GROUP = 22                # Apply group
OFPAT_SET_NW_TTL = 23           # IP TTL.
OFPAT_DEC_NW_TTL = 24           # Decrement IP TTL.
OFPAT_SET_FIELD = 25            # Set a header field using OXM TLV format.
OFPAT_PUSH_PBB = 26             # Push a new PBB service tag (I-TAG)
OFPAT_POP_PBB = 27              # Pop the outer PBB service tag (I-TAG)
OFPAT_PROB_DROP = 29            # probdrop packet 新增这里
OFPAT_EXPERIMENTER = 0xffff

# struct ofp_action_header
OFP_ACTION_HEADER_PACK_STR = '!HH4x'
OFP_ACTION_HEADER_SIZE = 8
assert calcsize(OFP_ACTION_HEADER_PACK_STR) == OFP_ACTION_HEADER_SIZE

# struct ofp_action_output
OFP_ACTION_OUTPUT_PACK_STR = '!HHIH6x'
OFP_ACTION_OUTPUT_SIZE = 16
assert calcsize(OFP_ACTION_OUTPUT_PACK_STR) == OFP_ACTION_OUTPUT_SIZE

# enum ofp_controller_max_len
OFPCML_MAX = 0xffe5         # maximum max_len value which can be used to
                            # request a specific byte length.
OFPCML_NO_BUFFER = 0xffff   # indicates that no buffering should be
                            # applied and the whole packet is to be
                            # sent to the controller.

# struct ofp_action_group
OFP_ACTION_GROUP_PACK_STR = '!HHI'
OFP_ACTION_GROUP_SIZE = 8
assert calcsize(OFP_ACTION_GROUP_PACK_STR) == OFP_ACTION_GROUP_SIZE

# struct ofp_action_set_queue
OFP_ACTION_SET_QUEUE_PACK_STR = '!HHI'
OFP_ACTION_SET_QUEUE_SIZE = 8
assert calcsize(OFP_ACTION_SET_QUEUE_PACK_STR) == OFP_ACTION_SET_QUEUE_SIZE

# struct ofp_action_mpls_ttl
OFP_ACTION_MPLS_TTL_PACK_STR = '!HHB3x'
OFP_ACTION_MPLS_TTL_SIZE = 8
assert calcsize(OFP_ACTION_MPLS_TTL_PACK_STR) == OFP_ACTION_MPLS_TTL_SIZE

# struct ofp_action_nw_ttl
OFP_ACTION_NW_TTL_PACK_STR = '!HHB3x'
OFP_ACTION_NW_TTL_SIZE = 8
assert calcsize(OFP_ACTION_NW_TTL_PACK_STR) == OFP_ACTION_NW_TTL_SIZE

# struct ofp_action_push
OFP_ACTION_PUSH_PACK_STR = '!HHH2x'
OFP_ACTION_PUSH_SIZE = 8
assert calcsize(OFP_ACTION_PUSH_PACK_STR) == OFP_ACTION_PUSH_SIZE

# struct ofp_action_pop_mpls
OFP_ACTION_POP_MPLS_PACK_STR = '!HHH2x'
OFP_ACTION_POP_MPLS_SIZE = 8
assert calcsize(OFP_ACTION_POP_MPLS_PACK_STR) == OFP_ACTION_POP_MPLS_SIZE

# struct ofp_action_prob_drop
OFP_ACTION_PROB_DROP_PACK_STR = '!HHI'
OFP_ACTION_PROB_DROP_SIZE = 8
assert calcsize(OFP_ACTION_PROB_DROP_PACK_STR) == OFP_ACTION_PROB_DROP_SIZE
1.OFPAT_PROB_DROP = 29            #probdrop packet

2.# struct ofp_action_prob_drop
OFP_ACTION_PROB_DROP_PACK_STR = '!HHI'
OFP_ACTION_PROB_DROP_SIZE = 8
assert calcsize(OFP_ACTION_PROB_DROP_PACK_STR) == OFP_ACTION_PROB_DROP_SIZE    #共占8字节,进行校验
声明数据格式,我们需要传参,固定传参中由type和len各占2字节用H表示,我们需要的参数为一位32为数据,占4字节,用I表示,故!HHI为格式,共占8字节

(二)实现动作解析,修改ofproto_v1_3_parser.py

@OFPAction.register_action_type(ofproto.OFPAT_POP_PBB,
                                ofproto.OFP_ACTION_HEADER_SIZE)
class OFPActionPopPbb(OFPAction):
    """
    Pop PBB action

    This action pops the outermost PBB service instance header from
    the packet.
    """

    def __init__(self, type_=None, len_=None):
        super(OFPActionPopPbb, self).__init__()

    @classmethod
    def parser(cls, buf, offset):
        (type_, len_) = struct.unpack_from(
            ofproto.OFP_ACTION_HEADER_PACK_STR, buf, offset)
        return cls()

@OFPAction.register_action_type(ofproto.OFPAT_PROB_DROP,
                                ofproto.OFP_ACTION_PROB_DROP_SIZE)
class OFPActionProbdrop(OFPAction):
    """
    Prob drop action

    This action Randomly discarded the packet.
    """

    def __init__(self, probd, type_=None, len_=None):
        super(OFPActionProbdrop, self).__init__()
        self.probd = probd

    @classmethod
    def parser(cls, buf, offset):
        (type_, len_, probd) = struct.unpack_from(
            ofproto.OFP_ACTION_PROB_DROP_PACK_STR, buf, offset)
        return cls(probd)

    def serialize(self, buf, offset):
        msg_pack_into(ofproto.OFP_ACTION_PROB_DROP_PACK_STR, buf, offset,
                      self.type, self.len, self.probd)
1.我们需要进行传参处理

def __init__(self, probd, type_=None, len_=None):
        super(OFPActionProbdrop, self).__init__()
        self.probd = probd

2.进行报文解析

@classmethod
    def parser(cls, buf, offset):
        (type_, len_, probd) = struct.unpack_from(
            ofproto.OFP_ACTION_PROB_DROP_PACK_STR, buf, offset)
        return cls(probd)

3.进行序列化处理,按照HHI进行序列化即可

def serialize(self, buf, offset):
    msg_pack_into(ofproto.OFP_ACTION_PROB_DROP_PACK_STR, buf, offset,
                self.type, self.len, self.probd)

(三)重新进行源码安装Ryu

进入ryu主目录,目录下含有setup.py安装文件

sudo python3 setup.py install

 (四)编写app文件,进行测试

        1.编写python文件

from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3,ofproto_v1_3_parser
from ryu.ofproto import nx_actions
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER,CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet

class otheraction(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self,*args,**kwargs):
        super(otheraction,self).__init__(*args,**kwargs)
        self.Dst_Src_Table={}

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER)
    def switch_features_handler(self,ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        match = ofp_parser.OFPMatch()
        actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]

        self.add_flow(datapath,0,match,actions,"default flow entry")

    def add_flow(self,datapath,priority,match,actions,remind_content):
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]

        mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority,
                                    match=match,instructions=inst);
        print("install to datapath,"+remind_content)
        datapath.send_msg(mod);

    @set_ev_cls(ofp_event.EventOFPPacketIn,MAIN_DISPATCHER)
    def packet_in_handler(self,ev):        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        in_port = msg.match['in_port']

        match = ofp_parser.OFPMatch(in_port=in_port)
        if(datapath.id == 1 and in_port == 1):  #我们只对第一个交换机,s1,添加概率丢包动作
            actions = [ofp_parser.OFPActionProbDrop(1000000000),ofp_parser.OFPActionOutput(2)]
        else:  #对于其他交换机,泛洪处理即可
            actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]

        self.add_flow(datapath,1,match,actions,"hub flow entry")

        out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id,
                                            in_port=in_port,actions=actions)

        datapath.send_msg(out)

        2.实验测试

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值