示例#1
0
    def upsert_mcast_service(self, ipaddress, receivers, status, service_type):
        """Update/insert new mcast services.

        Expected input:

        {
            "ip": "224.0.1.200",
            "receivers": ["ff:ff:ff:ff:ff:ff"],
            "status": True,
            "type": "emergency"
        }
        """

        addr = self.mcast_ip_to_ether(ipaddress)

        if addr not in self.mcast_services:

            schedule = self.schedule[-self._services_registered:] + \
                    self.schedule[:-self._services_registered]

            self.mcast_services[addr] = {
                "addr": addr,
                "ipaddress": ipaddress,
                "mcs": 6,
                "schedule": schedule,
                "receivers": [EtherAddress(x) for x in receivers],
                "status": status,
                "service_type": service_type
            }

            self._services_registered += 1

        else:

            self.mcast_services[addr]["receivers"] = \
                [EtherAddress(x) for x in receivers]
            self.mcast_services[addr]["status"] = status
            self.mcast_services[addr]["service_type"] = service_type

        return addr
    def put(self, *args, **kwargs):
        """Modify the LVAP

        Args:

            [0]: the lvap address (mandatory)

        Example URLs:

            PUT /api/v1/lvaps/60:F4:45:D0:3B:FC

            {
                "version": "1.0",
                "wtp": "04:F0:21:09:F9:AA"
            }
        """

        lvap = self.service.lvaps[EtherAddress(args[0])]

        if "blocks" in kwargs:

            addr = EtherAddress(kwargs['wtp'])
            wtp = self.service.devices[addr]
            pool = ResourcePool()

            for block_id in kwargs["blocks"]:
                pool.append(wtp.blocks[block_id])

            lvap.blocks = pool

        elif "wtp" in kwargs:

            wtp = self.service.devices[EtherAddress(kwargs['wtp'])]
            lvap.wtp = wtp

        if "encap" in kwargs:

            encap = EtherAddress(kwargs["encap"])
            lvap.encap = encap
示例#3
0
    def delete(self, *args, **kwargs):
        """Delete one or all devices.

        Args:

            [0]: the device address (mandatory)

        Example URLs:

            DELETE /api/v1/wtps
            DELETE /api/v1/wtps/00:0D:B9:2F:56:64
        """

        if args:
            self.service.remove(EtherAddress(args[0]))
        else:
            self.service.remove_all()
示例#4
0
    def delete(self, *args, **kwargs):
        """Delete the mcast_services .

        Args:

            [0]: the project id (mandatory)
            [1]: the app id (mandatory)
            [3]: the mcast service MAC address (mandatory)

        Example URLs:

            DELETE /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/apps/
                mcast_services/01:00:5E:00:01:C8
        """

        self.service.delete_mcast_service(EtherAddress(args[2]))
        self.service.save_service_state()
示例#5
0
    def delete(self, *args, **kwargs):
        """Delete one or all devices.

        Args:

            [0]: the device address

        Example URLs:

            DELETE /api/v1/vbses
            DELETE /api/v1/vbses/00:00:00:00:00:01
        """

        if args:
            self.service.remove(EtherAddress(args[0]))
        else:
            self.service.remove_all()
示例#6
0
    def __init__(self, slice_id, properties=None, devices=None):

        # set read-only parameters
        self.slice_id = int(slice_id)

        # logger :)
        self.log = logging.getLogger(self.__class__.__module__)

        # parse properties
        self.properties = self._parse_properties(properties)

        # parse per device properties
        self.devices = {}
        if devices:
            for device in devices:
                self.devices[EtherAddress(device)] = \
                    self._parse_properties(devices[device])
    def handle_ucqm_response(self, response, wtp, _):
        """Handle UCQM_RESPONSE message."""

        block = wtp.blocks[response.iface_id]
        block.ucqm = {}

        # generate data points
        points = []
        timestamp = datetime.utcnow()

        for entry in response.entries:
            addr = EtherAddress(entry['addr'])
            block.ucqm[addr] = {
                'addr': addr,
                'last_rssi_std': entry['last_rssi_std'],
                'last_rssi_avg': entry['last_rssi_avg'],
                'last_packets': entry['last_packets'],
                'hist_packets': entry['hist_packets'],
                'mov_rssi': entry['mov_rssi']
            }

            tags = dict(self.params)
            tags["wtp"] = wtp.addr
            tags["block_id"] = response.iface_id
            tags["addr"] = addr

            sample = {
                "measurement": 'ucqm_rssi',
                "tags": tags,
                "time": timestamp,
                "fields": block.ucqm[addr]
            }

            points.append(sample)

        # save to db
        self.write_points(points)

        if wtp.addr not in self.ucqm:
            self.ucqm[wtp.addr] = {}
        self.ucqm[wtp.addr][block.block_id] = block.ucqm
        self.ucqm[wtp.addr][block.block_id]['timestamp'] = timestamp

        # handle callbacks
        self.handle_callbacks()
    def handle_slice_stats_response(self, response, *_):
        """Handle WIFI_SLICE_STATS_RESPONSE message."""

        wtp = EtherAddress(response.device)

        # slc = str(response.slice_id)
        slc = self.slc_xid[response.xid]

        # update this object
        if wtp not in self.stats:
            self.slice_stats[slc][wtp] = {}

        # generate data points
        points = []
        timestamp = datetime.utcnow()

        for entry in response.stats:

            self.slice_stats[slc][wtp][entry.iface_id] = {
                'deficit_used': float(entry.deficit_used),
                'max_queue_length': float(entry.max_queue_length),
                'tx_packets': float(entry.tx_packets),
                'tx_bytes': float(entry.tx_bytes),
            }

            tags = dict(self.params)
            tags["slc"] = slc
            tags["wtp"] = wtp
            tags["iface_id"] = entry.iface_id

            sample = {
                "measurement": "wifi_slice_stats",
                "tags": tags,
                "time": timestamp,
                "fields": self.slice_stats[slc][wtp][entry.iface_id]
            }

            points.append(sample)

        # save to db
        self.write_points(points)

        # handle callbacks
        self.handle_callbacks()
