minix网络功能概述(5)

本文详细解析了IP协议的工作原理,包括IP模块的初始化过程、数据包的接收与发送流程、路由表的管理和维护等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

( 原文:http://www.nyx.net/~ctwong/minix/MinixNetworking.html
  文章借助了google的翻译功能,所以有些地方不太通顺,凑合着看吧   by hugion, 2009.5.25 )

 

ip.c
 
ip_init() is called in inet.c to perform initialization. ip_init initializes the ip_ass_table. The ip_ass_table is used to reassemble fragmented packets which are parts of the same datagram. ip_init calls either the function ipeth_init or ipps_init to initialize the functions for the array of ip_port_t structures (the table is called ip_port) which it uses to send messages and set ip addresses ie ip_dev_set_ipaddr, ip_dev_send, ip_dev_main. ip_port_t is defined in ip_int.h. 
ip_init ( )被称为在inet.c来执行初始化。 ip_init初始化ip_ass_table 。该ip_ass_table是用来重新零散包是相同报文头的数据。 ip_init调用函数ipeth_init或ipps_init初始化功能的一系列ip_port_t结构(表被称为ip_port ) ,其中使用发送报文和设置IP地址即ip_dev_set_ipaddr , ip_dev_send , ip_dev_main 。 ip_port_t定义在ip_int.h 。

 

The ip_port_table is the data structure which stores information for each network interface. There is a 1-1 correspondence between the network interfaces and the elements of the ip_port_table.
该ip_port_table是存储每个网络接口的数据结构信息。通讯网络接口和ip_port_table是一一对应的 。
 
ip_init initializes the ip_frame_id field with the current time. The ip_frame_id is used as the datagram id number for the outgoing datagram. ip_init then calls sr_add_minor to so that the user call ip directly in a system call through busing ips minor device number. Finally, ip_init calls ip_dev_main to perform some initialization. ip_dev_main is the network interface specific initialization.

ip_init初始化ip_frame_id域与当前的时间。该ip_frame_id用作为即将发出的数据报文编号。 ip_init然后调用sr_add_minor ,这样ip就直接使用次设备号进行系统调用,。最后, ip_init调用ip_dev_main执行一些初始化。 ip_dev_main是具体的网络接口初始化。
 
ip_open() is used in 2 differene ways: 1) by sr.c to get protocol specific information for the ip channel if the ip device was opened directly by the user ie (eg by calling Open(/dev/ip, whatever_mode_you_want) 2) by another protocol using the ip protocol (eg udp) calling it eg ip_open being called in udp_main by the udp protocol. ip_open returns an index in to the ip fd table array for the ip channel.  ip_open marks a upd fd as used, does some initialization, and sets the appropriate functions to get and put messages from and to a sr fd. It returns the index to the ip fd table for the ip fd_t element.
 
ip_open ( )是用来在2 种不同的方式: 1 ) sr.c得到议定的IP通道的具体信息,如果IP设备是用户直接打开(如调用open( /dev/ip, whatever_mode_you_want ) 2 )另一个协议使用IP协议(如UDP连接),如ip_open在udp_main的中被UDP协议调用。 ip_open返回ip通道在ip fd表的索引号。 ip_open标识所使用的udp fd,并执行一些初始化,并设定报文的获取和发送接口(和sr fd 打交道)。它返回IP fd_t元素。

 

ip_close implements the close system call on a ip file descriptor fd.
ip_close 实现ip文件描述符fd的关闭系统调用
 
ip_buffree is used by buf.c to release buffers.
ip_buffree 在  buf.c 中用来释放缓存
 
 
ip_read.c
 
