Beispiel #1
0
 def _make_bum_match(self, metadata):
     match = self.parser.OFPMatch()
     match.set_metadata(metadata)
     encoded_mac = mac_api.haddr_to_bin(mac_api.DONTCARE_STR)
     encoded_mask = mac_api.haddr_to_bin(mac_api.UNICAST)
     match.set_dl_dst_masked(encoded_mac, encoded_mask)
     return match
Beispiel #2
0
def to_actions(dp, acts):
    actions = []
    for a in acts:
        action_type = a.get('type')
        if action_type == 'OUTPUT':
            port = UTIL.ofp_port_from_user(
                a.get('port', ofproto_v1_0.OFPP_NONE))
            # NOTE: The reason of this magic number (0xffe5)
            #       is because there is no good constant in of1.0.
            #       The same value as OFPCML_MAX of of1.2 and of1.3 is used.
            max_len = str_to_int(a.get('max_len', 0xffe5))
            actions.append(dp.ofproto_parser.OFPActionOutput(port, max_len))
        elif action_type == 'SET_VLAN_VID':
            vlan_vid = str_to_int(a.get('vlan_vid', 0xffff))
            actions.append(dp.ofproto_parser.OFPActionVlanVid(vlan_vid))
        elif action_type == 'SET_VLAN_PCP':
            vlan_pcp = str_to_int(a.get('vlan_pcp', 0))
            actions.append(dp.ofproto_parser.OFPActionVlanPcp(vlan_pcp))
        elif action_type == 'STRIP_VLAN':
            actions.append(dp.ofproto_parser.OFPActionStripVlan())
        elif action_type == 'SET_DL_SRC':
            dl_src = haddr_to_bin(a.get('dl_src'))
            actions.append(dp.ofproto_parser.OFPActionSetDlSrc(dl_src))
        elif action_type == 'SET_DL_DST':
            dl_dst = haddr_to_bin(a.get('dl_dst'))
            actions.append(dp.ofproto_parser.OFPActionSetDlDst(dl_dst))
        elif action_type == 'SET_NW_SRC':
            nw_src = ipv4_to_int(a.get('nw_src'))
            actions.append(dp.ofproto_parser.OFPActionSetNwSrc(nw_src))
        elif action_type == 'SET_NW_DST':
            nw_dst = ipv4_to_int(a.get('nw_dst'))
            actions.append(dp.ofproto_parser.OFPActionSetNwDst(nw_dst))
        elif action_type == 'SET_NW_TOS':
            nw_tos = str_to_int(a.get('nw_tos', 0))
            actions.append(dp.ofproto_parser.OFPActionSetNwTos(nw_tos))
        elif action_type == 'SET_TP_SRC':
            tp_src = str_to_int(a.get('tp_src', 0))
            actions.append(dp.ofproto_parser.OFPActionSetTpSrc(tp_src))
        elif action_type == 'SET_TP_DST':
            tp_dst = str_to_int(a.get('tp_dst', 0))
            actions.append(dp.ofproto_parser.OFPActionSetTpDst(tp_dst))
        elif action_type == 'ENQUEUE':
            port = UTIL.ofp_port_from_user(
                a.get('port', ofproto_v1_0.OFPP_NONE))
            queue_id = UTIL.ofp_queue_from_user(a.get('queue_id', 0))
            actions.append(dp.ofproto_parser.OFPActionEnqueue(port, queue_id))
        else:
            LOG.error('Unknown action type')

    return actions