示例#9
0
    def get(self, *args, **kwargs):
        """Lists all clients in the ACL.

        Args:

            [0], the project id (mandatory)
            [0]: the device address (optional)

        Example URLs:

            GET /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/
                wifi_acl/

            {
                "60:57:18:B1:A4:B8": {
                    "addr": "60:57:18:B1:A4:B8",
                    "desc": "Dell Laptop"
                },
                "18:5E:0F:E3:B8:68": {
                    "addr": "18:5E:0F:E3:B8:68",
                    "desc": "Dell Laptop"
                },
                "60:F4:45:D0:3B:FC": {
                    "addr": "60:F4:45:D0:3B:FC",
                    "desc": "Roberto's iPhone"
                }
            }

            GET /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/
                wifi_acl/60:57:18:B1:A4:B8

            {
                "addr": "60:57:18:B1:A4:B8",
                "desc": "Dell Laptop"
            }
        """

        project_id = uuid.UUID(args[0])
        project = self.service.projects[project_id]

        allowed = project.wifi_props.allowed

        return allowed if not args else allowed[str(EtherAddress(args[1]))]
示例#10
0
    def _handle_tx_policy_status_response(self, status):
        """Handle an incoming TX_POLICY_STATUS_RESPONSE message."""

        block = self.device.blocks[status.iface_id]
        addr = EtherAddress(status.sta)

        if addr not in block.tx_policies:
            block.tx_policies[addr] = TxPolicy(addr, block)

        txp = block.tx_policies[addr]

        txp.set_mcs([float(x) / 2 for x in status.mcs])
        txp.set_ht_mcs([int(x) for x in status.mcs_ht])
        txp.set_rts_cts(status.rts_cts)
        txp.set_max_amsdu_len(status.max_amsdu_len)
        txp.set_mcast(status.tx_mcast)
        txp.set_no_ack(status.flags.no_ack)

        self.log.info("TX policy status: %s", txp)
示例#11
0
    def get(self, *args, **kwargs):
        """Access the mcast_services .

        Args:

            [0]: the project id (mandatory)
            [1]: the app id (mandatory)
            [2]: the mcast service MAC address (optional)

        Example URLs:

            GET /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/apps/
                mcast_services/01:00:5E:00:01:C8

            {
                addr: "01:00:5E:00:01:C8",
                ipaddress: "224.0.1.200",
                mcs: 0,
                schedule: [
                    1,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0
                ],
                receivers: [
                    "FF:FF:FF:FF:FF:FF"
                ],
                status: "true",
                service_type: "emergency"
            }
        """

        if len(args) == 2:
            return self.service.mcast_services

        return self.service.mcast_services[EtherAddress(args[2])]
示例#12
0
    def delete(self, *args, **kwargs):
        """Delete an entry in ACL.

        Args:

            [0], the project id (mandatory)
            [0]: the device address (mandatory)

        Example URLs:

            DELETE /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/
                wifi_acl/60:57:18:B1:A4:B8

        """

        project_id = uuid.UUID(args[0])
        project = self.service.projects[project_id]

        del project.wifi_props.allowed[str(EtherAddress(args[1]))]

        project.save()
    def handle_ncqm_response(self, response, wtp, _):
        """Handle NCQM_RESPONSE message."""

        block = wtp.blocks[response.iface_id]
        block.ncqm = {}

        for entry in response.entries:
            addr = EtherAddress(entry['addr'])
            block.ncqm[addr] = {
                'addr': addr,
                'last_rssi_std': entry['last_rssi_std'],
                'last_rssi_avg': entry['last_rssi_avg'],
                'last_packets': entry['last_packets'],
                'hist_packets': entry['hist_packets'],
                'mov_rssi': entry['mov_rssi']
            }

        self.ncqm = block.ncqm

        # handle callbacks
        self.handle_callbacks("ncqm")