ip_read() is called in 2 ways. 1) ip_read is called by a layer in order to read a packet. For example read_ip_packets attempts to read a packet by calling ip_read. 2) If a user process directly opens the ip device (eg by calling Open(/dev/ip, whatever_mode_you_want) then ip_read is called by the corresponding file descriptor in the sr_fd_table in sr.c. ip_read() is very similar to udp_read().

ip_read ( )在2种方式被调用。 1 ) ip_read被上层调用,以便读取包。例如read_ip_packets通过ip_read来读取一个包 。 2 )如果用户进程直接打开IP设备(如调用open(/dev/ip, whatever_mode_you_want ),然后ip_read被调用,相应的文件描述符在sr_fd_table在sr.c。 ip_read ( )非常相似udp_read ( ) 。
 
ip_read checks to see if there is a received packet in the if_rdbuf_head linked list. If there is it returns the packet to the user process by calling packet2user. If there is not it returns a NW_SUSPEND which suspends the user process.

ip_read检查,看看在if_rdbuf_head链表是否有收到的数据包。如果有,它调用packet2user将数据包传回到用户进程 。如果没有它返回一个NW_SUSPEND挂起用户进程。
 
ip_read first checks to see if the ip_fd_table element has been properly configured. This is checked by testing if the IFF_OPTSET flag is set.
ip_read第一次检查,看看ip_fd_table元素已正确配置。这是检查测试,如果IFF_OPTSET标志设置。
 
ip_arrived is called by the ethernet code or the psip code to inform ip that a new packet has just arrived.
ip_arrived 被以太网驱动或者psip 调用来通知收到一个新的包

 

ip_arrived calls ip_frag_chk to check the checksum and the header lengths. Next it checks the destination ip address of the packet.
ip_arrived 调用ip_frag_chk 检查校验和以及报文头长度. 接着检查目的报文的ip.
 
If the ip address of the packet is the same as the ip address of the port ip_port then ip_arrived calls ip_port_arrived to notify the port that a packet has arrived for the port. Next ip_arrived checks to see if the ip address is a broadcast address by calling broadcast_dst. If it is, it calls ip_port_arrive.

如果数据包的IP地址同port 表中的ip地址是一样的IP地址,t然后ip_arrived调用ip_port_arrived通知端口,一个数据包到达。下一步ip_arrived调用broadcast_dst检查IP地址是否是一个广播地址 。如果是,它调用ip_port_arrive 。
 
Next ip_arrived decrements the time to live (ih_ttl) field of the ip packet. Next ip_arrived calculates the checksum field (ih_hdr_chk) of the ip header by calling ip_hdr_chksum. ip_nettype returns the class type of the ip address eg Class A, Class B, etc. The possible class types of an ip address is defined in an rfc. If the class type is not A, B, or C, then the packet is discarded.

接着ip_arrived递减IP数据包生存期( ih_ttl )。然后ip_arrived调用ip_hdr_chksum 计算IP头的校验和字段( ih_hdr_chk )。 ip_nettype返回IP地址的类型例如: A类, B类等类别的可,类型的IP地址是指在符合RFC 。如果类类型不是A, B或C ,然后将数据包会被丢弃。
 
Next it looks up the destination in the route table of the port to look up to where ip_arrived should route the packet by calling iroute_frag. Suppose iroute_frag tells ip_arrived to route it to a different port ie network interface. If the route table entry has a gateway for that port then ip_arrived sends the packet to the gateway. If the destination is the same as the ip address of the other port then ip_arrived informs the other port a new packet has arrived by calling ip_port_arrive.  Next ip_arrived makes checks to see if the ip address is a broadcast address. Finally ip_arrived sends it to the other port.

下一步它在端口路由表来获得数据包目的地 ,来决定ip_arrived是否调用iroute_frag来对数据包进行路由。有可能iroute_frag会告诉ip_arrived路由到一个不同的端口即网络接口。如果路由表条目对该端口的入口有一个网关,然后ip_arrived发送数据包到网关。如果目的地同另一个端口IP地址相同,然后ip_arrived调用ip_port_arrive 通知该端口一个新的分组已经抵达。下一步ip_arrived使检查如果IP地址是否是一个广播地址。最后ip_arrived传送到其他港口。
 
Next ip_arrived checks to see if theres a gateway on the port. If not it throws an error.
下一步ip_arrived检查,看看该端口是否是网关的端口。如果不是抛出错误。
 
broadcast_dst returns 1 if the destination ip address dest is a broadcast address with respect to the port ip_port; else broadcast_dst returns 0. broadcast_dst looks at the net mask and subnet mask of ip_port to determine if dest is a broadcast address.

broadcast_dst返回1,如果目的地IP地址dest是一个广播地址 ;其他broadcast_dst返回0 。 broadcast_dst检查ip_port网络掩码和子网掩码 ,以确定是否dest是一个广播地址。
 
ip_port_arrive() notifies a port that a packet has arrived on the port (ie network interface). First it checks to see if the received packet is using fragementing so that its merely one packet in a fragmented datagram. It checks by checking the flags
ip_port_arrive ( )通知端口,一个数据包到达的端口(即网络接口) 。首先检查是否收到的数据包使用fragementing ,使其仅仅一包在一个支离破碎的数据。它通过检查标志来检查

 
if (ntohs(ip_hdr->ih_flags_fragoff) & (IH_FRAGOFF_MASK|IH_MORE_FRAGS))
 
If it is then ip_port_arrive calls reassemble to merge the packet with any other packet from the same datagram. If some of the packets of the datagram still havent arrived then reassemble() returns a null and the function ip_port_arrive is exited by calling return.
 
如果是,然后ip_port_arrive调用reassemble重新合并包(与任何其他数据包来自同一数据)。如果某些数据包的数据仍然到达抵达,然后reassemble( )返回一个空,ip_port_arrive就返回。

 

ip_port_arrive is very much like udp_ip_arrive. ip_port_arrive chooses which fd(s) to send the packet to. It does this by looking at the protocol field of the fd ie if_ipopt.nwio_proto. It first looks at the linked list whose head is pointed to by the ip_proto_any field of the port table entry. ip_proto_any is the head of a linked list of udp fds which receive messages on any local protocol. Then it looks at ip_proto which is a hash table of fds which receive messages on a specific protocol. If the udp fd is using the correct protocol, packet2user is called to put the packet in the queue of the fd.

ip_port_arrive非常像udp_ip_arrive 。 ip_port_arrive选择fd来传送数据包。为此,它会查找议fd的域即if_ipopt.nwio_proto 。它首先着查找链表由ip_proto_any领域的表项。 ip_proto_any是一个UDP fd的链表头,表明在本地任何端口接受报文。然后,它查找ip_proto,这是一个fd哈希表,这些fd表示特定的协议上接受报文。如果UDP fd是使用正确的协议, packet2user把数据包放在fd的队列中。

 
packet2user tries to send a packet to a layer or a user. If nothing is trying to read on the file descriptor fd at the time, then the packet is placed in the queue of the ip fd where the head of the queue is pointed to by if_rdbuf_head. If something is trying to read on the file descriptor fd, packet2user sends it to the user or layer trying to read on the file descriptor fd. If NWIO_RWDATONLY is set then the ip header is removed from the returned packet. The new packet is returned adjusting for the size as stored in if_rd_count which was set by the read system call. The packet is then sent back to the user by either calling if_put_pkt or if_put_userdata. if_put_pkt (when defined) is used to return received packets to the user  as in a read system call. if_put_userdata is used to return data from ioctl system calls. If if_put_pkt is defined the data is returned with the transfer size as a parameter; else if if_put_pkt is not defined, if_put_pkt is called twice in a way very similar to how udp_packet2user calls uf_put_userdata twice. The packet is then sent back to the user by calling if_put_userdata, and then an integer result is passed backed to the user by calling if_put_userdata again. If the size requested in the read system call is greater than or equal to the size of the packet, the size of the returned packet is returned as the integer result; else (ie size requested in the read system call is less than the size of the packet) the integer result returned is EPACKSIZE.

packet2user试图发送一个数据包到上层或用户。如果不尝试在文件描述符读取的时候,然后将数据包放置在IP fd队列中,if_rdbuf_head指向队列头。如果正在该文件描述符上读取的时候, packet2user传送到正在尝试读取的文件描述符用户或层。如果设置了NWIO_RWDATONLY,那么返回数据包的IP头就被移除。新的数据包返回的大小调整为存储在if_rd_count,其中正是通过读系统调用所确定的。通过调用if_put_pkt或if_put_userdata将数据返回给用户。 if_put_pkt (当定义)是用来接收数据包返回到用户在读取系统调用。 if_put_userdata是用来返回数据ioctl系统调用。如果if_put_pkt是指返回的数据与转让大小作为参数; if_put_pkt如果没有定义, if_put_pkt同udp_packet2user调用uf_put_userdata两次的方式十分相似。该数据包,然后调用if_put_userdata发回给用户 ,然后一个整数结果是通过对用户的支持,再次调用if_put_userdata。如果大小要求在阅读系统调用是大于或等于的大小数据包的大小传回的数据包返回的整数结果;别人(即大小要求在阅读系统调用不到的大小该数据包)的整数结果返回EPACKSIZE 。
 
ip_frag_chk checks the checksum and the header lengths and does other validations of the ip header.
ip_frag_chk检查校验和的标题长度,而且验证IP头的其他属性。

 

ip_arrived_broadcast  called by the network interface (psip or ethernet code) when a broadcast message has arrived. ip_arrived_broadcast calls ip_frag_chk to check the checksum and the header lengths. Next it checks the destination ip address of the packet. Next it checks if to see if the ip address is a broadcast address by calling broadcast_dst. If it is not, it throws an errors an exits the function; else ip_arrived_broadcast calls ip_port_arrive.
ip_arrived_broadcast 被所谓的网络接口调用(以太网psip或代码),当一个广播消息到来。 ip_arrived_broadcast调用ip_frag_chk检查校验和及头长度。下一步检查的目标IP地址的数据包。下一步,如果它检查,调用broadcast_dst看看IP地址是一个广播地址 。如果不是,它抛出一个错误的退出功能;其他ip_arrived_broadcast调用ip_port_arrive 。
 
Fragmentation is defined in the ip protocol. Check on the appropriate RFC. The data structure which handles a fragmented datagram is the ip_ass_t structure.
碎片是在IP协议定义的。查看相关的RFC 。数据结构处理,碎片的数据是ip_ass_t结构。
 
typedef struct ip_ass
{
    acc_t *ia_frags;
    int ia_min_ttl;
    ip_port_t *ia_port;
    time_t ia_first_time;
    ipaddr_t ia_srcaddr, ia_dstaddr;
    int ia_proto, ia_id;
} ip_ass_t;
 
ia_frags: points to a packet which is the head of linked list of packets. The linked list is a list of packets which are part of the same datagram.
        指向包的链表头的那一个包。链表列指拥有同样数据报头的数据包列表。      

  
ia_min_ttl: time to live for datagram. If (ia_first_time + ia_min_ttl) < (time when every packet for the packet has arrived - and hence can be reassembled) the datagram is dumped.
        数据报的生存时间。如果超出,数据报就被丢弃。       
ia_port: pointer to port in ip_port_table.
         指向ip port表的port
ia_first_time: initialized to 0. Time when first packet for the datagram arrived.
          初始化为0,指第一个数据报到达时间
ia_srcaddr: source ip address for packet(s) of datagram.
          数据报的源ip地址
ia_dstaddr: destination ip address for packet(s) of datagram.
          数据报的目的ip地址
ia_proto: protocol of packet(s) of datagram.
          数据报的协议类型
ia_id: datagram id number for datagram. Every packet for the same datagram should have the same datagram id number.
        数据包的报文id号,对于具有同样数据报的包拥有同样的数据报id号


reassemble(): reassemble attempts to reassemble a defragmented datagram which has been received in several different packets. First reassemble calls find_ass_ent to return a ip_ass_t structure. If no packet for the datagram had previously arrived a new ip_ass_t structure is returned by find_ass_ent; else if a packet for the datagram has already arrived then the previously used ip_ass_t structure is returned by find_ass_ent. Next if the packet just received is first packet received from the datagram, reassemble returns null. Then reassembles merges all the packets received for the datagram by calling merge_frags. If all of the packets for the datagram have all been received the completed datagram in returned by reassemble; else reassemble returns a null.
    重新企图重新一整理数据已经收到了几个不同的数据包。首先重新呼吁find_ass_ent返回一个ip_ass_t结构。如果没有数据包的数据曾到达一个新的ip_ass_t结构是由find_ass_ent ;如果其他的数据包已经到来那么以前使用ip_ass_t结构是由find_ass_ent 。下一步,如果包刚收到第一包收到数据,重新返回空。然后重新组合合并所有数据包收到的数据通过调用merge_frags 。如果所有的数据包的数据都已经收到了完成数据在重新返回;别人重新传回Null 。
 
find_ass_ent(): find_ass_ent returns a ip_ass_t structure for a fragmented datagram. The ip_ass_t structure is held in the ip_ass_table array. First find_ass_ent looks through the ip_ass_table array. If a packet of the datagram has already been received find_ass_ent returns the ip_ass_t structure which is already being used to reassemble the datagram; else it uses a new ip_ass_t structure for it.
           find_ass_ent返回ip_ass_t结构的零散数据。结构的ip_ass_t组成ip_ass_table阵列。首先find_ass_ent查找ip_ass_table。如果一个数据包的数据已经收到find_ass_ent返回ip_ass_t结构已被用于组装的数据;否则它采用了新的ip_ass_t结构的。
merge_frags(first, second): merge_frags merges two acc_t structures first and second so that the data in the first structure comes before the data in the second structure.
          merge_frags合并两个acc_t结构,第一和第二,这样的数据结构中的第一个收到的数据在第二结构。
ip_process_loopb():
 
ip_ioctl.c
 
ip_ioctl implements the ioctl system call on a ip device. A file descriptor to an ip device is obtained by using the open system call eg Open(/dev/ip, whatever_mode_you_want). The general description of what ioctl does depending on the request parameter are given in the ip.4 manual and therefore will not be covered here. The request parameter is the req parameter in the ip_ioctl function.

ip_ioctl实现IP设备的ioctl系统调用。对一个IP设备文件描述符是通过使用open(/dev/ip, whatever_mode_you_want)系统调用如打开 。一般说明什么ioctl并根据请求参数中给出的ip.4手册,因此将不包括在这里。请求参数是请求中的参数ip_ioctl功能。
 
reply_thr_get returns an integer result back to the user. It does this by calling if_get_userdata.
reply_thr_get返回一个整型结果返回给用户。为此,它调用if_get_userdata完成该功能 。
 
As mentioned before, for an ioctl call, you can return an integer result to the user either by calling sr_put_userdata(x, y, 0, 1) or sr_get_userdata(x, y, 0, 1). Since the ip_ioctl function is only called by sr.c and not by a layer/protocol (eg udp) , if_get_userdata/ if_put_userdata is always a pointer to the functions

如前所述,一个ioctl调用,您可以返回一个整型结果给用户或者调用sr_put_userdata(x, y, 0, 1) 或 sr_get_userdata(x, y, 0, 1)。自ip_ioctl功能只被sr.c调用而不是层/协议(如UDP连接) , if_get_userdata / if_put_userdata始终是一个指针的职能

 

sr_get_userdata /sr_put_userdata in sr.c. Hence it doesnt matter if we return an integer result by calling if_get_userdata or if_put_userdata. An integer result is returned to the user by calling sr_get_userdata in ip_ioctl.c by calling reply_thr_get.

sr_get_userdata/sr_put_userdata在sr.c.因此,调用if_get_userdata或if_put_userdata返回一个整数结果,就不是问题了 。一个整数结果返回, 调用sr_get_userdata,在ip_ioctl.c调用reply_thr_get时 。
 
ip_ioctl implements the system call in a way very similar to how udp_ioctl implements the ioctl system call. ip_ioctl calls if_get_userdata to get the structure passed in the ioctl system call.
ip_ioctl系统调用的实现方式同udp_ioctl系统调用的实现方式很类似。ip_ioctl调用if_get_userdata获取系统调用传输结构。
 
ip_ioctl is called with a request of NWIOSIPOPT to configure a ip channel ie a file descriptor which uses the ip protocol. In that case, ip_checkopt is called by ip_ioctl. ip_checkopt checks to make sure that the the configuration settings passed by the user are valid. If NWIO_HDR_O_SPEC is passed as a flag in the ioctl call the ip header options are checked by calling ip_chk_hdropt.

使用请求参数NWIOSIPOPT调用ip_ioctl来配置的IP通道(即IP协议使用的文件描述符)。在这种情况下,ip_ioctl调用ip_checkopt 。 ip_checkopt检查,以确保用户配置设置通过都是有效的。如果NWIO_HDR_O_SPEC是通过作为标志的ioctl调用,将会调用ip_chk_hdropt检查IP头选项。
 
ip_checkopt calls ip_hash_proto if the proposed configuration is valid.
ip_checkopt调用iip_hash_proto预期的配置是有效的。

 

ip_hash_proto() puts the ip_fd in the hash table ip_proto (if a protocol has been selected) or in the linked list ip_proto_any (if a protocol has not been selected) of the port table (if_port). ip_proto points to the hash table of fds which have selected a protocol. ip_proto_any points to the head of the linked list which have not selected a protocol.

ip_hash_proto ( )把ip_fd在哈希表ip_proto (如果议定书已选定)或链表ip_proto_any (如果协议没有被选中)端口表( if_port ) 。 ip_proto指向已经选择了一个协议哈希表的。 ip_proto_any指向没有选择了协议链表头。
 
ip_unhash_proto removes the ip_fd from the hash table ip_proto or linked list ip_proto_any of the port table (if_port).
ip_unhash_proto删除ip_fd,从哈希表ip_proto或链表ip_proto_any港口表( if_port ) 。
 
typedef struct ip_port
{
    int ip_flags, ip_dl_type;
    union
    {
        struct
        {
          int de_state;
          int de_flags;
          int de_port;
          int de_fd;
          acc_t *de_frame;
          acc_t *de_q_head;
          acc_t *de_q_tail;
          acc_t *de_arp_head;
          acc_t *de_arp_tail;
        } dl_eth;
        struct
        {
          int ps_port;
          acc_t *ps_send_head;
          acc_t *ps_send_tail;
        } dl_ps;
    } ip_dl;
    int ip_minor;
    ipaddr_t ip_ipaddr;
    ipaddr_t ip_netmask;
    ipaddr_t ip_subnetmask;
    u16_t ip_frame_id;
    u16_t ip_mss;
    ip_dev_t ip_dev_main;
    ip_dev_t ip_dev_set_ipaddr;
    ip_dev_send_t ip_dev_send;
    acc_t *ip_loopb_head;
    acc_t *ip_loopb_tail;
    event_t ip_loopb_event;
    struct ip_fd *ip_proto_any;
    struct ip_fd *ip_proto[IP_PROTO_HASH_NR];
} ip_port_t;
 
ip_minor: minor device number of ip device.
          ip设备的次设备号
ip_ipaddr: ip address of the associated network interface.
          相关联的网络接口的ip地址
ip_netmask: net mask of the ip address. The net mask of the ip address is determined from the class type (class A, B, C, D, E) of the ip address. Which class type determines which net mask if defined in the proper RFC.
           子网掩码的IP地址。子网掩码的IP地址是从类类型( A类,乙,丙,丁,戊类)的IP地址。这类类型确定哪些子网掩码如果界定在适当的RFC 。
ip_subnetmask: subnet mask of the ip address. Subnet mask define the subnet which the network interface belong to.
               子网掩码的IP地址。子网掩码确定的子网的网络接口属于。
ip_frame_id: used as the datagram id number for an outgoing datagram.
             发送数据的数据编号。
ip_mss: maximum segment size - maximum packet size of packet.
        最大分片大小-最大数据包大小的数据包。
ip_dev_main: set by network interface to the appropriate function which does some initialization and other things.
       网络接口所规定的函数指针,执行其他一些初始化的东西。
ip_dev_set_ipaddr: pointer to a function which is called when the ip address is set. If any calls are waiting for an ip address the calls are returned.
       函数指针,这是所谓的IP地址设置。
ip_dev_send: pointer to a function which is called when writing a packet to be sent.
       数据包发送的时候调用的函数指针   
ip_loopb_head:
 
ip_loopb_event:
 
ip_proto_any: head of linked list of fds which receive messages on any protocol.
         any方式接收报文的fd链表头.
ip_proto: hash table of fds which receive messages on a particular port.
         在指定端口接收消息的fd的hash表.
        
        
ip_write.c
 
ip_write(): ip_write is called to write a packet to a network interface.  ip_ ip_write () is called in 2 ways. 1) ip_write is called by a layer in order to write a packet. For example read_ip_packets attempts to read a packet by calling ip_write. 2) If a user process directly opens the ip device (eg by calling Open(/dev/ip, whatever_mode_you_want) then ip_write is called by the corresponding file descriptor in the sr_fd_table in sr.c. ip_write() is very similar to udp_write().
 
ip_write被称为写一包的网络接口。 ip_ ip_write ( )被称为在2种方式。 1 ) ip_write被称为上层,以便写一个数据包。例如read_ip_packets调用ip_write来读取数据包 。 2 )如果用户进程直接打开IP设备(如调用Open(/dev/ip, whatever_mode_you_want)然后则调用ip_write,被称为相应的文件描述符在sr.c的sr_fd_table表中。 ip_write ( )非常相似udp_write ( ) 。
 
ip_write() first checks if the requested bytes to write is greater than IP_MAX_PACKSIZE. If it is, then a EPACKSIZE error is returned. Next ip_write() gets the packet to write by calling if_get_userdata. Finally ip_write() calls ip_send to send the packet.

ip_write ( )首先检查如果被请求字节写大于IP_MAX_PACKSIZE 。如果是,那么EPACKSIZE错误返回。下一步ip_write ( )调用if_get_userdata将得到的数据包写入 。最后ip_write ( )调用ip_send发送数据包。
 
ip_send() first checks if the ip address has been set by checking if the IPF_ADDRSET flag has been set. Next ip_send checks if NWIO_RWDTONLY is set. NWIO_RWDTONLY is set if the packet sent to ip does not include the ip header. If NWIO_RWDTONLY is set, the ip header is added by ip.

ip_send ( )首先检查如果IP地址已经通过检查,如IPF_ADDRSET标志是否确定。下一步ip_send检查是否NWIO_RWDTONLY设置。 NWIO_RWDTONLY是如果发送到IP数据包不包括IP报头。如果NWIO_RWDTONLY设置,在IP头中加入了。
 
Next ip_send checks if NWIO_HDR_O_SPEC is set. NWIO_HDR_O_SPEC specifies all IP header options in advance. IP option headers are passed in the iho_data field of the ip_hdropt structure. Theres a field which is a ip_hdropt structure in the nwio_ipopt structure. The nwio_ipopt structure is passed in the ioctl system call when one tries to configure a ip channel with a request of NWIOSIPOPT. Then length of ip option headers is given in the iho_opt_size field of the ip_hdropt structure. If NWIO_HDR_O_SPEC is set, the ip option headers are added to the packet.

下一步ip_send检查是否NWIO_HDR_O_SPEC设置。 NWIO_HDR_O_SPEC指定所有IP报头选项提前。 IP选项头通过iho_data领域ip_hdropt结构传递的。 nwio_ipopt结构的ip_hdropt结构。该nwio_ipopt结构是通过在ioctl系统调用时试图配置的IP通道的要求NWIOSIPOPT 。然后长度IP选项头给出了iho_opt_size领域ip_hdropt结构。如果NWIO_HDR_O_SPEC是设置, IP选项头被添加到该数据包。
 
Bug in ip_send  It looks like if NWIO_HDR_O_SPEC is not set and NWIO_RWDTONLY is set then ip_send errors because ip_hdr->ih_ttl = 0 and ip_send returns a value of EINVAL.

如果NWIO_HDR_O_SPEC没有设置且NWIO_RWDTONLY设置,然后ip_send错误,因为ip_hdr->ih_ttl = 0,ip_send返回值EINVAL 。
 
ip_send then sets the ip version, the length of the packet, the fragmentation flags, the datagram id number, the ip source address, and the ip destination address. If the remote address has not already been specified by the ioctl call with request NWIOSIPOPT, then the destination address provided by the caller is checked for validation by calling chk_destaddr. Next ip_send calculates the checksum field (ih_hdr_chk) of the ip header by calling ip_hdr_chksum.

ip_send然后设置IP版本,长度的数据包,分片标志,数据报id号,数据包的IP源地址和目标地址的IP 。如果远程地址尚未指定的ioctl请求NWIOSIPOPT设置,然后在目标地址所被chk_destaddr调用检查 。下一步ip_send计算校验和字段( ih_hdr_chk )的IP头致电ip_hdr_chksum 。
 
ip_send then checks the destination ip address. If the destination ip address begins with 127 then the packet is sending a message to its own network interface ie the destination ip address is sending to the local loopback. Local loopback packets are put in the loopback queue. Each ip port has its own loopback queue.  The head of the loopback queue is pointed to by ip_loopb_head while the tail of the loopback queue is pointed to by ip_loopb_tail. The loopback queue is processed by ev_process. ev_process is called in the main function in inet.c.

ip_send然后检查目的地IP地址。如果目的IP地址从127,然后包是将报文发送给自己的网络接口即目的地的IP地址发送到本地回环。本地回送数据包放在回环队列。每个IP端口都有自己的回送队列。负责回环队列所指向ip_loopb_head,而尾部回环队列所指向ip_loopb_tail 。回环队列处理ev_process 。 ev_process是net.c中的主要功能函数.
 
If the destination ip address is the broadcast address 255.255.255.255, then ip_send sends it by calling ip_dev_send. If the destination ip address is the same as the ip address of the network interface, the packet is also put in the loopback queue.

如果目的IP地址是广播地址255.255.255.255 ,然后ip_send发送调用ip_dev_send 。如果目的IP地址是相同的IP地址的网络接口,数据包也将在回环队列。
 
Next ip_send checks to see if the destination ip address is on the same subnet as the network interface. If it is then it sends it to its destination by calling ip_dev_send.

下一步ip_send检查是否目标IP地址是在同一子网的网络接口。如果是那么它传送到目的地,调用ip_dev_send 。
 
ipr.c
 
ipr.c is the code for routing of packets. Packets are routed in ip_read.c and ip_write.c. Packets needed to be when the inet process needs to find out to which address it should route a packet in order for the packet to arrive at its destination. The route tables store the information which is used to determine to where a packet should be routed. There are 2 route tables used in inet: 1) oroute_table and 2) iroute_table. oroute_table handles the routing for outgoing packets. iroute_table handles the routing for incoming packets. oroute_table is an array of oroute_t structures while iroute_table is a structure of iroute_t structures. The oroute_t structure and the iroute_t structure are both defined in ipr.h. The iroute_t and oroute_t structure are very similar. Each element in the arrays whether it is a iroute_t or oroute_t structure represents a route in the route table. Recently used routes are strored in the iroute_hash_table and the oroute_hash_table. iroute_hash_table handles the routing for incoming packets while the oroute_hash_table handles the routing for outgoing packets.

