Wednesday, August 14, 2013

Using C# to manage an Extreme Extremeware based switch via SNMP

This is to provide an example of a plug-in I wrote for the Green Monster System to manage an Extreme Networks ExtremeWare based switch.  This is there older line of switches

Most of these commands were determined via many hours with network sniffer as the MIBs do not expose the OIDs used here.

The SNMP commands are performed via a base class that uses Nsoftware's SSNMP library.  That class is not included because of licensing.

If you need help or have questions feel free to send me mail.

 public bool createVlan(int tag, string name)
        {
            //1.3.6.1.4.1.1916.1.2.1.2.1.1.22016 i 22016 
            //1.3.6.1.4.1.1916.1.2.1.2.1.2.22016 s testvlan 
            //1.3.6.1.4.1.1916.1.2.1.2.1.3.22016 i 1 
            //1.3.6.1.4.1.1916.1.2.1.2.1.4.22016 i 22016 
            //1.3.6.1.4.1.1916.1.2.1.2.1.6.22016 i 4

            //Get new Index

            //1.3.6.1.4.1.1916.1.2.3.1.1.2.22018 i 1 
            //1.3.6.1.4.1.1916.1.2.3.1.1.3.22018 i 124 
            //1.3.6.1.4.1.1916.1.2.3.1.1.4.22018 i 4

            //1.3.6.1.2.1.31.1.2.1.1.22016.22018 i 22016 
            //1.3.6.1.2.1.31.1.2.1.2.22016.22018 i 22018 
            //1.3.6.1.2.1.31.1.2.1.3.22016.22018 i 4

            //Query to get the next available index for this switch
            int index1 = getAvailableIndex();
            if (index1 == -1)
                return false;

            bool results = false;
            SNMPDataCollection request = new SNMPDataCollection();
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.1.2.1.1." + index1, index1, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.1.2.1.2." + index1, name, SNMPBase.datatypes.str));
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.1.2.1.3." + index1, 1, SNMPBase.datatypes.integer)); //Vlan Type
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.1.2.1.4." + index1, index1, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.1.2.1.6." + index1, 4, SNMPBase.datatypes.integer)); //Vlan status
            results = sendSNMP(request);

            if (results == false)
                return false;

            int index2 = getAvailableIndex();
            if (index2 == -1)
                return false;

            request = new SNMPDataCollection();

            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.3.1.1.2." + index2, 1, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.3.1.1.3." + index2, tag, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.2.3.1.1.4." + index2, 4, SNMPBase.datatypes.integer));
            results = sendSNMP(request);
            if (results == false)
                return false;

            request = new SNMPDataCollection();
            request.Add(new SNMPData("1.3.6.1.2.1.31.1.2.1.1." + index1 + "." + index2, index1, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.2.1.31.1.2.1.2." + index1 + "." + index2, index2, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.2.1.31.1.2.1.3." + index1 + "." + index2, 4, SNMPBase.datatypes.integer));

            return sendSNMP(request);
        }
        public bool deleteVlan(int tag)
        {
            int untaggedindex = getVlanIndexID(tag, false);
            int taggedindex = getVlanIndexID(tag, true);
            if (untaggedindex == -1 || taggedindex == -1)
                return false;

            bool result = false;

            //remove the untagged to tagged mapping
            result = sendSNMP("1.3.6.1.2.1.31.1.2.1.3." + untaggedindex + "." + taggedindex, 6);
            if (result == false)
            {
                return false;
            }

            result = sendSNMP("1.3.6.1.4.1.1916.1.2.3.1.1.4." + taggedindex, 6);
            if (result == false)
            {
                return false;
            }

            result = sendSNMP("1.3.6.1.4.1.1916.1.2.1.2.1.6." + untaggedindex, 6);
            if (result == false)
            {
                return false;
            }
            return true;
        }

        public bool addPortToVlan(int tag, int ifIndex, bool isTagged)
        {

            //get the slot and port info for the ifIndex
            //string slotdata = getSNMP("1.3.6.1.2.1.31.1.1.1.1." + ifIndex, SNMPBase.datatypes.str);
            //int slot = Convert.ToInt32(slotdata.Substring(0, slotdata.IndexOf("/")));
            //int port = Convert.ToInt32(slotdata.Substring(slotdata.IndexOf("/") + 1));

            //Get the Vlan's Index ID
            int vlanIndex = getVlanIndexID(tag, isTagged);
            if (vlanIndex == -1)
                return false;
            //int tagged;
            //if (isTagged)
            //{
            //    tagged = 1;
            //}
            //else
            //{
            //    tagged = 2;
            //}

            //1.3.6.1.4.1.1916.1.6.3.0 i 0 
            //1.3.6.1.2.1.31.1.2.1.3.22015.1002 i 4
            //undofailed = port already in another vlan
            SNMPDataCollection request = new SNMPDataCollection();
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.6.3.0", 0, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.2.1.31.1.2.1.3." + vlanIndex.ToString() + "." + ifIndex, 4));

            return sendSNMP(request);
        }

        public bool addFirstPorttoVlan(int tag, int ifIndex, bool isTagged, string vlanName)
        {
            //Extreme allows empty vlans so create the vlan then add the ports
            bool response = false;
            response = createVlan(tag, vlanName);
            if (response == false)
            {
                return false;
            }

            //add the port
            response = addPortToVlan(tag, ifIndex, isTagged);
            if (response == false)
            {
                return false;
            }

            return true;
        }
        public bool removePortFromVlan(int tag, int ifIndex)
        {

            //Get the Vlan's Index ID
            int vlanIndex = getVlanIndexID(tag, false);
            if (vlanIndex == -1)
                return false;

            SNMPDataCollection request = new SNMPDataCollection();
            request.Add(new SNMPData("1.3.6.1.4.1.1916.1.6.3.0", 0, SNMPBase.datatypes.integer));
            request.Add(new SNMPData("1.3.6.1.2.1.31.1.2.1.3." + vlanIndex.ToString() + "." + ifIndex, 6, SNMPBase.datatypes.integer));

            return sendSNMP(request);
        }
 public bool? isPortInVlan(int tag, int ifIndex, bool tagged)
        {
            string slotdata;
            if (getSNMP("1.3.6.1.2.1.31.1.1.1.1." + ifIndex, SNMPBase.datatypes.str, out slotdata) == false)
                return null;

            int slot = Convert.ToInt32(slotdata.Substring(0, slotdata.IndexOf("\\")));
            int port = Convert.ToInt32(slotdata.Substring(slotdata.IndexOf("\\") + 1));

            Byte[] vlanMembers;
            if (getVlanMembers(tag, slot, tagged, out vlanMembers) == false)
                return null;

            return isPortMember(port, vlanMembers);

        }

        public Raw_VlanMemberCollection GetVlanMembers(int tag)
        {
            Raw_VlanMemberCollection data = new Raw_VlanMemberCollection();

            //get the number of slots 
            //int slots = Convert.ToInt32(getSNMP("1.3.6.1.4.1.1916.1.1.2.1.0", SNMPBase.datatypes.integer));

            NetworkPortCollection Ports = getPorts(false);
            int slots = GetNumberofSlots(Ports);

            // we have to process vlan memberships for each slot
            for (int slot = 1; slot <= slots; slot++)
            {
                //Get Tagged vlan members for slot
                Byte[] vlanMembers;
                if (getVlanMembers(tag, slot, true, out vlanMembers) == false)
                {
                    data.isErrorState = true;
                    return data;
                }

                ArrayList members = GetMemberPorts(vlanMembers); //Get a list of each port number based on mask


                foreach (int p in members)
                {
                    NetworkPort port = Ports.Find(o => o.slotNumber == slot && o.portNumber == p);
                    if (port != null) //we found our port lets update the membership
                    {
                        Raw_VlanMember member = new Raw_VlanMember();
                        member.isTagged = true;
                        member.tag = tag;
                        member.port = port.portNumber;
                        member.slot = port.slotNumber;
                        member.PortifIndex = port.ifIndex;
                        data.Add(member);
                    }
                }

                //Get un-Tagged vlan members for slot
                if (getVlanMembers(tag, slot, false, out vlanMembers) == false)
                {
                    data.isErrorState = true;
                    return data;
                }

                members = GetMemberPorts(vlanMembers); //Get a list of each port number based on mask
                //Ports = getPorts();

                foreach (int p in members)
                {
                    NetworkPort port = Ports.Find(o => o.slotNumber == slot && o.portNumber == p);
                    if (port != null) //we found our port lets update the membership
                    {
                        Raw_VlanMember member = new Raw_VlanMember();
                        member.isTagged = false;
                        member.tag = tag;
                        member.port = port.portNumber;
                        member.slot = port.slotNumber;
                        member.PortifIndex = port.ifIndex;
                        data.Add(member);
                    }
                }
            }
            return data;
        }
        private int GetNumberofSlots(NetworkPortCollection ports)
        {
            int maxslot = 1; // start off with 1 slot

            foreach (NetworkPort p in ports)
            {
                if (p.slotNumber > maxslot)
                    maxslot = p.slotNumber;
            }
            return maxslot;
        }

        public VlanCollection getVlans()
        {
            VlanCollection Vlans = new VlanCollection();

            //Get All the Vlans
            SNMPDataCollection data = walk("1.3.6.1.4.1.1916.1.2.1.2.1.10");
            if (data.isErrorState == true)
            {
                Vlans.isErrorState = true;
                return Vlans;
            }
            foreach (SNMPData obj in data)
            {
                string vlanTag = obj.value.ToString(); //each value will be a vlan
                string oid = obj.oid;
                int ifIndex = Convert.ToInt32(oid.Replace("1.3.6.1.4.1.1916.1.2.1.2.1.10.", string.Empty));

                //Will include 4095 which is the Management Vlan
                Vlan vlan = new Vlan();
                vlan.tag = Convert.ToInt32(vlanTag);
                vlan.ifIndex = Convert.ToInt32(ifIndex);
                vlan.name = getVlanName(vlan.tag);
                Vlans.Add(vlan);
            }

            return Vlans;
        }

        public NetworkPortCollection getPorts()
        {
            return getPorts(false);
        }

        public NetworkPortCollection getPorts(bool getPortStatus)
        {
            NetworkPortCollection Ports = new NetworkPortCollection();
            //Populate ports 
            SNMPDataCollection data = walk("1.3.6.1.2.1.31.1.1.1.17");
            if (data.isErrorState == true)
            {
                Ports.isErrorState = true;
                return Ports;
            }
            foreach (SNMPData obj in data)
            {
                //the port enumeration also returns VLan ifIndex and Mgmt port IfIndex
                //We can use 1.3.6.1.2.1.31.1.1.1.17 to see if a connector is present (is it a real port)

                if (obj.value.ToString() == "1") //connector is present
                {
                    int ifIndex = Convert.ToInt32(obj.oid.ToString().Substring(obj.oid.ToString().LastIndexOf(".") + 1));
                    int port = ifIndex % 1000;
                    int slot = (ifIndex - port) / 1000;

                    if (slot == 0) // if it was slot 0 set it to slot 1
                    {
                        slot = 1;
                    }

                    //Get the ports description
                    string description;
                    getSNMP("1.3.6.1.2.1.31.1.1.1.1." + ifIndex, SNMPBase.datatypes.str, out description);
                    if (description.ToLower() != "mgmt" && description.ToLower() != "management" && description.ToLower() != "management port") //we dont want to add the management ports
                    {
                        Ports.Add(new NetworkPort(ifIndex, slot, port));
                    }
                }
            }

            //Get Ports information
            foreach (NetworkPort port in Ports)
            {
                port.name = getPortDescription(port.ifIndex);
                if (getPortStatus)
                {
                    port.adminStatus = getPortAdminStatus(port.ifIndex);
                    port.operationStatus = getPortOperationStatus(port.ifIndex);
                }
            }
            return Ports;
        }
 /// 
        /// Query switch for member array of a given Vlan, slot and tag
        /// 
        /// 
        /// 
        /// 
        /// Extreme Vlan member array
        private bool getVlanMembers(int tag, int slot, bool isTagged, out Byte[] members)
        {
            members = new Byte[0];
            //Get the Vlan's Index ID
            int vlanIndex = getVlanIndexID(tag, false);
            if (vlanIndex == -1)
                return true; //Vlan was not found on switch

            int tagged;
            if (isTagged)
                tagged = 1;
            else
                tagged = 2;


            return getSNMP("1.3.6.1.4.1.1916.1.2.6.1.1." + tagged + "." + vlanIndex + "." + slot, out members);
        }

        /// 
        /// Process Byte Array to determine member ports
        /// 
        /// 
        /// Returns an array for port numbers for a MemberByteArray
        private ArrayList GetMemberPorts(Byte[] memberbytes)
        {
            //Find out which bit positions are set in a byte.  Based off which position and byte we are in we can determine the port number
            //ie bit 7 in byte 0 = port 1
            //ie bit 0 in byte 0 = port 8
            ArrayList members = new ArrayList();

            int bytecoute = 0;
            int portNumber = 0;
            int result = 0;

            foreach (Byte b in memberbytes)
            {
                if (memberbytes[bytecoute] == 0)
                {
                    bytecoute++; //No ports where active in the Byte
                }
                else //if we have port membership in the Byte lets see which ports
                {

                    for (int i = 0; i < 8; i++)//Loop through each bit 
                    {
                        result = memberbytes[bytecoute] & PORTMASKARRAY[i]; //Is each bit value (port) in the array?
                        if (result == PORTMASKARRAY[i])
                        {
                            portNumber = i + 1 + bytecoute * 8;
                            members.Add(portNumber); //Add the portnumber to our returned list
                        }
                    }
                    bytecoute++;
                }
            }
            return members;
        }

        private int getVlanIndexID(int tag, bool tagged)
        {
            int untaggedindex = -1;
            int taggedindex = -1;
            //walk to get the vlans
            SNMPDataCollection data = walk("1.3.6.1.4.1.1916.1.2.1.2.1.10");
            if (data.isErrorState == true) 
                return -1;

            foreach (SNMPData item in data)
            {
                if (Convert.ToInt32(item.value) == tag)
                {
                    untaggedindex = Convert.ToInt32(item.oid.Replace("1.3.6.1.4.1.1916.1.2.1.2.1.10.", ""));
                    break;
                }
            }

            if (untaggedindex == -1)
                return -1;


            data = walk("1.3.6.1.4.1.1916.1.2.7.1.1.2." + untaggedindex);
            if (data.isErrorState == true)
                return -1;

            foreach (SNMPData item in data)
            {
                taggedindex = Convert.ToInt32(item.value);
                break;
            }

            if (tagged)
                return taggedindex;
            else
                return untaggedindex;
        }

        private static bool isPortMember(int portnumber, Byte[] membershipstream)
        {
            //Determine the port number we are working with for the given slot
            //Mod by 1000 to remove slot number; set remainder to portnumber
            portnumber %= 1000;

            Byte[] PORTMASKARRAY = { 128, 64, 32, 16, 8, 4, 2, 1 };
            return (membershipstream[(portnumber - 1) / 8] & PORTMASKARRAY[(portnumber - 1) % 8]) != 0;
        }

        /// 
        /// Extreme Byte Stream generation, used for modifing port membership in Vlan
        /// 
        /// portnumber to add/remove from vlan
        /// 
        private Byte[] ReneratePortByteStream(int portnumber, int MAXPORTSPERSLOT)
        {
            //Determine the port number we are working with for the given slot
            //Mod by 1000 to remove slot number; set remainder to portnumber
            //portnumber %= 1000;


            Byte[] holdingByte = null;

            //Create an Array to hold the changing value
            int bytesNeeded = MAXPORTSPERSLOT / 8 + (MAXPORTSPERSLOT % 8 <= 0 ? 0 : 1);
            holdingByte = new byte[bytesNeeded];

            //Determin which byte we are working with
            int byteposition = portnumber / 8;

            //Mod to find the bit we are working with 
            int maskindex = (portnumber - 1) % 8;

            //Set the value in our Holding array for the corisponding bit
            holdingByte[byteposition] |= PORTMASKARRAY[maskindex];

            return holdingByte;
        }

        private int getAvailableIndex()
        {
            string data;
            if (getSNMP("1.3.6.1.4.1.1916.1.2.2.1.0", SNMPBase.datatypes.integer, out data) == false)
                return -1;

            return Convert.ToInt32(data);
        }


        private string ConvertToHex(object bytearray)
        {

            byte[] ba = (byte[])bytearray;

            StringBuilder hex = new StringBuilder(ba.Length * 2);
            foreach (byte b in ba)
                hex.AppendFormat("{0:x2}", b);
            return hex.ToString();
        }

No comments: