Example #1
0
    def _port_del(self, ev):
        # free mac addresses associated to this VM port,
        # and delete related flow entries for later reuse of mac address

        dps_needs_barrier = set()

        msg = ev.msg
        datapath = msg.datapath
        datapath_id = datapath.id
        port_no = msg.desc.port_no

        rule = nx_match.ClsRule()
        rule.set_in_port(port_no)
        datapath.send_flow_del(rule=rule, cookie=0)

        rule = nx_match.ClsRule()
        datapath.send_flow_del(rule=rule, cookie=0, out_port=port_no)
        dps_needs_barrier.add(datapath)

        try:
            port_nw_id = self.nw.get_network(datapath_id, port_no)
        except PortUnknown:
            # race condition between rest api delete port
            # and openflow port deletion ofp_event
            pass
        else:
            if port_nw_id in (NW_ID_UNKNOWN, NW_ID_EXTERNAL):
                datapath.send_barrier()
                return

        for mac_ in self.mac2port.mac_list(datapath_id, port_no):
            for (_dpid, dp) in self.dpset.get_all():
                if self.mac2port.port_get(dp.id, mac_) is None:
                    continue

                rule = nx_match.ClsRule()
                rule.set_dl_src(mac_)
                dp.send_flow_del(rule=rule, cookie=0)

                rule = nx_match.ClsRule()
                rule.set_dl_dst(mac_)
                dp.send_flow_del(rule=rule, cookie=0)
                dps_needs_barrier.add(dp)

                self.mac2port.mac_del(dp.id, mac_)

            self.mac2net.del_mac(mac_)

        self.nw.port_deleted(datapath.id, port_no)

        for dp in dps_needs_barrier:
            dp.send_barrier()
Example #2
0
    def state_change_handler(self, ev):
        dp = ev.datapath
        assert dp is not None
        LOG.debug(dp)

        if ev.state == MAIN_DISPATCHER:
            self._register(dp)
            switch = self._get_switch(dp.id)
            LOG.debug('register %s', switch)
            self.send_event_to_observers(event.EventSwitchEnter(switch))

            if not self.link_discovery:
                return

            if self.install_flow:
                ofproto = dp.ofproto
                ofproto_parser = dp.ofproto_parser

                # TODO:XXX need other versions
                if ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
                    rule = nx_match.ClsRule()
                    rule.set_dl_dst(
                        addrconv.mac.text_to_bin(lldp.LLDP_MAC_NEAREST_BRIDGE))
                    rule.set_dl_type(ETH_TYPE_LLDP)
                    actions = [
                        ofproto_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                                       self.LLDP_PACKET_LEN)
                    ]
                    dp.send_flow_mod(rule=rule,
                                     cookie=0,
                                     command=ofproto.OFPFC_ADD,
                                     idle_timeout=0,
                                     hard_timeout=0,
                                     actions=actions)
                else:
                    LOG.error('cannot install flow. unsupported version. %x',
                              dp.ofproto.OFP_VERSION)

            for port in switch.ports:
                if not port.is_reserved():
                    self._port_added(port)
            self.lldp_event.set()

        elif ev.state == DEAD_DISPATCHER:
            # dp.id is None when datapath dies before handshake
            if dp.id is None:
                return
            switch = self._get_switch(dp.id)
            self._unregister(dp)
            LOG.debug('unregister %s', switch)
            self.send_event_to_observers(event.EventSwitchLeave(switch))

            if not self.link_discovery:
                return

            for port in switch.ports:
                if not port.is_reserved():
                    self.ports.del_port(port)
                    self._link_down(port)
            self.lldp_event.set()
Example #3
0
    def test_rule_set_in_port(self, dp):
        in_port = 32
        self._verify = ['in_port', in_port]

        rule = nx_match.ClsRule()
        rule.set_in_port(in_port)
        self.add_rule(dp, rule)
Example #4
0
    def test_rule_set_dl_type_lacp(self, dp):
        dl_type = ether.ETH_TYPE_SLOW
        self._verify = ['dl_type', dl_type]

        rule = nx_match.ClsRule()
        rule.set_dl_type(dl_type)
        self.add_rule(dp, rule)
Example #5
0
    def add_action(self, dp, action, rule = None):
        if rule is None:
            rule = nx_match.ClsRule()

        self.send_flow_mod(
                dp, rule, 0, dp.ofproto.OFPFC_ADD, 0, 0, None,
                0xffffffff, None, dp.ofproto.OFPFF_SEND_FLOW_REM, action)
    def _pre_install_flow_entry(self, switch):
        # 'switch' is a Switch object

        # add flow entry for BGP, both IPv4 and IPv6
        rule4 = nx_match.ClsRule()
        rule4.set_dl_type(ether.ETH_TYPE_IP)
        rule4.set_nw_proto(inet.IPPROTO_TCP)
        rule4.set_tp_dst(BGP4.BGP_TCP_PORT)

        rule6 = nx_match.ClsRule()
        rule6.set_dl_type(ether.ETH_TYPE_IPV6)
        rule6.set_nw_proto(inet.IPPROTO_TCP)
        rule6.set_tp_dst(BGP4.BGP_TCP_PORT)

        actions = []
        actions.append(
            switch.dp.ofproto_parser.OFPActionOutput(
                port=ofproto_v1_0.OFPP_CONTROLLER,
                # 0 means "omit all the packet content", and
                # 65535(0xffff) is the max len could be assigned
                max_len=65535))

        msg4 = switch.dp.ofproto_parser.NXTFlowMod(
            datapath=switch.dp,
            cookie=0,
            command=switch.dp.ofproto.OFPFC_MODIFY,
            # 0 timeout means no timeout
            idle_timeout=0,
            hard_timeout=0,
            out_port=ofproto_v1_0.OFPP_CONTROLLER,
            rule=rule4,
            actions=actions)

        msg6 = switch.dp.ofproto_parser.NXTFlowMod(
            datapath=switch.dp,
            cookie=0,
            command=switch.dp.ofproto.OFPFC_MODIFY,
            idle_timeout=0,
            hard_timeout=0,
            out_port=ofproto_v1_0.OFPP_CONTROLLER,
            rule=rule6,
            actions=actions)

        switch.dp.send_msg(msg4)
        switch.dp.send_msg(msg6)

        LOG.debug('Pre-installed flow entry')