ipr.c是代码路由的数据包。数据包路由的ip_read.c和ip_write.c 。包时,需要在Inet进程需要找出这些地址应该路线一包,以便数据包到达目的地。路由表储存的资料来确定一个数据包的地方应路由。Inet使用的路由表有2个: 1 ) oroute_table和2 ) iroute_table 。 oroute_table处理路由即将发送的包。 iroute_table处理路由传入的数据包。 oroute_table是一系列的oroute_t结构而iroute_table是一个结构iroute_t结构。该oroute_t结构和iroute_t结构都定义ipr.h.该iroute_t和oroute_t结构非常相似。每个元素的阵列无论是iroute_t或oroute_t结构是一个路线的路由表。最近使用过的路线strored在iroute_hash_table和oroute_hash_table 。 iroute_hash_table处理路由传入的数据包,而oroute_hash_table处理路由即将发送的包。
 
typedef struct iroute
{
    ipaddr_t irt_dest;
    ipaddr_t irt_gateway;
    ipaddr_t irt_subnetmask;
    int irt_dist;
    int irt_port;
    int irt_flags;
} iroute_t;
 
irt_dest: the destination ip address for the route. This ip address typically represents a subnet or network. Therefore the last several digits of the ip address would be zero. This route is used only if the destination address of the packet belongs to the subnet or network represented by the ip address irt_dest.
      路由的目的地IP地址。这个IP地址通常是一个子网或网络。因此,在过去几个数字的IP地址将是零。这条路由使用,只有在目标地址的数据包属于子网或网络为代表的IP地址irt_dest 。