Beispiel #3
0
    def _add_local_port_dispatch(self, lport):
        lport_id = lport.id
        mac = lport.mac
        port_key = lport.unique_key
        network_id = lport.lswitch.unique_key
        topic = lport.topic

        parser = self.parser
        ofproto = self.ofproto

        # Go to dispatch table according to unique metadata & mac
        match = parser.OFPMatch()
        match.set_metadata(network_id)
        match.set_dl_dst(haddr_to_bin(mac))
        actions = [parser.OFPActionSetField(reg7=port_key)]
        action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                   actions)
        goto_inst = parser.OFPInstructionGotoTable(
            const.INGRESS_CONNTRACK_TABLE)
        inst = [action_inst, goto_inst]
        self.mod_flow(inst=inst,
                      table_id=const.INGRESS_DESTINATION_PORT_LOOKUP_TABLE,
                      priority=const.PRIORITY_HIGH,
                      match=match)

        # Egress classifier for port
        match = parser.OFPMatch(reg7=port_key)
        inst = [parser.OFPInstructionGotoTable(const.INGRESS_CONNTRACK_TABLE)]
        self.mod_flow(inst=inst,
                      table_id=const.EGRESS_TABLE,
                      priority=const.PRIORITY_MEDIUM,
                      match=match)
        self._add_multicast_broadcast_handling_for_local_port(
            lport_id, port_key, network_id, topic)
Beispiel #4
0
    def add_flow(self, datapath, in_port, dst, src, actions):
        ofproto = datapath.ofproto

        match = datapath.ofproto_parser.OFPMatch(in_port=in_port,
                                                 dl_dst=haddr_to_bin(dst),
                                                 dl_src=haddr_to_bin(src))

        mod = datapath.ofproto_parser.OFPFlowMod(
            datapath=datapath,
            match=match,
            cookie=0,
            command=ofproto.OFPFC_ADD,
            idle_timeout=0,
            hard_timeout=0,
            priority=ofproto.OFP_DEFAULT_PRIORITY,
            flags=ofproto.OFPFF_SEND_FLOW_REM,
            actions=actions)
        datapath.send_msg(mod)
Beispiel #5
0
 def _delete_dst_classifier_flow_for_port(self, network_id, mac):
     parser = self.parser
     ofproto = self.ofproto
     match = parser.OFPMatch()
     match.set_metadata(network_id)
     match.set_dl_dst(haddr_to_bin(mac))
     self.mod_flow(table_id=const.L2_LOOKUP_TABLE,
                   command=ofproto.OFPFC_DELETE,
                   priority=const.PRIORITY_MEDIUM,
                   match=match)
Beispiel #6
0
def mac_addr_all_zeros(mac_addr):
    """Returns True if mac_addr is all zeros.

    Args:
        mac_addr (str): MAC address.
    Returns:
        bool: True if all zeros.
    """
    mac_bin = haddr_to_bin(mac_addr)
    return mac_bin == DONTCARE
Beispiel #7
0
def mac_addr_is_unicast(mac_addr):
    """Returns True if mac_addr is a unicast Ethernet address.

    Args:
        mac_addr (str): MAC address.
    Returns:
        bool: True if a unicast Ethernet address.
    """
    mac_bin = haddr_to_bin(mac_addr)
    if mac_bin == BROADCAST:
        return False
    return not is_multicast(mac_bin)
Beispiel #8
0
    def _delete_router_port(self, router, router_port):
        """
        Handle the removal of a router interface from a router. Undoes the
        actions in #_add_new_router_port.
        :param router:        The router on which the interface is removed
        :type router:         LogicalRouter model object
        :param router_port:   The router interface being removed
        :type router_port:    RouterInterface model object
        """
        LOG.info("Removing logical router interface = %s",
                 router_port)
        local_network_id = router_port.lswitch.unique_key

        parser = self.parser
        ofproto = self.ofproto
        router_unique_key = router.unique_key
        ip = router_port.network.ip
        mac = router_port.mac

        # Delete rule for making packets go from L2_LOOKUP_TABLE
        # to L3_LOOKUP_TABLE
        match = parser.OFPMatch()
        match.set_metadata(local_network_id)
        match.set_dl_dst(os_ken_mac_lib.haddr_to_bin(mac))
        self.mod_flow(
            table_id=const.L2_LOOKUP_TABLE,
            command=ofproto.OFPFC_DELETE,
            priority=const.PRIORITY_HIGH,
            match=match)

        # Delete ARP & ICMP responder for router interface
        if ip.version == common_const.IP_VERSION_4:
            arp_responder.ArpResponder(self, local_network_id, ip).remove()
            icmp_responder.ICMPResponder(self, ip,
                                         router_key=router_unique_key).remove()

        # Delete rule for packets whose destination is router interface.
        match = self._get_router_interface_match(router_unique_key, ip)
        self.mod_flow(
            table_id=const.L3_LOOKUP_TABLE,
            command=ofproto.OFPFC_DELETE,
            priority=const.PRIORITY_HIGH,
            match=match)

        # Delete rule for routing packets to subnet of this router port
        match = self._get_router_route_match(router_unique_key,
                                             router_port.network)
        self.mod_flow(
            table_id=const.L3_LOOKUP_TABLE,
            command=ofproto.OFPFC_DELETE,
            priority=const.PRIORITY_MEDIUM,
            match=match)