示例#14
0
    def delete(self, *args, **kwargs):
        """Delete an entry in ACL.

        Args:

            [0], the project id (mandatory)
            [0]: the device address (mandatory)

        Example URLs:

            DELETE /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/
                wifi_acl/60:57:18:B1:A4:B8
        """

        project_id = uuid.UUID(args[0])
        project = self.service.projects[project_id]

        if len(args) == 2:
            project.remove_acl(EtherAddress(args[1]))
        else:
            project.remove_acl()
示例#15
0
    def get(self, *args, **kwargs):
        """List devices.

        Args:

            [0]: the device address (optional)

        Example URLs:

            GET /api/v1/vbses

            [
                {
                    "addr": "00:00:00:00:00:01",
                    "cells": {},
                    "connection": null,
                    "desc": "Ettus B210",
                    "last_seen": 0,
                    "last_seen_ts": "1970-01-01T01:00:00.000000Z",
                    "period": 0,
                    "state": "disconnected"
                }
            ]

            GET /api/v1/vbses/00:00:00:00:00:01

            {
                "addr": "00:00:00:00:00:01",
                "cells": {},
                "connection": null,
                "desc": "Ettus B210",
                "last_seen": 0,
                "last_seen_ts": "1970-01-01T01:00:00.000000Z",
                "period": 0,
                "state": "disconnected"
            }
        """

        return self.service.devices \
            if not args else self.service.devices[EtherAddress(args[0])]
    def handle_ncqm_response(self, response, wtp, _):
        """Handle NCQM_RESPONSE message."""

        block = wtp.blocks[response.iface_id]
        block.ncqm = {}

        for entry in response.entries:
            addr = EtherAddress(entry['addr'])
            block.ncqm[addr] = {
                'addr': addr,
                'last_rssi_std': entry['last_rssi_std'],
                'last_rssi_avg': entry['last_rssi_avg'],
                'last_packets': entry['last_packets'],
                'hist_packets': entry['hist_packets'],
                'mov_rssi': entry['mov_rssi']
            }

        if wtp.addr not in self.ncqm:
            self.ncqm[wtp.addr] = {}
        self.ncqm[wtp.addr][block.block_id] = block.ncqm
        self.ucqm[wtp.addr][block.block_id]['timestamp'] = datetime.utcnow()

        # handle callbacks
        self.handle_callbacks()
示例#17
0
    def mcast_ip_to_ether(cls, ip_mcast_addr):
        """Transform an IP multicast address into an Ethernet one."""

        if ip_mcast_addr is None:
            return '\x00' * 6

        # The first 24 bits are fixed according to class D IP
        # and IP multicast address convenctions
        mcast_base = '01:00:5e'

        # The 23 low order bits are mapped.
        ip_addr_bytes = str(ip_mcast_addr).split('.')

        # The first IP byte is not use,
        # and only the last 7 bits of the second byte are used.
        second_byte = int(ip_addr_bytes[1]) & 127
        third_byte = int(ip_addr_bytes[2])
        fourth_byte = int(ip_addr_bytes[3])

        mcast_upper = format(second_byte, '02x') + ':' + \
            format(third_byte, '02x') + ':' + \
            format(fourth_byte, '02x')

        return EtherAddress(mcast_base + ':' + mcast_upper)
示例#18
0
    def put(self, *args, **kwargs):
        """Update the description of the device.

        Request:

            version: protocol version (1.0)
            desc: a human readable description of the device (optional)

        Example URLs:

            PUT /api/v1/vbses/00:0D:B9:2F:56:64

            {
                "version":"1.0",
                "desc": "SrsLTE eNB"
            }
        """

        addr = EtherAddress(args[0])

        if 'desc' in kwargs:
            self.service.update(addr, kwargs['desc'])
        else:
            self.service.update(addr)
示例#19
0
    def _handle_vap_status_response(self, status):
        """Handle an incoming STATUS_VAP message."""

        bssid = EtherAddress(status.bssid)
        ssid = SSID(status.ssid)

        project = self.manager.projects_manager.load_project_by_ssid(ssid)

        if not project:
            self.log.warning("Unable to find SSID %s", ssid)
            self.send_del_vap(bssid)
            return

        # If the VAP does not exists, then create a new one
        if bssid not in self.manager.vaps:

            incoming = self.device.blocks[status.iface_id]

            self.manager.vaps[bssid] = VAP(bssid, incoming,
                                           project.wifi_props.ssid)

        vap = self.manager.vaps[bssid]

        self.log.info("VAP status %s", vap)
示例#20
0
    def send_add_lvap_request(self, lvap, block, set_mask):
        """Send a ADD_LVAP message."""

        flags = Container(ht_caps=lvap.ht_caps,
                          authenticated=lvap.authentication_state,
                          associated=lvap.association_state,
                          set_mask=set_mask)

        encap = EtherAddress("00:00:00:00:00:00")
        if lvap.encap:
            encap = lvap.encap

        bssid = EtherAddress()
        if lvap.bssid:
            bssid = lvap.bssid

        ssid = SSID()
        if lvap.ssid:
            ssid = lvap.ssid

        msg = Container(length=80,
                        flags=flags,
                        assoc_id=lvap.assoc_id,
                        iface_id=block.block_id,
                        ht_caps_info=Container(**lvap.ht_caps_info),
                        sta=lvap.addr.to_raw(),
                        encap=encap.to_raw(),
                        bssid=bssid.to_raw(),
                        ssid=ssid.to_raw(),
                        networks=[])

        for network in lvap.networks:
            msg.length = msg.length + 6 + WIFI_NWID_MAXSIZE + 1
            msg.networks.append(
                Container(bssid=network[0].to_raw(), ssid=network[1].to_raw()))

        return self.send_message(self.proto.PT_ADD_LVAP_REQUEST, msg,
                                 lvap.handle_add_lvap_response)
    def sta(self, sta):
        """ Set the station address. """

        self.params['sta'] = EtherAddress(sta)
示例#22
0
    def get(self, *args, **kwargs):
        """List the LVAPs.

        Args:

            [0], the project id (mandatory)
            [1]: the lvap address (optional)

        Example URLs:

            GET /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/lvaps

            [
                {
                    "addr": "60:F4:45:D0:3B:FC",
                    "assoc_id": 732,
                    "association_state": true,
                    "authentication_state": true,
                    "blocks": [
                        ...
                    ],
                    "bssid": "52:31:3E:D0:3B:FC",
                    "encap": "00:00:00:00:00:00",
                    "ht_caps": true,
                    "ht_caps_info": {
                        "DSSS_CCK_Mode_in_40_MHz": false,
                        "Forty_MHz_Intolerant": false,
                        "HT_Delayed_Block_Ack": false,
                        "HT_Greenfield": false,
                        "LDPC_Coding_Capability": true,
                        "L_SIG_TXOP_Protection_Support": false,
                        "Maximum_AMSDU_Length": false,
                        "Reserved": false,
                        "Rx_STBC": 0,
                        "SM_Power_Save": 3,
                        "Short_GI_for_20_MHz": true,
                        "Short_GI_for_40_MHz": true,
                        "Supported_Channel_Width_Set": true,
                        "Tx_STBC": false
                    },
                    "networks": [
                        [
                            "52:31:3E:D0:3B:FC",
                            "EmPOWER"
                        ]
                    ],
                    "pending": [],
                    "ssid": "EmPOWER",
                    "state": "running",
                    "wtp": {
                        ...
                    }
                }
            ]

            GET /api/v1/projects/52313ecb-9d00-4b7d-b873-b55d3d9ada26/lvaps/
                60:F4:45:D0:3B:FC

            {
                "addr": "60:F4:45:D0:3B:FC",
                "assoc_id": 732,
                "association_state": true,
                "authentication_state": true,
                "blocks": [
                    ...
                ],
                "bssid": "52:31:3E:D0:3B:FC",
                "encap": "00:00:00:00:00:00",
                "ht_caps": true,
                "ht_caps_info": {
                    "DSSS_CCK_Mode_in_40_MHz": false,
                    "Forty_MHz_Intolerant": false,
                    "HT_Delayed_Block_Ack": false,
                    "HT_Greenfield": false,
                    "LDPC_Coding_Capability": true,
                    "L_SIG_TXOP_Protection_Support": false,
                    "Maximum_AMSDU_Length": false,
                    "Reserved": false,
                    "Rx_STBC": 0,
                    "SM_Power_Save": 3,
                    "Short_GI_for_20_MHz": true,
                    "Short_GI_for_40_MHz": true,
                    "Supported_Channel_Width_Set": true,
                    "Tx_STBC": false
                },
                "networks": [
                    [
                        "52:31:3E:D0:3B:FC",
                        "EmPOWER"
                    ]
                ],
                "pending": [],
                "ssid": "EmPOWER",
                "state": "running",
                "wtp": {
                    ...
                }
            }

        """

        project_id = uuid.UUID(args[0])
        project = self.service.projects[project_id]

        return project.lvaps \
            if len(args) == 1 else project.lvaps[EtherAddress(args[1])]