Example #7
0
    def test_rule_set_dl_src(self, dp):
        dl_src = 'b8:a1:94:51:78:83'
        dl_src_bin = self.haddr_to_bin(dl_src)
        self._verify = ['dl_src', dl_src_bin]

        rule = nx_match.ClsRule()
        rule.set_dl_src(dl_src_bin)
        self.add_rule(dp, rule)
Example #8
0
 def _port_flow_add(self, dp, port_no):
     self.logger.debug('ovs_port_update dpid %s port_no %s',
                       dpid_lib.dpid_to_str(dp.id), port_no)
     rule = nx_match.ClsRule()
     rule.set_in_port(port_no)
     ofproto = dp.ofproto
     actions = [dp.ofproto_parser.OFPActionOutput(ofproto.OFPP_NORMAL)]
     dp.send_flow_mod(rule=rule, cookie=self._COOKIE_NORMAL,
                      command=ofproto.OFPFC_ADD,
                      idle_timeout=0, hard_timeout=0,
                      priority=self._PRIORITY_NORMAL, actions=actions)
Example #9
0
    def port_state_change_handler(self, ev):
        dp = ev.datapath
        assert dp is not None
        LOG.debug(dp)

        ev.state = MAIN_DISPATCHER
        self.install_flow = True
        if self.install_flow:
            ofproto = dp.ofproto
            ofproto_parser = dp.ofproto_parser

            # TODO:XXX need other versions
            if ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
                rule = nx_match.ClsRule()
                rule.set_dl_dst(
                    addrconv.mac.text_to_bin(lldp.LLDP_MAC_NEAREST_BRIDGE))
                rule.set_dl_type(ETH_TYPE_LLDP)
                actions = [
                    ofproto_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                                   self.LLDP_PACKET_LEN)
                ]
                dp.send_flow_mod(rule=rule,
                                 cookie=self.LLDP_FLOW_COOKIE,
                                 command=ofproto.OFPFC_ADD,
                                 idle_timeout=0,
                                 hard_timeout=0,
                                 actions=actions,
                                 priority=0xFFFF)
            elif ofproto.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
                match = ofproto_parser.OFPMatch(
                    eth_type=ETH_TYPE_LLDP,
                    eth_dst=lldp.LLDP_MAC_NEAREST_BRIDGE)
                # OFPCML_NO_BUFFER is set so that the LLDP is not
                # buffered on switch
                parser = ofproto_parser
                actions = [
                    parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                           ofproto.OFPCML_NO_BUFFER)
                ]
                inst = [
                    parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                 actions)
                ]
                mod = parser.OFPFlowMod(datapath=dp,
                                        match=match,
                                        cookie=self.LLDP_FLOW_COOKIE,
                                        idle_timeout=0,
                                        hard_timeout=0,
                                        instructions=inst,
                                        priority=0xFFFF)
                dp.send_msg(mod)
            else:
                LOG.error('cannot install flow. unsupported version. %x',
                          dp.ofproto.OFP_VERSION)
Example #10
0
def cls_rule(in_port=None, tun_id=None, dl_src=None, dl_dst=None):
    """Convenience function to initialize nx_match.ClsRule()"""
    rule = nx_match.ClsRule()
    if in_port is not None:
        rule.set_in_port(in_port)
    if tun_id is not None:
        rule.set_tun_id(tun_id)
    if dl_src is not None:
        rule.set_dl_src(dl_src)
    if dl_dst is not None:
        rule.set_dl_dst(dl_dst)
    return rule
Example #11
0
 def send_delete_all_flows(self):
     rule = nx_match.ClsRule()
     self.send_flow_mod(rule=rule,
                        cookie=0,
                        command=self.ofproto.OFPFC_DELETE,
                        idle_timeout=0,
                        hard_timeout=0,
                        priority=0,
                        buffer_id=0,
                        out_port=self.ofproto.OFPP_NONE,
                        flags=0,
                        actions=None)
Example #12
0
    def packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto

        rule = nx_match.ClsRule()
        datapath.send_flow_mod(rule=rule,
                               cookie=0,
                               command=ofproto.OFPFC_ADD,
                               idle_timeout=0,
                               hard_timeout=0,
                               priority=ofproto.OFP_DEFAULT_PRIORITY,
                               flags=0,
                               actions=None)