irt_gateway: ip address to route all packets which use this route.
             IP地址的所有数据包路由使用这条路线。
irt_subnetmask: subnet mask of route. Used with irt_dest to determine whether or not a packet should use this route.
             路由的子网掩码。使用irt_dest来确定是否应该使用一包这条路线。
irt_dist: route distance. Used to determine which route is best.
          路线距离。用于确定该路线是最好的。
irt_port: index in to ip_port table. This route is used only for the ip channel which corresponds to the element in the ip_port_table.
          ip_port表索引值。这条只用于ip通道对应元素的ip_port_table 。
irt_flags: flags to store information about route.
           路由存储信息的标记
typedef struct oroute
{
    int ort_port;
    ipaddr_t ort_dest;
    ipaddr_t ort_subnetmask;
    int ort_dist;
    i32_t ort_pref;
    ipaddr_t ort_gateway;
    time_t ort_exp_tim;
    time_t ort_timestamp;
    int ort_flags;
 
    struct oroute *ort_nextnw;
    struct oroute *ort_nextgw;
    struct oroute *ort_nextdist;
} oroute_t;
 
ort_dest: the destination ip address for the route. This ip address typically represents a subnet or network. Therefore the last several digits of the ip address would be zero. This route is used only if the destination address of the packet belongs to the subnet or network represented by the ip address ort_dest.
              路由的目的地IP地址。这个IP地址通常是一个子网或网络。因此,在过去几个数字的IP地址将是零。这条航线使用,只有在目标地址的数据包属于子网或网络为代表的IP地址ort_dest 。 
             
