void NetworkInterfaceInfo::Get_NDD_STAT()

in source/code/scxsystemlib/networkinterface/networkinterface.cpp [1486:1771]


    void NetworkInterfaceInfo::Get_NDD_STAT(SCXHandle<NetworkInterfaceDependencies> deps)
    {
        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT entry");

       /* This function provides the support for those drivers which report 
        * speed related stats as part of configuration parameters.
        * (defined in header files: /usr/include/sys/cdli_*.h) 
        *
        * The list of supported drivers is as follows: 
        * kent_config for the PCI Ethernet Device Driver (22100020)
        * phxent for the 10/100 Mbps Ethernet PCI Adapter Device Driver (23100020)
        * scent for the 10/100 Mbps Ethernet PCI Adapter II Device Driver (1410ff01)
        * gxent for the Gigabit Ethernet-SX PCI Adapter Device Driver (14100401)
        * goent for Gigabit Ethernet-SX PCI-X Adapter Device Driver (14106802), 
        *   10/100/1000 Base-T Ethernet PCI-X Adapter Device Driver (14106902), 
        *   2-Port Gigabit Ethernet-SX PCI-X Adapter Device Driver (14108802), 
        *   2-Port 10/100/1000 Base-TX PCI-X Adapter Device Driver (14108902), 
        *   4-Port 10/100/1000 Base-TX PCI-X Adapter Device Driver (14101103), 
        *   4-Port 10/100/1000 Base-TX PCI-Exp Adapter Dev Driver(14106803), 
        *   2-Port Gigabit Ethernet-SX PCI-Express Adapter Device Driver
        *                                                     (14103f03), 
        *   2-Port 10/100/1000 Base-TX PCI-Express Adapter Device Driver 
        *                                                     (14104003).
        *
        * ment  Gigabit Ethernet-SX PCI-X Adapter Device Driver (14106703).
        *
        * hea for Host Ethernet Adapter Device Driver.
        *********************END OF SUPPORTED DRIVERS ************************************/

       /* This function doesn't provide the support for the following drivers 
        * due to the overlap of their device_type values with some of the 
        * above list drivers:
        * 
        * bent for the Gigabit Ethernet-SX Adapter Device Driver (e414a816).
        *  (reason: ENT_BT_PCI, ENT_UTP_PCI, ENT_BT_PCI_OTHER,and ENT_UTP_PCI_OTHER 
        *  have the same value as ENT_CENT_PCI_TX,ENT_UTP_PCI,
        *  ENT_GX_PCI_OTHER, ENT_UTP_PCI_OTHER(defined for gxent) respectively
        *
        * ment for Gigabit Ethernet-SX Adapter Device Driver (14101403)
        *   (reason: ENT_MT_SX_PCI has the same value as ENT_GX_PCI defined for gxent)
        *
        * kngent for the 10 Gigabit Ethernet-SR PCI-X 2.0 DDR Adapter Device 
        * Driver (1410eb02) and the 10 Gigabit Ethernet-LR PCI_X 2.0 DDR 
        * Adapter Device Driver (1410ec02).
        * (reason: ENT_KNGENT_LR_PCIX and ENT_KNGENT_SR_PCIX have the same value as 
        *  ENT_CENT_PCI_TX and ENT_EPENT_PCI_TX respectively (defined for 
        *  goent driver))
        */

        union ARG 
        {
            kent_all_stats_t kent;
            phxent_all_stats_t phxent;
            scent_all_stats_t scent;
            gxent_all_stats_t gxent;
            goent_all_stats_t goent;
            ment_all_stats_t ment;
            hea_all_stats_t hea;
            lncent_all_stats_t lncent;
            shient_all_stats_t shient;
        } arg; // Used for ioctl argument. 

        // First, we need to connect to the adapter in question.
        struct sockaddr_ndd_8022 sa;
        int s;

        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT Connecting to socket");
        s = socket(AF_NDD, SOCK_DGRAM, 0);
        if (s < 0)
        {
            std::wstringstream errMsg;
            errMsg.str(L"");
            errMsg << L"socket(AF_NDD,SOCK_DGRAM,0) failed. errno: " << errno << L"- interface: " << m_name;
            SCXCoreLib::SCXLogSeverity severity(suppressor.GetSeverity(SCXCoreLib::StrFrom(errMsg.str())));
            SCX_LOG(m_log, severity, errMsg.str());
            return;
        }

        // Close the resource through a helper class, should an exception happens. 
        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT Setting up AutoClose");
        AutoClose _fd(m_log, s);

        sa.sndd_8022_family = AF_NDD;
        sa.sndd_8022_len = sizeof(struct sockaddr_ndd_8022);
        sa.sndd_8022_filtertype = NS_TAP;
        sa.sndd_8022_filterlen = sizeof(ns_8022_t);
        strcpy((char *)sa.sndd_8022_nddname, SCXCoreLib::StrToUTF8(m_name).c_str());

        SCX_LOGTRACE(m_log, wstring(L"NetworkInterfaceInfo::Get_NDD_STAT Binding to socket") + m_name);
        if (deps->bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_ndd_8022)) < 0) 
        {
            // This is to log file name and line number along with the rest of error message.
            SCXCoreLib::SCXErrnoException e(L"bind() failed. errno: ", errno, SCXSRCLOCATION);
            SCX_LOGERROR(m_log, e.What());
            return;
        }

        int on = 1;
        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT Setting option SO_REUSEADDR");
        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
        {
            SCXCoreLib::SCXErrnoException e(L"setsockopt() failed. errno: ", errno, SCXSRCLOCATION);
            SCX_LOGERROR(m_log, e.What());
            return;
        }

        // Populate the ioctl argument accordingly. 
        // The ioctl argument for the stat related commands must be struct nddctl.
        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT Populating ioctl");
        nddctl ioctl_arg;
        ioctl_arg.nddctl_buflen = sizeof(ARG);
        ioctl_arg.nddctl_buf = (caddr_t)&arg;

        // Issue the ioctl command to get the device extended stats.
        // (http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.kernelext%2Fdoc%2Fkernextc%2Fndd_get_all_stats_devctrlop.htm)
        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT Issuing ioctl");
        if (deps->ioctl(s,NDD_GET_ALL_STATS,&ioctl_arg) < 0) 
        {
            SCXCoreLib::SCXErrnoException e(L"ioctl(s,NDD_GET_ALL_STATS,&arg) failed. errno: ", errno, SCXSRCLOCATION);
            SCX_LOGERROR(m_log, e.What());
            return;
        }
        m_autoSense = false;
        m_speed = 0;
        m_maxSpeed = 0;
        unsigned int device_type = arg.kent.ent_gen_stats.device_type;
        scxulong auto_speed = 0; // meida_speed, speed_negotiated, or link_negotiated.

        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT At device switch");

        // Find out which driver we are dealing with. 
        // If supported then retrieve the intended info.
        // (http://pic.dhe.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.kernelext%2Fdoc%2Fkernextc%2Fconfig.htm)
        switch (device_type)
        {
            // kent 
            case ENT_3COM:
            case ENT_IENT:
            case ENT_IEN_ISA:
            case ENT_LCE:
            case ENT_KEN_PCI:
            case ENT_LSA:
            case ENT_IEN_PCMCIA:
                // PCI Ethernet Adapter Device Driver (22100020) only supports the 
                // following additional configuration parameters
                // (speed is not one of them!):
                // Full Duplex, Hardware Transmit Queue, Hardware Receive Queue.
                m_maxSpeed = SPEED_100; // This is a 10/100Mbps Eth PCI adapter.
                break;

                // phxent
            case ENT_PHX_PCI:
            case ENT_CLVR_PCI:
            case ENT_PHX_INT_PCI:
            case ENT_CLVR_INT_PCI:
                m_maxSpeed = SPEED_100; // This is a 10/100Mbps Eth PCI adapter.
                set_speed(arg.phxent.phxent_stats.speed_selected, arg.phxent.phxent_stats.media_speed);
                break;

                // scent
            case ENT_SCENT_PCI:
                m_maxSpeed = SPEED_100; // This is a 10/100Mbps Eth PCI adapter.
                set_speed(arg.scent.scent_stats.speed_selected, arg.scent.scent_stats.speed_negotiated);
                break;

                // gxent
            case ENT_GX_PCI:
            case ENT_UTP_PCI:
            case ENT_GX_PCI_OTHER:
            case ENT_UTP_PCI_OTHER:
                m_maxSpeed = SPEED_1000; // This is a Gigabit Ethernet PCI adapter.
                auto_speed = arg.gxent.gxent_stats.link_negotiated;
                if (auto_speed & NDD_GXENT_LNK_10MB)
                {
                    auto_speed = MEDIA_10_FULL;
                }
                else if (auto_speed & NDD_GXENT_LNK_100MB) 
                {
                    auto_speed = MEDIA_100_FULL;
                }
                else if (auto_speed & NDD_GXENT_LNK_1000MB) 
                {
                    auto_speed = MEDIA_1000_FULL;
                }
                set_speed(arg.gxent.gxent_stats.speed_selected, auto_speed);
                break; 

                // goent
            case ENT_GOENT_PCI_TX:
            case ENT_GOENT_PCI_SX:
            case ENT_DENT_PCI_TX:
            case ENT_DENT_PCI_SX:
            case ENT_CENT_PCI_TX:
            case ENT_EPENT_PCI_TX:
            case ENT_EPENT_PCI_SX:
            case ENT_CLENT_PCI_TX:
                m_maxSpeed = SPEED_1000; // This is a Gigabit Ethernet PCI adapter.
                set_speed(arg.goent.goent_stats.speed_selected, arg.goent.goent_stats.speed_negotiated);
                break;

                // ment
            case ENT_SM_SX_PCI:
                m_maxSpeed = SPEED_1000; // This is a Gigabit Ethernet-SX Adapter. 
                auto_speed = arg.ment.ment_stats.link_negotiated;
                if (auto_speed & NDD_MENT_LNK_10MB)
                {
                    auto_speed = MEDIA_10_FULL;
                }
                else if (arg.ment.ment_stats.link_negotiated & NDD_MENT_LNK_100MB)
                {
                    auto_speed = MEDIA_100_FULL;
                }
                else if (arg.ment.ment_stats.link_negotiated & NDD_MENT_LNK_1000MB)
                {
                    auto_speed = MEDIA_1000_FULL;
                }
                set_speed(arg.ment.ment_stats.speed_selected, auto_speed);
                break;

                // lncent 
            case ENT_LNC_TYPE:
            case ENT_LNC_VF:
                //Support for Lancer drivers
                m_maxSpeed = SPEED_10000; // This is 10 Gigabit Ethernet PCI adapter.
                break;

            default:
                // Is it a Host Ethernet Adapter?
                // The reason I am using the sizeof() to indentify 
                // the HEA device type, is that there is no device type for it.
                // The ndd_2_flags in ndd_t structure represents the HEA device
                // type. I couldn't find a way to query the ndd_t structure. 
                // (I tried the NDD_GET_NDD command defined in ndd.h but 
                // it didn't work!

                if (ioctl_arg.nddctl_buflen = sizeof(hea_all_stats_t))
                {
                    switch(arg.hea.hea_stats.speed_selected)
                    {
                        case HEA_MEDIA_10_HALF:
                        case HEA_MEDIA_10_FULL:
                            m_speed = m_maxSpeed = SPEED_10;
                            break;

                        case HEA_MEDIA_100_HALF:
                        case HEA_MEDIA_100_FULL:
                            m_speed = m_maxSpeed = SPEED_100;
                            break;

                        case HEA_MEDIA_1000_FULL:
                            m_speed = m_maxSpeed = SPEED_1000;
                            break;

                        case HEA_MEDIA_10000_FULL:
                            m_speed = m_maxSpeed = SPEED_10000;
                            break;

                        case HEA_MEDIA_AUTO:
                            m_autoSense = true;
                            break;

                        default:
                            std::wstringstream errMsg;
                            errMsg.str(L"");
                            errMsg << L"Invalid seleced speed: " << arg.hea.hea_stats.speed_selected << L"- interface: " << m_name;
                            SCXCoreLib::SCXLogSeverity severity(suppressor.GetSeverity(SCXCoreLib::StrFrom(errMsg.str())));
                            SCX_LOG(m_log, severity, errMsg.str());
                            break;
                    }
                }
                else // Not supported driver.
                {
                    std::wstringstream errMsg;
                    errMsg.str(L"");
                    errMsg << L"The driver not supported for the interface: " << m_name << " with device type: " << device_type;
                    SCXCoreLib::SCXLogSeverity severity(suppressor.GetSeverity(SCXCoreLib::StrFrom(errMsg.str())));
                    SCX_LOG(m_log, severity, errMsg.str());
                }
                break;
        }

        SCX_LOGTRACE(m_log, L"NetworkInterfaceInfo::Get_NDD_STAT After device switch");

        m_knownAttributesMask |= eAutoSense;

    } // End of Get_NDD_STAT()