Ejemplo n.º 1
0
def test_get_vlan_static_names_should_strip_nullbytes():
    mib = QBridgeMib(Mock())
    with patch('nav.mibs.qbridge_mib.QBridgeMib.retrieve_column') as retrieve:
        retrieve.return_value = succeed(
            {(1,): "normal", (2,): "bad\x00", (3,): "\x00crazy\x00"}
        )
        deferred = mib.get_vlan_static_names()
        result = deferred.result

    assert "bad" in result.values()
    assert "crazy" in result.values()
Ejemplo n.º 2
0
    def _get_dot1q_mac_port_mapping(self):
        qbridge = QBridgeMib(self.agent)
        fdb = yield qbridge.get_forwarding_database()
        baseports = yield self._get_baseports()

        mapping = defaultdict(set)
        for mac, port in fdb:
            if port in baseports:
                ifindex = baseports[port]
                mapping[ifindex].add(mac)

        defer.returnValue(dict(mapping))
Ejemplo n.º 3
0
 def __init__(self, *args, **kwargs):
     super(Dot1q, self).__init__(*args, **kwargs)
     self.bridgemib = BridgeMib(self.agent)
     self.qbridgemib = QBridgeMib(self.agent)
Ejemplo n.º 4
0
class Dot1q(Plugin):
    """Collect 802.1q info from BRIDGE and Q-BRIDGE MIBs."""
    baseports = {}
    pvids = {}

    def __init__(self, *args, **kwargs):
        super(Dot1q, self).__init__(*args, **kwargs)
        self.bridgemib = BridgeMib(self.agent)
        self.qbridgemib = QBridgeMib(self.agent)

    def _remap_vlan(self, vlan_ident):
        """Hook-in for subclasses to remap VLAN numbers if necessary"""
        return vlan_ident

    @inlineCallbacks
    def handle(self):
        """Collects VLAN configuration using Q-BRIDGE-MIB.

        If no PVID information can be found in Q-BRIDGE, the plugin assumes
        the device either doesn't support Q-BRIDGE or doesn't support 802.1q
        and exits.

        """
        self._logger.debug("Collecting 802.1q VLAN information")

        self.baseports = yield self.bridgemib.get_baseport_ifindex_map()
        self.pvids = yield self.qbridgemib.get_baseport_pvid_map()
        if self.pvids:
            self._process_pvids()
        else:
            return

        yield self._get_vlan_names()
        yield self._get_tagging_info()

    def _process_pvids(self):
        """Process the list of collected port/PVID mappings.

        If no PVID data was found, it is assumed that this bridge
        either does not support Q-BRIDGE-MIB or does not support
        802.1q, and the plugin exits.

        """
        self._logger.debug("PVID mapping: %r", self.pvids)

        for port, pvid in self.pvids.items():
            self._set_port_pvid(port, pvid)

    def _set_port_pvid(self, port, pvid):
        if port in self.baseports:
            ifindex = self.baseports[port]
            interface = self.containers.factory(ifindex, shadows.Interface)
            interface.vlan = pvid
            interface.trunk = False  # default all ports to non-tagging at first
        else:
            self._logger.debug("saw reference to non-existant baseport %s",
                               port)

    @inlineCallbacks
    def _get_tagging_info(self):
        """Retrieves and processes information about VLAN egress ports and
        tagging.

        The set of untagged ports is subtracted from the total set of
        egress ports for each vlan, resulting in a set of ports that
        transmit and receive tagged frames for this vlan (i.e. trunk
        ports).

        """
        egress, untagged = yield self._retrieve_vlan_ports()
        trunkports = self._find_trunkports(egress, untagged)
        self._logger.debug("trunkports: %r", trunkports)

        self._store_trunkports(trunkports)

    @inlineCallbacks
    def _retrieve_vlan_ports(self):
        query = self.qbridgemib
        egress = yield query.get_vlan_current_egress_ports()
        untagged = yield query.get_vlan_current_untagged_ports()

        if not egress and not untagged:
            egress = yield query.get_vlan_static_egress_ports()
            untagged = yield query.get_vlan_static_untagged_ports()

        returnValue((egress, untagged))

    def _find_trunkports(self, egress, untagged):
        trunkports = defaultdict(list)
        for vlan, (egress, untagged) in mergedicts(egress, untagged).items():
            try:
                tagged = egress - untagged
            except ValueError:
                self._logger.error(
                    "vlan %s subtraction mismatch between "
                    "EgressPorts and UntaggedPorts", vlan)
            else:
                for port in tagged:
                    trunkports[port].append(vlan)
            finally:
                self._logger.debug("vlan: %s egress: %r untagged: %r", vlan,
                                   egress, untagged)

        return trunkports

    def _store_trunkports(self, trunkports):
        for port, vlans in trunkports.items():
            self._set_trunkport(port, vlans)

    def _set_trunkport(self, port, vlans):
        if port not in self.baseports:
            self._logger.debug("saw reference to non-existant baseport %s",
                               port)
            return

        # Mark as trunk
        ifindex = self.baseports[port]
        interface = self.containers.factory(ifindex, shadows.Interface)
        interface.trunk = True

        # Store a hex string representation of enabled VLANs
        # in swportallowedvlan
        allowed = self.containers.factory(ifindex, shadows.SwPortAllowedVlan)
        allowed.interface = interface
        allowed.hex_string = vlan_list_to_hex(vlans)

    @inlineCallbacks
    def _get_vlan_names(self):
        names = yield self.qbridgemib.get_vlan_static_names()
        if names:
            for vlannum, name in names.items():
                vlannum = self._remap_vlan(vlannum)
                suffix = '+{}'.format(vlannum)
                if name.endswith(suffix):
                    name = name[:-len(suffix)]
                vlan = self.containers.factory(name, shadows.Vlan)
                vlan.net_type = shadows.NetType.get('lan')
                vlan.vlan = vlannum
                vlan.net_ident = name
                vlan.netbox = self.netbox
                self._logger.debug("Found vlan {}: {}".format(vlannum, name))