ort_gateway: ip address to route all packets which use this route.
            IP地址的所有数据包路由使用这条路线。
ort_subnetmask: subnet mask of route. Used with ort_dest to determine whether or not a packet should use this route.
 
ort_dist: route distance. Used to determine which route is best.
             路线距离。用于确定该路线是最好的。
ort_pref: used to determine which route is best( ). Not certain.
           用于确定该路线是最好的。
ort_port: index in to ip_port table. This route is used only for the ip channel which corresponds to the element in the ip_port_table.
           ip_port表索引值。这条只用于ip通道对应元素的ip_port_table 。
ort_flags: flags to store information about route.
          路由存储信息的标记
ort_exp_tim: expiration time for route. No longer used if current time is later than ort_exp_tim. Set to 0 if route has no expiration time.
             路由期限。当前时间超过  ort_exp_tim就不再使用。设置为0表示路由无期限
ort_timestamp: time that the route was added.
             路由添加时间
ort_nextnw: head of linked list of route entries which are being used.
             使用的路由入口的链表头
ort_nextgw: head of linked list of route entries which are being used and have the same ort_port, ort_dest, and ort_subnetmask.
            负责链表干线条目正在使用,并且具有同样ort_port , ort_dest ,和ort_subnetmask 。
ort_nextdist: head of linked list of route entries which are being used and have the same ort_port, ort_dest, ort_subnetmask, and ort_gateway.
             负责链表干线条目正在使用,并且具有同样ort_port , ort_dest , ort_subnetmask ,和ort_gateway 。
            
