IP4

IP全称Internet Protocol。

它算是整个网络协议中最重要的一部分,它的主要作用是在复杂的网络环境中,将数据包发送给最终的目的地址。

本文以IP4作为介绍对象。

需要注意,在网络协议中有Protocol这个词,而对应UEFI也有一个Protocol的概念,后者其实表示的是UEFI可调用的接口。

IP4的初始化驱动是Ip4Driver.c,它做的事情主要是以下的几个部分:

1. 通过Ip4CreateService()函数初始化IP4_SERVICE结构体;

2. 安装gEfiIp4ServiceBindingProtocolGuid对应的Protocol;

3. 参数配置;

4. 启动收发数据并处理的程序;

这一步是通过Ip4ReceiveFrame()函数来启动的,它注册了MNP接收到数据之后的回调函数,而在这个回调函数中又执行了Ip4ReceiveFrame(),形成了循环收发数据并处理的过程。

5. 启动定时器处理各种其它需要IP4来处理的情形,具体的就是下面的函数:

/**
  There are two steps for this the heart beat timer of IP4 service instance. 
  First, it times out all of its IP4 children's received-but-not-delivered 
  and transmitted-but-not-recycle packets, and provides time input for its 
  IGMP protocol.
  Second, a dedicated timer is used to poll underlying media status. In case 
  of cable swap, a new round auto configuration will be initiated. The timer 
  will signal the IP4 to run DHCP configuration again. IP4 driver will free
  old IP address related resource, such as route table and Interface, then
  initiate a DHCP process to acquire new IP, eventually create route table 
  for new IP address.

  @param[in]  Event                  The IP4 service instance's heart beat timer.
  @param[in]  Context                The IP4 service instance.

**/
VOID
EFIAPI
Ip4TimerTicking (
  IN EFI_EVENT              Event,
  IN VOID                   *Context
  )

下面首先介绍Ip4CreateService()函数创建的IP4_SERVICE结构体,然后是两个另外的重要的结构体:IP4_INTERFACE和IP4_PROTOCOL;

它们之间的区别大致是:

1. IP4_SERVICE描述的是一个网络设备的特征,它包括了其下的所有IP4_INTERFACE和IP4_PROTOCOL;

2. IP4_INTERFACE用于描述网络层的信息,比如IP地址等;

3. IP4_PROTOCOL主要用作底层的数据收发;

IP4_SERVICE和IP4_PROTOCOL在之前讲过的MNP和SNP中都有,算是UEFI实现的一部分;而IP4_INTERFACE更像是网络协议架构中的网络层的表现。

IP4_SERVICE structure

IP4_SERVICE位于Ip4Impl.h文件中,如下所示:

struct _IP4_SERVICE {
  UINT32                          Signature;
  EFI_SERVICE_BINDING_PROTOCOL    ServiceBinding;
  INTN                            State;

  //
  // List of all the IP instances and interfaces, and default
  // interface and route table and caches.
  //
  UINTN                           NumChildren;
  LIST_ENTRY                      Children;

  LIST_ENTRY                      Interfaces;

  IP4_INTERFACE                   *DefaultInterface;
  IP4_ROUTE_TABLE                 *DefaultRouteTable;

  //
  // Ip reassemble utilities, and IGMP data
  //
  IP4_ASSEMBLE_TABLE              Assemble;
  IGMP_SERVICE_DATA               IgmpCtrl;

  //
  // Low level protocol used by this service instance
  //
  EFI_HANDLE                      Image;
  EFI_HANDLE                      Controller;

  EFI_HANDLE                      MnpChildHandle;
  EFI_MANAGED_NETWORK_PROTOCOL    *Mnp;

  EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
  EFI_SIMPLE_NETWORK_MODE         SnpMode;

  EFI_EVENT                       Timer;

  EFI_EVENT                       ReconfigEvent;

  BOOLEAN                         Reconfig;

  //
  // Underlying media present status. 
  //
  BOOLEAN                         MediaPresent;

  //
  // IPv4 Configuration II Protocol instance
  //
  IP4_CONFIG2_INSTANCE            Ip4Config2Instance;

  CHAR16                          *MacString;

  UINT32                          MaxPacketSize;
  UINT32                          OldMaxPacketSize; ///< The MTU before IPsec enable.
};

这些值的介绍如下:

