Ejemplo n.º 1
0
def packet_to_flow_match(packet):
    """
    Create a flow match that matches packet with the given wildcards

    @param packet The packet to use as a flow template
    @param pkt_format Currently only L2 is supported.  Will indicate the 
    overall packet type for parsing
    @return An ofp_match object if successful.  None if format is not
    recognized.  The wildcards of the match will be cleared for the
    values extracted from the packet.

    @todo check min length of packet
    @todo Check if packet is other than L2 format
    @todo implement other fields covered by OpenFlow 1.2 
    """
    match_ls = match_list()

    if Ether in packet:
        ether = packet[Ether]
        eth_type = match.eth_type(ether.type)
        eth_dst = match.eth_dst(parse_mac(ether.dst))
        eth_src = match.eth_src(parse_mac(ether.src))
        match_ls.add(eth_type)
        match_ls.add(eth_dst)
        match_ls.add(eth_src)
    else:
        return match_ls

    if Dot1Q in packet:
        #TODO: nicer way to get last vlan tag?
        vlan = packet[Dot1Q:0]
        vlan_vid = match.vlan_vid(vlan.vlan)
        vlan_pcp = match.vlan_pcp(vlan.prio)
        match_ls.add(vlan_vid)
        match_ls.add(vlan_pcp)
        vlan_pl = vlan.payload
        while vlan_pl is not None and vlan_pl.name == Dot1Q.name:
            vlan = vlan_pl
            vlan_pl = vlan.payload
        #We need to overwrite the already
        # inserted eth_type    
        eth_index = match.tlvs.index()
        eth_type = match.eth_type(vlan.type)
        match_ls.tlvs.insert(vlan.type,eth_index)
    #TODO ARP

    if MPLS in packet:
        mpls = packet[MPLS:0]
        mpls_label = match.mpls_label(mpls.label)
        mpls_tc =  match.mpls_tc(mpls.cos)
        match_ls.add(mpls_label)
        match_ls.add(mpls_tc)
        return match_ls

    if IP in packet:
        ip = packet[IP]
        ipv4_src = match.ipv4_src(parse_ip(ip.src))
        ipv4_dst = match.ipv4_dst(parse_ip(ip.dst))
        ip_dscp =  match.ip_dscp(ip.tos >> 2) 
        ip_ecn =   match.ip_ecn(ip.tos & 0x03)
        match_ls.add(ipv4_src)
        match_ls.add(ipv4_dst)
        match_ls.add(ip_dscp)
        match_ls.add(ip_ecn)
    else:
        return match_ls
    
    if TCP in packet:
        tcp = packet[TCP]
        ip_proto = match.ip_proto(6)
        tcp_src = match.tcp_src(tcp.sport)
        tcp_dst = match.tcp_dst(tcp.dport)
        match_ls.add(ip_proto)
        match_ls.add(tcp_src)
        match_ls.add(tcp_dst)
        return match_ls

    if UDP in packet:
        udp = packet[UDP]
        ip_proto = match.ip_proto(17)
        udp_src = match.tcp_src(udp.sport)
        udp_dst = match.tcp_dst(udp.dport)
        match_ls.add(ip_proto)
        match_ls.add(udp_src)
        match_ls.add(udp_dst)        
        return match_ls

    if ICMP in packet:
        icmp = packet[ICMP]
        ip_proto = match.ip_proto(1)
        icmp_type = match.icmp_type(icmp.type)
        icmp_code = match.icmp_code(icmp.code)
        match_ls.add(icmp_type)
        match_ls.add(icmp_code)        
        return match_ls

    return match_ls
