Title: ip_port / ip_port_table[]


For every interface listed in inet.conf, there is a single ip port. For example, for the following inet.conf file:

eth0 DP8390 0 { default; };
psip1;

there will be an ip port associated with the ethernet interface and an ip port associated with the psip interface. Each of these ip ports is a struct ip_port (see below) and each ip_port struct is in ip_port_table[]. So, for the example inet.conf file above, ip_port_table[] will have 2 elements; ip_port_table[0] will be for the ethernet interface and ip_port_table[1] will be for the psip interface.

Each element in ip_port_table[] is associated with several ip file descriptors. For example, the udp code (during initialization) will open up an ip file descriptor and this ip file descriptor will be associated with one of the elements in ip_port_table[].



typedef struct ip_port

{
int ip_flags, ip_dl_type;
int ip_port;
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;
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;



int ip_flags:

The possible ip_flags are #define'd in ip_int.h:

#define IPF_EMPTY 0x0
#define IPF_CONFIGURED 0x1
#define IPF_IPADDRSET 0x2
#define IPF_NETMASKSET 0x4

After the initialization of the ip port, ip_flags is set to IPF_CONFIGURED. If the "ifconfig -h host-IP-address" command is issued, ip_ioctl() sets the IPF_IPADDRSET flag before setting the ip address and (optionally) the subnet mask.


int ip_dl_type:

"dl" stands for "data link" (layer). ip_dl_type is set to the corresponding data link layer type of the port. These types include NETTYPE_ETH (ethernet) and NETTYPE_PSIP (psip).


int ip_port:

The port number of the ip device. For example, for a system with the following /etc/inet.conf file:

eth0 DP8390 0 { default; };
psip1;

there will be 2 ports: port 0 for the ethernet device and port 1 for the psip device.

Note that this port will not necessarily be the same as dl_eth.de_port (see below).


struct dl_eth: The dl_eth struct is used (instead of dl_ps) if the underlying data link layer device of this port is an ethernet device.


int de_state:

The possible de_state values are #define'd in ip_int.h:

#define IES_EMPTY 0x0
#define IES_SETPROTO 0x1
#define IES_GETIPADDR 0x2
#define IES_MAIN 0x3
#define IES_ERROR 0x4

When the ip port is being initialized, de_state changes in quick succession from IES_EMPTY to IES_SETPROTO to IES_GETIPADDR before entering IES_MAIN, which is its normal operational state.


int de_flags:

de_flags is initialized to IEF_EMPTY. Note that "SP" stands for "SusPend".

#define IEF_EMPTY 0x1
#define IEF_SUSPEND 0x8
#define IEF_READ_IP 0x10
#define IEF_READ_SP 0x20
#define IEF_WRITE_SP 0x80


int de_port:

The ethernet port number. For example, if there were two ethernet devices, one ethernet device would have port 0 and the other would have port 1, regardless of how many psip devices were on the system.

This value is initialized in ip_init(). Also see the initial comments in ip_config.c for a description of ip_conf[].

Note that this port will not necessarily be the same as ip_port (see above).


int de_fd:

Initialized by calling eth_open(), de_fd is the ip port's associated ethernet file descriptor.


acc_t *de_frame:
acc_t *de_q_head:
acc_t *de_q_tail:


The queueing for ethernet packets being sent out by the ethernet task is somewhat convoluted. If no ethernet packets are waiting to be sent out by the ethernet task (driver),
eth_write_port() stores an ethernet packet in an ethernet port's etp_wr_pack field until the packet is sent off by the ethernet task. After the ethernet task successfully sends the packet off, this field is set to NULL (either by eth_write_port() or write_int()). If the ethernet task cannot immediately send the ethernet packet off, the packet remains in etp_wr_pack. If another packet arrives for the ip port to send off to the ethernet port, the ip port encapsulates the ip packet with an ethernet header and the resulting ethernet packet is placed in the dl_eth.de_frame field of the ip port. If the ip port has additional packets that it wishes to send out, the packets are placed in the dl_eth.de_q_head/dl_eth.de_q_tail queue until the ethernet packets in etp_wr_pack and dl_eth.de_frame are sent out.

It's important to note that neither etp_wr_pack nor dl_eth.de_frame are linked lists (i.e., queues). They each hold only a single ethernet packet.


acc_t *de_arp_head:
acc_t *de_arp_tail:


If the arp table (i.e., arp cache) does not contain an entry for a given ip address, arp_ip_eth() returns NW_SUSPEND and the outgoing packet is placed in the ip port's de_arp_head/de_arp_tail queue. Before being placed in this queue, the packet is encapsulated in a "xmit" header (as opposed to an ethernet header).

xmit_hdr is declared in generic/ip_eth.c:

typedef struct xmit_hdr

{
time_t xh_time;
ipaddr_t xh_ipaddr;
} xmit_hdr_t;
where xh_time is the time at which the packet is placed in the de_arp_head/de_arp_tail queue and xh_ipaddr is the destination ip address of the packet.


struct dl_ps:
int ps_port:
acc_t *ps_send_head:
acc_t *ps_send_tail:


The dl_ps struct is used (instead of dl_eth) if the underlying data link layer device is a psip device. Coverage of psip is not included in this documentation.


ipaddr_t ip_ipaddr:
ipaddr_t ip_netmask:
ipaddr_t ip_subnetmask:


The ip address of a port can be set in two ways, either with RARP or through the "ifconfig -h host-IP-address" command. If set by the ifconfig command, a message requesting an NWIOSIPCONF (Set IP CONFiguration) is sent to the appropriate ip device (e.g., /dev/ip00, causing ip_ioctl() to be called. The user then passes in a nwio_ipconf struct which contains either the ip address or the subnet mask or both.

The netmask is simply a reflection of the class to which the ip address belongs. For example, if the ip address is 194.77.33.5, then it is a class C address and its netmask is therefore 255.255.255.0. See ip_nettype() for more information.


u16_t ip_frame_id:

ip_frame_id is initialized to the time at which the ip port was configured and incremented each time a packet is sent out. The ih_id field of each packet's ip header is set to ip_frame_id. If a packet is fragmented, the receiver can properly order the framents.


u16_t ip_mss:

If the ip_port_table[] element has an underlying ethernet layer, ip_mss is initialized to ETH_MAX_PACK_SIZE-ETH_HDR_SIZE (1514-14=1500), the size of the payload of an ethernet packet in bytes. If the size of the resulting ip packet is too large, the code fragments the packet.


ip_dev_t ip_dev_main:

ip_dev_main is initialized to ipeth_main() for ethernet devices. This function is called in ip_init().


ip_dev_t ip_dev_set_ipaddr:

ip_dev_set_ipaddr is initialized to ipeth_set_ipaddr() for ethernet devices.


ip_dev_send_t ip_dev_send:

ip_dev_send is initialized to ipeth_send() for ethernet devices or ipps_send() for psip devices.


acc_t *ip_loopb_head:
acc_t *ip_loopb_tail:
event_t ip_loopb_event:


Ip packets destined for the loopback address (127.0.0.1) or destined for the ip address of the ip port itself are placed in the ip_loopb_head/ip_loopb_tail before being delivered back to the ip port.

ip_loopb_event is an event that has been placed in the system-wide event queue.


struct ip_fd *ip_proto_any:
struct ip_fd *ip_proto[IP_PROTO_HASH_NR]:


For a description of ip_proto_any and ip_proto[], click here.