示例#1
0
    def _wait_bpdu_timer(self):
        time_exceed = False

        while True:
            self.wait_timer_event = hub.Event()
            message_age = (self.designated_times.message_age
                           if self.designated_times else 0)
            timer = self.port_times.max_age - message_age
            timeout = hub.Timeout(timer)
            try:
                self.wait_timer_event.wait()
            except hub.Timeout as t:
                if t is not timeout:
                    err_msg = 'Internal error. Not my timeout.'
                    raise RyuException(msg=err_msg)
                self.logger.info('[port=%d] Wait BPDU timer is exceeded.',
                                 self.ofport.port_no, extra=self.dpid_str)
                time_exceed = True
            finally:
                timeout.cancel()
                self.wait_timer_event = None

            if time_exceed:
                break

        if time_exceed:  # Bridge.recalculate_spanning_tree
            hub.spawn(self.wait_bpdu_timeout)
示例#2
0
    def _wait(self):
        """ Wait until specific OFP message received
             or timer is exceeded. """
        assert self.waiter is None

        self.waiter = hub.Event()
        self.rcv_msgs = []
        timeout = False

        timer = hub.Timeout(WAIT_TIMER)
        try:
            self.waiter.wait()
        except hub.Timeout as t:
            if t is not timer:
                raise RyuException('Internal error. Not my timeout.')
            timeout = True
        finally:
            timer.cancel()

        self.waiter = None

        if timeout:
            raise TestTimeout(self.state)
        if (self.rcv_msgs and isinstance(self.rcv_msgs[0],
                                         ofproto_v1_3_parser.OFPErrorMsg)):
            raise TestReceiveError(self.state, self.rcv_msgs[0])
示例#3
0
    def do_handshake(self, site, version):
        site['handshake_state'] = 'PENDING'
        ipaddr = \
               self.net_switch_app.switch['datapath'].address[0]

        auth = HTTPBasicAuth('admin', 'admin')
        headers = {
            'content-type': 'application/json',
            'Accept': 'application/json',
            'charsets': 'utf-8'
        }

        r = requests.post('http://' + site['fa_url'] + url_tenants + '/' +
                          str(site['tenant_id']) + '/handshake',
                          headers=headers,
                          auth=auth,
                          data=json.dumps({
                              "version": version,
                              "src_site": self.my_site,
                              "tenant_id": site['tenant_id'],
                              "tunnel_ip": ipaddr,
                              "tunnel_type": 'VXLAN'
                          }))

        if int(r.status_code) == 200:
            msg = r.json()
            validate(msg, handshake_schema)

            site['handshake_state'] = 'SUCCESS'
            site['tunnel_attr'] = {
                "tunnel_ip": msg['tunnel_ip'],
                "tunnel_type": msg['tunnel_type']
            }
            return
        raise RyuException("FA handshake failed %s" % r.text)
示例#4
0
    def hand_shake(self, req, tenant_id, **kwargs):

        if (tenant_id in tenants_net_tables and tenants_net_tables[tenant_id]
            ) and (tenant_id in tenants_site_tables
                   and tenants_site_tables[tenant_id]):
            net_table = tenants_net_tables[tenant_id]
            site_table = tenants_site_tables[tenant_id]
        else:
            return Response(
                content_type='application/json',
                status=500,
                body="Handshake failed: Missing site/net table XXX Pending.")

        # Handshake validation
        msg = json.loads(req.body)
        validate(msg, handshake_schema)

        if msg['version'] != net_table['version']:
            raise RyuException("Handshake failed: Version mismatch %s %s" %
                               (msg['version'], net_table['version']))

        logging.info("Start jandshake for tenant %s", tenant_id)

        for site in tenants_site_tables[tenant_id]:
            if site['name'] == msg['src_site']:

                status, body = self._process_handshake_req(
                    site, tenant_id, msg)

                body = json.dumps(body)
                return Response(content_type='application/json', body=body)

        return Response(content_type='application/json',
                        status=500,
                        body="Handshake failed: Src site was not found.")
示例#5
0
    def _site_tenant(self, site_id, tenant_id):
        if tenant_id in tenants_site_tables:
            site_table = tenants_site_tables[tenant_id]
            distant_tenant_attr = site_table[site_id]
            return distant_tenant_attr

        raise RyuException("Tenant translation failed")
示例#6
0
    def _get_sites_vnid(self, site_name, tenant_id, network_id):
        if tenant_id in tenants_net_tables:
            net_table = tenants_net_tables[tenant_id]
            net_list = net_table['table'][network_id]
            for site_net_attr in net_list:
                if site_net_attr['site_name'] == site_name:
                    return site_net_attr['vnid']

        raise RyuException("Network translation failed")
示例#7
0
    def _register_networks(self, table, tenant_id):
        pip = self.net_switch_app.switch['datapath'].address[0]

        for vnid in table['table']:
            logging.info("Register %s in controller", vnid)

            rep = self.net_switch_app.send_request(
                EventRegisterVNIDReq(vnid, pip))

            if rep.port:
                self._add_flows_for_vnid(tenant_id, vnid, rep.port)
            else:
                raise RyuException(
                    "Error failed to create port for vnid %s\n" % vnid)