Beispiel #9
0
    def _add_dst_classifier_flow_for_port(self, network_id, mac, port_key):
        parser = self.parser
        ofproto = self.ofproto

        match = parser.OFPMatch()
        match.set_metadata(network_id)
        match.set_dl_dst(haddr_to_bin(mac))
        actions = [parser.OFPActionSetField(reg7=port_key)]
        action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                   actions)
        goto_inst = parser.OFPInstructionGotoTable(const.EGRESS_TABLE)
        inst = [action_inst, goto_inst]
        self.mod_flow(inst=inst,
                      table_id=const.L2_LOOKUP_TABLE,
                      priority=const.PRIORITY_MEDIUM,
                      match=match)
Beispiel #10
0
    def _remove_local_port_pipeline_interface(self, lport):
        parser = self.parser
        ofproto = self.ofproto
        local_network_id = lport.lswitch.unique_key

        # Remove egress classifier for port
        match = parser.OFPMatch(reg7=lport.unique_key)
        self.mod_flow(table_id=const.EGRESS_TABLE,
                      command=ofproto.OFPFC_DELETE,
                      priority=const.PRIORITY_MEDIUM,
                      match=match)

        # Remove ingress destination lookup for port
        match = parser.OFPMatch()
        match.set_metadata(local_network_id)
        match.set_dl_dst(haddr_to_bin(lport.mac))
        self.mod_flow(table_id=const.INGRESS_DESTINATION_PORT_LOOKUP_TABLE,
                      command=ofproto.OFPFC_DELETE,
                      priority=const.PRIORITY_HIGH,
                      match=match)

        # Update multicast and broadcast
        self._del_multicast_broadcast_handling_for_local(
            lport.id, lport.topic, local_network_id)
Beispiel #11
0
 def _get_multicast_broadcast_match(self, network_id):
     match = self.parser.OFPMatch(eth_dst='01:00:00:00:00:00')
     addint = haddr_to_bin('01:00:00:00:00:00')
     match.set_dl_dst_masked(addint, addint)
     match.set_metadata(network_id)
     return match
