通过无线网络的主动管理之五:无线连接下的重定向

上一篇:通过无线网络的主动管理之四:其他AMT无线主动管理经验

      AMT的重定向功能对于远程诊断和修复来说,是非常有用的,其中重定向功能主要有三部分:SOL,IDER和KVM。当然KVM也可以不走重定向端口,直接走VNC的5900端口。对于远程诊断和修复来说,比较重要的一点是,在系统重启过程中,重定向连接是不能断的,否则控制台端不知道客户机端的情况。

      按照本系列文章前面几篇的介绍,我们知道在正常的情况下,AMT到无线热点的连接在操作系统启动过程中无线网卡加载后会自动断开,释放无线网卡给操作系统使用,由操作系统来连接无线热点;同时在关机过程中,会有上述相反的过程,操作系统释放对无线网卡的控制,然后有AMT重新控制无线网卡来连接无线热点。在这个过程中,由于有无线网卡控制权的转换,则无线网卡需要先断开到无线热点的连接,然后在控制权转换后,再次连接无线热点,中间将会出现一段时间内无线网卡没有IP地址。那么,结果就是,在这个过程中,通过无线放到到AMT的连接都将会被断开。由于重定向走的是TCP连接,和走SOAP的远程调用相比,这个连接是需要一直保持的,而无线网卡控制权的转变将会使得重定向的TCP连接无法一直保持,也就意味着基于无线主动管理的远程诊断和修复案例无法持续执行。

      在实际使用中,一般我们可能会考虑这样的折衷方法。比如,在操作系统控制无线网卡的时候来开始远程维护的任务,开启重定向连接;那么,在重启系统时,网络连接将会被断开,因为我们知道在重启后,AMT控制无线接口后在一段时间内无线接口将重新获取IP地址,这个时候重定向连接又可以成功了;所以,可以考虑等待一段时间再尝试连接,直到可以成功连接上为止。很明显,这种方法对用户的使用感来说不是很好,用户无法知道什么时候能再次连接上,并且会是什么原因导致最后无法连接上。是不是有更好的方法解决这个问题呢?当然是有的。

      Intel AMT的WS-Management调用在类AMT_EthernetPortSetting中提供了一个新的接口,名为SetLinkPreference,并且提供了LinkPreference成员,可以获取的当前的Link Preference状态。SetLinkPreference函数有两个参数,一个参数是LinkPreference,无符号整型,有两个有效值:1和2;1代表ME连接优先,2代表操作系统连接优先;另外一个参数是Timout,单位为秒,表示在设置LinkPreference为1后,多长时间自动将LinkPrefrence设为2,也就是这个参数只在LinkPreference设置为1的时候有效。AMT_EthernetPortSetting的LinkPreference成员可以用来检查当前的值为多少,但是需要注意一点的是,在读取LinkPrefrence值时,先要判断LinkPrefrenceExist是否为真,否则会异常。目前,此参数只在无线网卡上有效。

      很容易理解,SetLinkPreference函数提供了一种手动控制无线网卡被谁控制的功能。回到文章开头提到的远程诊断和修复,我们只需要在远程诊断过程中一直让AMT来控制无线网卡,前面的问题就解决了。大致过程是这样:首先通过SetLinkPreference设置由AMT来控制无线网卡;等待一段时间,当AMT控制的无线网卡正确连接到无线热点,并获取IP地址后,就可以按照有线连接的方式来执行远程诊断和修复了。只要当重定向连接没有断,无线网卡的控制权就一直有AMT所有,所以当重定向意外终端后,再此连接可能无法连接上了,因为可能无线网卡的控制权又回到了操作系统。这个时候还得按前面说得步骤,首先将控制权赋给AMT,再连接。

      下图就是从操作系统的无线网络管理工具能看到的通过SetLinkPreference设置无线控制权给AMT的前后变化,左图是设置前,右图是设置后。
  

      目前AMT的SDK中还没有这方面的参考代码,笔者根据SDK里面例子的样式,分别写了C++和C#的代码,供有兴趣的读者参考。

      SetLinkPreference C++ Sample;

#include "CIM_EthernetPort.h"
#include "AMT_EthernetPortSettings.h" 

// Set Link Prefrence for Wireless Interface
bool SetLinkPrefrence(ICimWsmanClient* wsmanClient)
{
         if( wsmanClient == NULL) return false;

          // Getting the EPR of CIM_ComputerSystem representing the Intel AMT
        CimReference computerSystemAMTRef = AssociationTraversalTypedUtils::DiscoverIntelAMT(wsmanClient); 

         // From the Intel AMT instance - Traversing CIM_EhternetPort
         vector<shared_ptr<CimBase>> sdPolicy = AssociationTraversalTypedUtils::EnumerateAssociated(wsmanClient, computerSystemAMTRef, "CIM_EthernetPort", "CIM_SystemDevice");

          for(unsigned int i=0; i<sdPolicy.size(); i++)
        {
                   CIM_EthernetPort eport = *((CIM_EthernetPort *)sdPolicy[i].get());

                   shared_ptr<CimBase> epsPtr = AssociationTraversalTypedUtils::GetAssociated(wsmanClient, eport.Reference(), "AMT_EthernetPortSettings", "CIM_ElementSettingData");

                   AMT_EthernetPortSettings epsetting = *((AMT_EthernetPortSettings *)epsPtr.get());
                   if( epsetting.LinkPreferenceExists())
                   {
                            AMT_EthernetPortSettings::SetLinkPreference_INPUT input;
                            input.LinkPreference(1);
                            input.Timeout(180);
                            int res_int = epsetting.SetLinkPreference(input);
                            if(res_int != 0) return false;
                   }
         }
         return true;
}

    SetLinkPreference C# Sample.

   … …
Collection<CimBase> sdPolicy = AssociationTraversalTypedUtils.EnumerateAssociated(_wsmanClient,   
                                                                                                      AssociationTraversalTypedUtils.DiscoverIntelAMT(_wsmanClient),
                                                                                                      typeof(CIM_EthernetPort),
                                                                                                      typeof(CIM_SystemDevice));

    // AMT might have a few network interfaces and each has it's own port
    foreach (CIM_EthernetPort element in sdPolicy)
    {
           // Traverse the relevant instance of the AMT_EthernetPortSettings using the ethernet port as EPR
        AMT_EthernetPortSettings cur = (AMT_EthernetPortSettings)AssociationTraversalTypedUtils.GetAssociated(_wsmanClient,
                                                                                                element.Reference,
                                                                                                typeof(AMT_EthernetPortSettings),
                                                                                                typeof(CIM_ElementSettingData));
        if (cur.LinkPreferenceExist)
        {
                  uint res_int = 0;
                   res_int = cur.SetLinkPreference(1, 180);
                  if(res_int != 0)
                  {
                                     // Do error handling here.
                      }
        }
        ...
Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.