Ejemplo n.º 5
0
 def __init__(self, *args, **kwargs):
     super(Dot1q, self).__init__(*args, **kwargs)
     self.bridgemib = BridgeMib(self.agent)
     self.qbridgemib = QBridgeMib(self.agent)
Ejemplo n.º 6
0
class Dot1q(Plugin):
    """Collect 802.1q info from BRIDGE and Q-BRIDGE MIBs."""
    baseports = {}
    pvids = {}

    def __init__(self, *args, **kwargs):
        super(Dot1q, self).__init__(*args, **kwargs)
        self.bridgemib = BridgeMib(self.agent)
        self.qbridgemib = QBridgeMib(self.agent)

    @inlineCallbacks
    def handle(self):
        """Collects VLAN configuration using Q-BRIDGE-MIB.

        If no PVID information can be found in Q-BRIDGE, the plugin assumes
        the device either doesn't support Q-BRIDGE or doesn't support 802.1q
        and exits.

        """
        self._logger.debug("Collecting 802.1q VLAN information")

        self.baseports = yield self.bridgemib.get_baseport_ifindex_map()
        self.pvids = yield self.qbridgemib.get_baseport_pvid_map()
        if self.pvids:
            self._process_pvids()
        else:
            return

        yield self._get_tagging_info()

    def _process_pvids(self):
        """Process the list of collected port/PVID mappings.

        If no PVID data was found, it is assumed that this bridge
        either does not support Q-BRIDGE-MIB or does not support
        802.1q, and the plugin exits.

        """
        self._logger.debug("PVID mapping: %r", self.pvids)

        for port, pvid in self.pvids.items():
            self._set_port_pvid(port, pvid)

    def _set_port_pvid(self, port, pvid):
        if port in self.baseports:
            ifindex = self.baseports[port]
            interface = self.containers.factory(ifindex,
                                                shadows.Interface)
            interface.vlan = pvid
        else:
            self._logger.debug("saw reference to non-existant baseport %s",
                               port)

    @inlineCallbacks
    def _get_tagging_info(self):
        """Retrieves and processes information about VLAN egress ports and
        tagging.

        The set of untagged ports is subtracted from the total set of
        egress ports for each vlan, resulting in a set of ports that
        transmit and receive tagged frames for this vlan (i.e. trunk
        ports).

        """
        egress, untagged = yield self._retrieve_vlan_ports()
        trunkports = self._find_trunkports(egress, untagged)
        self._logger.debug("trunkports: %r", trunkports)

        self._store_trunkports(trunkports)

    @inlineCallbacks
    def _retrieve_vlan_ports(self):
        query = self.qbridgemib
        egress = yield query.get_vlan_current_egress_ports()
        untagged = yield query.get_vlan_current_untagged_ports()

        if not egress or not untagged:
            egress = yield query.get_vlan_static_egress_ports()
            untagged = yield query.get_vlan_static_untagged_ports()

        returnValue((egress, untagged))

    def _find_trunkports(self, egress, untagged):
        trunkports = {}
        for vlan, (egress, untagged) in mergedicts(egress, untagged).items():
            try:
                tagged = egress - untagged
            except ValueError:
                self._logger.error("vlan %s subtraction mismatch between "
                                   "EgressPorts and UntaggedPorts", vlan)
            else:
                for port in tagged.get_ports():
                    if port not in trunkports:
                        trunkports[port] = [vlan]
                    else:
                        trunkports[port].append(vlan)
            finally:
                self._logger.debug("vlan: %s egress: %r untagged: %r",
                   vlan, egress.get_ports(), untagged.get_ports())

        return trunkports


    def _store_trunkports(self, trunkports):
        for port, vlans in trunkports.items():
            self._set_trunkport(port, vlans)

    def _set_trunkport(self, port, vlans):
        if port not in self.baseports:
            self._logger.debug("saw reference to non-existant baseport %s",
                               port)
            return

        # Mark as trunk
        ifindex = self.baseports[port]
        interface = self.containers.factory(ifindex, shadows.Interface)
        interface.trunk = True

        # Store a hex string representation of enabled VLANs
        # in swportallowedvlan
        allowed = self.containers.factory(ifindex, shadows.SwPortAllowedVlan)
        allowed.interface = interface
        allowed.hex_string = vlan_list_to_hex(vlans)