Beispiel #12
0
def to_match(dp, attrs):
    ofp = dp.ofproto

    wildcards = ofp.OFPFW_ALL
    in_port = 0
    dl_src = 0
    dl_dst = 0
    dl_vlan = 0
    dl_vlan_pcp = 0
    dl_type = 0
    nw_tos = 0
    nw_proto = 0
    nw_src = 0
    nw_dst = 0
    tp_src = 0
    tp_dst = 0

    for key, value in attrs.items():
        if key == 'in_port':
            in_port = UTIL.ofp_port_from_user(value)
            wildcards &= ~ofp.OFPFW_IN_PORT
        elif key == 'dl_src':
            dl_src = haddr_to_bin(value)
            wildcards &= ~ofp.OFPFW_DL_SRC
        elif key == 'dl_dst':
            dl_dst = haddr_to_bin(value)
            wildcards &= ~ofp.OFPFW_DL_DST
        elif key == 'dl_vlan':
            dl_vlan = str_to_int(value)
            wildcards &= ~ofp.OFPFW_DL_VLAN
        elif key == 'dl_vlan_pcp':
            dl_vlan_pcp = str_to_int(value)
            wildcards &= ~ofp.OFPFW_DL_VLAN_PCP
        elif key == 'dl_type':
            dl_type = str_to_int(value)
            wildcards &= ~ofp.OFPFW_DL_TYPE
        elif key == 'nw_tos':
            nw_tos = str_to_int(value)
            wildcards &= ~ofp.OFPFW_NW_TOS
        elif key == 'nw_proto':
            nw_proto = str_to_int(value)
            wildcards &= ~ofp.OFPFW_NW_PROTO
        elif key == 'nw_src':
            ip = value.split('/')
            nw_src = struct.unpack('!I', socket.inet_aton(ip[0]))[0]
            mask = 32
            if len(ip) == 2:
                mask = int(ip[1])
                assert 0 < mask <= 32
            v = (32 - mask) << ofp.OFPFW_NW_SRC_SHIFT | \
                ~ofp.OFPFW_NW_SRC_MASK
            wildcards &= v
        elif key == 'nw_dst':
            ip = value.split('/')
            nw_dst = struct.unpack('!I', socket.inet_aton(ip[0]))[0]
            mask = 32
            if len(ip) == 2:
                mask = int(ip[1])
                assert 0 < mask <= 32
            v = (32 - mask) << ofp.OFPFW_NW_DST_SHIFT | \
                ~ofp.OFPFW_NW_DST_MASK
            wildcards &= v
        elif key == 'tp_src':
            tp_src = str_to_int(value)
            wildcards &= ~ofp.OFPFW_TP_SRC
        elif key == 'tp_dst':
            tp_dst = str_to_int(value)
            wildcards &= ~ofp.OFPFW_TP_DST
        else:
            LOG.error("unknown match name %s, %s, %d", key, value, len(key))

    match = dp.ofproto_parser.OFPMatch(
        wildcards, in_port, dl_src, dl_dst, dl_vlan, dl_vlan_pcp,
        dl_type, nw_tos, nw_proto, nw_src, nw_dst, tp_src, tp_dst)

    return match
Beispiel #13
0
 def _make_bum_match(self, **kwargs):
     match = self.parser.OFPMatch(**kwargs)
     bum_addr = mac_api.haddr_to_bin(mac_api.UNICAST)
     match.set_dl_dst_masked(bum_addr, bum_addr)
     return match
Beispiel #14
0
 def haddr_to_bin(self, string):
     return mac.haddr_to_bin(string)