示例#23
0
    def _handle_auth_request(self, request):
        """Handle an incoming AUTH_REQUEST message."""

        sta = EtherAddress(request.sta)

        if sta not in self.manager.lvaps:
            self.log.info("Auth request from unknown LVAP %s", sta)
            return

        lvap = self.manager.lvaps[sta]

        incoming_bssid = EtherAddress(request.bssid)

        # The request bssid is the lvap current bssid, then just reply
        if lvap.bssid == incoming_bssid:
            lvap.bssid = incoming_bssid
            lvap.authentication_state = True
            lvap.association_state = False
            lvap.ssid = None
            lvap.commit()
            self.send_auth_response(lvap)
            return

        # Otherwise check if the requested BSSID belongs to a unique tenant
        for project in self.manager.projects_manager.projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_SHARED:
                continue

            bssid = project.generate_bssid(lvap.addr)

            if bssid == incoming_bssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = False
                lvap.ssid = None
                lvap.commit()
                self.send_auth_response(lvap)
                return

        # Finally check if this is a shared bssid
        for project in self.manager.projects_manager.projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_UNIQUE:
                continue

            if incoming_bssid in project.vaps:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = False
                lvap.ssid = None
                lvap.commit()
                self.send_auth_response(lvap)
                return

        self.log.info("Auth request from unknown BSSID %s", incoming_bssid)
    def get(self, *args, **kwargs):
        """List the LVAPs.

        Args:

            [0]: the lvap address (optional)

        Example URLs:

            GET /api/v1/lvaps

            [
                {
                    "addr": "60:F4:45:D0:3B:FC",
                    "assoc_id": 732,
                    "association_state": false,
                    "authentication_state": false,
                    "blocks": [
                        ...
                    ],
                    "bssid": null,
                    "encap": "00:00:00:00:00:00",
                    "ht_caps": true,
                    "ht_caps_info": {
                        "DSSS_CCK_Mode_in_40_MHz": false,
                        "Forty_MHz_Intolerant": false,
                        "HT_Delayed_Block_Ack": false,
                        "HT_Greenfield": false,
                        "LDPC_Coding_Capability": true,
                        "L_SIG_TXOP_Protection_Support": false,
                        "Maximum_AMSDU_Length": false,
                        "Reserved": false,
                        "Rx_STBC": 0,
                        "SM_Power_Save": 3,
                        "Short_GI_for_20_MHz": true,
                        "Short_GI_for_40_MHz": true,
                        "Supported_Channel_Width_Set": true,
                        "Tx_STBC": false
                    },
                    "networks": [
                        [
                            "52:31:3E:D0:3B:FC",
                            "EmPOWER"
                        ]
                    ],
                    "pending": [],
                    "ssid": null,
                    "state": "running",
                    "wtp": {
                        ...
                    }
                }
            ]

            GET /api/v1/lvaps/60:F4:45:D0:3B:FC

            {
                "addr": "60:F4:45:D0:3B:FC",
                "assoc_id": 732,
                "association_state": false,
                "authentication_state": false,
                "blocks": [
                    ...
                ],
                "bssid": null,
                "encap": "00:00:00:00:00:00",
                "ht_caps": true,
                "ht_caps_info": {
                    "DSSS_CCK_Mode_in_40_MHz": false,
                    "Forty_MHz_Intolerant": false,
                    "HT_Delayed_Block_Ack": false,
                    "HT_Greenfield": false,
                    "LDPC_Coding_Capability": true,
                    "L_SIG_TXOP_Protection_Support": false,
                    "Maximum_AMSDU_Length": false,
                    "Reserved": false,
                    "Rx_STBC": 0,
                    "SM_Power_Save": 3,
                    "Short_GI_for_20_MHz": true,
                    "Short_GI_for_40_MHz": true,
                    "Supported_Channel_Width_Set": true,
                    "Tx_STBC": false
                },
                "networks": [
                    [
                        "52:31:3E:D0:3B:FC",
                        "EmPOWER"
                    ]
                ],
                "pending": [],
                "ssid": null,
                "state": "running",
                "wtp": {
                    ...
                }
            }
        """

        return self.service.lvaps \
            if not args else self.service.lvaps[EtherAddress(args[0])]