Example #13
0
    def dp_handler(self, ev):
        if not ev.enter:
            return

        dp = ev.dp
        rule = nx_match.ClsRule()
        ofproto = dp.ofproto
        dp.send_flow_mod(rule=rule,
                         cookie=self._COOKIE_CATCHALL,
                         command=ofproto.OFPFC_ADD,
                         idle_timeout=0, hard_timeout=0,
                         priority=self._PRIORITY_CATCHALL,
                         actions=[])
        for port in ev.ports:
            self._port_add(dp, port.port_no)
Example #14
0
    def _modflow_and_send_packet(msg, src, dst, actions):
        datapath = msg.datapath
        ofproto = datapath.ofproto

        #
        # install flow and then send packet
        #
        rule = nx_match.ClsRule()
        rule.set_in_port(msg.in_port)
        rule.set_dl_dst(dst)
        rule.set_dl_src(src)
        datapath.send_flow_mod(
            rule=rule, cookie=0, command=datapath.ofproto.OFPFC_ADD,
            idle_timeout=0, hard_timeout=0,
            priority=ofproto.OFP_DEFAULT_PRIORITY,
            buffer_id=0xffffffff, out_port=ofproto.OFPP_NONE,
            flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)

        datapath.send_packet_out(msg.buffer_id, msg.in_port, actions)
Example #15
0
    def set_switch_flow(self, datapath, src_mac, k_id):
        dpid = datapath.id
        outport_list = self.Topo.switch_outport(src_mac, dpid, k_id)

        # Set rule
        rule = nx_match.ClsRule()
        rule.set_dl_type(ether.ETH_TYPE_IP)
        ## match camera MAC
        #rule.set_dl_src( haddr_to_bin(src_mac) )
        src_id = int(src_mac.replace(':', ''), 16)
        nw_src = self.Topo.convert_host_id_to_ip(src_id)
        rule.set_nw_src(self.ipv4_to_int(nw_src))
        ## match IP with descriptor K
        nw_dst = self.Topo.convert_k_id_to_ip(k_id)
        ## Discard IP phase 4: reserved for sender
        rule.set_nw_dst_masked(self.ipv4_to_int(nw_dst),
                               self.ipv4_to_int("255.255.255.0"))
        self.logger.info("!!! --- K = %s, dst_ip = %s", str(k_id), nw_dst)

        # Duplicate packet
        action_list = []
        for port in outport_list:
            action = datapath.ofproto_parser.OFPActionOutput(port)
            action_list.append(action)
            self.logger.info("!!! ----- Add port: %s", port)

            # Deal with different type of switch
            if len(action_list) > 0:
                # At least one output
                if self.Topo.switch_type(dpid) == 0:
                    # Switch - on the way
                    pass
                else:
                    # Switch - the last hop
                    # Set broadcast MAC
                    dl_dst = 'ff:ff:ff:ff:ff:ff'
                    dl_dst_bin = haddr_to_bin(dl_dst)
                    action = datapath.ofproto_parser.OFPActionSetDlDst(
                        dl_dst_bin)
                    action_list.append(action)

                # Send action
                self.add_action(datapath, action_list, rule=rule)
Example #16
0
def generate_add_flowmod(in_port=None):
    if in_port is None:
        in_port = 32
    rule = nx_match.ClsRule()
    rule.set_in_port(in_port)
    match_tuple = rule.match_tuple()
    match = ofproto_v1_0_parser.OFPMatch(*match_tuple)

    cookie = 0
    command = ofproto_v1_0.OFPFC_ADD
    idle_timeout = 0
    hard_timeout = 0
    priority = ofproto_v1_0.OFP_DEFAULT_PRIORITY
    buffer_id = 0xffffffff
    out_port = ofproto_v1_0.OFPP_NONE
    flags = 0
    actions = None
    datapath = OF_1_0_DATAPATH

    return ofproto_v1_0_parser.OFPFlowMod(datapath, match, cookie, command,
                                          idle_timeout, hard_timeout, priority,
                                          buffer_id, out_port, flags, actions)
