source: trunk/minix/servers/inet/generic/ip_ps.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 6.1 KB
Line 
1/*
2generic/ip_ps.c
3
4pseudo IP specific part of the IP implementation
5
6Created: Apr 23, 1993 by Philip Homburg
7
8Copyright 1995 Philip Homburg
9*/
10
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"
19
20THIS_FILE
21
22FORWARD void ipps_main ARGS(( ip_port_t *ip_port ));
23FORWARD void ipps_set_ipaddr ARGS(( ip_port_t *ip_port ));
24FORWARD int ipps_send ARGS(( struct ip_port *ip_port, ipaddr_t dest,
25 acc_t *pack, int type ));
26
27PUBLIC int ipps_init(ip_port)
28ip_port_t *ip_port;
29{
30 int result;
31
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;
41}
42
43PUBLIC void ipps_get(ip_port_nr)
44int ip_port_nr;
45{
46 int result;
47 ipaddr_t dest;
48 acc_t *acc, *pack, *next_part;
49 ip_port_t *ip_port;
50
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);
54
55 while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
56 {
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;
59
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));
64
65 if (bf_bufsize(pack) > ip_port->ip_mtu)
66 {
67 next_part= pack;
68 pack= ip_split_pack(ip_port, &next_part,
69 ip_port->ip_mtu);
70 if (pack == NULL)
71 continue;
72
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;
78
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)
82 {
83 ip_port->ip_dl.dl_ps.ps_send_tail->
84 acc_ext_link= next_part;
85 }
86 else
87 {
88 ip_port->ip_dl.dl_ps.ps_send_head=
89 next_part;
90 }
91 ip_port->ip_dl.dl_ps.ps_send_tail= next_part;
92 }
93
94 result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
95 if (result != NW_SUSPEND)
96 {
97 assert(result == NW_OK);
98 continue;
99 }
100
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;
106
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;
112 }
113}
114
115PUBLIC void ipps_put(ip_port_nr, nexthop, pack)
116int ip_port_nr;
117ipaddr_t nexthop;
118acc_t *pack;
119{
120 ip_port_t *ip_port;
121
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);
129}
130
131PRIVATE void ipps_main(ip_port)
132ip_port_t *ip_port;
133{
134 /* nothing to do */
135}
136
137PRIVATE void ipps_set_ipaddr(ip_port)
138ip_port_t *ip_port;
139{
140}
141
142PRIVATE int ipps_send(ip_port, dest, pack, type)
143struct ip_port *ip_port;
144ipaddr_t dest;
145acc_t *pack;
146int type;
147{
148 int result;
149 acc_t *acc, *next_part;
150
151 if (type != IP_LT_NORMAL)
152 {
153 ip_arrived_broadcast(ip_port, bf_dupacc(pack));
154
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.
158 */
159 dest= HTONL(0xffffffff);
160 }
161
162 /* Note that allocating a packet may trigger a cleanup action,
163 * which may cause the send queue to become empty.
164 */
165 while (ip_port->ip_dl.dl_ps.ps_send_head != NULL)
166 {
167 acc= bf_memreq(sizeof(dest));
168
169 if (ip_port->ip_dl.dl_ps.ps_send_head == NULL)
170 {
171 bf_afree(acc); acc= NULL;
172 continue;
173 }
174
175 /* Prepend nexthop address */
176 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
177 acc->acc_next= pack;
178 pack= acc; acc= NULL;
179
180 assert(pack->acc_linkC == 1);
181 pack->acc_ext_link= NULL;
182
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;
185
186 return NW_OK;
187 }
188
189 while (pack)
190 {
191 if (bf_bufsize(pack) > ip_port->ip_mtu)
192 {
193 next_part= pack;
194 pack= ip_split_pack(ip_port, &next_part,
195 ip_port->ip_mtu);
196 if (pack == NULL)
197 {
198 return NW_OK;
199 }
200
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;
206
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;
211 }
212 result= psip_send(ip_port->ip_dl.dl_ps.ps_port, dest, pack);
213 if (result == NW_SUSPEND)
214 {
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;
220
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;
227 }
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;
233
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));
238 }
239
240 return NW_OK;
241}
242
243#if 0
244int ipps_check(ip_port_t *ip_port)
245{
246 int n, bad;
247 acc_t *prev, *curr;
248
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)
251 {
252 n++;
253 }
254 bad= 0;
255 if (prev != NULL && prev != ip_port->ip_dl.dl_ps.ps_send_tail_)
256 {
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++;
261 }
262 if (n != ip_port->ip_dl.dl_ps.ps_send_nr)
263 {
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++;
268 }
269 return bad == 0;
270}
271#endif
272
273/*
274 * $PchId: ip_ps.c,v 1.15 2003/01/21 15:57:52 philip Exp $
275 */
Note: See TracBrowser for help on using the repository browser.