示例#25
0
    def _handle_assoc_request(self, request):
        """Handle an incoming ASSOC_REQUEST message."""

        sta = EtherAddress(request.sta)

        ht_caps = request.flags.ht_caps
        ht_caps_info = dict(request.ht_caps_info)
        del ht_caps_info['_io']

        if sta not in self.manager.lvaps:
            self.log.info("Assoc request from unknown LVAP %s", sta)
            return

        lvap = self.manager.lvaps[sta]

        incoming_bssid = EtherAddress(request.bssid)

        if lvap.bssid != incoming_bssid:
            self.log.info("Assoc request for invalid BSSID %s", incoming_bssid)
            return

        incoming_ssid = SSID(request.ssid)

        # Check if the requested SSID is from a unique project
        for project in self.manager.projects_manager.projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_SHARED:
                continue

            bssid = project.generate_bssid(lvap.addr)

            if bssid != incoming_bssid:
                self.log.info("Invalid BSSID %s", incoming_bssid)
                continue

            if project.wifi_props.ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.ht_caps = ht_caps
                lvap.ht_caps_info = ht_caps_info
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        # Check if the requested SSID is from a unique project
        for project in self.manager.projects_manager.projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_UNIQUE:
                continue

            if incoming_bssid not in project.vaps:
                self.log.info("Invalid BSSID %s", incoming_bssid)
                continue

            if project.wifi_props.ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.ht_caps = ht_caps
                lvap.ht_caps_info = ht_caps_info
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        self.log.info("Unable to find SSID %s", incoming_ssid)
示例#26
0
    def get_prefix(self):
        """Return tenant prefix."""

        tokens = [self.project_id.hex[0:12][i:i + 2] for i in range(0, 12, 2)]
        return EtherAddress(':'.join(tokens))
 def decreaseQuantum(self, slc, wtp, ratesProm):
     res = False
     self.decreased_quantums = ""
     updated_slice = {}
     # para todos los lvaps en el wtp
     for sta in self.context.lvaps:
         lvap = self.context.lvaps[sta]
         if lvap.wtp != None and lvap.wtp.addr == wtp.to_str():
             lvap_slice = self.getSliceLvap(sta)
             if not (self.change_quantum[lvap_slice][wtp]):
                 promised_rate = ratesProm[lvap_slice]
                 lvap_rate = self.getLVAPRateMBits(sta.to_str())
                 # si al menos un lvap tiene mayor rate al prometido y el quantum de esa slice en el wtp es mayor al minimo, le saco recursos
                 if lvap_rate > promised_rate:
                     actual_slice = self.context.wifi_slices[str(
                         lvap_slice)]
                     wtp_quantum = actual_slice.properties['quantum']
                     if EtherAddress(wtp) in actual_slice.devices:
                         wtp_quantum = actual_slice.devices[wtp]['quantum']
                     if wtp_quantum > self.quantum_min:
                         res = True
                         self.change_quantum[lvap_slice][wtp] = True
                         updated_slice = {
                             'slice_id': actual_slice.slice_id,
                             'properties': {
                                 'amsdu_aggregation':
                                 actual_slice.
                                 properties['amsdu_aggregation'],
                                 'quantum':
                                 actual_slice.properties['quantum'],
                                 'sta_scheduler':
                                 actual_slice.properties['sta_scheduler']
                             },
                             'devices': actual_slice.devices
                         }
                         addr = EtherAddress(wtp)
                         if addr not in updated_slice['devices']:
                             self.decreased_quantums = self.decreased_quantums + "// S-" + lvap_slice + "--" + str(
                                 updated_slice['properties']['quantum']
                             ) + "->" + str(
                                 updated_slice['properties']['quantum'] -
                                 updated_slice['properties']['quantum'] *
                                 self.quantum_decrease)
                             updated_slice['devices'][addr] = {
                                 'amsdu_aggregation':
                                 actual_slice.
                                 properties['amsdu_aggregation'],
                                 'quantum':
                                 actual_slice.properties['quantum'] -
                                 actual_slice.properties['quantum'] *
                                 self.quantum_decrease,
                                 'sta_scheduler':
                                 actual_slice.properties['sta_scheduler']
                             }
                         else:
                             self.decreased_quantums = self.decreased_quantums + "// S-" + lvap_slice + "--" + str(
                                 updated_slice['devices'][addr]['quantum']
                             ) + "->" + str(
                                 updated_slice['devices'][addr]['quantum'] -
                                 updated_slice['devices'][addr]['quantum'] *
                                 self.quantum_decrease)
                             updated_slice['devices'][addr][
                                 'quantum'] = updated_slice['devices'][
                                     addr]['quantum'] - updated_slice[
                                         'devices'][addr][
                                             'quantum'] * self.quantum_decrease
                         self.context.upsert_wifi_slice(**updated_slice)
     #return updated_slice
     return res