1. Signature:它的值是SIGNATURE_32 ('I', 'P', '4', 'S');

2. ServiceBinding:对应的就是IP4的ServiceBindingProtocol,下面有CreateChild()和DestroyChild()两个接口;

3. State:它有如下的值:

//
// The state of IP4 service. It starts from UNSTARTED. It transits
// to STARTED if autoconfigure is started. If default address is
// configured, it becomes CONFIGED. and if partly destroyed, it goes
// to DESTROY.
//
#define IP4_SERVICE_UNSTARTED   0
#define IP4_SERVICE_STARTED     1
#define IP4_SERVICE_CONFIGED    2
#define IP4_SERVICE_DESTROY     3

注释中已经说明白了各个状态的变换;

4. NumChildrenChildren:表示通过ServiceBindingProtocol的CreateChild()创建的子例,这个子例才是真正的IP4实例,类型是IP4_PROTOCOL

5. Interfaces:跟上面说的Children类似,不过这里的子例类型是IP4_INTERFACE,它在EFI_IP4_PROTOCOL的Configure()接口中会被初始化,后续还会进一步介绍这个结构体;

6. DefaultInterface:跟上面类似,不过上面的Interfaces是一个IP4_INTERFACE的链表,而这个是一个单独的IP4_INTERFACE,它在Ip4CreateService()的时候初始化,所以在创建好的IP4_SERVICE结构体中都有一个默认的IP4_INTERFACE;

7. DefaultRouteTable:默认的路由表,关于路由表的说明如下:

///
/// Each IP4 instance has its own route table. Each ServiceBinding
/// instance has a default route table and default address.
///
/// All the route table entries with the same mask are linked
/// together in one route area. For example, RouteArea[0] contains
/// the default routes. A route table also contains a route cache.
///
typedef struct _IP4_ROUTE_TABLE IP4_ROUTE_TABLE;

struct _IP4_ROUTE_TABLE {
  INTN                      RefCnt;
  UINT32                    TotalNum;
  LIST_ENTRY                RouteArea[IP4_MASK_NUM];
  IP4_ROUTE_TABLE           *Next;
  IP4_ROUTE_CACHE           Cache;
};

8. Assemble:关于它的介绍如下:

///
/// Each Ip service instance has an assemble table to reassemble
/// the packets before delivery to its children. It is organized
/// as hash table.
///
typedef struct {
  LIST_ENTRY      Bucket[IP4_ASSEMLE_HASH_SIZE];
} IP4_ASSEMBLE_TABLE;

9. IgmpCtrl:关于IgmpCtrl的介绍如下:

///
/// The IGMP status. Each IP4 service instance has a IGMP_SERVICE_DATA
/// attached. The Igmpv1QuerySeen remember whether the server on this
/// connected network is v1 or v2.
///
typedef struct {
  INTN                    Igmpv1QuerySeen;
  LIST_ENTRY              Groups;
} IGMP_SERVICE_DATA;

10. ImageController:对应的就是EFI_DRIVER_BINDING_PROTOCOL中的ImageHandle和DriverBindingHandle;

11. MnpChildHandleMnpMnpConfigDataSnpMode:都是当前Handle上挂载的MNP和SNP的信息,其中MnpConfigData在Ip4CreateService()中会做配置,并且还会在该函数中做好MNP的配置:

Status = Ip4ServiceConfigMnp (IpSb, TRUE);

在MNP的介绍中已经说过,MNP被Config之后该网络就真正开始运行了;

12. Timer:对应的处理函数是Ip4TimerTicking(),具体这个函数做了什么就不说了;

13. ReconfigEvent:对应的处理函数是Ip4AutoReconfigCallBack(),用于DHCP;

14. Reconfig:这个跟前面说的ReconfigEvent不是一回事儿,这里的Reconfig只是的是对应MNP是否重新配置;

15. MediaPresent:表示的是物理连接是否OK,也是从UNDI-SNP-MNP一层层传上来的;

16. Ip4Config2Instance:用于配置IP4的一个实例;

17. MacString:表示MAC地址的字符串;

18. MaxPacketSizeOldMaxPacketSize:直接列出它的计算方式:

IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);
  if (NetLibGetVlanId (IpSb->Controller) != 0) {
    //
    // This is a VLAN device, reduce MTU by VLAN tag length
    //
    IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;
  }
  IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;

IP4_INTERFACE structure