Example #17
0
    def _packet_in_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto

        dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0)

        dpid = datapath.id
        self.mac2port.dpid_add(dpid)
        LOG.info("packet in %s %s %s %s", dpid, haddr_to_str(src),
                 haddr_to_str(dst), msg.in_port)

        self.mac2port.port_add(dpid, msg.in_port, src)
        out_port = self.mac2port.port_get(dpid, dst)

        if out_port == None:
            LOG.info("out_port not found")
            out_port = ofproto.OFPP_FLOOD

        actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]

        if out_port != ofproto.OFPP_FLOOD:
            rule = nx_match.ClsRule()
            rule.set_in_port(msg.in_port)
            rule.set_dl_dst(dst)
            rule.set_dl_type(nx_match.ETH_TYPE_IP)
            rule.set_nw_dscp(0)
            datapath.send_flow_mod(rule=rule,
                                   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_packet_out(msg.buffer_id, msg.in_port, actions)
    def state_change_handler(self, ev):
        dp = ev.datapath
        assert dp is not None
        LOG.debug(dp)

        if ev.state == MAIN_DISPATCHER:
            dp_multiple_conns = False
            if dp.id in self.dps:
                LOG.warning('Multiple connections from %s', dpid_to_str(dp.id))
                dp_multiple_conns = True
                (self.dps[dp.id]).close()

            self._register(dp)
            switch = self._get_switch(dp.id)
            LOG.debug('register %s', switch)

            if not dp_multiple_conns:
                self.send_event_to_observers(event.EventSwitchEnter(switch))
            else:
                evt = event.EventSwitchReconnected(switch)
                self.send_event_to_observers(evt)

            if not self.link_discovery:
                return

            if self.install_flow:
                ofproto = dp.ofproto
                ofproto_parser = dp.ofproto_parser

                # TODO:XXX need other versions
                if ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
                    rule = nx_match.ClsRule()
                    rule.set_dl_dst(
                        addrconv.mac.text_to_bin(lldp.LLDP_MAC_NEAREST_BRIDGE))
                    rule.set_dl_type(ETH_TYPE_LLDP)
                    actions = [
                        ofproto_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                                       self.LLDP_PACKET_LEN)
                    ]
                    dp.send_flow_mod(rule=rule,
                                     cookie=0,
                                     command=ofproto.OFPFC_ADD,
                                     idle_timeout=0,
                                     hard_timeout=0,
                                     actions=actions,
                                     priority=0xFFFF)
                elif ofproto.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
                    match = ofproto_parser.OFPMatch(
                        eth_type=ETH_TYPE_LLDP,
                        eth_dst=lldp.LLDP_MAC_NEAREST_BRIDGE)
                    # OFPCML_NO_BUFFER is set so that the LLDP is not
                    # buffered on switch
                    parser = ofproto_parser
                    actions = [
                        parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                               ofproto.OFPCML_NO_BUFFER)
                    ]
                    inst = [
                        parser.OFPInstructionActions(
                            ofproto.OFPIT_APPLY_ACTIONS, actions)
                    ]
                    mod = parser.OFPFlowMod(datapath=dp,
                                            match=match,
                                            idle_timeout=0,
                                            hard_timeout=0,
                                            instructions=inst,
                                            priority=0xFFFF)
                    dp.send_msg(mod)
                else:
                    LOG.error('cannot install flow. unsupported version. %x',
                              dp.ofproto.OFP_VERSION)

            # Do not add ports while dp has multiple connections to controller.
            if not dp_multiple_conns:
                for port in switch.ports:
                    if not port.is_reserved():
                        self._port_added(port)

            self.lldp_event.set()

        elif ev.state == DEAD_DISPATCHER:
            # dp.id is None when datapath dies before handshake
            if dp.id is None:
                return

            switch = self._get_switch(dp.id)
            if switch:
                if switch.dp is dp:
                    self._unregister(dp)
                    LOG.debug('unregister %s', switch)
                    evt = event.EventSwitchLeave(switch)
                    self.send_event_to_observers(evt)

                    if not self.link_discovery:
                        return

                    for port in switch.ports:
                        if not port.is_reserved():
                            self.ports.del_port(port)
                            self._link_down(port)
                    self.lldp_event.set()
Example #19
0
    def _send_location_req(self, tenant_id, vnid, vip, net):
        logging.debug('Send location-req %d:%d %s to %s', tenant_id, vnid, vip,
                      net['site_name'])
        fa_url = self._find_url(tenant_id, net['site_name'])
        auth = HTTPBasicAuth('admin', 'admin')
        headers = {
            'content-type': 'application/json',
            'Accept': 'application/json',
            'charsets': 'utf-8'
        }

        r = requests.post('http://' + fa_url + url_tenants + '/' +
                          str(net['tenant_id']) + '/location-req',
                          headers=headers,
                          auth=auth,
                          data=json.dumps({
                              "src_tenant_id": tenant_id,
                              "dst_tenant_id": net['tenant_id'],
                              "vnid": net['vnid'],
                              "vip": vip
                          }))

        if int(r.status_code) == 200:
            reply = r.json()
            validate(reply, location_reply_schema)

            pip = self.switch['datapath'].address[0]
            dp = self.switch['datapath']

            # send to SDN controller location update
            self.send_event(
                'FaSdnController',
                EventLocUpdateReq(pip, reply['vnid'], str(reply['vip']),
                                  str(reply['vmac'])))

            # Set outgoing flow in the datapath
            dp = self.switch['datapath']
            ofproto = dp.ofproto
            tunnel_port = self.tunnel_port
            parser = dp.ofproto_parser

            actions = []
            rule = nx_match.ClsRule()

            # hardware
            rule.set_in_port(tunnel_port.port_no)
            rule.set_dl_type(0x0800)

            # ip
            rule.set_nw_dst(ipv4_text_to_int(vip))
            #rule.set_nw_proto(packet[1].proto)
            #rule.set_nw_proto(4) # "ip"

            # encap
            rule.set_tun_id(
                vnid
            )  # We assume NET sends the source VNID in the VXLAN header for now

            # set tunnel key       SET_TUNNEL
            actions.append(dp.ofproto_parser.NXActionSetTunnel(net['vnid']))

            # set tunnel dst pIP   REG_LOAD
            actions.append(
                dp.ofproto_parser.NXActionRegLoad(
                    0x1f,  # ofs_nbits (ofs < 6 | nbits - 1)
                    0x014004,  # dst
                    ipv4_text_to_int(str(reply['pip']['ip']))))

            # forward              OUTPUT(PROXY)
            actions.append(
                dp.ofproto_parser.OFPActionOutput(ofproto.OFPP_IN_PORT))

            logging.debug('Set outgoing flow for %d:%s=>%s', net['vnid'], vip,
                          reply['pip']['ip'])

            dp.send_flow_mod(rule=rule,
                             cookie=0,
                             command=ofproto.OFPFC_ADD,
                             idle_timeout=0,
                             hard_timeout=0,
                             actions=actions)