ipr_init(): initialization called in main function of inet.c. Initializes the oroute_table which handles the routing for outgoing packets and the iroute_table which handles the routing for incoming packets.
            初始化呼吁主要职能inet.c.初始化oroute_table处理路由为即将离任的包和iroute_table处理路由传入的数据包。
           
iroute_frag(): returns a pointer to the route table entry (iroute_t) given the ip channel and the destination of the packet for an incoming packet. First iroute_frag checks if the address was stored in iroute_hash_table which stores recently used routes. If the address was stored in iroute_hash_table it returns the corresponding route table entry; else iroute_frag checks the array iroute_table for a route which can used for the destination ip address on the ip channel. A route can be used only if the route is being used on the same ip channel as requested and the route belongs on the same subnet as the destination ip address. This is tested by the call

返回一个指针的路由表项( iroute_t )给出的IP通道和目的地的数据包的传入的数据包。第一iroute_frag检查如果地址存放在iroute_hash_table存储最近使用的路线。如果该地址被存储在iroute_hash_table返回相应的路由表条目;其他iroute_frag检查数组iroute_table的路线,可用于在目的地IP地址的IP通道。一个路由才可以使用,如果路线上使用相同的IP通道的要求和路线属于同一个子网为目的地的IP地址。这是测试的要求
 