Beispiel #15
0
class RunTestMininet(app_manager.OSKenApp):

    _CONTEXTS = {'dpset': dpset.DPSet}
    OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]

    ZERO_MAC = mac.haddr_to_bin('00:00:00:00:00:00')
    BROADCAST_MAC = mac.haddr_to_bin('ff:ff:ff:ff:ff:ff')
    OSKEN_MAC = mac.haddr_to_bin('fe:ee:ee:ee:ee:ef')
    HOST_MAC = mac.haddr_to_bin('00:00:00:00:00:01')
    OSKEN_IP = int(netaddr.IPAddress('10.0.0.100'))
    HOST_IP = int(netaddr.IPAddress('10.0.0.1'))

    def __init__(self, *args, **kwargs):
        super(RunTestMininet, self).__init__(*args, **kwargs)

    def _send_msg(self, dp, data):
        buffer_id = 0xffffffff
        in_port = dp.ofproto.OFPP_LOCAL
        actions = [dp.ofproto_parser.OFPActionOutput(1, 0)]
        msg = dp.ofproto_parser.OFPPacketOut(dp, buffer_id, in_port, actions,
                                             data)
        dp.send_msg(msg)

    def _add_flow(self, dp, match, actions):
        inst = [
            dp.ofproto_parser.OFPInstructionActions(
                dp.ofproto.OFPIT_APPLY_ACTIONS, actions)
        ]
        mod = dp.ofproto_parser.OFPFlowMod(dp,
                                           cookie=0,
                                           cookie_mask=0,
                                           table_id=0,
                                           command=dp.ofproto.OFPFC_ADD,
                                           idle_timeout=0,
                                           hard_timeout=0,
                                           priority=0xff,
                                           buffer_id=0xffffffff,
                                           out_port=dp.ofproto.OFPP_ANY,
                                           out_group=dp.ofproto.OFPG_ANY,
                                           flags=0,
                                           match=match,
                                           instructions=inst)
        dp.send_msg(mod)

    def _find_protocol(self, pkt, name):
        for p in pkt.protocols:
            if hasattr(p, 'protocol_name'):
                if p.protocol_name == name:
                    return p

    def _get_protocols(self, pkt):
        protocols = {}
        for p in pkt:
            if hasattr(p, 'protocol_name'):
                protocols[p.protocol_name] = p
            else:
                protocols['payload'] = p
        return protocols

    def _build_ether(self, ethertype, dst_mac=HOST_MAC):
        e = ethernet.ethernet(dst_mac, self.OSKEN_MAC, ethertype)
        return e

    def _build_arp(self, opcode, dst_ip=HOST_IP):
        if opcode == arp.ARP_REQUEST:
            _eth_dst_mac = self.BROADCAST_MAC
            _arp_dst_mac = self.ZERO_MAC
        elif opcode == arp.ARP_REPLY:
            _eth_dst_mac = self.HOST_MAC
            _arp_dst_mac = self.HOST_MAC

        e = self._build_ether(ether.ETH_TYPE_ARP, _eth_dst_mac)
        a = arp.arp(hwtype=1,
                    proto=ether.ETH_TYPE_IP,
                    hlen=6,
                    plen=4,
                    opcode=opcode,
                    src_mac=self.OSKEN_MAC,
                    src_ip=self.OSKEN_IP,
                    dst_mac=_arp_dst_mac,
                    dst_ip=dst_ip)
        p = packet.Packet()
        p.add_protocol(e)
        p.add_protocol(a)
        p.serialize()

        return p

    def _build_echo(self, _type, echo):
        e = self._build_ether(ether.ETH_TYPE_IP)
        ip = ipv4.ipv4(version=4,
                       header_length=5,
                       tos=0,
                       total_length=84,
                       identification=0,
                       flags=0,
                       offset=0,
                       ttl=64,
                       proto=inet.IPPROTO_ICMP,
                       csum=0,
                       src=self.OSKEN_IP,
                       dst=self.HOST_IP)
        ping = icmp.icmp(_type, code=0, csum=0, data=echo)

        p = packet.Packet()
        p.add_protocol(e)
        p.add_protocol(ip)
        p.add_protocol(ping)
        p.serialize()
        return p

    def _garp(self):
        p = self._build_arp(arp.ARP_REQUEST, self.OSKEN_IP)
        return p.data

    def _arp_request(self):
        p = self._build_arp(arp.ARP_REQUEST, self.HOST_IP)
        return p.data

    def _arp_reply(self):
        p = self._build_arp(arp.ARP_REPLY, self.HOST_IP)
        return p.data

    def _echo_request(self, echo):
        p = self._build_echo(icmp.ICMP_ECHO_REQUEST, echo)
        return p.data

    def _echo_reply(self, echo):
        p = self._build_echo(icmp.ICMP_ECHO_REPLY, echo)
        return p.data

    @handler.set_ev_cls(ofp_event.EventOFPPacketIn, handler.MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath

        pkt = packet.Packet(array.array('B', msg.data))
        p_arp = self._find_protocol(pkt, "arp")
        p_icmp = self._find_protocol(pkt, "icmp")
        p_ipv4 = self._find_protocol(pkt, "ipv4")

        if p_arp:
            src_ip = str(netaddr.IPAddress(p_arp.src_ip))
            dst_ip = str(netaddr.IPAddress(p_arp.dst_ip))
            if p_arp.opcode == arp.ARP_REQUEST:
                LOG.debug("--- PacketIn: ARP_Request: %s->%s", src_ip, dst_ip)
                if p_arp.dst_ip == self.OSKEN_IP:
                    LOG.debug("--- send Pkt: ARP_Reply")
                    data = self._arp_reply()
                    self._send_msg(dp, data)
                elif p_arp.dst_ip == self.HOST_IP:
                    LOG.debug("    PacketIn: GARP")
                    LOG.debug("--- send Pkt: ARP_Request")
                    data = self._arp_request()
                    self._send_msg(dp, data)
            elif p_arp.opcode == arp.ARP_REPLY:
                LOG.debug("--- PacketIn: ARP_Reply: %s->%s", src_ip, dst_ip)
                LOG.debug("--- send Pkt: Echo_Request")
                echo = icmp.echo(id_=66, seq=1)
                data = self._echo_request(echo)
                self._send_msg(dp, data)

        if p_icmp:
            src = str(netaddr.IPAddress(p_ipv4.src))
            dst = str(netaddr.IPAddress(p_ipv4.dst))
            if p_icmp.type == icmp.ICMP_ECHO_REQUEST:
                LOG.debug("--- PacketIn: Echo_Request: %s->%s", src, dst)
                if p_ipv4.dst == self.OSKEN_IP:
                    LOG.debug("--- send Pkt: Echo_Reply")
                    echo = p_icmp.data
                    echo.data = bytearray(echo.data)
                    data = self._echo_reply(echo)
                    self._send_msg(dp, data)
            elif p_icmp.type == icmp.ICMP_ECHO_REPLY:
                LOG.debug("--- PacketIn: Echo_Reply: %s->%s", src, dst)

    @handler.set_ev_cls(dpset.EventDP, dpset.DPSET_EV_DISPATCHER)
    def handler_datapath(self, ev):
        if ev.enter:
            dp = ev.dp

            LOG.debug("--- send Pkt: Gratuitous ARP_Request")
            data = self._garp()
            self._send_msg(dp, data)
Beispiel #16
0
    def _add_new_router_port(self, router, router_port):
        """
        Handle the creation of a new router interface on the router.
        * Match L2 address and update reg5
        * Install ARP and ICMP responders
        * Match packets with router as dst
        * Add flows for  new route entries
        :param router:        The router on which the interface is added
        :type router:         LogicalRouter model object
        :param router_port:   The router interface being added
        :type router_port:    RouterInterface model object
        """
        LOG.info("Adding new logical router interface = %r",
                 router_port)
        local_network_id = router_port.lswitch.unique_key

        parser = self.parser
        ofproto = self.ofproto

        mac = router_port.mac
        router_unique_key = router.unique_key
        dst_ip = router_port.network.ip
        is_ipv4 = (netaddr.IPAddress(dst_ip).version ==
                   common_const.IP_VERSION_4)

        # Add rule for making packets go from L2_LOOKUP_TABLE
        # to L3_LOOKUP_TABLE
        match = parser.OFPMatch()
        match.set_metadata(local_network_id)
        match.set_dl_dst(os_ken_mac_lib.haddr_to_bin(mac))
        actions = [parser.OFPActionSetField(reg5=router_unique_key)]
        action_inst = parser.OFPInstructionActions(
            ofproto.OFPIT_APPLY_ACTIONS, actions)
        goto_inst = parser.OFPInstructionGotoTable(const.L3_LOOKUP_TABLE)
        inst = [action_inst, goto_inst]
        self.mod_flow(
            inst=inst,
            table_id=const.L2_LOOKUP_TABLE,
            priority=const.PRIORITY_HIGH,
            match=match)

        # Add router ARP & ICMP responder for IPv4 Addresses
        if is_ipv4:
            arp_responder.ArpResponder(self,
                                       local_network_id,
                                       dst_ip, mac).add()
            icmp_responder.ICMPResponder(self,
                                         dst_ip,
                                         router_key=router_unique_key).add()

        # If router interface is not concrete, send to local controller. local
        # controller will create icmp unreachable message. A virtual router
        # interface will not be in local cache, as it doesn't have chassis
        # information.
        lport = self.db_store.get_one(l2.LogicalPort(id=router_port.id))
        if not lport:
            match = self._get_router_interface_match(router_unique_key, dst_ip)
            actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                              ofproto.OFPCML_NO_BUFFER)]
            action_inst = parser.OFPInstructionActions(
                ofproto.OFPIT_APPLY_ACTIONS, actions)
            self.mod_flow(
                inst=[action_inst],
                table_id=const.L3_LOOKUP_TABLE,
                priority=const.PRIORITY_HIGH,
                match=match)
        else:
            self._add_concrete_router_interface(lport, router=router)

        # Add rule for routing packets to subnet of this router port
        match = self._get_router_route_match(router_unique_key,
                                             router_port.network)
        self._add_subnet_send_to_route(match, local_network_id, router_port)