示例#8
0
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath

        for port_no, port in ev.msg.ports.items():
            if port.name == self.CONF.netfa.fa_br_name:
                # We found our datapath
                self.switch = {'datapath': datapath}
            if port.name == self.CONF.netfa.fa_tun_name:
                # We found our fa tunnel port
                self.tunnel_port = port

        if not self.switch or not self.tunnel_port:
            raise RyuException("No NET FA bridge yet")

        logging.info('Found Federation Agent Bridge %s with tunnel port %s',
                     self.CONF.netfa.fa_br_name, self.CONF.netfa.fa_tun_name)
示例#9
0
    def loc_query_handler(self, ev):
        vnid = ev.vNID
        vip = ev.vIP

        logging.debug('Enter  loc_query_handler for %d:%s', vnid, vip)

        for tenant_id, net_table in tenants_net_tables.items():
            if vnid in net_table['table']:
                for net in net_table['table'][vnid]:
                    if net['site_name'] != self.CONF.netfa.my_site:
                        self._send_location_req(tenant_id, vnid, vip, net)
                found = True
                break

        if not found:
            raise RyuException("Can not find VNID %s" % vnid)
示例#10
0
    def _state_machine(self):
        """ Port state machine.
             Change next status when timer is exceeded
             or _change_status() method is called."""
        role_str = {
            ROOT_PORT: 'ROOT_PORT          ',
            DESIGNATED_PORT: 'DESIGNATED_PORT    ',
            NON_DESIGNATED_PORT: 'NON_DESIGNATED_PORT'
        }
        state_str = {
            PORT_STATE_DISABLE: 'DISABLE',
            PORT_STATE_BLOCK: 'BLOCK',
            PORT_STATE_LISTEN: 'LISTEN',
            PORT_STATE_LEARN: 'LEARN',
            PORT_STATE_FORWARD: 'FORWARD'
        }

        if self.state is PORT_STATE_DISABLE:
            self.ofctl.set_port_status(self.ofport, self.state)

        while True:
            self.logger.info('[port=%d] %s / %s',
                             self.ofport.port_no,
                             role_str[self.role],
                             state_str[self.state],
                             extra=self.dpid_str)

            self.state_event = hub.Event()
            timer = self._get_timer()
            if timer:
                timeout = hub.Timeout(timer)
                try:
                    self.state_event.wait()
                except hub.Timeout as t:
                    if t is not timeout:
                        err_msg = 'Internal error. Not my timeout.'
                        raise RyuException(msg=err_msg)
                    new_state = self._get_next_state()
                    self._change_status(new_state, thread_switch=False)
                finally:
                    timeout.cancel()
            else:
                self.state_event.wait()

            self.state_event = None
示例#11
0
    def _test_throughput_check(self, throughputs, start, end):
        msgs = []
        elapsed_sec = end[0] - start[0]

        for throughput in throughputs:
            match = str(throughput[KEY_FLOW].match)
            # get oxm_fields of OFPMatch
            fields = dict(throughput[KEY_FLOW].match._fields2)

            if match not in start[1] or match not in end[1]:
                raise TestError(self.state, match=match)
            increased_bytes = end[1][match][0] - start[1][match][0]
            increased_packets = end[1][match][1] - start[1][match][1]

            if throughput[KEY_PKTPS]:
                key = KEY_PKTPS
                conv = 1
                measured_value = increased_packets
                unit = 'pktps'
            elif throughput[KEY_KBPS]:
                key = KEY_KBPS
                conv = 1024 / 8  # Kilobits -> bytes
                measured_value = increased_bytes
                unit = 'kbps'
            else:
                raise RyuException(
                    'An invalid key exists that is neither "%s" nor "%s".' %
                    (KEY_KBPS, KEY_PKTPS))

            expected_value = throughput[key] * elapsed_sec * conv
            margin = expected_value * THROUGHPUT_THRESHOLD
            self.logger.debug("measured_value:[%s]", measured_value)
            self.logger.debug("expected_value:[%s]", expected_value)
            self.logger.debug("margin:[%s]", margin)
            if math.fabs(measured_value - expected_value) > margin:
                msgs.append('{0} {1:.2f}{2}'.format(
                    fields, measured_value / elapsed_sec / conv, unit))

        if msgs:
            raise TestFailure(self.state, detail=', '.join(msgs))
示例#12
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)
示例#13
0
 def _validate_datapath(self):
     if not self.net_switch_app.switch:
         raise RyuException("FA handshake failed: No datapath")
示例#14
0
    def _find_url(self, tenant_id, name):
        for site in tenants_site_tables[tenant_id]:
            if site['name'] == name:
                return site['fa_url']

        raise RyuException("Error finding FA url on %s" % name)