if (((dest ^ iroute->irt_dest) & iroute->irt_subnetmask) != 0)
 
which returns 0 if it does belong on the same subnet. Finally if a route is found, iroute_frag adds the route to the hash table iroute_hash_table and returns it.

它返回0如果不属于同一个子网中。最后一条是,如果发现, iroute_frag增加了航线的哈希表iroute_hash_table并返回它。
 
oroute_frag():oroute_frag does the same thing as iroute_frag only for outgoing packets. It does this by calling oroute_find_ent.
 
oroute_frag是否一样iroute_frag不仅对即将离任的数据包。为此,它会要求oroute_find_ent 。
 
ipr_add_iroute(): ipr_add_iroute adds a route to the iroute_table which handles incoming packets. Static routes are always added as new routes. Non-static routes modify old routes if an old route has the same ip channel, destination address, subnet mask, and gateway.
                  ipr_add_iroute增加了一个通往iroute_table处理传入的数据包。静态路由总是增加新的航线。非静态路由修改旧路线的老路线,如果有相同的IP通道,目的地地址,子网掩码和网关。
                 
ipr_add_oroute():
ipr_add_oroute adds a route to the oroute_table which handles outgoing packets. First it checks if the gateway is on the same subnet as the destination address. Next it checks if a static route is being added. Static routes are always added as new routes. Non-static routes modify old routes only if an old route has the same ip channel, destination address, subnet mask, gateway, distance, and preference
            ipr_add_oroute增加了一个通往oroute_table处理输出数据包。首先检查是否网关是在同一子网的目标地址。下一步检查如果一个静态路由正在增加。静态路由总是增加新的航线。非静态路由修改旧的路线,只有一个老路线,相同的IP通道,目的地地址,子网掩码,网关,距离和偏好
 