Example #20
0
    def _add_flows_for_vnid(self, tenant_id, vnid, port):
        dp = self.net_switch_app.switch['datapath']
        ofproto = dp.ofproto
        tunnel_port = self.net_switch_app.tunnel_port
        parser = dp.ofproto_parser

        # Outbound flow
        actions = []
        rule = nx_match.ClsRule()

        # hardware
        command = ovs_vsctl.VSCtlCommand('get', ('Interface', port, 'ofport'))
        self.net_switch_app.vsctl.run_command([command])

        assert len(command.result) == 1
        ofport = command.result[0][0]

        rule.set_in_port(ofport)

        logging.debug("Set outbound flow for vnid %s(%s):", vnid,
                      self._vnid_uuid_to_vnid(vnid))

        for site in tenants_site_tables[tenant_id]:
            if site['name'] != self.my_site:

                remote_vnid = self._get_sites_vnid(site['name'], tenant_id,
                                                   vnid)
                remote_ip = str(site['site_proxy'][0]['ip'])

                # set tunnel key       SET_TUNNEL
                actions.append(
                    dp.ofproto_parser.NXActionSetTunnel(
                        self._vnid_uuid_to_vnid(remote_vnid)))
                # set tunnel dst pIP   REG_LOAD
                actions.append(
                    dp.ofproto_parser.NXActionRegLoad(
                        0x1f,  # ofs_nbits (ofs < 6 | nbits - 1)
                        0x014004,  # dst
                        ipv4_text_to_int(remote_ip)))

                # forward              OUTPUT(PROXY)
                actions.append(
                    dp.ofproto_parser.OFPActionOutput(tunnel_port.port_no))
                logging.debug(
                    '--------ACTION: vnid:%s(%s)=>site %s:vnid:%s(%s) via tunnel %s',
                    vnid, self._vnid_uuid_to_vnid(vnid), site['name'],
                    remote_vnid, self._vnid_uuid_to_vnid(remote_vnid),
                    site['site_proxy'][0]['ip'])

        res = dp.send_flow_mod(rule=rule,
                               cookie=0,
                               command=ofproto.OFPFC_ADD,
                               idle_timeout=0,
                               hard_timeout=0,
                               actions=actions)

        # Inbound flow
        actions = []
        rule = nx_match.ClsRule()

        rule.set_in_port(tunnel_port.port_no)
        rule.set_tun_id(self._vnid_uuid_to_vnid(vnid))

        # forward              OUTPUT to local SDN controller vnid port
        actions.append(dp.ofproto_parser.OFPActionOutput(ofport))
        logging.debug('Set inbound flow for %s(%s)=> local SDN port:%s', vnid,
                      self._vnid_uuid_to_vnid(vnid), ofport)

        res = dp.send_flow_mod(rule=rule,
                               cookie=0,
                               command=ofproto.OFPFC_ADD,
                               idle_timeout=0,
                               hard_timeout=0,
                               actions=actions)
