def has_vlan(vlan_filter, vlan): """ Check VLAN is within vlan_filter :param vlan_filter: :param vlan: :return: """ if not isinstance(vlan, int): vlan = int(vlan) if not is_vlan(vlan): return False for p in vlan_filter.split(","): p = p.strip() if not p: continue if "-" in p: # Range match = rx_range.match(p) if match: try: f, t = [int(x) for x in match.groups()] if f <= vlan <= t: return True except ValueError: pass else: # Single value try: v = int(p) if v == vlan: return True except ValueError: pass return False
def get_switchport( self) -> DefaultDict[int, Dict[str, Union[int, list, None]]]: result = defaultdict(lambda: { "tagged_vlans": [], "untagged_vlan": None }) pid_ifindex_mappings = self.get_bridge_ifindex_mappings() self.logger.debug("PID <-> ifindex mappings: %s", pid_ifindex_mappings) for oid, pvid in self.snmp.getnext( mib["Q-BRIDGE-MIB::dot1qPvid"], max_repetitions=self.get_max_repetitions(), max_retries=self.get_getnext_retires(), timeout=self.get_snmp_timeout(), ): if not pvid: # if pvid is 0 continue elif not is_vlan(pvid): # on Alcatel DSLAM it 16777217 self.logger.warning( "Bad value for untagged vlan.Skipping.. oid %s: vlan %s", oid, pvid) continue o = int(oid.split(".")[-1]) if o in pid_ifindex_mappings: o = pid_ifindex_mappings[o] else: self.logger.warning( "PortID %s not in ifindex mapping. Use as is", o) result[o]["untagged_vlan"] = pvid for oid, ports_mask in self.snmp.getnext( mib["Q-BRIDGE-MIB::dot1qVlanCurrentEgressPorts"], max_repetitions=self.get_max_repetitions(), max_retries=self.get_getnext_retires(), display_hints={ mib["Q-BRIDGE-MIB::dot1qVlanCurrentEgressPorts"]: render_bin }, timeout=self.get_snmp_timeout(), ): vlan_num = int(oid.split(".")[-1]) # Getting port as mask, convert to vlan: Iface list for port, is_egress in enumerate(chain.from_iterable( "{0:08b}".format(mask) for mask in ports_mask), start=1): if is_egress == "0": continue elif port not in pid_ifindex_mappings: self.logger.error("Port %s not in PID mappings", port) continue elif vlan_num == result[ pid_ifindex_mappings[port]]["untagged_vlan"]: continue result[pid_ifindex_mappings[port]]["tagged_vlans"] += [ vlan_num ] return result
def execute_snmp(self, interface=None, vlan=None, mac=None): r = [] iface_map = self.get_iface_mapping() self.logger.debug("Interface map: %s", iface_map) port_oid = mib["Q-BRIDGE-MIB::dot1qTpFdbPort"] status_oid = mib["Q-BRIDGE-MIB::dot1qTpFdbStatus"] if vlan: port_oid = mib["Q-BRIDGE-MIB::dot1qTpFdbPort", vlan] status_oid = mib["Q-BRIDGE-MIB::dot1qTpFdbStatus", vlan] mac_port = {} for r_oid, iface in self.snmp.getnext( port_oid, max_repetitions=self.get_max_repetitions(), max_retries=self.get_getnext_retires(), bulk=self.get_bulk(), ): if not iface: # For iface == 0 continue r_oid = tuple(r_oid.rsplit(".", 7)[-7:]) if iface not in iface_map: self.logger.error( "Unknown interface index %s, for MAC: %s", iface, ":".join("%02x" % int(c) for c in r_oid[1:]), ) continue iface = iface_map[iface] if interface and iface != interface: continue mac_port[r_oid] = iface # Apply status for r_oid, status in self.snmp.getnext( status_oid, max_repetitions=self.get_max_repetitions(), max_retries=self.get_getnext_retires(), bulk=self.get_bulk(), ): r_oid = tuple(r_oid.rsplit(".", 7)[-7:]) if r_oid not in mac_port: continue vlan_id, mac = r_oid[0], ":".join("%02x" % int(c) for c in r_oid[1:]) # Some devices return CPU/management vlan as 0 if vlan_id != "0" and not is_vlan(vlan_id): # Found vlan `4155` on Eltex MES-3124F fw 2.5.48.6 self.logger.error( "Invalid vlan number %s, for MAC: %s, Port: %s", vlan_id, mac, mac_port[r_oid]) continue r += [{ "interfaces": [mac_port[r_oid]], "mac": mac, "type": self.mac_status_map[status], "vlan_id": max(int(vlan_id), 1), }] return r
def execute_cli(self): # Get switchports and fill tagged/untagged lists if they are not empty switchports = self.get_switchport_cli() # Get portchannels portchannel_members = {} for pc in self.scripts.get_portchannel(): i = pc["interface"] t = pc["type"] == "L" for m in pc["members"]: portchannel_members[m] = (i, t) # Get IPv4 interfaces ipv4_interfaces = defaultdict(list) # interface -> [ipv4 addresses] c_iface = None for line in self.cli("display ip interface").splitlines(): match = self.rx_dis_ip_int.search(line) if match: c_iface = self.profile.convert_interface_name(match.group("interface")) continue # Primary ip match = self.rx_ip.search(line) if not match: continue ip = match.group("ip") ipv4_interfaces[c_iface] += [ip] # interfaces = {} # Get OSPF interfaces ospfs = self.get_ospfint() # Get NDP interfaces ndps = self.get_ndpint() # Get ifindexes ifindexes = self.get_ifindex() # Get STP interfaces stps = self.get_stpint() # Get LLDP interfaces lldps = self.get_lldpint() # Get VRRP interfaces vrrps = self.get_vrrpint() v = self.cli("display interface", cached=True) il = self.rx_iface_sep.split(v)[1:] for full_ifname, data in zip(il[::2], il[1::2]): ifname = self.profile.convert_interface_name(full_ifname) if ifname.startswith("NULL"): continue # I do not known, what are these if ifname.startswith("DCN-Serial") or ifname.startswith("Cpos-Trunk"): continue sub = { "name": ifname, "admin_status": True, "oper_status": True, "enabled_protocols": [], "enabled_afi": [], } if ifname in switchports and ifname not in portchannel_members: # Bridge sub["enabled_afi"] += ["BRIDGE"] u, t = switchports[ifname]["untagged"], switchports[ifname].get("tagged") if u: sub["untagged_vlan"] = u if t: sub["tagged_vlans"] = t elif ifname in ipv4_interfaces: # IPv4 sub["enabled_afi"] = ["IPv4"] sub["ipv4_addresses"] = ipv4_interfaces[ifname] if ifname in ospfs: # OSPF sub["enabled_protocols"] += ["OSPF"] if ifname.lower().startswith("vlanif"): # SVI sub["vlan_ids"] = [int(ifname[6:].strip())] if ifname.lower().startswith("vlan-interface"): # SVI sub["vlan_ids"] = [int(ifname[14:].strip())] # Parse data ifindex = self.rx_inline_ifindex.search(data) a_stat, data = data.split("\n", 1) a_stat = a_stat.lower().endswith("up") o_stat = None for line in data.splitlines(): line = line.strip() # Oper. status if o_stat is None: match = self.rx_line_proto.search(line) if match: o_stat = match.group("o_state").lower().endswith("up") continue # Process description if line.startswith("Description:"): d = line[12:].strip() if d != "---": sub["description"] = d continue # Process description if line.startswith("Description :"): d = line[13:].strip() if d != "---": sub["description"] = d continue # MAC if not sub.get("mac"): match = self.rx_mac.search(line) if match and match.group("mac") != "0000-0000-0000": sub["mac"] = match.group("mac") continue # Static vlans match = self.rx_pvid.search(line) if match and "untagged_vlan" not in sub: sub["untagged_vlan"] = int(match.group("pvid")) if "BRIDGE" not in sub["enabled_afi"]: sub["enabled_afi"] += ["BRIDGE"] continue # Static vlans if line.startswith("Encapsulation "): enc = line[14:] if enc.startswith("802.1Q"): sub["vlan_ids"] = [enc.split(",")[2].split()[2]] continue # MTU match = self.rx_mtu.search(line) if match: sub["mtu"] = int(match.group("mtu")) continue # IP Unnumbered match = self.rx_ipv4_unnumb.search(line) if match: sub["ip_unnumbered_subinterface"] = match.group("iface") sub["enabled_afi"] = ["IPv4"] continue if "." not in ifname: if o_stat is None: o_stat = False match = self.rx_iftype.match(ifname) iftype = self.profile.get_interface_type(match.group(1)) if iftype is None: self.logger.info("Iface name %s, type unknown", match.group(1)) continue # Skip ignored interfaces iface = { "name": ifname, "admin_status": a_stat, "oper_status": o_stat, "type": iftype, "enabled_protocols": [], "subinterfaces": [sub], } if ifname in ifindexes: iface["snmp_ifindex"] = int(ifindexes[ifname], 16) elif ifindex: iface["snmp_ifindex"] = int(ifindex.group("ifindex")) if "mac" in sub: iface["mac"] = sub["mac"] if "description" in sub: iface["description"] = sub["description"] if ifname in ndps: # NDP iface["enabled_protocols"] += ["NDP"] if ifname in stps: # STP iface["enabled_protocols"] += ["STP"] if ifname in lldps: # LLDP iface["enabled_protocols"] += ["LLDP"] if ifname in vrrps.keys(): # VRRP sub["enabled_protocols"] += ["VRRP"] sub["ipv4_addresses"] += vrrps[ifname] # Portchannel member if ifname in portchannel_members: ai, is_lacp = portchannel_members[ifname] iface["aggregated_interface"] = ai iface["subinterfaces"] = [] if is_lacp: iface["enabled_protocols"] += ["LACP"] interfaces[ifname] = iface else: if ifindex: sub["snmp_ifindex"] = int(ifindex.group("ifindex")) ifname, vlan_id = ifname.split(".") if is_vlan(vlan_id): sub["vlan_ids"] = [vlan_id] interfaces[ifname]["subinterfaces"] += [sub] # VRF and forwarding_instance proccessed vrfs, vrf_if_map = self.get_mpls_vpn_mappings() for i in interfaces.keys(): iface_vrf = "default" subs = interfaces[i]["subinterfaces"] interfaces[i]["subinterfaces"] = [] if i in vrf_if_map: iface_vrf = vrf_if_map[i] vrfs[vrf_if_map[i]]["interfaces"] += [interfaces[i]] else: vrfs["default"]["interfaces"] += [interfaces[i]] for s in subs: if s["name"] in vrf_if_map and vrf_if_map[s["name"]] != iface_vrf: vrfs[vrf_if_map[s["name"]]]["interfaces"] += [ { "name": s["name"], "type": "other", "enabled_protocols": [], "subinterfaces": [s], } ] else: interfaces[i]["subinterfaces"] += [s] return list(vrfs.values())
def get_base_router(self): fi = {"forwarding_instance": "default", "type": "ip", "interfaces": []} port_info = self.cli("show port") for line in port_info.splitlines(): match = self.re_port_info.search(line) if match: port_detail = self.cli("show port %s detail" % match.group("name")) match_detail = self.re_port_detail_info.search(port_detail) if not match_detail: match_detail = self.re_port_detail_info_sr.search(port_detail) my_dict = match.groupdict() my_dict.update(match_detail.groupdict()) if "aggregated_interface" in my_dict: if is_int(my_dict["aggregated_interface"]): my_dict["aggregated_interface"] = "-".join( ["lag", my_dict["aggregated_interface"]] ) else: del my_dict["aggregated_interface"] my_dict["type"] = "physical" my_dict["subinterfaces"] = [] my_dict.pop("bad_stat") my_dict["description"] = my_dict["description"].replace("\n", "") fi["interfaces"].append(my_dict) lag_info = self.cli("show lag detail") lags = self.re_lag_split.split(lag_info) for lag in lags[1:]: match = self.re_lag_detail.search(lag) if match: my_dict = match.groupdict() my_dict["type"] = "aggregated" if my_dict["name"]: my_dict["name"] = "-".join(["lag", my_dict["name"]]) my_dict["subinterfaces"] = [] saps = self.cli( "show service sap-using sap %s | match invert-match [" % my_dict["name"] ) for sapline in saps.splitlines(): sap = self.re_lag_subs.match(sapline) if sap: if sap.group("physname"): vlans = sap.group("sapname") s = { "name": ":".join([sap.group("physname"), vlans]), "admin_status": self.fix_status(sap.group("admin_status")), "oper_status": self.fix_status(sap.group("admin_status")), } if "." in vlans and "*" not in vlans: up_tag, down_tag = vlans.split(".") if is_vlan(down_tag): s["vlan_ids"] = [int(up_tag), int(down_tag)] else: s["vlan_ids"] = [int(up_tag)] elif "*" in vlans: s["vlan_ids"] = [] elif int(vlans) == 0: s["vlan_ids"] = [] else: s["vlan_ids"] = [int(vlans)] my_dict["subinterfaces"].append(s) my_dict["oper_status"] = self.fix_status(my_dict["oper_status"]) my_dict["admin_status"] = self.fix_status(my_dict["admin_status"]) if my_dict["protocols"].lower() == "enabled": my_dict["protocols"] = ["LACP"] else: my_dict["protocols"] = [] my_dict["description"] = my_dict["description"].replace("\n", "") fi["interfaces"].append(my_dict) intf = self.cli('show router "Base" interface detail') fi["interfaces"] += self.parse_interfaces(intf, fi["interfaces"]) return fi
def parse_interfaces(self, data, vrf): ifaces = self.re_int.split(data) result = [] iftypeVPRN = ": VPRN" iftypeNetwork = ": Network" iftypeSubsc = ": VPRN Sub" iftypeGroup = ": VPRN Grp" iftypeRed = ": VPRN Red" iftypeIES = ": IES" for iface in ifaces[1:]: parent_iface = "" my_dict = {} if iftypeGroup in iface: match_obj = self.re_int_desc_group.search(iface) if match_obj: my_dict = match_obj.groupdict() if not my_dict["mac"] or my_dict["mac"] == "": del my_dict["mac"] my_dict["type"] = "other" my_dict["subinterfaces"] = [] elif iftypeSubsc in iface: match_obj = self.re_int_desc_subs.search(iface) my_dict = match_obj.groupdict() my_dict["subinterfaces"] = [{}] my_dict["type"] = "loopback" my_sub = { "oper_status": my_dict["oper_status"], "admin_status": my_dict["admin_status"], "name": my_dict["name"], } if "enabled_afi" in my_dict: my_sub["enabled_afi"] = my_dict["enabled_afi"] my_dict.pop("enabled_afi") if "ipv4_addresses" in my_dict: my_sub["ipv4_addresses"] = my_dict["ipv4_addresses"] my_dict.pop("ipv4_addresses") if "ipv6_addresses" in my_dict: my_sub["ipv6_addresses"] = my_dict["ipv6_addresses"] my_dict.pop("ipv6_addresses") my_dict["subinterfaces"][0].update(my_sub) elif iftypeRed in iface: match_obj = self.re_int_desc_vprn.search(iface) my_dict = match_obj.groupdict() if "subinterfaces" in my_dict: my_dict["subinterfaces"] = [ {"name": my_dict["subinterfaces"], "type": "tunnel"} ] my_dict["type"] = "tunnel" elif iftypeNetwork in iface or iftypeVPRN in iface or iftypeIES in iface: match_obj = self.re_int_desc_vprn.search(iface) if match_obj: my_dict = match_obj.groupdict() if not my_dict.get("mac"): del my_dict["mac"] if "subinterfaces" in my_dict: if my_dict["subinterfaces"].startswith("sdp"): my_dict["type"] = "tunnel" elif my_dict["subinterfaces"].startswith("loopback"): my_dict["type"] = "loopback" match = self.re_iface.search(my_dict["subinterfaces"]) if match: parent_iface = match.group("iface") if ":" in my_dict["subinterfaces"]: vlans = my_dict["subinterfaces"].split(":")[1] if "." in vlans and "*" not in vlans: up_tag, down_tag = vlans.split(".") if is_vlan(down_tag): my_dict["vlan_ids"] = [int(up_tag), int(down_tag)] else: my_dict["vlan_ids"] = [int(up_tag)] elif "*" in vlans: my_dict["vlan_ids"] = [] elif int(vlans) == 0: my_dict["vlan_ids"] = [] else: my_dict["vlan_ids"] = [int(vlans)] my_dict["subinterfaces"] = [{"name": my_dict["name"]}] else: continue else: continue if my_dict["description"] == "(Not Specified)": my_dict.pop("description") proto = my_dict["protocols"] my_dict["protocols"] = self.fix_protocols(my_dict["protocols"]) if "srrp" in my_dict: my_dict["protocols"] += ["SRRP"] my_dict.pop("srrp") my_dict["oper_status"] = self.fix_status(my_dict["oper_status"]) my_dict["admin_status"] = self.fix_status(my_dict["admin_status"]) if "ipaddr_section" in my_dict: my_dict.update(self.fix_ip_addr(my_dict["ipaddr_section"])) my_dict.pop("ipaddr_section") if "subinterfaces" in my_dict: if not isinstance(my_dict["subinterfaces"], (list, dict)): my_dict["subinterfaces"] = [my_dict["subinterfaces"]] if len(my_dict["subinterfaces"]) == 1: my_sub = { "oper_status": my_dict["oper_status"], "admin_status": my_dict["admin_status"], "protocols": my_dict["protocols"], } my_dict.pop("protocols") if "enabled_afi" in my_dict: my_sub["enabled_afi"] = my_dict["enabled_afi"] my_dict.pop("enabled_afi") if "ipv4_addresses" in my_dict: my_sub["ipv4_addresses"] = my_dict["ipv4_addresses"] my_dict.pop("ipv4_addresses") if "ipv6_addresses" in my_dict: my_sub["ipv6_addresses"] = my_dict["ipv6_addresses"] my_dict.pop("ipv6_addresses") if "vlan_ids" in my_dict: my_sub["vlan_ids"] = my_dict["vlan_ids"] my_dict.pop("vlan_ids") if "MPLS" in proto: if "enabled_afi" in my_sub: my_sub["enabled_afi"] += ["MPLS"] else: my_sub["enabled_afi"] = ["MPLS"] if "mac" in my_dict and my_dict["mac"]: my_sub["mac"] = my_dict["mac"] if "mtu" in my_dict: my_sub["mtu"] = my_dict["mtu"] my_dict.pop("mtu") my_dict["subinterfaces"][0].update(my_sub) if vrf: found = False for i in vrf: if i["name"] == parent_iface: my_sub["name"] = my_dict["name"] i["subinterfaces"] += [my_sub] found = True break if found: continue if "type" not in my_dict: my_dict["type"] = "unknown" result += [my_dict] return result
def execute_cli(self): untagged = {} tagged = {} l3_ids = {} vlans_requested = False interfaces = {} ifaces = [] v = self.cli("show interfaces media | match interface:") ifaces = self.rx_phys.findall(v) for iface in ifaces: if not self.filter_interface(0, iface, True): continue v = self.cli("show interfaces %s" % iface) L = self.rx_log_split.split(v) phy = L.pop(0) phy = phy.replace(" )", "") match = self.rx_phy_name.search(phy) name = match.group("ifname") if name.endswith(")"): name = name[:-1] # Do not remove, additional verification if not self.filter_interface(0, name, True): continue # Detect interface type if name.startswith("lo"): iftype = "loopback" elif name.startswith(("fxp", "me")): iftype = "management" elif name.startswith(("ae", "reth", "fab", "swfab")): iftype = "aggregated" elif name.startswith(("vlan", "vme")): iftype = "SVI" elif name.startswith("irb"): iftype = "SVI" elif name.startswith( ("fc", "fe", "ge", "xe", "sxe", "xle", "et", "fte")): iftype = "physical" elif name.startswith(("gr", "ip", "st")): iftype = "tunnel" elif name.startswith("em"): if self.is_work_em: iftype = "physical" else: iftype = "management" else: iftype = "unknown" # Get interface parameters iface = { "name": name, "admin_status": match.group("admin").lower() == "enabled", "oper_status": match.group("oper").lower() == "up", "type": iftype, } def_si = { "name": name, "admin_status": match.group("admin").lower() == "enabled", "oper_status": match.group("oper").lower() == "up", } # Get description match = self.rx_phy_description.search(phy) if match and match.group("description") != "-=unused=-": iface["description"] = smart_text(match.group("description"), errors="ignore", encoding="ascii") # Get ifindex match = self.rx_phy_ifindex.search(phy) if match: iface["snmp_ifindex"] = match.group("ifindex") # Get MAC mac = None match = self.rx_phy_mac.search(phy) if match: mac = match.group("mac") iface["mac"] = mac def_si["mac"] = mac match = self.rx_mtu.search(phy) if match: def_si["mtu"] = match.group("mtu") # Process subinterfaeces subs = [] for s in L: match = self.rx_log_name.search(s) sname = match.group("name") if not self.profile.valid_interface_name(self, sname): continue si = { "name": sname, "snmp_ifindex": match.group("ifindex"), "admin_status": True, "oper_status": True, "enabled_afi": [], } if mac: si["mac"] = mac # Get MTU match = self.rx_mtu.search(s) if match: si["mtu"] = match.group("mtu") # Get description match = self.rx_phy_description.search(s) if match: si["description"] = smart_text(match.group("description"), errors="ignore", encoding="ascii") # Get vlans vlan_ids = [] match = self.rx_flags_vlan.search(s) if match: # Skip like this # Logical interface ge-0/0/13.0 (Index 143) (SNMP ifIndex 551) # Flags: Up 0x0 VLAN-Tag [ 0x0000.0 ] Encapsulation: ENET2 # Protocol aenet, AE bundle: ae0.0 if is_vlan(match.group("vlan")): vlan_ids = [int(match.group("vlan"))] if match.group("vlan2") and is_vlan(match.group("vlan2")): vlan_ids += [int(match.group("vlan2"))] # `irb` and `vlan` interfaces display other, # then `eth-switch` protocol if l3_ids.get(sname): vlan_ids = [l3_ids[sname]] # Process protocols for p in self.rx_log_protocol.split(s)[1:]: match = self.rx_log_pname.search(p) proto = match.group("proto") local_addresses = self.rx_log_address.findall(p) if proto == "iso": # Protocol ISO si["enabled_afi"] += ["ISO"] if local_addresses: si["iso_addresses"] = local_addresses elif proto == "mpls": # MPLS protocol si["enabled_afi"] += ["MPLS"] elif proto == "inet": # Protocol IPv4 si["enabled_afi"] += ["IPv4"] si["ipv4_addresses"] = [ "%s/32" % a for a in local_addresses ] # Find connected networks for match in self.rx_log_netaddress.finditer(p): net, addr = match.groups() n, m = net.split("/") si["ipv4_addresses"] += ["%s/%s" % (addr, m)] elif proto == "inet6": # Protocol IPv6 si["enabled_afi"] += ["IPv6"] si["ipv6_addresses"] = [ "%s/128" % a for a in local_addresses ] # Find connected networks for match in self.rx_log_netaddress6.finditer(p): net, addr = match.groups() n, m = net.split("/") si["ipv6_addresses"] += ["%s/%s" % (addr, m)] elif proto == "aenet": # Aggregated match = self.rx_log_ae.search(p) if match: bundle = match.group("bundle") iface["aggregated_interface"] = bundle elif proto.lower() == "eth-switch" or proto.lower( ) == "multiservice": if proto.lower() == "eth-switch": si["enabled_afi"] += ["BRIDGE"] if not vlans_requested: if self.is_switch and ( self.profile.command_exist(self, "vlans") or self.profile.command_exist( self, "vlan")): v = self.cli("show vlans detail") untagged, tagged, l3_ids = self.get_vlan_port_mapping( v) if not l3_ids: # Found in ex4500, Junos: 15.1R7.8 v = self.cli("show vlans extensive") untagged1, tagged1, l3_ids = self.get_vlan_port_mapping( v) vlans_requested = True if untagged.get(si["name"]): si["untagged_vlans"] = untagged[si["name"]] if tagged.get(si["name"]): si["tagged_vlans"] = sorted(tagged[si["name"]]) # Set vlan_ids for EX series if l3_ids.get(si["name"]): si["vlan_ids"] = [l3_ids[si["name"]]] # x = untagged.get(si["name"]) # if x: # si["untagged_vlans"] """ Why we are setting vlan_ids only on IP interfaces ? # Set vlan_ids if vlan_ids and ( "IPv4" in si["enabled_afi"] or "IPv6" in si["enabled_afi"] ): si["vlan_ids"] = vlan_ids """ if vlan_ids: si["vlan_ids"] = vlan_ids if self.rx_flags_unnumbered.search(s): match = self.rx_iface_unnumbered.search(s) if match: si["ip_unnumbered_subinterface"] = match.group("name") # Get tunnel type if iface["type"] == "tunnel": si["tunnel"] = {} if sname.startswith("ip"): si["tunnel"]["type"] = "IPIP" elif sname.startswith("st"): si["tunnel"]["type"] = "IPsec" elif sname.startswith("gr"): si["tunnel"]["type"] = "GRE" match = self.rx_ppp_address.search(s) if match and int(match.group("proto")) == 47: # GRE si["tunnel"]["local_address"] = match.group("src") si["tunnel"]["remote_address"] = match.group("dst") else: raise self.NotSupportedError("Unknown tunnel type") # Append to subinterfaces list subs += [si] if not subs: subs += [def_si] # Append to collected interfaces iface["subinterfaces"] = subs interfaces[name] = iface time.sleep(1) # VRF and forwarding_instance proccessed vrfs, vrf_if_map = self.get_mpls_vpn_mappings() for i in interfaces.keys(): iface_vrf = "default" subs = interfaces[i]["subinterfaces"] interfaces[i]["subinterfaces"] = [] if i in vrf_if_map: iface_vrf = vrf_if_map[i] vrfs[vrf_if_map[i]]["interfaces"] += [interfaces[i]] else: vrfs["default"]["interfaces"] += [interfaces[i]] for s in subs: if s["name"] in vrf_if_map and vrf_if_map[ s["name"]] != iface_vrf: vrfs[vrf_if_map[s["name"]]]["interfaces"] += [{ "name": s["name"], "type": "other", "enabled_protocols": [], "subinterfaces": [s], }] else: interfaces[i]["subinterfaces"] += [s] return list(vrfs.values())
def execute_snmp(self, **kwargs): ifaces = {} # For interfaces subifaces = {} # For subinterfaces like Fa 0/1.XXX switchports = self.get_switchport() portchannels = self.get_portchannels() # portchannel map ips = self.get_ip_ifaces() # Getting initial iface info, filter result if needed for iface in self.scripts.get_interface_properties( enable_ifindex=True, enable_oper_status=True): if not self.filter_interface(iface["ifindex"], iface["interface"], iface.get("oper_status")): continue if "." in iface["interface"]: subifaces[iface["ifindex"]] = { "name": iface["interface"], "snmp_ifindex": iface["ifindex"], "oper_status": iface.get("oper_status", True), } # if "mac" in iface: # subifaces[iface["ifindex"]]["mac"] = iface["mac"] else: ifaces[iface["ifindex"]] = { "name": iface["interface"], "snmp_ifindex": iface["ifindex"], "oper_status": iface.get("oper_status", True), "enabled_protocols": [], "subinterfaces": [], } # if "mac" in iface: # ifaces[iface["ifindex"]]["mac"] = iface["mac"] # Fill interface info iter_tables = [] iter_tables += [ self.iter_iftable( "admin_status", self.SNMP_ADMIN_STATUS_TABLE, ifindexes=ifaces, clean=self.clean_status, ) ] iter_tables += [ self.iter_iftable("mac", self.SNMP_MAC_TABLE, ifindexes=ifaces, clean=self.clean_mac) ] iter_tables += [ self.iter_iftable( "description", self.SNMP_IF_DESCR_TABLE, ifindexes=chain(ifaces, subifaces), clean=self.clean_ifdescription, ) ] iter_tables += [ self.iter_iftable("mtu", "IF-MIB::ifMtu", ifindexes=chain(ifaces, subifaces), clean=self.clean_mtu) ] # Collect and merge results data = self.merge_tables(*tuple(iter_tables)) if not ifaces: # If empty result - raise error raise NotImplementedError # Format result to ifname -> iface interfaces = {} for ifindex, iface in ifaces.items(): if ifindex in data: iface.update(data[ifindex]) iface["type"] = self.clean_iftype(iface["name"], ifindex) if not iface["type"]: self.logger.error("Unknown type for interface %s", iface["name"]) continue if ifindex in ips: iface["subinterfaces"] += [{ "name": iface["name"], "enabled_afi": ["IPv4"], "ipv4_addresses": [IPv4(*i) for i in ips[ifindex]], }] if ifindex in switchports: sub = { "name": iface["name"], "enabled_afi": ["BRIDGE"], } sub.update(switchports[ifindex]) iface["subinterfaces"] += [sub] if ifindex in portchannels: iface["aggregated_interface"] = ifaces[ portchannels[ifindex]]["name"] iface["enabled_protocols"] = ["LACP"] interfaces[iface["name"]] = iface # Proccessed subinterfaces for ifindex, sub in subifaces.items(): ifname, num = sub["name"].split(".", 1) if ifname not in interfaces: self.logger.info("Sub %s for ignored iface %s", sub["name"], ifname) continue if ifindex in data: sub.update(data[ifindex]) if ifindex in ips: sub["enabled_afi"] = ["IPv4"] sub["ipv4_addresses"] = [IPv4(*i) for i in ips[ifindex]] if num.isdigit(): vlan_ids = int(sub["name"].rsplit(".", 1)[-1]) if is_vlan(vlan_ids): sub["vlan_ids"] = vlan_ids interfaces[ifname]["subinterfaces"] += [sub] # VRF and forwarding_instance proccessed vrfs, vrf_if_map = self.get_mpls_vpn_mappings() for i in interfaces.keys(): iface_vrf = "default" subs = interfaces[i]["subinterfaces"] interfaces[i]["subinterfaces"] = [] if i in vrf_if_map: iface_vrf = vrf_if_map[i] vrfs[vrf_if_map[i]]["interfaces"] += [interfaces[i]] else: vrfs["default"]["interfaces"] += [interfaces[i]] for s in subs: if s["name"] in vrf_if_map and vrf_if_map[ s["name"]] != iface_vrf: vrfs[vrf_if_map[s["name"]]]["interfaces"] += [{ "name": s["name"], "type": "other", "enabled_protocols": [], "subinterfaces": [s], }] else: interfaces[i]["subinterfaces"] += [s] return list(vrfs.values())
def execute_cli(self): interfaces = [] v = self.cli("show interfaces") for match in self.rx_iface.finditer(v): ifname = match.group("ifname") admin_status = match.group("admin_status") == "up" oper_status = match.group("oper_status") == "up" iface = { "name": ifname, "type": self.profile.get_interface_type(ifname), "admin_status": admin_status, "oper_status": oper_status, } sub = { "name": ifname, "admin_status": admin_status, "oper_status": oper_status } if iface["type"] == "physical": sub["enabled_afi"] = ["BRIDGE"] if ifname.startswith("Gi"): sw_ifname = "gigabitethernet %s" % ifname[2:] elif ifname.startswith("Fa"): sw_ifname = "fastethernet %s" % ifname[2:] elif ifname.startswith("Ex"): sw_ifname = "extreme-ethernet %s" % ifname[2:] elif ifname.startswith("Te"): sw_ifname = "tengigabitethernet %s" % ifname[2:] elif ifname.startswith("Po"): sw_ifname = "port-channel %s" % ifname[2:] c = self.cli("show interfaces switchport %s" % sw_ifname) for i in parse_table(c, footer="^Forbidden VLANs:"): vlan_id = i[0] if not is_vlan(vlan_id): continue if i[2] == "Untagged": sub["untagged_vlan"] = vlan_id else: if "tagged_vlans" in sub: sub["tagged_vlans"] += [vlan_id] else: sub["tagged_vlans"] = [vlan_id] if iface["name"].startswith("vlan"): sub["vlan_ids"] = iface["name"][4:] if match.group("mac"): mac = match.group("mac").strip() iface["mac"] = mac sub["mac"] = mac if match.group("descr"): descr = match.group("descr").strip() iface["description"] = descr sub["description"] = descr iface["subinterfaces"] = [sub] interfaces += [iface] v = self.cli("show ip interface") for match in self.rx_ip_iface.finditer(v): ifname = match.group("ifname") for i in interfaces: if i["name"] == ifname: i["subinterfaces"][0]["enabled_afi"] = ["IPv4"] i["subinterfaces"][0]["ipv4_addresses"] = [ match.group("ip") ] break return [{"interfaces": interfaces}]
def test_is_vlan(raw, expected): assert is_vlan(raw) is expected