. service tells you which device it couldn't stat
[minix3.git] / servers / inet / generic / ip_ps.c
blob9e8f9065821f40db8051449824eed54ff9c4d41f
1 /*
2 generic/ip_ps.c
4 pseudo IP specific part of the IP implementation
6 Created: Apr 23, 1993 by Philip Homburg
8 Copyright 1995 Philip Homburg
9 */
11 #include "inet.h"
12 #include "assert.h"
13 #include "type.h"
14 #include "buf.h"
15 #include "event.h"
16 #include "ip.h"
17 #include "ip_int.h"
18 #include "psip.h"
20 THIS_FILE
22 FORWARD void ipps_main ARGS(( ip_port_t *ip_port ));
23 FORWARD void ipps_set_ipaddr ARGS(( ip_port_t *ip_port ));
24 FORWARD int ipps_send ARGS(( struct ip_port *ip_port, ipaddr_t dest,
25 acc_t *pack, int type ));
27 PUBLIC int ipps_init(ip_port)
28 ip_port_t *ip_port;
30 int result;
32 result= psip_enable(ip_port->ip_dl.dl_ps.ps_port, ip_port->ip_port);
33 if (result == -1)
34 return -1;
35 ip_port->ip_dl.dl_ps.ps_send_head= NULL;
36 ip_port->ip_dl.dl_ps.ps_send_tail= NULL;
37 ip_port->ip_dev_main= ipps_main;
38 ip_port->ip_dev_set_ipaddr= ipps_set_ipaddr;
39 ip_port->ip_dev_send= ipps_send;
40 return result;
43 PUBLIC void ipps_get(ip_port_nr)
44 int ip_port_nr;
46 int result;
47 ipaddr_t dest;
48 acc_t *acc, *pack, *next_part;
49 ip_port_t *ip_port;
51 assert(ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
52 ip_port= &ip_port_table[ip_port_nr];
53 assert(ip_port->ip_dl_type == IPDL_PSIP);
55 while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
57 pack= ip_port->ip_dl.dl_ps.ps_send_head;
58 ip_port->ip_dl.dl_ps.ps_send_head= pack->acc_ext_link;
60 /* Extract nexthop address */
61 pack= bf_packIffLess(pack, sizeof(dest));
62 dest= *(ipaddr_t *)ptr2acc_data(pack);
63 pack= bf_delhead(pack, sizeof(dest));
65 if (bf_bufsize(pack) > ip_port->ip_mtu)
67 next_part= pack;
68 pack= ip_split_pack(ip_port, &next_part,
69 ip_port->ip_mtu);
70 if (pack == NULL)
71 continue;
73 /* Prepend nexthop address */
74 acc= bf_memreq(sizeof(dest));
75 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
76 acc->acc_next= next_part;
77 next_part= acc; acc= NULL;
79 assert(next_part->acc_linkC == 1);
80 next_part->acc_ext_link= NULL;
81 if (ip_port->ip_dl.dl_ps.ps_send_head)
83 ip_port->ip_dl.dl_ps.ps_send_tail->
84 acc_ext_link= next_part;
86 else
88 ip_port->ip_dl.dl_ps.ps_send_head=
89 next_part;
91 ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
94 result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
95 if (result != NW_SUSPEND)
97 assert(result == NW_OK);
98 continue;
101 /* Prepend nexthop address */
102 acc= bf_memreq(sizeof(dest));
103 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
104 acc->acc_next= pack;
105 pack= acc; acc= NULL;
107 pack->acc_ext_link= ip_port->ip_dl.dl_ps.ps_send_head;
108 ip_port->ip_dl.dl_ps.ps_send_head= pack;
109 if (pack->acc_ext_link == NULL)
110 ip_port->ip_dl.dl_ps.ps_send_tail= pack;
111 break;
115 PUBLIC void ipps_put(ip_port_nr, nexthop, pack)
116 int ip_port_nr;
117 ipaddr_t nexthop;
118 acc_t *pack;
120 ip_port_t *ip_port;
122 assert(ip_port_nr >= 0 && ip_port_nr < ip_conf_nr);
123 ip_port= &ip_port_table[ip_port_nr];
124 assert(ip_port->ip_dl_type == IPDL_PSIP);
125 if (nexthop == HTONL(0xffffffff))
126 ip_arrived_broadcast(ip_port, pack);
127 else
128 ip_arrived(ip_port, pack);
131 PRIVATE void ipps_main(ip_port)
132 ip_port_t *ip_port;
134 /* nothing to do */
137 PRIVATE void ipps_set_ipaddr(ip_port)
138 ip_port_t *ip_port;
142 PRIVATE int ipps_send(ip_port, dest, pack, type)
143 struct ip_port *ip_port;
144 ipaddr_t dest;
145 acc_t *pack;
146 int type;
148 int result;
149 acc_t *acc, *next_part;
151 if (type != IP_LT_NORMAL)
153 ip_arrived_broadcast(ip_port, bf_dupacc(pack));
155 /* Map all broadcasts to the on-link broadcast address.
156 * This saves the application from having to to find out
157 * if the destination is a subnet broadcast.
159 dest= HTONL(0xffffffff);
162 /* Note that allocating a packet may trigger a cleanup action,
163 * which may cause the send queue to become empty.
165 while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
167 acc= bf_memreq(sizeof(dest));
169 if (ip_port->ip_dl.dl_ps.ps_send_head == NULL)
171 bf_afree(acc); acc= NULL;
172 continue;
175 /* Prepend nexthop address */
176 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
177 acc->acc_next= pack;
178 pack= acc; acc= NULL;
180 assert(pack->acc_linkC == 1);
181 pack->acc_ext_link= NULL;
183 ip_port->ip_dl.dl_ps.ps_send_tail->acc_ext_link= pack;
184 ip_port->ip_dl.dl_ps.ps_send_tail= pack;
186 return NW_OK;
189 while (pack)
191 if (bf_bufsize(pack) > ip_port->ip_mtu)
193 next_part= pack;
194 pack= ip_split_pack(ip_port, &next_part,
195 ip_port->ip_mtu);
196 if (pack == NULL)
198 return NW_OK;
201 /* Prepend nexthop address */
202 acc= bf_memreq(sizeof(dest));
203 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
204 acc->acc_next= next_part;
205 next_part= acc; acc= NULL;
207 assert(next_part->acc_linkC == 1);
208 next_part->acc_ext_link= NULL;
209 ip_port->ip_dl.dl_ps.ps_send_head= next_part;
210 ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
212 result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
213 if (result == NW_SUSPEND)
215 /* Prepend nexthop address */
216 acc= bf_memreq(sizeof(dest));
217 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
218 acc->acc_next= pack;
219 pack= acc; acc= NULL;
221 assert(pack->acc_linkC == 1);
222 pack->acc_ext_link= ip_port->ip_dl.dl_ps.ps_send_head;
223 ip_port->ip_dl.dl_ps.ps_send_head= pack;
224 if (!pack->acc_ext_link)
225 ip_port->ip_dl.dl_ps.ps_send_tail= pack;
226 break;
228 assert(result == NW_OK);
229 pack= ip_port->ip_dl.dl_ps.ps_send_head;
230 if (!pack)
231 break;
232 ip_port->ip_dl.dl_ps.ps_send_head= pack->acc_ext_link;
234 /* Extract nexthop address */
235 pack= bf_packIffLess(pack, sizeof(dest));
236 dest= *(ipaddr_t *)ptr2acc_data(pack);
237 pack= bf_delhead(pack, sizeof(dest));
240 return NW_OK;
243 #if 0
244 int ipps_check(ip_port_t *ip_port)
246 int n, bad;
247 acc_t *prev, *curr;
249 for (n= 0, prev= NULL, curr= ip_port->ip_dl.dl_ps.ps_send_head_;
250 curr; prev= curr, curr= curr->acc_ext_link)
252 n++;
254 bad= 0;
255 if (prev != NULL && prev != ip_port->ip_dl.dl_ps.ps_send_tail_)
257 printf("ipps_check, ip[%d]: wrong tail: got %p, expected %p\n",
258 ip_port-ip_port_table,
259 ip_port->ip_dl.dl_ps.ps_send_tail_, prev);
260 bad++;
262 if (n != ip_port->ip_dl.dl_ps.ps_send_nr)
264 printf("ipps_check, ip[%d]: wrong count: got %d, expected %d\n",
265 ip_port-ip_port_table,
266 ip_port->ip_dl.dl_ps.ps_send_nr, n);
267 bad++;
269 return bad == 0;
271 #endif
274 * $PchId: ip_ps.c,v 1.15 2003/01/21 15:57:52 philip Exp $