[9] | 1 | /*
|
---|
| 2 | generic/ip_ps.c
|
---|
| 3 |
|
---|
| 4 | pseudo IP specific part of the IP implementation
|
---|
| 5 |
|
---|
| 6 | Created: Apr 23, 1993 by Philip Homburg
|
---|
| 7 |
|
---|
| 8 | Copyright 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 |
|
---|
| 20 | THIS_FILE
|
---|
| 21 |
|
---|
| 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 ));
|
---|
| 26 |
|
---|
| 27 | PUBLIC int ipps_init(ip_port)
|
---|
| 28 | ip_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 |
|
---|
| 43 | PUBLIC void ipps_get(ip_port_nr)
|
---|
| 44 | int 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 |
|
---|
| 115 | PUBLIC void ipps_put(ip_port_nr, nexthop, pack)
|
---|
| 116 | int ip_port_nr;
|
---|
| 117 | ipaddr_t nexthop;
|
---|
| 118 | acc_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 |
|
---|
| 131 | PRIVATE void ipps_main(ip_port)
|
---|
| 132 | ip_port_t *ip_port;
|
---|
| 133 | {
|
---|
| 134 | /* nothing to do */
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | PRIVATE void ipps_set_ipaddr(ip_port)
|
---|
| 138 | ip_port_t *ip_port;
|
---|
| 139 | {
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 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;
|
---|
| 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
|
---|
| 244 | int 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 | */
|
---|