示例#28
0
    def _handle_lvap_status_response(self, status):
        """Handle an incoming LVAP_STATUS_RESPONSE message."""

        sta = EtherAddress(status.sta)

        # If the LVAP does not exists, then create a new one
        if sta not in self.manager.lvaps:
            self.manager.lvaps[sta] = \
                LVAP(sta, assoc_id=status.assoc_id, state=PROCESS_RUNNING)

        lvap = self.manager.lvaps[sta]

        # update LVAP params
        lvap.encap = EtherAddress(status.encap)
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)
        lvap.ht_caps = bool(status.flags.ht_caps)
        lvap.ht_caps_info = dict(status.ht_caps_info)
        del lvap.ht_caps_info['_io']

        ssid = SSID(status.ssid)
        if ssid == SSID():
            ssid = None

        bssid = EtherAddress(status.bssid)
        if bssid == EtherAddress("00:00:00:00:00:00"):
            bssid = None

        lvap.bssid = bssid

        incoming = self.device.blocks[status.iface_id]

        if status.flags.set_mask:
            lvap.downlink = incoming
        else:
            lvap.uplink.append(incoming)

        # if this is not a DL+UL block then stop here
        if not status.flags.set_mask:
            return

        # if an SSID is set and the incoming SSID is different from the
        # current one then raise an LVAP leave event
        if lvap.ssid and ssid != lvap.ssid:
            self.send_client_leave_message_to_self(lvap)
            lvap.ssid = None

        # if the incoming ssid is not none then raise an lvap join event
        if ssid:
            lvap.ssid = ssid
            self.send_client_join_message_to_self(lvap)

        # udpate networks
        networks = list()

        for network in status.networks:
            incoming = (EtherAddress(network.bssid), SSID(network.ssid))
            networks.append(incoming)

        lvap.networks = networks

        self.log.info("LVAP status: %s", lvap)
    def try_handover(self, sta, slc, rate, ratesProm, actual_rate):
        posibles_handovers = []
        lvap = self.context.lvaps[EtherAddress(sta)]
        blocks = self.blocks().sort_by_rssi(lvap.addr)

        def filterBlocks(block):
            if block.ucqm[lvap.addr][
                    'mov_rssi'] > self.RSSI_min and block.hwaddr.to_str(
                    ) != lvap.blocks[0].hwaddr.to_str():
                return True
            else:
                return False

        # Filtramos los wtp que tengan malo RSSI
        filtered_blocks = list(filter(filterBlocks, blocks))
        # obtengo el uso del wtp actual
        query = 'select * from wifi_channel_stats where wtp=\'' + lvap.wtp.addr.to_str(
        ) + '\' and block_id=\'' + str(
            lvap.blocks[0].block_id) + '\' and time > now() - ' + str(
                int(self.every / 1000)) + 's;'
        result = self.query(query)
        current_channel_stats = list(result.get_points())
        current_usage = 0
        for current_stats in current_channel_stats:
            current_usage += current_stats[
                'tx']  # + current_stats['rx'] + current_stats['ed']
        current_usage = current_usage / len(current_channel_stats)
        # obtengo historial de handovers para verificar ping pong
        query = 'select * from lvaps_handover where sta=\'' + sta + '\' and time > now() - ' + str(
            int(self.every / 1000) * 10) + 's;'
        result = self.query(query)
        handover_list = list(result.get_points())
        for block in filtered_blocks:
            query = 'select * from wifi_channel_stats where wtp=\'' + block.wtp.addr.to_str(
            ) + '\' and block_id=\'' + str(
                block.block_id) + '\' and time > now() - ' + str(
                    int(self.every / 1000)) + 's;'
            result = self.query(query)
            channel_stats = list(result.get_points())
            usage = 0
            for stats in channel_stats:
                usage += stats['tx']  #+ stats['rx'] + stats['ed']
            usage = usage / len(channel_stats)
            # si el uso del wtp es menor al actual, lo agrego como posible handover
            if usage * 1.1 < current_usage and self.wtp_handovers[
                    block.wtp.addr] < self.max_handovers and not (
                        self.ping_pong(handover_list, block.wtp.addr)):
                posibles_handovers.append({'block': block, 'usage': usage})
        if len(posibles_handovers) > 0:
            # Ordeno los bloques por usage asi me quedo con el que tenga menos
            posibles_handovers.sort(key=lambda x: x['usage'])
            # escribo en logger
            self.write_log(
                slc, sta, "H", lvap.blocks[0].wtp.addr.to_str() + "->" +
                posibles_handovers[0]['block'].wtp.addr.to_str(),
                "Usage new WTP: " + str(posibles_handovers[0]['usage']))
            # Do Handover
            lvap.blocks = posibles_handovers[0]['block']
            self.wtp_handovers[posibles_handovers[0]['block'].wtp.addr] += 1
            # guardar cambios
            # generate data points
            points = []
            timestamp = datetime.utcnow()
            fields = {"wtp": posibles_handovers[0]['block'].wtp.addr}
            tags = {"sta": sta}
            sample = {
                "measurement": 'lvaps_handover',
                "tags": tags,
                "time": timestamp,
                "fields": fields
            }
            points.append(sample)
            # save to db
            self.write_points(points)
            return True
        else:
            # No encontre WTP con uso menor al actual, entonces me fijo si algun wtp tiene lvaps con rate mayor al prometido
            for block in filtered_blocks:
                extra_rate = 0
                for sta2 in self.context.lvaps:
                    lvap = self.context.lvaps[sta2]
                    if lvap.wtp != None and lvap.wtp.addr == block.wtp.addr:
                        lvap_slice = self.getSliceLvap(sta2)
                        promised_rate = ratesProm[lvap_slice]
                        lvap_rate = self.getLVAPRateMBits(sta2.to_str())
                        if (lvap_rate - promised_rate) > 0:
                            extra_rate += (lvap_rate - promised_rate)
                if extra_rate > 0 and (
                        extra_rate >= (actual_rate * 1.2)
                        or extra_rate >= rate) and self.wtp_handovers[
                            block.wtp.addr] < self.max_handovers and not (
                                self.ping_pong(handover_list, block.wtp.addr)):
                    posibles_handovers.append({
                        'block': block,
                        'extra_rate': extra_rate
                    })
            if len(posibles_handovers) > 0:
                # Ordeno los bloques por rate extra asi me quedo con el que tenga mas
                posibles_handovers.sort(key=lambda x: x['extra_rate'])
                # escribo en logger
                self.write_log(
                    slc, sta, "H", lvap.blocks[0].wtp.addr.to_str() + "->" +
                    posibles_handovers[0]['block'].wtp.addr.to_str(),
                    "Extra rate new WTP: " +
                    str(posibles_handovers[0]['extra_rate']))
                # Do Handover
                lvap.blocks = posibles_handovers[-1]['block']
                self.wtp_handovers[posibles_handovers[-1]
                                   ['block'].wtp.addr] += 1
                # guardar cambios
                # generate data points
                points = []
                timestamp = datetime.utcnow()
                fields = {"wtp": posibles_handovers[-1]['block'].wtp.addr}
                tags = {"sta": sta}
                sample = {
                    "measurement": 'lvaps_handover',
                    "tags": tags,
                    "time": timestamp,
                    "fields": fields
                }
                points.append(sample)
                # save to db
                self.write_points(points)
                return True
            else:
                return False