Routes for outgoing packets which are being used are put in linked lists. out_nextnw, out_nextgw, out_nextdist are used to point to the next member of the linked lists. oroute_head is the head of the main linked list. Each member of the list have distinct ort_port, ort_dest, ort_subnetmask ordered triplets. Each of the members of the linked list headed by oroute_head is itself a head of a linked list which all have the same ort_port, ort_dest, and ort_subnetmask. Each member of that linked list is itself a head of a linked list which all have same ort_port, ort_dest, ort_subnetmask, and gateway.

为即将发送的包被Routes放在链表。 out_nextnw , out_nextgw , out_nextdist是用来指向下一个成员链表。 oroute_head是由主要链表。每个成员的名单有不同ort_port , ort_dest , ort_subnetmask下令三胞胎。每个成员的链表由oroute_head本身就是一个头一个链表,所有具有相同的ort_port , ort_dest ,并ort_subnetmask 。每个成员的链表本身就是一个头一个链表,所有具有相同ort_port , ort_dest , ort_subnetmask ,以及网关。
 
If no route in oroute_table is found which matches a new route is added. The new route is added by placing the new route in the correct linked list.
如果没有路线oroute_table发现其中一个新的比赛路线是补充。这条新航线是把增加的这条新航线的正确链表。
 
ipr_gateway_down(): ipr_gateway_down is called to notify the routing table that a gateway is down.
                ipr_gateway_down被称为通知路由表,一个网关下来。
               
ipr_destunrch():
ipr_destunrch is called to notify the routing table that a destination is unreachable.
                 ipr_destunrch被称为通知路由表,一个是无法到达目的地。
                
ipr_ttl_exc():ipr_ttl_exc is called to notify the routing table that a destination has received a ttl exceeded.
            ipr_ttl_exc被称为通知路由表,一个目的地已收到了TTL超过。
           
ipr_get_oroute():
ipr_get_oroute gets the route table entry from the oroute_table array.
                 ipr_get_oroute得到的路由表条目从oroute_table数组。
                
oroute_find_ent(): returns a pointer to the route table entry (oroute_t) given the ip channel and the destination of the packet for an incoming packet. First oroute_find_ent checks if the address was stored in oroute_hash_table which stores recently used routes. If the address was stored in oroute_hash_table it returns the corresponding route table entry; else oroute_find_ent checks the array oroute_table for a route which can used for the destination ip address on the ip channel. A route can be used only if the route is being used on the same ip channel as requested and the route belongs on the same subnet as the destination ip address. This is tested by the call
 
 返回一个指针的路由表项( oroute_t )给出的IP通道和目的地的数据包的传入的数据包。第一oroute_find_ent检查如果地址存放在oroute_hash_table存储最近使用的路线。如果该地址被存储在oroute_hash_table返回相应的路由表条目;其他oroute_find_ent检查数组oroute_table的路线,可用于在目的地IP地址的IP通道。一个路由才可以使用,如果路线上使用相同的IP通道的要求和路线属于同一个子网为目的地的IP地址。这是测试的要求
 
if (((dest ^ oroute->ort_dest) & oroute->ort_subnetmask) != 0)
 
which returns 0 if it does belong on the same subnet. Finally if a route is found, oroute_find_ent adds the route to the hash table oroute_hash_table and returns it.

它返回0如果不属于同一个子网中。最后一条是,如果发现, oroute_find_ent增加了航线的哈希表oroute_hash_table并返回它。
 
oroute_del(): oroute_del deletes a route for outgoing packets. First it finds the route in the linked list of routes. Next it removes it. Finally it sorts the remaining routes in the linked list.

oroute_del删除航线即将离任的包。首先发现的路线在链表的路线。下一步它删除它。最后,各种各样其余路线链表。
 
sort_dists(): sort_dists sorts a linked list on the ort_dist and ort_dest field where ort_nextdist points to the next member of the list. The sort simply places the best element at the head of the list and returns it as the return value.
             sort_dists各种各样的链接列表中ort_dist和ort_dest领域, ort_nextdist点到下一个成员名单。那种简单地把最好的内容的首长名单,并传回它的返回值。
            
sort_gws(): sort_gws sorts a linked list on the ort_dist and ort_dest field where ort_nextdist points to the next member of the list. The sort simply places the best element at the head of the list and returns it as the return value.
            

sort_gws各种各样的链接列表中ort_dist和ort_dest领域, ort_nextdist点到下一个成员名单。那种简单地把最好的内容的首长名单,并传回它的返回值。

 
oroute_uncache_nw(): oroute_uncache_nw zeros all of the entries in the oroute_hash table for the subnet represented by the dest ip address and the netmsk subnetmask. oroute_uncache_nw is called to remove a route from the cache ie hash table.
            oroute_uncache_nw零的所有条目oroute_hash表的子网所代表的dest IP地址和netmsk subnetmask 。 oroute_uncache_nw被称为移除路线从缓存即哈希表。
           
ipr_get_iroute (): ipr_get_iroute gets the route table entry from the iroute_table array.
              ipr_get_iroute得到的路由表条目从iroute_table数组。
             
ipr_del_iroute(): ipr_del_iroute deletes a route for incoming packets. First it finds the route in the iroute_table. Next it removes it. Finally it uncaches it from the hash table.
               ipr_del_iroute删除的途径传入的数据包。首先发现的路线在iroute_table 。下一步它删除它。最后, uncaches从哈希表。
              
iroute_uncache_nw(): iroute_uncache_nw zeros all of the entries in the iroute_hash table for the subnet represented by the dest ip address and the netmsk subnetmask. iroute_uncache_nw is called to remove a route from the cache ie hash table.

     iroute_uncache_nw零的所有条目iroute_hash表的子网所代表的dest IP地址和netmsk subnetmask 。 iroute_uncache_nw被称为移除路线从缓存即哈希表。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值