Ejemplo n.º 2
0
def init_lrp_egress_clause(options):

    # figure out all linked lsp on a LS which has a connection with this LRP
    opposite_side_changed_lsp(
        LR, LRP, LSP, State) <= (lsp_link_lrp(
            LSP1, LS, UUID_LS, LRP, LR, UUID_LR,
            UUID_LR_CHASSIS, State1) & exchange_lsp_array(
                UUID_LSP, LSP, UUID_LS, UUID_CHASSIS, UUID_LRP1, State2) &
                                 (State == State1 + State2) & (State != 0))
    # figure out all regular lsp
    opposite_side_changed_lsp(LR, LRP, LSP, State) <= (
        lrp_array(UUID_LRP, LRP, UUID_LR, UUID_LSP1, State1)
        & exchange_lsp_array(UUID_LSP1, LSP1, UUID_LS, UUID_CHASSIS1, UUID_LRP,
                             State2) & ls_array(LS, UUID_LS, State3)
        & lr_array(LR, UUID_LR, State4)
        & lsp_array(UUID_LSP, LSP, UUID_LS, UUID_CHASSIS2, UUID_LRP2, State5) &
        (UUID_CHASSIS2 != None) &
        (State == State1 + State2 + State3 + State4 + State5) & (State != 0))

    opposite_side_has_patch_port(LR, LRP, State) <= (
        local_patchport(LSP, LS, State1) & lsp_link_lrp(
            LSP1, LS, UUID_LS, LRP, LR, UUID_LR, UUID_LR_CHASSIS, State2) &
        # NOTE only consider local_patchport, it means a gateway's oppsite
        # LS has remote patchport cannot trigger this flow
        (State == State1 + State2))

    # update eth_dst by searching active lsp
    lrp_update_eth_dst(LR, Priority, Match, Action, State) <= (
        (Priority == 3) & opposite_side_changed_lsp(LR, LRP, LSP, State)
        & match.ip_proto(Match1) &
        # we have to match the lrp portID, because in ecmp,
        # two ports may have same dst IP but different dst mac
        match.reg_dst(LRP[LRP_PORTID], Match2)
        & match.reg_2(LSP[LSP_IP_INT], Match3) &
        (Match == Match1 + Match2 + Match3)
        & action.load(LSP[LSP_MAC_INT], NXM_Reg(ETH_DST_IDX), Action1)
        & action.resubmit_next(Action2) & (Action == Action1 + Action2))

    # push packet to table TABLE_SEARCH_IP_MAC to search unknow mac,ip pair
    lrp_update_eth_dst(LR, Priority, Match, Action, State) <= (
        (Priority == 2) & lr_array(LR, UUID_LR, State) &
        (State != 0) & match.match_none(Match)
        & action.mod_dl_dst("00:00:00:00:00:00", Action1)
        & action.resubmit_table(TABLE_SEARCH_IP_MAC, Action2)
        & action.resubmit_next(Action3) &
        (Action == Action1 + Action2 + Action3))

    lrp_ip_undnat_stage1(LR, Priority, Match, Action,
                         State) <= (nat.lundnat_xlate_stage1(
                             LR, Priority, Match, Action, State))
    lrp_ip_undnat_stage2(LR, Priority, Match, Action,
                         State) <= (nat.lundnat_xlate_stage2(
                             LR, Priority, Match, Action, State))

    lrp_ip_snat_stage1(LR, Priority, Match, Action,
                       State) <= (nat.lsnat_xlate_stage1(
                           LR, Priority, Match, Action, State))
    lrp_ip_snat_stage2(LR, Priority, Match, Action,
                       State) <= (nat.lsnat_xlate_stage2(
                           LR, Priority, Match, Action, State))

    # ovs should drop it if the packet's dst_mac = 00:00:00:00:00:00 and
    # it is a redirect packet. This flow avoids infinite loop.
    lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
        (Priority == 4) & lr_array(LR, UUID_LR, State) &
        (State != 0) & match.reg_flag(FLAG_REDIRECT, Match1)
        & match.eth_dst("00:00:00:00:00:00", Match2) &
        (Match == Match1 + Match2)
        & action.resubmit_table(TABLE_DROP_PACKET, Action))

    # ask controller to generate arp, if we cannot found the ip,mac pair.
    # If opposite LS has patch-port will create this flow
    lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
        (Priority == 3) &
        # oppsite LS must has patchport
        opposite_side_has_patch_port(LR, LRP, State) & (State != 0)
        & match.ip_proto(Match1) & match.eth_dst("00:00:00:00:00:00", Match2)
        & match.reg_dst(LRP[LRP_PORTID], Match3) &
        (Match == Match1 + Match2 + Match3) &
        # reg2 and reg3 were transfered to pkt_controller as well
        action.generate_arp(TABLE_LRP_EGRESS_FORWARD_PACKET, Action1)
        & action.resubmit_table(TABLE_DROP_PACKET, Action2) &
        (Action == Action1 + Action2))

    # upload packet to controller, if this packet cannot trigger generating
    # arp and didn't know the destination's macaddress. controller will
    # ask tuplenet to generate it.
    if options.has_key('ONDEMAND'):
        if options.has_key('ENABLE_REDIRECT'):
            # A regular tuplenet node(with ondemand) may not know where dst lsp is,
            # so it uploads packet to controller and redirects pkt to an edge node.
            lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
                (Priority == 2) & lr_array(LR, UUID_LR, State) &
                (State != 0) & match.ip_proto(Match1) &
                # set macaddress to 0, then other host know this packet
                # should be threw to LR pipline
                match.eth_dst("00:00:00:00:00:00", Match2) &
                (Match == Match1 + Match2) & action.load(
                    1,
                    NXM_Reg(REG_FLAG_IDX, FLAG_REDIRECT_BIT_IDX,
                            FLAG_REDIRECT_BIT_IDX), Action1)
                & action.upload_unknow_dst(Action2)
                & action.resubmit_table(TABLE_EMBED2_METADATA, Action3)
                & action.resubmit_table(TABLE_REDIRECT_CHASSIS, Action4) &
                (Action == Action1 + Action2 + Action3 + Action4))
        else:
            lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
                (Priority == 2) & lr_array(LR, UUID_LR, State) &
                (State != 0) & match.ip_proto(Match1)
                & match.eth_dst("00:00:00:00:00:00", Match2) &
                (Match == Match1 + Match2) & action.upload_unknow_dst(Action))
    else:
        if options.has_key('ENABLE_REDIRECT'):
            # A edge node(with ondemand disable) should know where is dst, but
            # tuplenet instance may down so ovs-flow doesn't know the new dst(
            # a lsp may be create while tuplenet is down, ovs-flow not updated).
            # This ovs-flow should redirect this packet to other edge now as well,
            # BUT NOT upload to controller
            lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
                (Priority == 2) & lr_array(LR, UUID_LR, State) &
                (State != 0) & match.ip_proto(Match1) &
                # set macaddress to 0, then other host know this packet
                # should be threw to LR pipline
                match.eth_dst("00:00:00:00:00:00", Match2) &
                (Match == Match1 + Match2) & action.load(
                    1,
                    NXM_Reg(REG_FLAG_IDX, FLAG_REDIRECT_BIT_IDX,
                            FLAG_REDIRECT_BIT_IDX), Action1)
                & action.resubmit_table(TABLE_EMBED2_METADATA, Action2)
                & action.resubmit_table(TABLE_REDIRECT_CHASSIS, Action3) &
                (Action == Action1 + Action2 + Action3))

    lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
        (Priority == 1) & lr_array(LR, UUID_LR, State) &
        (State != 0) & match.eth_dst("00:00:00:00:00:00", Match)
        & action.resubmit_table(TABLE_DROP_PACKET, Action))

    lrp_handle_unknow_dst_pkt(LR, Priority, Match, Action, State) <= (
        (Priority == 0) & lr_array(LR, UUID_LR, State) &
        (State != 0) & match.match_none(Match) & action.resubmit_next(Action))

    lrp_forward_packet(LR, Priority, Match, Action, State) <= (
        (Priority == 3) & lsp_link_lrp(LSP, LS, UUID_LS, LRP, LR, UUID_LR,
                                       UUID_LR_CHASSIS, State) &
        (State != 0) & match.reg_dst(LRP[LRP_PORTID], Match)
        & action.load(LS[LS_ID], NXM_Reg(REG_DP_IDX), Action1)
        & action.load(LSP[LSP_PORTID], NXM_Reg(REG_SRC_IDX), Action2)
        & action.resubmit_next(Action3) &
        (Action == Action1 + Action2 + Action3))