IP4_INTERFACE位于Ip4If.h文件中,如下所示(注释中所说的IP4 instance指的是IP4_PROTOCOL):

//
// Each IP4 instance has its own station address. All the instances
// with the same station address share a single interface structure.
// Each interface has its own ARP child, and shares one MNP child.
// Notice the special cases that DHCP can configure the interface
// with 0.0.0.0/0.0.0.0.
//
struct _IP4_INTERFACE {
  UINT32                        Signature;
  LIST_ENTRY                    Link;
  INTN                          RefCnt;

  //
  // IP address and subnet mask of the interface. It also contains
  // the subnet/net broadcast address for quick access. The fields
  // are invalid if (Configured == FALSE)
  //
  IP4_ADDR                      Ip;
  IP4_ADDR                      SubnetMask;
  IP4_ADDR                      SubnetBrdcast;
  IP4_ADDR                      NetBrdcast;
  BOOLEAN                       Configured;

  //
  // Handle used to create/destroy ARP child. All the IP children
  // share one MNP which is owned by IP service binding.
  //
  EFI_HANDLE                    Controller;
  EFI_HANDLE                    Image;

  EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;
  EFI_ARP_PROTOCOL              *Arp;
  EFI_HANDLE                    ArpHandle;

  //
  // Queues to keep the frames sent and waiting ARP request.
  //
  LIST_ENTRY                    ArpQues;
  LIST_ENTRY                    SentFrames;
  IP4_LINK_RX_TOKEN             *RecvRequest;

  //
  // The interface's MAC and broadcast MAC address.
  //
  EFI_MAC_ADDRESS               Mac;
  EFI_MAC_ADDRESS               BroadcastMac;
  UINT32                        HwaddrLen;

  //
  // All the IP instances that have the same IP/SubnetMask are linked
  // together through IpInstances. If any of the instance enables
  // promiscuous receive, PromiscRecv is true.
  //
  LIST_ENTRY                    IpInstances;
  BOOLEAN                       PromiscRecv;
};

IP4_PROTOCOL structure

IP4_PROTOCOL位于Ip4Impl.h中,如下所示:

struct _IP4_PROTOCOL {
  UINT32                    Signature;

  EFI_IP4_PROTOCOL          Ip4Proto;
  EFI_HANDLE                Handle;
  INTN                      State;

  IP4_SERVICE               *Service;
  LIST_ENTRY                Link;       // Link to all the IP protocol from the service

  //
  // User's transmit/receive tokens, and received/deliverd packets
  //
  NET_MAP                   RxTokens;
  NET_MAP                   TxTokens;   // map between (User's Token, IP4_TXTOKE_WRAP)
  LIST_ENTRY                Received;   // Received but not delivered packet
  LIST_ENTRY                Delivered;  // Delivered and to be recycled packets
  EFI_LOCK                  RecycleLock;

  //
  // Instance's address and route tables. There are two route tables.
  // RouteTable is used by the IP4 driver to route packet. EfiRouteTable
  // is used to communicate the current route info to the upper layer.
  //
  IP4_INTERFACE             *Interface;
  LIST_ENTRY                AddrLink;   // Ip instances with the same IP address.
  IP4_ROUTE_TABLE           *RouteTable;

  EFI_IP4_ROUTE_TABLE       *EfiRouteTable;
  UINT32                    EfiRouteCount;

  //
  // IGMP data for this instance
  //
  IP4_ADDR                  *Groups;    // stored in network byte order
  UINT32                    GroupCount;

  EFI_IP4_CONFIG_DATA       ConfigData;

};

IP4 Interface

这个的IP4 Interface就是指UEFI下的Protocol接口了:

///
/// The EFI IPv4 Protocol implements a simple packet-oriented interface that can be 
/// used by drivers, daemons, and applications to transmit and receive network packets.
///
struct _EFI_IP4_PROTOCOL {
  EFI_IP4_GET_MODE_DATA        GetModeData;
  EFI_IP4_CONFIGURE            Configure;
  EFI_IP4_GROUPS               Groups;
  EFI_IP4_ROUTES               Routes;
  EFI_IP4_TRANSMIT             Transmit;
  EFI_IP4_RECEIVE              Receive;
  EFI_IP4_CANCEL               Cancel;
  EFI_IP4_POLL                 Poll;
};

to be continued......