Free (GPLv2) TCP/IP stack developed by TASS Belgium
Dependents: lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more
pico_stack.c
00001 /********************************************************************* 00002 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved. 00003 See LICENSE and COPYING for usage. 00004 00005 . 00006 00007 Authors: Daniele Lacamera 00008 *********************************************************************/ 00009 00010 00011 #include "pico_config.h" 00012 #include "pico_frame.h" 00013 #include "pico_device.h" 00014 #include "pico_protocol.h" 00015 #include "pico_stack.h" 00016 #include "pico_addressing.h" 00017 #include "pico_dns_client.h" 00018 00019 #include "pico_olsr.h" 00020 #include "pico_aodv.h" 00021 #include "pico_eth.h" 00022 #include "pico_arp.h" 00023 #include "pico_ipv4.h" 00024 #include "pico_ipv6.h" 00025 #include "pico_icmp4.h" 00026 #include "pico_icmp6.h" 00027 #include "pico_igmp.h" 00028 #include "pico_udp.h" 00029 #include "pico_tcp.h" 00030 #include "pico_socket.h" 00031 #include "heap.h" 00032 00033 #define IS_LIMITED_BCAST(f) (((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST) 00034 00035 const uint8_t PICO_ETHADDR_ALL[6] = { 00036 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 00037 }; 00038 00039 # define PICO_SIZE_MCAST 3 00040 const uint8_t PICO_ETHADDR_MCAST[6] = { 00041 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 00042 }; 00043 00044 #ifdef PICO_SUPPORT_IPV6 00045 # define PICO_SIZE_MCAST6 2 00046 const uint8_t PICO_ETHADDR_MCAST6[6] = { 00047 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 00048 }; 00049 #endif 00050 00051 00052 volatile pico_time pico_tick; 00053 volatile pico_err_t pico_err; 00054 00055 static uint32_t _rand_seed; 00056 00057 void WEAK pico_rand_feed(uint32_t feed) 00058 { 00059 if (!feed) 00060 return; 00061 00062 _rand_seed *= 1664525; 00063 _rand_seed += 1013904223; 00064 _rand_seed ^= ~(feed); 00065 } 00066 00067 uint32_t WEAK pico_rand(void) 00068 { 00069 pico_rand_feed((uint32_t)pico_tick); 00070 return _rand_seed; 00071 } 00072 00073 void pico_to_lowercase(char *str) 00074 { 00075 int i = 0; 00076 if (!str) 00077 return; 00078 00079 while(str[i]) { 00080 if ((str[i] <= 'Z') && (str[i] >= 'A')) 00081 str[i] = (char) (str[i] - (char)('A' - 'a')); 00082 00083 i++; 00084 } 00085 } 00086 00087 /* NOTIFICATIONS: distributed notifications for stack internal errors. 00088 */ 00089 00090 int pico_notify_socket_unreachable(struct pico_frame *f) 00091 { 00092 if (0) {} 00093 00094 #ifdef PICO_SUPPORT_ICMP4 00095 else if (IS_IPV4(f)) { 00096 pico_icmp4_port_unreachable(f); 00097 } 00098 #endif 00099 #ifdef PICO_SUPPORT_ICMP6 00100 else if (IS_IPV6(f)) { 00101 pico_icmp6_port_unreachable(f); 00102 } 00103 #endif 00104 00105 return 0; 00106 } 00107 00108 int pico_notify_proto_unreachable(struct pico_frame *f) 00109 { 00110 if (0) {} 00111 00112 #ifdef PICO_SUPPORT_ICMP4 00113 else if (IS_IPV4(f)) { 00114 pico_icmp4_proto_unreachable(f); 00115 } 00116 #endif 00117 #ifdef PICO_SUPPORT_ICMP6 00118 else if (IS_IPV6(f)) { 00119 pico_icmp6_proto_unreachable(f); 00120 } 00121 #endif 00122 return 0; 00123 } 00124 00125 int pico_notify_dest_unreachable(struct pico_frame *f) 00126 { 00127 if (0) {} 00128 00129 #ifdef PICO_SUPPORT_ICMP4 00130 else if (IS_IPV4(f)) { 00131 pico_icmp4_dest_unreachable(f); 00132 } 00133 #endif 00134 #ifdef PICO_SUPPORT_ICMP6 00135 else if (IS_IPV6(f)) { 00136 pico_icmp6_dest_unreachable(f); 00137 } 00138 #endif 00139 return 0; 00140 } 00141 00142 int pico_notify_ttl_expired(struct pico_frame *f) 00143 { 00144 if (0) {} 00145 00146 #ifdef PICO_SUPPORT_ICMP4 00147 else if (IS_IPV4(f)) { 00148 pico_icmp4_ttl_expired(f); 00149 } 00150 #endif 00151 #ifdef PICO_SUPPORT_ICMP6 00152 else if (IS_IPV6(f)) { 00153 pico_icmp6_ttl_expired(f); 00154 } 00155 #endif 00156 return 0; 00157 } 00158 00159 int pico_notify_frag_expired(struct pico_frame *f) 00160 { 00161 if (0) {} 00162 00163 #ifdef PICO_SUPPORT_ICMP4 00164 else if (IS_IPV4(f)) { 00165 pico_icmp4_frag_expired(f); 00166 } 00167 #endif 00168 #ifdef PICO_SUPPORT_ICMP6 00169 else if (IS_IPV6(f)) { 00170 pico_icmp6_frag_expired(f); 00171 } 00172 #endif 00173 return 0; 00174 } 00175 00176 int pico_notify_pkt_too_big(struct pico_frame *f) 00177 { 00178 if (0) {} 00179 00180 #ifdef PICO_SUPPORT_ICMP4 00181 else if (IS_IPV4(f)) { 00182 pico_icmp4_mtu_exceeded(f); 00183 } 00184 #endif 00185 #ifdef PICO_SUPPORT_ICMP6 00186 else if (IS_IPV6(f)) { 00187 pico_icmp6_pkt_too_big(f); 00188 } 00189 #endif 00190 return 0; 00191 } 00192 00193 00194 /* Transport layer */ 00195 MOCKABLE int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto) 00196 { 00197 int32_t ret = -1; 00198 switch (proto) { 00199 00200 #ifdef PICO_SUPPORT_ICMP4 00201 case PICO_PROTO_ICMP4: 00202 ret = pico_enqueue(pico_proto_icmp4.q_in, f); 00203 break; 00204 #endif 00205 00206 #ifdef PICO_SUPPORT_ICMP6 00207 case PICO_PROTO_ICMP6: 00208 ret = pico_enqueue(pico_proto_icmp6.q_in, f); 00209 break; 00210 #endif 00211 00212 00213 #if defined(PICO_SUPPORT_IGMP) && defined(PICO_SUPPORT_MCAST) 00214 case PICO_PROTO_IGMP: 00215 ret = pico_enqueue(pico_proto_igmp.q_in, f); 00216 break; 00217 #endif 00218 00219 #ifdef PICO_SUPPORT_UDP 00220 case PICO_PROTO_UDP: 00221 ret = pico_enqueue(pico_proto_udp.q_in, f); 00222 break; 00223 #endif 00224 00225 #ifdef PICO_SUPPORT_TCP 00226 case PICO_PROTO_TCP: 00227 ret = pico_enqueue(pico_proto_tcp.q_in, f); 00228 break; 00229 #endif 00230 00231 default: 00232 /* Protocol not available */ 00233 dbg("pkt: no such protocol (%d)\n", proto); 00234 pico_notify_proto_unreachable(f); 00235 pico_frame_discard(f); 00236 ret = -1; 00237 } 00238 return ret; 00239 } 00240 00241 int32_t pico_network_receive(struct pico_frame *f) 00242 { 00243 if (0) {} 00244 00245 #ifdef PICO_SUPPORT_IPV4 00246 else if (IS_IPV4(f)) { 00247 pico_enqueue(pico_proto_ipv4.q_in, f); 00248 } 00249 #endif 00250 #ifdef PICO_SUPPORT_IPV6 00251 else if (IS_IPV6(f)) { 00252 pico_enqueue(pico_proto_ipv6.q_in, f); 00253 } 00254 #endif 00255 else { 00256 dbg("Network not found.\n"); 00257 pico_frame_discard(f); 00258 return -1; 00259 } 00260 return (int32_t)f->buffer_len; 00261 } 00262 00263 /* Network layer: interface towards socket for frame sending */ 00264 int32_t pico_network_send(struct pico_frame *f) 00265 { 00266 if (!f || !f->sock || !f->sock->net) { 00267 pico_frame_discard(f); 00268 return -1; 00269 } 00270 00271 return f->sock->net->push(f->sock->net, f); 00272 } 00273 00274 int pico_source_is_local(struct pico_frame *f) 00275 { 00276 if (0) { } 00277 00278 #ifdef PICO_SUPPORT_IPV4 00279 else if (IS_IPV4(f)) { 00280 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00281 if (hdr->src.addr == PICO_IPV4_INADDR_ANY) 00282 return 1; 00283 00284 if (pico_ipv4_link_find(&hdr->src)) 00285 return 1; 00286 } 00287 #endif 00288 #ifdef PICO_SUPPORT_IPV6 00289 else if (IS_IPV6(f)) { 00290 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; 00291 if (pico_ipv6_is_unspecified(hdr->src.addr) || pico_ipv6_link_find(&hdr->src)) 00292 return 1; 00293 } 00294 #endif 00295 return 0; 00296 } 00297 00298 #ifdef PICO_SUPPORT_ETH 00299 /* DATALINK LEVEL: interface from network to the device 00300 * and vice versa. 00301 */ 00302 00303 /* The pico_ethernet_receive() function is used by 00304 * those devices supporting ETH in order to push packets up 00305 * into the stack. 00306 */ 00307 00308 static int destination_is_bcast(struct pico_frame *f) 00309 { 00310 if (!f) 00311 return 0; 00312 00313 if (IS_IPV6(f)) 00314 return 0; 00315 00316 #ifdef PICO_SUPPORT_IPV4 00317 else { 00318 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00319 return pico_ipv4_is_broadcast(hdr->dst.addr); 00320 } 00321 #else 00322 return 0; 00323 #endif 00324 } 00325 00326 static int destination_is_mcast(struct pico_frame *f) 00327 { 00328 int ret = 0; 00329 if (!f) 00330 return 0; 00331 00332 #ifdef PICO_SUPPORT_IPV6 00333 if (IS_IPV6(f)) { 00334 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *) f->net_hdr; 00335 ret = pico_ipv6_is_multicast(hdr->dst.addr); 00336 } 00337 00338 #endif 00339 #ifdef PICO_SUPPORT_IPV4 00340 else { 00341 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00342 ret = pico_ipv4_is_multicast(hdr->dst.addr); 00343 } 00344 #endif 00345 00346 return ret; 00347 } 00348 00349 #ifdef PICO_SUPPORT_IPV4 00350 static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f) 00351 { 00352 if (IS_IPV4(f)) { 00353 pico_enqueue(pico_proto_ipv4.q_in, f); 00354 } else { 00355 (void)pico_icmp4_param_problem(f, 0); 00356 pico_frame_discard(f); 00357 return -1; 00358 } 00359 00360 return (int32_t)f->buffer_len; 00361 } 00362 #endif 00363 00364 #ifdef PICO_SUPPORT_IPV6 00365 static int32_t pico_ipv6_ethernet_receive(struct pico_frame *f) 00366 { 00367 if (IS_IPV6(f)) { 00368 pico_enqueue(pico_proto_ipv6.q_in, f); 00369 } else { 00370 /* Wrong version for link layer type */ 00371 pico_frame_discard(f); 00372 return -1; 00373 } 00374 00375 return (int32_t)f->buffer_len; 00376 } 00377 #endif 00378 00379 static int32_t pico_ll_receive(struct pico_frame *f) 00380 { 00381 struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr; 00382 f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); 00383 00384 #if (defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_ETH) 00385 if (hdr->proto == PICO_IDETH_ARP) 00386 return pico_arp_receive(f); 00387 00388 #endif 00389 00390 #if defined (PICO_SUPPORT_IPV4) 00391 if (hdr->proto == PICO_IDETH_IPV4) 00392 return pico_ipv4_ethernet_receive(f); 00393 00394 #endif 00395 00396 #if defined (PICO_SUPPORT_IPV6) 00397 if (hdr->proto == PICO_IDETH_IPV6) 00398 return pico_ipv6_ethernet_receive(f); 00399 00400 #endif 00401 00402 pico_frame_discard(f); 00403 return -1; 00404 } 00405 00406 static void pico_ll_check_bcast(struct pico_frame *f) 00407 { 00408 struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr; 00409 /* Indicate a link layer broadcast packet */ 00410 if (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) == 0) 00411 f->flags |= PICO_FRAME_FLAG_BCAST; 00412 } 00413 00414 int32_t pico_ethernet_receive(struct pico_frame *f) 00415 { 00416 struct pico_eth_hdr *hdr; 00417 if (!f || !f->dev || !f->datalink_hdr) 00418 { 00419 pico_frame_discard(f); 00420 return -1; 00421 } 00422 00423 hdr = (struct pico_eth_hdr *) f->datalink_hdr; 00424 if ((memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) && 00425 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) && 00426 #ifdef PICO_SUPPORT_IPV6 00427 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST6, PICO_SIZE_MCAST6) != 0) && 00428 #endif 00429 (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0)) 00430 { 00431 pico_frame_discard(f); 00432 return -1; 00433 } 00434 00435 pico_ll_check_bcast(f); 00436 return pico_ll_receive(f); 00437 } 00438 00439 static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac) 00440 { 00441 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00442 00443 /* place 23 lower bits of IP in lower 23 bits of MAC */ 00444 pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FFu); 00445 pico_mcast_mac[4] = (uint8_t)((long_be(hdr->dst.addr) & 0x0000FF00u) >> 8u); 00446 pico_mcast_mac[3] = (uint8_t)((long_be(hdr->dst.addr) & 0x007F0000u) >> 16u); 00447 00448 return (struct pico_eth *)pico_mcast_mac; 00449 } 00450 00451 00452 #ifdef PICO_SUPPORT_IPV6 00453 static struct pico_eth *pico_ethernet_mcast6_translate(struct pico_frame *f, uint8_t *pico_mcast6_mac) 00454 { 00455 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; 00456 00457 /* first 2 octets are 0x33, last four are the last four of dst */ 00458 pico_mcast6_mac[5] = hdr->dst.addr[PICO_SIZE_IP6 - 1]; 00459 pico_mcast6_mac[4] = hdr->dst.addr[PICO_SIZE_IP6 - 2]; 00460 pico_mcast6_mac[3] = hdr->dst.addr[PICO_SIZE_IP6 - 3]; 00461 pico_mcast6_mac[2] = hdr->dst.addr[PICO_SIZE_IP6 - 4]; 00462 00463 return (struct pico_eth *)pico_mcast6_mac; 00464 } 00465 #endif 00466 00467 static int pico_ethernet_ipv6_dst(struct pico_frame *f, struct pico_eth *const dstmac) 00468 { 00469 int retval = -1; 00470 if (!dstmac) 00471 return -1; 00472 00473 #ifdef PICO_SUPPORT_IPV6 00474 if (destination_is_mcast(f)) { 00475 uint8_t pico_mcast6_mac[6] = { 00476 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 00477 }; 00478 pico_ethernet_mcast6_translate(f, pico_mcast6_mac); 00479 memcpy(dstmac, pico_mcast6_mac, PICO_SIZE_ETH); 00480 retval = 0; 00481 } else { 00482 struct pico_eth *neighbor = pico_ipv6_get_neighbor(f); 00483 if (neighbor) 00484 { 00485 memcpy(dstmac, neighbor, PICO_SIZE_ETH); 00486 retval = 0; 00487 } 00488 } 00489 00490 #else 00491 (void)f; 00492 pico_err = PICO_ERR_EPROTONOSUPPORT; 00493 #endif 00494 return retval; 00495 } 00496 00497 00498 /* Ethernet send, first attempt: try our own address. 00499 * Returns 0 if the packet is not for us. 00500 * Returns 1 if the packet is cloned to our own receive queue, so the caller can discard the original frame. 00501 * */ 00502 static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr) 00503 { 00504 if (!hdr) 00505 return 0; 00506 00507 /* Check own mac */ 00508 if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)) { 00509 struct pico_frame *clone = pico_frame_copy(f); 00510 dbg("sending out packet destined for our own mac\n"); 00511 (void)pico_ethernet_receive(clone); 00512 return 1; 00513 } 00514 00515 return 0; 00516 } 00517 00518 /* Ethernet send, second attempt: try bcast. 00519 * Returns 0 if the packet is not bcast, so it will be handled somewhere else. 00520 * Returns 1 if the packet is handled by the pico_device_broadcast() function, so it can be discarded. 00521 * */ 00522 static int32_t pico_ethsend_bcast(struct pico_frame *f) 00523 { 00524 if (IS_LIMITED_BCAST(f)) { 00525 (void)pico_device_broadcast(f); /* We can discard broadcast even if it's not sent. */ 00526 return 1; 00527 } 00528 00529 return 0; 00530 } 00531 00532 /* Ethernet send, third attempt: try unicast. 00533 * If the device driver is busy, we return 0, so the stack won't discard the frame. 00534 * In case of success, we can safely return 1. 00535 */ 00536 static int32_t pico_ethsend_dispatch(struct pico_frame *f) 00537 { 00538 int ret = f->dev->send(f->dev, f->start, (int) f->len); 00539 if (ret <= 0) 00540 return 0; /* Failure to deliver! */ 00541 else { 00542 return 1; /* Frame is in flight by now. */ 00543 } 00544 } 00545 00546 00547 00548 00549 /* This function looks for the destination mac address 00550 * in order to send the frame being processed. 00551 */ 00552 00553 int32_t MOCKABLE pico_ethernet_send(struct pico_frame *f) 00554 { 00555 struct pico_eth dstmac; 00556 uint8_t dstmac_valid = 0; 00557 uint16_t proto = PICO_IDETH_IPV4; 00558 00559 #ifdef PICO_SUPPORT_IPV6 00560 /* Step 1: If the frame has an IPv6 packet, 00561 * destination address is taken from the ND tables 00562 */ 00563 if (IS_IPV6(f)) { 00564 if (pico_ethernet_ipv6_dst(f, &dstmac) < 0) 00565 { 00566 pico_ipv6_nd_postpone(f); 00567 return 0; /* I don't care if frame was actually postponed. If there is no room in the ND table, discard safely. */ 00568 } 00569 00570 dstmac_valid = 1; 00571 proto = PICO_IDETH_IPV6; 00572 } 00573 else 00574 #endif 00575 00576 /* In case of broadcast (IPV4 only), dst mac is FF:FF:... */ 00577 if (IS_BCAST(f) || destination_is_bcast(f)) 00578 { 00579 memcpy(&dstmac, PICO_ETHADDR_ALL, PICO_SIZE_ETH); 00580 dstmac_valid = 1; 00581 } 00582 00583 /* In case of multicast, dst mac is translated from the group address */ 00584 else if (destination_is_mcast(f)) { 00585 uint8_t pico_mcast_mac[6] = { 00586 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 00587 }; 00588 pico_ethernet_mcast_translate(f, pico_mcast_mac); 00589 memcpy(&dstmac, pico_mcast_mac, PICO_SIZE_ETH); 00590 dstmac_valid = 1; 00591 } 00592 00593 #if (defined PICO_SUPPORT_IPV4) 00594 else { 00595 struct pico_eth *arp_get; 00596 arp_get = pico_arp_get(f); 00597 if (arp_get) { 00598 memcpy(&dstmac, arp_get, PICO_SIZE_ETH); 00599 dstmac_valid = 1; 00600 } else { 00601 /* At this point, ARP will discard the frame in any case. 00602 * It is safe to return without discarding. 00603 */ 00604 pico_arp_postpone(f); 00605 return 0; 00606 /* Same case as for IPv6 ... */ 00607 } 00608 00609 } 00610 #endif 00611 00612 /* This sets destination and source address, then pushes the packet to the device. */ 00613 if (dstmac_valid) { 00614 struct pico_eth_hdr *hdr; 00615 hdr = (struct pico_eth_hdr *) f->datalink_hdr; 00616 if ((f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) 00617 { 00618 f->start -= PICO_SIZE_ETHHDR; 00619 f->len += PICO_SIZE_ETHHDR; 00620 f->datalink_hdr = f->start; 00621 hdr = (struct pico_eth_hdr *) f->datalink_hdr; 00622 memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH); 00623 memcpy(hdr->daddr, &dstmac, PICO_SIZE_ETH); 00624 hdr->proto = proto; 00625 } 00626 00627 if (pico_ethsend_local(f, hdr) || pico_ethsend_bcast(f) || pico_ethsend_dispatch(f)) { 00628 /* one of the above functions has delivered the frame accordingly. (returned != 0) 00629 * It is safe to directly return success. 00630 * */ 00631 return 0; 00632 } 00633 } 00634 00635 /* Failure: do not dequeue the frame, keep it for later. */ 00636 return -1; 00637 } 00638 00639 #endif /* PICO_SUPPORT_ETH */ 00640 00641 00642 void pico_store_network_origin(void *src, struct pico_frame *f) 00643 { 00644 #ifdef PICO_SUPPORT_IPV4 00645 struct pico_ip4 *ip4; 00646 #endif 00647 00648 #ifdef PICO_SUPPORT_IPV6 00649 struct pico_ip6 *ip6; 00650 #endif 00651 00652 #ifdef PICO_SUPPORT_IPV4 00653 if (IS_IPV4(f)) { 00654 struct pico_ipv4_hdr *hdr; 00655 hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00656 ip4 = (struct pico_ip4 *) src; 00657 ip4->addr = hdr->src.addr; 00658 } 00659 00660 #endif 00661 #ifdef PICO_SUPPORT_IPV6 00662 if (IS_IPV6(f)) { 00663 struct pico_ipv6_hdr *hdr; 00664 hdr = (struct pico_ipv6_hdr *) f->net_hdr; 00665 ip6 = (struct pico_ip6 *) src; 00666 memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6); 00667 } 00668 00669 #endif 00670 } 00671 00672 int pico_address_compare(union pico_address *a, union pico_address *b, uint16_t proto) 00673 { 00674 #ifdef PICO_SUPPORT_IPV6 00675 if (proto == PICO_PROTO_IPV6) { 00676 return pico_ipv6_compare(&a->ip6, &b->ip6); 00677 } 00678 00679 #endif 00680 #ifdef PICO_SUPPORT_IPV4 00681 if (proto == PICO_PROTO_IPV4) { 00682 return pico_ipv4_compare(&a->ip4, &b->ip4); 00683 } 00684 00685 #endif 00686 return 0; 00687 00688 } 00689 00690 int pico_frame_dst_is_unicast(struct pico_frame *f) 00691 { 00692 if (0) { 00693 return 0; 00694 } 00695 00696 #ifdef PICO_SUPPORT_IPV4 00697 if (IS_IPV4(f)) { 00698 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00699 if (pico_ipv4_is_multicast(hdr->dst.addr) || pico_ipv4_is_broadcast(hdr->dst.addr)) 00700 return 0; 00701 00702 return 1; 00703 } 00704 00705 #endif 00706 00707 #ifdef PICO_SUPPORT_IPV6 00708 if (IS_IPV6(f)) { 00709 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; 00710 if (pico_ipv6_is_multicast(hdr->dst.addr) || pico_ipv6_is_unspecified(hdr->dst.addr)) 00711 return 0; 00712 00713 return 1; 00714 } 00715 00716 #endif 00717 else return 0; 00718 } 00719 00720 00721 /* LOWEST LEVEL: interface towards devices. */ 00722 /* Device driver will call this function which returns immediately. 00723 * Incoming packet will be processed later on in the dev loop. 00724 */ 00725 int32_t pico_stack_recv(struct pico_device *dev, uint8_t *buffer, uint32_t len) 00726 { 00727 struct pico_frame *f; 00728 int32_t ret; 00729 if (len == 0) 00730 return -1; 00731 00732 f = pico_frame_alloc(len); 00733 if (!f) 00734 { 00735 dbg("Cannot alloc incoming frame!\n"); 00736 return -1; 00737 } 00738 00739 /* Association to the device that just received the frame. */ 00740 f->dev = dev; 00741 00742 /* Setup the start pointer, length. */ 00743 f->start = f->buffer; 00744 f->len = f->buffer_len; 00745 if (f->len > 8) { 00746 uint32_t rand, mid_frame = (f->buffer_len >> 2) << 1; 00747 mid_frame -= (mid_frame % 4); 00748 memcpy(&rand, f->buffer + mid_frame, sizeof(uint32_t)); 00749 pico_rand_feed(rand); 00750 } 00751 00752 memcpy(f->buffer, buffer, len); 00753 ret = pico_enqueue(dev->q_in, f); 00754 if (ret <= 0) { 00755 pico_frame_discard(f); 00756 } 00757 00758 return ret; 00759 } 00760 00761 static int32_t _pico_stack_recv_zerocopy(struct pico_device *dev, uint8_t *buffer, uint32_t len, int ext_buffer, void (*notify_free)(uint8_t *)) 00762 { 00763 struct pico_frame *f; 00764 int ret; 00765 if (len == 0) 00766 return -1; 00767 00768 f = pico_frame_alloc_skeleton(len, ext_buffer); 00769 if (!f) 00770 { 00771 dbg("Cannot alloc incoming frame!\n"); 00772 return -1; 00773 } 00774 00775 if (pico_frame_skeleton_set_buffer(f, buffer) < 0) 00776 { 00777 dbg("Invalid zero-copy buffer!\n"); 00778 PICO_FREE(f->usage_count); 00779 PICO_FREE(f); 00780 return -1; 00781 } 00782 00783 if (notify_free) { 00784 f->notify_free = notify_free; 00785 } 00786 00787 f->dev = dev; 00788 ret = pico_enqueue(dev->q_in, f); 00789 if (ret <= 0) { 00790 pico_frame_discard(f); 00791 } 00792 00793 return ret; 00794 } 00795 00796 int32_t pico_stack_recv_zerocopy(struct pico_device *dev, uint8_t *buffer, uint32_t len) 00797 { 00798 return _pico_stack_recv_zerocopy(dev, buffer, len, 0, NULL); 00799 } 00800 00801 int32_t pico_stack_recv_zerocopy_ext_buffer(struct pico_device *dev, uint8_t *buffer, uint32_t len) 00802 { 00803 return _pico_stack_recv_zerocopy(dev, buffer, len, 1, NULL); 00804 } 00805 00806 int32_t pico_stack_recv_zerocopy_ext_buffer_notify(struct pico_device *dev, uint8_t *buffer, uint32_t len, void (*notify_free)(uint8_t *buffer)) 00807 { 00808 return _pico_stack_recv_zerocopy(dev, buffer, len, 1, notify_free); 00809 } 00810 00811 int32_t pico_sendto_dev(struct pico_frame *f) 00812 { 00813 if (!f->dev) { 00814 pico_frame_discard(f); 00815 return -1; 00816 } else { 00817 if (f->len > 8) { 00818 uint32_t rand, mid_frame = (f->buffer_len >> 2) << 1; 00819 mid_frame -= (mid_frame % 4); 00820 memcpy(&rand, f->buffer + mid_frame, sizeof(uint32_t)); 00821 pico_rand_feed(rand); 00822 } 00823 00824 return pico_enqueue(f->dev->q_out, f); 00825 } 00826 } 00827 00828 struct pico_timer 00829 { 00830 void *arg; 00831 void (*timer)(pico_time timestamp, void *arg); 00832 }; 00833 00834 struct pico_timer_ref 00835 { 00836 pico_time expire; 00837 struct pico_timer *tmr; 00838 }; 00839 00840 typedef struct pico_timer_ref pico_timer_ref; 00841 00842 DECLARE_HEAP(pico_timer_ref, expire); 00843 00844 static heap_pico_timer_ref *Timers; 00845 00846 int32_t pico_seq_compare(uint32_t a, uint32_t b) 00847 { 00848 uint32_t thresh = ((uint32_t)(-1)) >> 1; 00849 00850 if (a > b) /* return positive number, if not wrapped */ 00851 { 00852 if ((a - b) > thresh) /* b wrapped */ 00853 return -(int32_t)(b - a); /* b = very small, a = very big */ 00854 else 00855 return (int32_t)(a - b); /* a = biggest, b = a bit smaller */ 00856 00857 } 00858 00859 if (a < b) /* return negative number, if not wrapped */ 00860 { 00861 if ((b - a) > thresh) /* a wrapped */ 00862 return (int32_t)(a - b); /* a = very small, b = very big */ 00863 else 00864 return -(int32_t)(b - a); /* b = biggest, a = a bit smaller */ 00865 00866 } 00867 00868 return 0; 00869 } 00870 00871 static void pico_check_timers(void) 00872 { 00873 struct pico_timer *t; 00874 struct pico_timer_ref tref_unused, *tref = heap_first(Timers); 00875 pico_tick = PICO_TIME_MS(); 00876 while((tref) && (tref->expire < pico_tick)) { 00877 t = tref->tmr; 00878 if (t && t->timer) 00879 t->timer(pico_tick, t->arg); 00880 00881 if (t) 00882 { 00883 PICO_FREE(t); 00884 } 00885 00886 t = NULL; 00887 heap_peek(Timers, &tref_unused); 00888 tref = heap_first(Timers); 00889 } 00890 } 00891 00892 void MOCKABLE pico_timer_cancel(struct pico_timer *t) 00893 { 00894 uint32_t i; 00895 struct pico_timer_ref *tref = Timers->top; 00896 if (!t) 00897 return; 00898 00899 for (i = 1; i <= Timers->n; i++) { 00900 if (tref[i].tmr == t) { 00901 Timers->top[i].tmr = NULL; 00902 PICO_FREE(t); 00903 break; 00904 } 00905 } 00906 } 00907 00908 #define PROTO_DEF_NR 11 00909 #define PROTO_DEF_AVG_NR 4 00910 #define PROTO_DEF_SCORE 32 00911 #define PROTO_MIN_SCORE 32 00912 #define PROTO_MAX_SCORE 128 00913 #define PROTO_LAT_IND 3 /* latency indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */ 00914 #define PROTO_MAX_LOOP (PROTO_MAX_SCORE << PROTO_LAT_IND) /* max global loop score, so per tick */ 00915 00916 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret) 00917 { 00918 int temp, i, j, sum; 00919 int max_total = PROTO_MAX_LOOP, total = 0; 00920 00921 /* dbg("USED SCORES> "); */ 00922 00923 for (i = 0; i < PROTO_DEF_NR; i++) { 00924 00925 /* if used looped score */ 00926 if (ret[i] < score[i]) { 00927 temp = score[i] - ret[i]; /* remaining loop score */ 00928 00929 /* dbg("%3d - ",temp); */ 00930 00931 if (index[i] >= PROTO_DEF_AVG_NR) 00932 index[i] = 0; /* reset index */ 00933 00934 j = index[i]; 00935 avg[i][j] = temp; 00936 00937 index[i]++; 00938 00939 if (ret[i] == 0 && ((score[i] * 2) <= PROTO_MAX_SCORE) && ((total + (score[i] * 2)) < max_total)) { /* used all loop score -> increase next score directly */ 00940 score[i] *= 2; 00941 total += score[i]; 00942 continue; 00943 } 00944 00945 sum = 0; 00946 for (j = 0; j < PROTO_DEF_AVG_NR; j++) 00947 sum += avg[i][j]; /* calculate sum */ 00948 00949 sum /= 4; /* divide by 4 to get average used score */ 00950 00951 /* criterion to increase next loop score */ 00952 if (sum > (score[i] - (score[i] / 4)) && ((score[i] * 2) <= PROTO_MAX_SCORE) && ((total + (score[i] / 2)) < max_total)) { /* > 3/4 */ 00953 score[i] *= 2; /* double loop score */ 00954 total += score[i]; 00955 continue; 00956 } 00957 00958 /* criterion to decrease next loop score */ 00959 if ((sum < (score[i] / 4)) && ((score[i] / 2) >= PROTO_MIN_SCORE)) { /* < 1/4 */ 00960 score[i] /= 2; /* half loop score */ 00961 total += score[i]; 00962 continue; 00963 } 00964 00965 /* also add non-changed scores */ 00966 total += score[i]; 00967 } 00968 else if (ret[i] == score[i]) { 00969 /* no used loop score - gradually decrease */ 00970 00971 /* dbg("%3d - ",0); */ 00972 00973 if (index[i] >= PROTO_DEF_AVG_NR) 00974 index[i] = 0; /* reset index */ 00975 00976 j = index[i]; 00977 avg[i][j] = 0; 00978 00979 index[i]++; 00980 00981 sum = 0; 00982 for (j = 0; j < PROTO_DEF_AVG_NR; j++) 00983 sum += avg[i][j]; /* calculate sum */ 00984 00985 sum /= 2; /* divide by 4 to get average used score */ 00986 00987 if ((sum == 0) && ((score[i] / 2) >= PROTO_MIN_SCORE)) { 00988 score[i] /= 2; /* half loop score */ 00989 total += score[i]; 00990 for (j = 0; j < PROTO_DEF_AVG_NR; j++) 00991 avg[i][j] = score[i]; 00992 } 00993 00994 } 00995 } 00996 /* dbg("\n"); */ 00997 00998 return 0; 00999 } 01000 01001 void pico_stack_tick(void) 01002 { 01003 static int score[PROTO_DEF_NR] = { 01004 PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE 01005 }; 01006 static int index[PROTO_DEF_NR] = { 01007 0, 0, 0, 0, 0, 0 01008 }; 01009 static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR]; 01010 static int ret[PROTO_DEF_NR] = { 01011 0 01012 }; 01013 01014 pico_check_timers(); 01015 01016 /* dbg("LOOP_SCORES> %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d\n",score[0],score[1],score[2],score[3],score[4],score[5],score[6],score[7],score[8],score[9],score[10]); */ 01017 01018 /* score = pico_protocols_loop(100); */ 01019 01020 ret[0] = pico_devices_loop(score[0], PICO_LOOP_DIR_IN); 01021 pico_rand_feed((uint32_t)ret[0]); 01022 01023 ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN); 01024 pico_rand_feed((uint32_t)ret[1]); 01025 01026 ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN); 01027 pico_rand_feed((uint32_t)ret[2]); 01028 01029 ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN); 01030 pico_rand_feed((uint32_t)ret[3]); 01031 01032 01033 ret[5] = score[5]; 01034 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6) 01035 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP) 01036 ret[5] = pico_sockets_loop(score[5]); /* swapped */ 01037 pico_rand_feed((uint32_t)ret[5]); 01038 #endif 01039 #endif 01040 01041 ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN); 01042 pico_rand_feed((uint32_t)ret[4]); 01043 01044 01045 ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT); 01046 pico_rand_feed((uint32_t)ret[6]); 01047 01048 ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT); 01049 pico_rand_feed((uint32_t)ret[7]); 01050 01051 ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT); 01052 pico_rand_feed((uint32_t)ret[8]); 01053 01054 ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT); 01055 pico_rand_feed((uint32_t)ret[9]); 01056 01057 ret[10] = pico_devices_loop(score[10], PICO_LOOP_DIR_OUT); 01058 pico_rand_feed((uint32_t)ret[10]); 01059 01060 /* calculate new loop scores for next iteration */ 01061 calc_score(score, index, (int (*)[])avg, ret); 01062 } 01063 01064 void pico_stack_loop(void) 01065 { 01066 while(1) { 01067 pico_stack_tick(); 01068 PICO_IDLE(); 01069 } 01070 } 01071 01072 MOCKABLE struct pico_timer *pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg) 01073 { 01074 struct pico_timer *t = PICO_ZALLOC(sizeof(struct pico_timer)); 01075 struct pico_timer_ref tref; 01076 if (!t) { 01077 pico_err = PICO_ERR_ENOMEM; 01078 return NULL; 01079 } 01080 01081 tref.expire = PICO_TIME_MS() + expire; 01082 t->arg = arg; 01083 t->timer = timer; 01084 tref.tmr = t; 01085 heap_insert(Timers, &tref); 01086 if (Timers->n > PICO_MAX_TIMERS) { 01087 dbg("Warning: I have %d timers\n", (int)Timers->n); 01088 } 01089 01090 return t; 01091 } 01092 01093 int pico_stack_init(void) 01094 { 01095 01096 #ifdef PICO_SUPPORT_IPV4 01097 pico_protocol_init(&pico_proto_ipv4); 01098 #endif 01099 01100 #ifdef PICO_SUPPORT_IPV6 01101 pico_protocol_init(&pico_proto_ipv6); 01102 #endif 01103 01104 #ifdef PICO_SUPPORT_ICMP4 01105 pico_protocol_init(&pico_proto_icmp4); 01106 #endif 01107 01108 #ifdef PICO_SUPPORT_ICMP6 01109 pico_protocol_init(&pico_proto_icmp6); 01110 #endif 01111 01112 #if defined(PICO_SUPPORT_IGMP) && defined(PICO_SUPPORT_MCAST) 01113 pico_protocol_init(&pico_proto_igmp); 01114 #endif 01115 01116 #ifdef PICO_SUPPORT_UDP 01117 pico_protocol_init(&pico_proto_udp); 01118 #endif 01119 01120 #ifdef PICO_SUPPORT_TCP 01121 pico_protocol_init(&pico_proto_tcp); 01122 #endif 01123 01124 #ifdef PICO_SUPPORT_DNS_CLIENT 01125 pico_dns_client_init(); 01126 #endif 01127 01128 pico_rand_feed(123456); 01129 01130 /* Initialize timer heap */ 01131 Timers = heap_init(); 01132 if (!Timers) 01133 return -1; 01134 01135 #if ((defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_ETH)) 01136 /* Initialize ARP module */ 01137 pico_arp_init(); 01138 #endif 01139 01140 #ifdef PICO_SUPPORT_IPV6 01141 /* Initialize Neighbor discovery module */ 01142 pico_ipv6_nd_init(); 01143 #endif 01144 01145 #ifdef PICO_SUPPORT_OLSR 01146 pico_olsr_init(); 01147 #endif 01148 #ifdef PICO_SUPPORT_AODV 01149 pico_aodv_init(); 01150 #endif 01151 01152 pico_stack_tick(); 01153 pico_stack_tick(); 01154 pico_stack_tick(); 01155 return 0; 01156 } 01157
Generated on Tue Jul 12 2022 15:59:22 by 1.7.2