Ejemplo n.º 3
0
def init_lsp_ingress_clause(options):

    if options.has_key('GATEWAY'):
        # push RARP to controller, only Edge node should consider receiving rarp
        lsp_arp_controller(LS, Priority, Match, Action, State) <= (
            (Priority == 2) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.arp_proto(Match1) &
            match.arp_op(2, Match2) &
            (Match == Match1 + Match2) &
            action.upload_arp(Action)
            )

    if not options.has_key('ONDEMAND'):
        # maybe gratuitous ARP, push to controller.
        # maybe a unknow dst arp
        lsp_arp_controller(LS, Priority, Match, Action, State) <= (
            (Priority == 1) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.arp_proto(Match1) &
            match.arp_op(1, Match2) &
            (Match == Match1 + Match2) &
            action.upload_arp(Action1) &
            action.resubmit_next(Action2) &
            (Action == Action1 + Action2)
            )

    lsp_arp_controller(LS, Priority, Match, Action, State) <= (
        (Priority == 0) &
        ls_array(LS, UUID_LS, State) & (State != 0) &
        (match.match_none(Match)) &
        action.resubmit_next(Action)
        )

    lsp_arp_response(LS, Priority, Match, Action, State) <= (
        (Priority == 2) &
        ls_array(LS, UUID_LS, State) & (State != 0) &
        match.arp_proto(Match1) &
        match.arp_op(1, Match2) &
        (Match == Match1 + Match2) &
        action.resubmit_table(TABLE_ARP_FEEDBACK_CONSTRUCT, Action1) &
        action.resubmit_next(Action2) &
        (Action == Action1 + Action2)
        )

    lsp_arp_response(LS, Priority, Match, Action, State) <= (
        (Priority == 0) &
        ls_array(LS, UUID_LS, State) & (State != 0) &
        (match.match_none(Match)) &
        action.resubmit_next(Action)
        )


    if options.has_key('ENABLE_UNTUNNEL') and options.has_key('dsrport'):
        # NOTE: it helps reduce time-cost
        _lsp_lrp_ls_changed(LS, LRP, State) <= (
            ls_array(LS, UUID_LS, State1) &
            lsp_link_lrp(LSP, LS1, UUID_LS1, LRP, LR,
                         UUID_LR, UUID_LR_CHASSIS, State2) &
            (State == State1 + State2) & (State != 0)
        )
        lsp_untunnel_deliver(LS, Priority, Match, Action, State) <= (
             _lsp_lrp_ls_changed(LS, LRP, State) &
            (Priority == _cal_priority(LRP[LRP_PREFIX], 2, LRP[LRP_ILK_IDX])) &
            match.ip_proto(Match1) &
            match.ip_dst_prefix(LRP[LRP_IP], LRP[LRP_PREFIX], Match2) &
            (Match == Match1 + Match2) &
            action.resubmit_next(Action)
        )

        lsp_untunnel_deliver(LS, Priority, Match, Action, State) <= (
            (Priority == 1) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.ip_proto(Match) &
            # output packet to local port which is an internal port.
            # packet goes into tcpip stack
            action.mod_dl_dst(options['dsrport']['mac'], Action1) &
            action.output(options['dsrport']['ofport'], Action2) &
            (Action == Action1 + Action2)
            )


    lsp_untunnel_deliver(LS, Priority, Match, Action, State) <= (
        (Priority == 0) &
        ls_array(LS, UUID_LS, State) & (State != 0) &
        (match.match_none(Match)) &
        action.resubmit_next(Action)
        )

    # deliver to LR which has snat/dnat
    lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
        (Priority == 5) &
        # TODO optimize it
        lnat_data(LNAT, LR, XLATE_TYPE, UUID_LR, State1) &
        lsp_link_lrp(LSP, LS, UUID_LS, LRP, LR,
                     UUID_LR, UUID_LR_CHASSIS, State2) &
        (State == State1 + State2) & (State != 0) &
        match.eth_dst(LNAT[LNAT_XLATE_MAC], Match) &
        action.load(LSP[LSP_PORTID], NXM_Reg(REG_DST_IDX), Action1) &
        action.resubmit_next(Action2) &
        (Action == Action1 + Action2)
        )

    # deliver to another lsp on local chassis
    lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
        (Priority == 4) &
        local_lsp(LSP, LS, State) & (State != 0) &
        match.eth_dst(LSP[LSP_MAC], Match) &
        action.load(LSP[LSP_PORTID],
                    NXM_Reg(REG_DST_IDX), Action1) &
        action.resubmit_next(Action2) &
        (Action == Action1 + Action2)
        )

    # it helps reduce time-cost
    _lsp_remote_lsp_changed(LSP, LS, PHY_CHASSIS, State) <= (
                    remote_lsp(LSP, LS, PHY_CHASSIS, State) & (State != 0))

    if options.has_key('ENABLE_REDIRECT'):
        # output deliver to another remote chassis.
        # use bundle_load to check if dst chassis is dead or live.
        lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
            (Priority == 3) &
            _lsp_remote_lsp_changed(LSP, LS, PHY_CHASSIS, State) &
            match.eth_dst(LSP[LSP_MAC], Match) &
            action.load(LSP[LSP_PORTID],
                        NXM_Reg(REG_DST_IDX), Action1) &
            action.bundle_load(NXM_Reg(REG_OUTPORT_IDX),
                               [PHY_CHASSIS[PCH_OFPORT]], Action2) &
            # if we want output this packet in next step, we set 1->reg5
            # in next step flow, no need to clean this reg5, because
            # it should output a port means the end of packet process
            action.load(1, NXM_Reg(REG5_IDX), Action3) &
            action.resubmit_next(Action4) &
            (Action == Action1 + Action2 + Action3 + Action4)
            )
    else:
        # deliver to remote chassis by using output,(set outport to reg4)
        lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
            (Priority == 3) &
            _lsp_remote_lsp_changed(LSP, LS, PHY_CHASSIS, State) &
            match.eth_dst(LSP[LSP_MAC], Match) &
            action.load(LSP[LSP_PORTID],
                        NXM_Reg(REG_DST_IDX), Action1) &
            action.load(PHY_CHASSIS[PCH_OFPORT],
                        NXM_Reg(REG_OUTPORT_IDX), Action2) &
            # if we want output this packet in next step, we set 1->reg5
            # in next step flow, no need to clean this reg5, because
            # it should output a a port means the end of packet process
            action.load(1, NXM_Reg(REG5_IDX), Action3) &
            action.resubmit_next(Action4) &
            (Action == Action1 + Action2 + Action3 + Action4)
            )

    # deliver the packet which not match above flow to the patchport
    # patch port's ip address should be 255.255.255.255
    lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
        (Priority == 2) &
        local_patchport(LSP, LS, State) & (State != 0) &
        match.match_none(Match) &
        action.load(LSP[LSP_PORTID],
                    NXM_Reg(REG_DST_IDX), Action1) &
        action.resubmit_table(TABLE_LSP_EGRESS_FIRST, Action2) &
        (Action == Action1 + Action2)
        )

    if options.has_key('ONDEMAND'):
        # ovs must upload this packet to controller if cannot found the
        # destination. controller will tell tuplenet to generate more flows
        lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
            (Priority == 0) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.match_none(Match) &
            action.upload_unknow_dst(Action1) &
            # resubmit this packet to next stage, gateway host can
            # do delivering if gateway enable redirect feature
            action.load(st.TP_OFPORT_NONE, NXM_Reg(REG_OUTPORT_IDX), Action2) &
            action.load(1, NXM_Reg(REG5_IDX), Action3) &
            action.resubmit_next(Action4) &
            (Action == Action1 + Action2 + Action3 + Action4)
            )

    else:
        # deliver packet to drop table if this packet cannot
        # found the destination.
        lsp_lookup_dst_port(LS, Priority, Match, Action, State) <= (
            (Priority == 0) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.match_none(Match) &
            action.resubmit_table(TABLE_DROP_PACKET, Action)
            )

    if options.has_key('ENABLE_REDIRECT'):
        # if it is a redirectd packet and reg4 is 0xffff, then we should drop
        # it, because we don't want cause infinite loop
        lsp_output_dst_port(LS, Priority, Match, Action, State) <= (
            (Priority == 4) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.reg_5(1, Match1) &
            match.reg_flag(FLAG_REDIRECT, Match2) &
            match.reg_outport(st.TP_OFPORT_NONE, Match3) &
            (Match == Match1 + Match2 + Match3) &
            action.resubmit_table(TABLE_DROP_PACKET, Action)
            )

        # if this packet was failed to deliver to remote chassis, we send it to
        # other gateway to help forwarding
        lsp_output_dst_port(LS, Priority, Match, Action, State) <= (
            (Priority == 3) &
            ls_array(LS, UUID_LS, State) & (State != 0) &
            match.reg_5(1, Match1) &
            match.reg_outport(st.TP_OFPORT_NONE, Match2) &
            (Match == Match1 + Match2) &
            action.resubmit_table(TABLE_REDIRECT_CHASSIS, Action)
            )

    # output to a port base on reg4's value
    lsp_output_dst_port(LS, Priority, Match, Action, State) <= (
        (Priority == 2) &
        ls_array(LS, UUID_LS, State) &  (State != 0) &
        match.reg_5(1, Match) &
        action.resubmit_table(TABLE_EMBED2_METADATA, Action1) &
        action.resubmit_table(TABLE_OUTPUT_PKT, Action2) &
        (Action == Action1 + Action2)
        )

    # just deliver to next stage
    lsp_output_dst_port(LS, Priority, Match, Action, State) <= (
        (Priority == 1) &
        ls_array(LS, UUID_LS, State) & (State != 0) &
        match.match_none(Match) &
        action.resubmit_table(TABLE_LSP_EGRESS_FIRST, Action)
        )