Example #21
0
    def location_request(self, req, tenant_id, **kwargs):

        msg = json.loads(req.body)
        validate(msg, location_request_schema)

        logging.debug('Enter location_request with %s', msg)

        # send location request to controller
        reply = self.net_switch_app.send_request(
            EventLocationReq(msg['vnid'], str(msg['vip'])))

        # XXX return error code
        if reply.vIP == "0.0.0.0":
            return Response(content_type='application/json', status=500)

        # set incoming flow in the datapath
        dp = self.net_switch_app.switch['datapath']
        tunnel_port = self.net_switch_app.tunnel_port

        rule = nx_match.ClsRule()
        actions = []
        ofproto = dp.ofproto

        # hardware
        rule.set_in_port(tunnel_port.port_no)
        rule.set_dl_type(0x0800)

        # ip
        rule.set_nw_dst(ipv4_text_to_int(str(msg['vip'])))
        #rule.set_nw_proto(packet[1].proto)
        #rule.set_nw_proto(4) # "ip"

        # encap
        rule.set_tun_id(msg['vnid'])

        # set tunnel key       SET_TUNNEL
        actions.append(dp.ofproto_parser.NXActionSetTunnel(msg['vnid']))

        # set tunnel dst pIP   REG_LOAD
        actions.append(
            dp.ofproto_parser.NXActionRegLoad(
                0x1f,  # ofs_nbits (ofs < 6 | nbits - 1)
                0x014004,  # dst
                ipv4_text_to_int(reply.pIP)))

        # forward              OUTPUT(PROXY)
        actions.append(dp.ofproto_parser.OFPActionOutput(ofproto.OFPP_IN_PORT))

        logging.debug('Installing incoming flow for %d:%s=>%s', msg['vnid'],
                      msg['vip'], reply.pIP)

        dp.send_flow_mod(rule=rule,
                         cookie=0,
                         command=ofproto.OFPFC_ADD,
                         idle_timeout=0,
                         hard_timeout=0,
                         actions=actions)

        # Send reply to peer FA
        net_list = tenants_net_tables[tenant_id]['table'][msg['vnid']]

        vnid = ""
        for net in net_list:
            if net['tenant_id'] == msg['src_tenant_id']:
                vnid = net['vnid']

        if not vnid:
            raise RyuException("Can not find peer network")

        body = {
            "vnid": vnid,
            "vip": msg['vip'],
            "vmac": reply.vMAC,
            "tenant_id": msg['src_tenant_id'],
            "pip": {
                "ip": self.net_switch_app.switch['datapath'].address[0]
            }
        }

        body = json.dumps(body)
        return Response(content_type='application/json', body=body)
    def border_switch_out(self, msg, pkt, dst_switch, dst_reply, _4or6):
        """
        Deploy the flow table on border switch and send the packet from
        the initial switch.
        """
        if _4or6 == 4:
            ip_layer = self.find_packet(pkt, 'ipv4')
        else:
            ip_layer = self.find_packet(pkt, 'ipv6')

        initial_dp = msg.datapath
        initial_switch = self.dpid_to_switch[initial_dp.id]
        dp = dst_switch.dp
        ipDestAddr = netaddr.IPAddress(ip_layer.dst)
        macAddr = dst_switch.ip_to_mac[ipDestAddr][0]
        outport_no = dst_reply.outport_no

        if _4or6 == 4:
            # ip src exact match
            wildcards = ofproto_v1_0.OFPFW_ALL
            wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
            wildcards &= ~(0x3f << ofproto_v1_0.OFPFW_NW_DST_SHIFT)

            match = dp.ofproto_parser.OFPMatch(
                # because of wildcards, parameters other than dl_type
                # and nw_dst could be any value
                wildcards=wildcards,
                in_port=0,
                dl_src=0,
                dl_dst=0,
                dl_vlan=0,
                dl_vlan_pcp=0,
                dl_type=ether.ETH_TYPE_IP,
                nw_tos=0,
                nw_proto=0,
                nw_src=0,
                nw_dst=ipDestAddr.value,
                tp_src=0,
                tp_dst=0)
        else:
            rule = nx_match.ClsRule()
            rule.set_dl_type(ether.ETH_TYPE_IPV6)
            rule.set_ipv6_dst(struct.unpack('!8H', ipDestAddr.packed))

        actions = []
        actions.append(
            dp.ofproto_parser.OFPActionSetDlSrc(
                dst_switch.ports[outport_no].hw_addr.packed))
        actions.append(dp.ofproto_parser.OFPActionSetDlDst(macAddr.packed))
        actions.append(dp.ofproto_parser.OFPActionOutput(outport_no))

        if _4or6 == 4:
            mod = dp.ofproto_parser.OFPFlowMod(
                datapath=dp,
                match=match,
                cookie=0,
                command=dp.ofproto.OFPFC_MODIFY,
                idle_timeout=Routing.FLOW_IDLE_TIMEOUT,
                hard_timeout=Routing.FLOW_HARD_TIMEOUT,
                out_port=outport_no,
                actions=actions)
        else:
            mod = dp.ofproto_parser.NXTFlowMod(
                datapath=dp,
                cookie=0,
                command=dp.ofproto.OFPFC_MODIFY,
                idle_timeout=Routing.FLOW_IDLE_TIMEOUT,
                hard_timeout=Routing.FLOW_HARD_TIMEOUT,
                out_port=outport_no,
                rule=rule,
                actions=actions)

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

        dp.send_msg(mod)
        initial_dp.send_msg(out)
Example #23
0
 def _port_flow_del(self, dp, port_no):
     self.logger.debug('_port_flow_del dp %s port_no %d',
                       dpid_lib.dpid_to_str(dp.id), port_no)
     rule = nx_match.ClsRule()
     rule.set_in_port(port_no)
     dp.send_flow_del(rule=rule, cookie=self._COOKIE_NORMAL)