示例#30
0
    def get(self, *args, **kwargs):
        """List devices.

        Args:

            [0]: the device address (optional)

        Example URLs:

            GET /api/v1/wtps

            [
                {
                    "addr": "00:0D:B9:2F:56:64",
                    "blocks": {},
                    "connection": null,
                    "desc": "PC Engines ALIX 2D",
                    "last_seen": 0,
                    "last_seen_ts": "1970-01-01T01:00:00.000000Z",
                    "period": 0,
                    "state": "disconnected"
                }
            ]

            GET /api/v1/wtps/00:0D:B9:2F:56:64 (disconnected)

            {
                "addr": "00:0D:B9:2F:56:64",
                "blocks": {},
                "connection": null,
                "desc": "PC Engines ALIX 2D",
                "last_seen": 0,
                "last_seen_ts": "1970-01-01T01:00:00.000000Z",
                "period": 0,
                "state": "disconnected"
            }

            GET /api/v1/wtps/00:0D:B9:2F:56:64 (connected)

            {
                "addr": "00:0D:B9:30:3E:18",
                "blocks": {
                    "0": {
                        "addr": "00:0D:B9:30:3E:18",
                        "band": "HT20",
                        "channel": 36,
                        "ht_supports": [
                            0,
                            1,
                            2,
                            3,
                            4,
                            5,
                            6,
                            7,
                            8,
                            9,
                            10,
                            11,
                            12,
                            13,
                            14,
                            15
                        ],
                        "hwaddr": "04:F0:21:09:F9:9E",
                        "supports": [
                            6,
                            9,
                            12,
                            18,
                            24,
                            36,
                            48,
                            54
                        ],
                        "tx_policies": {
                            "60:F4:45:D0:3B:FC": {
                                "addr": "60:F4:45:D0:3B:FC",
                                "ht_mcs": [
                                    0,
                                    1,
                                    2,
                                    3,
                                    4,
                                    5,
                                    6,
                                    7,
                                    8,
                                    9,
                                    10,
                                    11,
                                    12,
                                    13,
                                    14,
                                    15
                                ],
                                "max_amsdu_len": 3839,
                                "mcast": "legacy",
                                "mcs": [
                                    6.0,
                                    9.0,
                                    12.0,
                                    18.0,
                                    24.0,
                                    36.0,
                                    48.0,
                                    54.0
                                ],
                                "no_ack": false,
                                "rts_cts": 2436,
                                "ur_count": 3
                            }
                        }
                    },
                    "1": {
                        "addr": "00:0D:B9:30:3E:18",
                        "band": "HT20",
                        "channel": 6,
                        "ht_supports": [
                            0,
                            1,
                            2,
                            3,
                            4,
                            5,
                            6,
                            7,
                            8,
                            9,
                            10,
                            11,
                            12,
                            13,
                            14,
                            15
                        ],
                        "hwaddr": "D4:CA:6D:14:C2:09",
                        "supports": [
                            1,
                            2,
                            5,
                            6,
                            9,
                            11,
                            12,
                            18,
                            24,
                            36,
                            48,
                            54
                        ],
                        "tx_policies": {}
                    }
                },
                "connection": {
                    "addr": [
                        "192.168.1.9",
                        46066
                    ]
                },
                "desc": "PC Engines ALIX 2D",
                "last_seen": 8560,
                "last_seen_ts": "2019-08-23T13:09:43.140533Z",
                "period": 0,
                "state": "online"
            }
        """

        return self.service.devices \
            if not args else self.service.devices[EtherAddress(args[0])]