Ejemplo n.º 4
0
    action.move(NXM_Reg(TUN_ID_IDX, 0, 23),
                NXM_Reg(REG_DP_IDX, 0, 23), Action1) &
    action.move(NXM_Reg(TUN_METADATA0_IDX, 0, 15),
                NXM_Reg(REG_SRC_IDX, 0, 15), Action2) &
    action.move(NXM_Reg(TUN_METADATA0_IDX, 16, 31),
                NXM_Reg(REG_DST_IDX, 0, 15), Action3) &
    action.move(NXM_Reg(TUN_METADATA0_IDX, 32, 63),
                NXM_Reg(REG_FLAG_IDX, 0, 31), Action4) &
    (Action == Action1 + Action2 + Action3 + Action4)
    )

pipeline_forward(Priority, Match, Action) <= (
    (Priority == 1) &
    match.ip_proto(Match1) &
    # a ip packet with 00 macaddress means it was a redirect packet which
    # send out by other host, deliver this packet to LR to help redirect
    match.eth_dst("00:00:00:00:00:00", Match2) &
    match.reg_flag(FLAG_REDIRECT, Match3) &
    (Match == Match1 + Match2 + Match3) &
    # TABLE_LRP_INGRESS_FIRST table is a tracing-point
    # as well and dec_ttl, skip that table
    action.resubmit_table(TABLE_LRP_INGRESS_IP_ROUTE, Action)
    )

# it is a regular packet, foward to lsp egress table immediately
pipeline_forward(Priority, Match, Action) <= (
    (Priority == 0) &
    match.match_none(Match) &
    action.resubmit_table(TABLE_LSP_EGRESS_FIRST, Action)
    )