Example #24
0
    def packet_in_handler(self, ev):
        # LOG.debug('packet in ev %s msg %s', ev, ev.msg)
        msg = ev.msg
        datapath = msg.datapath

        dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0)

        try:
            port_nw_id = self.nw.get_network(datapath.id, msg.in_port)
        except PortUnknown:
            port_nw_id = NW_ID_UNKNOWN

        if port_nw_id != NW_ID_UNKNOWN:
            # Here it is assumed that the
            # (port <-> network id)/(mac <-> network id) relationship
            # is stable once the port is created. The port will be destroyed
            # before assigning new network id to the given port.
            # This is correct nova-network/nova-compute.
            try:
                # allow external -> known nw id change
                self.mac2net.add_mac(src, port_nw_id, NW_ID_EXTERNAL)
            except MacAddressDuplicated:
                LOG.warn(
                    'mac address %s is already in use.'
                    ' So (dpid %s, port %s) can not use it', haddr_to_str(src),
                    datapath.id, msg.in_port)
                #
                # should we install drop action pro-actively for future?
                #
                self._drop_packet(msg)
                return

        old_port = self.mac2port.port_add(datapath.id, msg.in_port, src)
        if old_port is not None and old_port != msg.in_port:
            # We really overwrite already learned mac address.
            # So discard already installed stale flow entry which conflicts
            # new port.
            rule = nx_match.ClsRule()
            rule.set_dl_dst(src)
            datapath.send_flow_mod(
                rule=rule,
                cookie=0,
                command=datapath.ofproto.OFPFC_DELETE,
                idle_timeout=0,
                hard_timeout=0,
                priority=datapath.ofproto.OFP_DEFAULT_PRIORITY,
                out_port=old_port)

            # to make sure the old flow entries are purged.
            datapath.send_barrier()

        src_nw_id = self.mac2net.get_network(src, NW_ID_UNKNOWN)
        dst_nw_id = self.mac2net.get_network(dst, NW_ID_UNKNOWN)

        # we handle multicast packet as same as broadcast
        broadcast = (dst == mac.BROADCAST) or mac.is_multicast(dst)
        out_port = self.mac2port.port_get(datapath.id, dst)

        #
        # there are several combinations:
        # in_port: known nw_id, external, unknown nw,
        # src mac: known nw_id, external, unknown nw,
        # dst mac: known nw_id, external, unknown nw, and broadcast/multicast
        # where known nw_id: is quantum network id
        #       external: means that these ports are connected to outside
        #       unknown nw: means that we don't know this port is bounded to
        #                   specific nw_id or external
        #       broadcast: the destination mac address is broadcast address
        #                  (or multicast address)
        #
        # Can the following logic be refined/shortened?
        #

        # When NW_ID_UNKNOWN is found, registering ports might be delayed.
        # So just drop only this packet and not install flow entry.
        # It is expected that when next packet arrives, the port is registers
        # with some network id

        if port_nw_id != NW_ID_EXTERNAL and port_nw_id != NW_ID_UNKNOWN:
            if broadcast:
                # flood to all ports of external or src_nw_id
                self._flood_to_nw_id(msg, src, dst, src_nw_id)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
                return
            elif src_nw_id == NW_ID_UNKNOWN:
                self._drop_packet(msg)
                return
            else:
                # src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                #
                # try learned mac check if the port is net_id
                # or
                # flood to all ports of external or src_nw_id
                self._learned_mac_or_flood_to_nw_id(msg, src, dst, src_nw_id,
                                                    out_port)

        elif port_nw_id == NW_ID_EXTERNAL:
            if src_nw_id != NW_ID_EXTERNAL and src_nw_id != NW_ID_UNKNOWN:
                if broadcast:
                    # flood to all ports of external or src_nw_id
                    self._flood_to_nw_id(msg, src, dst, src_nw_id)
                elif (dst_nw_id != NW_ID_EXTERNAL
                      and dst_nw_id != NW_ID_UNKNOWN):
                    if src_nw_id == dst_nw_id:
                        # try learned mac
                        # check if the port is external or same net_id
                        # or
                        # flood to all ports of external or src_nw_id
                        self._learned_mac_or_flood_to_nw_id(
                            msg, src, dst, src_nw_id, out_port)
                    else:
                        # should not occur?
                        LOG.debug("should this case happen?")
                        self._drop_packet(msg)
                elif dst_nw_id == NW_ID_EXTERNAL:
                    # try learned mac
                    # or
                    # flood to all ports of external or src_nw_id
                    self._learned_mac_or_flood_to_nw_id(
                        msg, src, dst, src_nw_id, out_port)
                else:
                    assert dst_nw_id == NW_ID_UNKNOWN
                    LOG.debug("Unknown dst_nw_id")
                    self._drop_packet(msg)
            elif src_nw_id == NW_ID_EXTERNAL:
                self._modflow_and_drop_packet(msg, src, dst)
            else:
                # should not occur?
                assert src_nw_id == NW_ID_UNKNOWN
                self._drop_packet(msg)
        else:
            # drop packets
            assert port_nw_id == NW_ID_UNKNOWN
            self._drop_packet(msg)
    def deploy_flow_entry(self, msg, pkt, switch_list, _4or6):
        """
            deploy flow entry into switch
            e.g. if 'switch_list' is [A, B, C], then this method will
                deploy flow entries A->B, B->C
        """
        # TODO
        # this method and last_switch_out should be restructured
        dp = msg.datapath
        length = len(switch_list)
        for i in xrange(length - 1):
            this_switch = switch_list[i]
            next_switch = switch_list[i + 1]
            outport_no = this_switch.peer_to_local_port[next_switch]
            if _4or6 == 4:
                ip_layer = self.find_packet(pkt, 'ipv4')
            else:
                ip_layer = self.find_packet(pkt, 'ipv6')

            ip_dst = netaddr.IPAddress(ip_layer.dst)
            outport = this_switch.ports[outport_no]
            mac_src = outport.hw_addr
            mac_dst = next_switch.ports[outport.peer_port_no].hw_addr
            if _4or6 == 4:
                # ip src exact match
                wildcards = ofproto_v1_0.OFPFW_ALL
                wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
                wildcards &= ~(0x3f << ofproto_v1_0.OFPFW_NW_DST_SHIFT)

                match = dp.ofproto_parser.OFPMatch(
                    # because of wildcards, parameters other than dl_type
                    # and nw_dst could be any value
                    wildcards=wildcards,
                    in_port=0,
                    dl_src=0,
                    dl_dst=0,
                    dl_vlan=0,
                    dl_vlan_pcp=0,
                    dl_type=ether.ETH_TYPE_IP,
                    nw_tos=0,
                    nw_proto=0,
                    nw_src=0,
                    nw_dst=ip_dst.value,
                    tp_src=0,
                    tp_dst=0)
            else:
                rule = nx_match.ClsRule()
                rule.set_dl_type(ether.ETH_TYPE_IPV6)
                rule.set_ipv6_dst(struct.unpack('!8H', ip_dst.packed))

            actions = []
            actions.append(dp.ofproto_parser.OFPActionSetDlSrc(mac_src.packed))
            actions.append(dp.ofproto_parser.OFPActionSetDlDst(mac_dst.packed))
            actions.append(dp.ofproto_parser.OFPActionOutput(outport_no))

            if _4or6 == 4:
                mod = dp.ofproto_parser.OFPFlowMod(
                    datapath=this_switch.dp,
                    match=match,
                    cookie=0,
                    command=dp.ofproto.OFPFC_MODIFY,
                    idle_timeout=Routing.FLOW_IDLE_TIMEOUT,
                    hard_timeout=Routing.FLOW_HARD_TIMEOUT,
                    out_port=outport_no,
                    actions=actions)
            else:
                mod = dp.ofproto_parser.NXTFlowMod(
                    datapath=this_switch.dp,
                    cookie=0,
                    command=dp.ofproto.OFPFC_MODIFY,
                    idle_timeout=Routing.FLOW_IDLE_TIMEOUT,
                    hard_timeout=Routing.FLOW_HARD_TIMEOUT,
                    out_port=outport_no,
                    rule=rule,
                    actions=actions)

            this_switch.dp.send_msg(mod)
            LOG.info('Flow entry deployed to %s', this_switch)

        # send packet out from the first switch
        switch = switch_list[0]
        next_switch = switch_list[1]
        outport_no = switch.peer_to_local_port[next_switch]

        outport = switch.ports[outport_no]
        mac_src = outport.hw_addr
        mac_dst = next_switch.ports[outport.peer_port_no].hw_addr
        actions = []
        actions.append(dp.ofproto_parser.OFPActionSetDlSrc(mac_src.packed))
        actions.append(dp.ofproto_parser.OFPActionSetDlDst(mac_dst.packed))
        actions.append(dp.ofproto_parser.OFPActionOutput(outport_no))

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

        switch.dp.send_msg(out)
    def last_switch_out(self, msg, pkt, outport_no, _4or6):
        """
        The packet has already reached the last switch and needs to be forwarded.
        Does NOT support output to routers out of the AS
        """
        if _4or6 == 4:
            ip_layer = self.find_packet(pkt, 'ipv4')
        else:
            ip_layer = self.find_packet(pkt, 'ipv6')

        dp = msg.datapath
        switch = self.dpid_to_switch[dp.id]
        ipDestAddr = netaddr.IPAddress(ip_layer.dst)

        LOG.debug('last_switch_out: switch %s, port_no %s', switch, outport_no)
        try:
            # TODO introduce ARP timeout
            mac_addr = switch.ip_to_mac[ipDestAddr][0]
        except KeyError:
            # don't know MAC address yet, send ARP/ICMP message
            # and temporarily store the packets
            if _4or6 == 4:
                self._send_arp_request(msg.datapath, outport_no, ipDestAddr)
            else:
                self._send_icmp_NS(msg.datapath, outport_no, ipDestAddr)
            switch.msg_buffer.append((msg, pkt, outport_no, _4or6))
            return False

        if _4or6 == 4:
            # ip src exact match
            wildcards = ofproto_v1_0.OFPFW_ALL
            wildcards &= ~ofproto_v1_0.OFPFW_DL_TYPE
            wildcards &= ~(0x3f << ofproto_v1_0.OFPFW_NW_DST_SHIFT)

            match = dp.ofproto_parser.OFPMatch(
                # because of wildcards, parameters other than dl_type
                # and nw_dst could be any value
                wildcards=wildcards,
                in_port=0,
                dl_src=0,
                dl_dst=0,
                dl_vlan=0,
                dl_vlan_pcp=0,
                dl_type=ether.ETH_TYPE_IP,
                nw_tos=0,
                nw_proto=0,
                nw_src=0,
                nw_dst=ipDestAddr.value,
                tp_src=0,
                tp_dst=0)
        else:
            rule = nx_match.ClsRule()
            rule.set_dl_type(ether.ETH_TYPE_IPV6)
            rule.set_ipv6_dst(struct.unpack('!8H', ipDestAddr.packed))

        actions = []
        actions.append(
            dp.ofproto_parser.OFPActionSetDlSrc(
                switch.ports[outport_no].hw_addr.packed))
        actions.append(dp.ofproto_parser.OFPActionSetDlDst(mac_addr.packed))
        actions.append(dp.ofproto_parser.OFPActionOutput(outport_no))

        if _4or6 == 4:
            mod = dp.ofproto_parser.OFPFlowMod(
                datapath=dp,
                match=match,
                cookie=0,
                command=dp.ofproto.OFPFC_MODIFY,
                idle_timeout=Routing.FLOW_IDLE_TIMEOUT,
                hard_timeout=Routing.FLOW_HARD_TIMEOUT,
                out_port=outport_no,
                actions=actions)
        else:
            mod = dp.ofproto_parser.NXTFlowMod(
                datapath=dp,
                cookie=0,
                command=dp.ofproto.OFPFC_MODIFY,
                idle_timeout=Routing.FLOW_IDLE_TIMEOUT,
                hard_timeout=Routing.FLOW_HARD_TIMEOUT,
                out_port=outport_no,
                rule=rule,
                actions=actions)

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

        dp.send_msg(mod)
        dp.send_msg(out)
        return True