/*---------------------------------------------------------------------------*/ static void packet_input(void) { // printf("Tcpip: packet_input"); // rpl_trace(rpl_dataptr_from_packetbuf()); #if UIP_CONF_IP_FORWARD if(uip_len > 0) { tcpip_is_forwarding = 1; if(uip_fw_forward() == UIP_FW_LOCAL) { tcpip_is_forwarding = 0; check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input forward output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } tcpip_is_forwarding = 0; } #else /* UIP_CONF_IP_FORWARD */ if(uip_len > 0) { // printf("Tcpip: packet_input 2"); // rpl_trace(rpl_dataptr_from_packetbuf()); if(packetbuf_attr(PACKETBUF_ATTR_IS_ANYCAST)) { anycast_packet_received(); } check_for_tcp_syn(); uip_input(); if(uip_len > 0) { // printf("Tcpip: packet_input 3"); // rpl_trace(rpl_dataptr_from_packetbuf()); #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } #endif /* UIP_CONF_IP_FORWARD */ }
/*---------------------------------------------------------------------------*/ static void packet_input(void) { if(uip_len > 0) { #if UIP_CONF_IP_FORWARD tcpip_is_forwarding = 1; if(uip_fw_forward() != UIP_FW_LOCAL) { tcpip_is_forwarding = 0; return; } tcpip_is_forwarding = 0; #endif /* UIP_CONF_IP_FORWARD */ check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else /* NETSTACK_CONF_WITH_IPV6 */ PRINTF("tcpip packet_input output len %d\n", uip_len); tcpip_output(); #endif /* NETSTACK_CONF_WITH_IPV6 */ #endif /* UIP_CONF_TCP_SPLIT */ } } }
/*---------------------------------------------------------------------------*/ void uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len) { #if UIP_UDP if(data != NULL) { uip_udp_conn = c; uip_slen = len; memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data, len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN? UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len); uip_process(UIP_UDP_SEND_CONN); #if UIP_CONF_IPV6_MULTICAST /* Let the multicast engine process the datagram before we send it */ if(uip_is_addr_mcast_routable(&uip_udp_conn->ripaddr)) { UIP_MCAST6.out(); } #endif /* UIP_IPV6_MULTICAST */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else if(uip_len > 0) { tcpip_output(); } #endif } uip_slen = 0; #endif /* UIP_UDP */ }
/*---------------------------------------------------------------------------*/ static uint8_t packet_input(struct net_buf *buf) { uint8_t ret = 0; #if UIP_CONF_IP_FORWARD if(uip_len > 0) { tcpip_is_forwarding = 1; if(uip_fw_forward() == UIP_FW_LOCAL) { tcpip_is_forwarding = 0; check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input forward output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } tcpip_is_forwarding = 0; } #else /* UIP_CONF_IP_FORWARD */ if(uip_len(buf) > 0) { check_for_tcp_syn(buf); ret = uip_input(buf); if(ret && uip_len(buf) > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(buf); #else /* UIP_CONF_TCP_SPLIT */ #if NETSTACK_CONF_WITH_IPV6 PRINTF("tcpip packet_input output len %d\n", uip_len(buf)); ret = tcpip_ipv6_output(buf); #else PRINTF("tcpip packet_input output len %d\n", uip_len(buf)); ret = tcpip_output(buf, NULL); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } #endif /* UIP_CONF_IP_FORWARD */ return ret; }
/*---------------------------------------------------------------------------*/ static void packet_input(void) { #if UIP_CONF_IP_FORWARD if(uip_len > 0) { tcpip_is_forwarding = 1; if(uip_fw_forward() == UIP_FW_LOCAL) { tcpip_is_forwarding = 0; check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input forward output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } tcpip_is_forwarding = 0; } #else /* UIP_CONF_IP_FORWARD */ if(uip_len > 0) { check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } #endif /* UIP_CONF_IP_FORWARD */ }
/*---------------------------------------------------------------------------*/ static void packet_input(void) { if(uip_len > 0) { check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else /* NETSTACK_CONF_WITH_IPV6 */ tcpip_output(); #endif /* NETSTACK_CONF_WITH_IPV6 */ } } }
/*---------------------------------------------------------------------------*/ void uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len) { #if UIP_UDP if(data != NULL) { uip_udp_conn = c; uip_slen = len; memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data, len > UIP_BUFSIZE? UIP_BUFSIZE: len); uip_process(UIP_UDP_SEND_CONN); #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else if(uip_len > 0) { tcpip_output(); } #endif } uip_slen = 0; #endif /* UIP_UDP */ }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)) { UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) { nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_len = 0; return; } } else { nexthop = &locrt->nexthop; } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_len = 0; return; } #endif /* UIP_CONF_IPV6_RPL */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { #if UIP_ND6_SEND_NA if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_len = 0; return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; } #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(&nbr->lladdr); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(&nbr->lladdr); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
/*---------------------------------------------------------------------------*/ static void eventhandler(c_event_t ev, p_data_t data) { #if UIP_TCP static unsigned char i; // register struct listenport *l; #endif /*UIP_TCP*/ switch(ev) { case EVENT_TYPE_TIMER_EXP: /* We get this event if one of our timers have expired. */ { /* Check the clock so see if we should call the periodic uIP processing. */ if(data == &periodic && etimer_expired(&periodic)) { #if UIP_TCP for(i = 0; i < UIP_CONNS; ++i) { if(uip_conn_active(i)) { /* Only restart the timer if there are active connections. */ etimer_restart(&periodic); uip_periodic(i); #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else if(uip_len > 0) { PRINTF("tcpip_output from periodic len %d\n\r", uip_len); tcpip_output(); PRINTF("tcpip_output after periodic len %d\n\r", uip_len); } #endif /* NETSTACK_CONF_WITH_IPV6 */ } } #endif /* UIP_TCP */ #if UIP_CONF_IP_FORWARD uip_fw_periodic(); #endif /* UIP_CONF_IP_FORWARD */ } #if NETSTACK_CONF_WITH_IPV6 #if UIP_CONF_IPV6_REASSEMBLY /* * check the timer for reassembly */ if(data == &uip_reass_timer && etimer_expired(&uip_reass_timer)) { uip_reass_over(); tcpip_ipv6_output(); } #endif /* UIP_CONF_IPV6_REASSEMBLY */ /* * check the different timers for neighbor discovery and * stateless autoconfiguration */ /*if(data == &uip_ds6_timer_periodic && etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); tcpip_ipv6_output(); }*/ #if !UIP_CONF_ROUTER if(data == &uip_ds6_timer_rs && etimer_expired(&uip_ds6_timer_rs)) { uip_ds6_send_rs(); tcpip_ipv6_output(); } #endif /* !UIP_CONF_ROUTER */ if(data == &uip_ds6_timer_periodic && etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); tcpip_ipv6_output(); } #endif /* NETSTACK_CONF_WITH_IPV6 */ } break; #if UIP_TCP case EVENT_TYPE_TCP_POLL: if(data != NULL) { uip_poll_conn(data); #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else /* NETSTACK_CONF_WITH_IPV6 */ if(uip_len > 0) { PRINTF("tcpip_output from tcp poll len %d\n\r", uip_len); tcpip_output(); } #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Start the periodic polling, if it isn't already active. */ start_periodic_tcp_timer(); } break; #endif /* UIP_TCP */ #if UIP_UDP case EVENT_TYPE_UDP_POLL: if(data != NULL) { uip_udp_periodic_conn(data); #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else if(uip_len > 0) { tcpip_output(); } #endif /* UIP_UDP */ } break; #endif /* UIP_UDP */ case EVENT_TYPE_PCK_INPUT: packet_input(); break; }; }
/*---------------------------------------------------------------------------*/ static void eventhandler(process_event_t ev, process_data_t data) { #if UIP_TCP static unsigned char i; register struct listenport *l; #endif /*UIP_TCP*/ struct process *p; switch(ev) { case PROCESS_EVENT_EXITED: /* This is the event we get if a process has exited. We go through the TCP/IP tables to see if this process had any open connections or listening TCP ports. If so, we'll close those connections. */ p = (struct process *)data; #if UIP_TCP l = s.listenports; for(i = 0; i < UIP_LISTENPORTS; ++i) { if(l->p == p) { uip_unlisten(l->port); l->port = 0; l->p = PROCESS_NONE; } ++l; } { struct uip_conn *cptr; for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) { if(cptr->appstate.p == p) { cptr->appstate.p = PROCESS_NONE; cptr->tcpstateflags = UIP_CLOSED; } } } #endif /* UIP_TCP */ #if UIP_UDP { struct uip_udp_conn *cptr; for(cptr = &uip_udp_conns[0]; cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { if(cptr->appstate.p == p) { cptr->lport = 0; } } } #endif /* UIP_UDP */ break; case PROCESS_EVENT_TIMER: /* We get this event if one of our timers have expired. */ { /* Check the clock so see if we should call the periodic uIP processing. */ if(data == &periodic && etimer_expired(&periodic)) { #if UIP_TCP for(i = 0; i < UIP_CONNS; ++i) { if(uip_conn_active(i)) { /* Only restart the timer if there are active connections. */ etimer_restart(&periodic); uip_periodic(i); #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else if(uip_len > 0) { PRINTF("tcpip_output from periodic len %d\n", uip_len); tcpip_output(); PRINTF("tcpip_output after periodic len %d\n", uip_len); } #endif /* UIP_CONF_IPV6 */ } } #endif /* UIP_TCP */ #if UIP_CONF_IP_FORWARD uip_fw_periodic(); #endif /* UIP_CONF_IP_FORWARD */ } #if UIP_CONF_IPV6 #if UIP_CONF_IPV6_REASSEMBLY /* * check the timer for reassembly */ if(data == &uip_reass_timer && etimer_expired(&uip_reass_timer)) { uip_reass_over(); tcpip_ipv6_output(); } #endif /* UIP_CONF_IPV6_REASSEMBLY */ /* * check the different timers for neighbor discovery and * stateless autoconfiguration */ /*if(data == &uip_ds6_timer_periodic && etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); tcpip_ipv6_output(); }*/ #if !UIP_CONF_ROUTER if(data == &uip_ds6_timer_rs && etimer_expired(&uip_ds6_timer_rs)) { uip_ds6_send_rs(); tcpip_ipv6_output(); } #endif /* !UIP_CONF_ROUTER */ if(data == &uip_ds6_timer_periodic && etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); tcpip_ipv6_output(); } #endif /* UIP_CONF_IPV6 */ } break; #if UIP_TCP case TCP_POLL: if(data != NULL) { uip_poll_conn(data); #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else /* UIP_CONF_IPV6 */ if(uip_len > 0) { PRINTF("tcpip_output from tcp poll len %d\n", uip_len); tcpip_output(); } #endif /* UIP_CONF_IPV6 */ /* Start the periodic polling, if it isn't already active. */ start_periodic_tcp_timer(); } break; #endif /* UIP_TCP */ #if UIP_UDP case UDP_POLL: if(data != NULL) { uip_udp_periodic_conn(data); #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else if(uip_len > 0) { tcpip_output(); } #endif /* UIP_UDP */ } break; #endif /* UIP_UDP */ case PACKET_INPUT: packet_input(); break; }; }
/* ----------------------------------------------------------------------------- * \brief Deliver an incoming packet to the TCP/IP stack * * This function is called by theServer to * deliver an incoming packet to the TCP/IP stack. The * incoming packet must be present in the uip_buf buffer, * and the length of the packet must be in the global * uip_len variable. * -------------------------------------------------------------------------- */ void xtcpip_input(chanend mac_tx) { /*_______________*/ #if UIP_CONF_IPV4 /* ORIGINAL_XMOS */ if (BUF->type == htons(UIP_ETHTYPE_IP)) { uip_arp_ipin(); uip_input(); if (uip_len > 0) { if (uip_udpconnection() && (TCPBUF->proto != UIP_PROTO_ICMP) && (TCPBUF->proto != UIP_PROTO_IGMP)) uip_arp_out( uip_udp_conn); else uip_arp_out( NULL); xtcp_tx_buffer(mac_tx); } } else if (BUF->type == htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); if (uip_len > 0) { xtcp_tx_buffer(mac_tx); } for (int i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_arp_event(i); if (uip_len > 0) { uip_arp_out(&uip_udp_conns[i]); xtcp_tx_buffer(mac_tx); } } } #endif /* UIP_CONF_IPV4 ORIGINAL_XMOS */ /*_______________*/ /* contiki tcpip.c */ #if UIP_CONF_IP_FORWARD if(uip_len > 0) { tcpip_is_forwarding = 1; if(uip_fw_forward() == UIP_FW_LOCAL) { tcpip_is_forwarding = 0; check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(mac_tx); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 xtcpip_ipv6_output(mac_tx); #else PRINTF("tcpip packet_input forward output len %d\n", uip_len); xtcpip_output(mac_tx); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } tcpip_is_forwarding = 0; } #else /* UIP_CONF_IP_FORWARD */ if(uip_len > 0) { uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(mac_tx); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 xtcpip_ipv6_output(mac_tx); #else PRINTF("tcpip packet_input output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } #endif /* UIP_CONF_IP_FORWARD */ }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t* nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif uip_len = 0; return; } } else { nexthop = &locrt->nexthop; } } /* end of next hop determination */ // if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { if(0){ /* * I-D.ietf.6lowpan-nd 5.7: As all prefixes but the link-local prefix are * always assumed to be off-link, multicast-based address resolution between * neighbors is not needed. * In addition, there are neither INCOMPLETE, STALE, DELAY, nor PROBE NCEs * in 6LoWPAN-ND. */ return; } else { tcpip_output(&(nbr->lladdr)); uip_len = 0; return; } } /*multicast IP destination address */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_clear_buf(); return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_clear_buf(); return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t *route; /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); /* No route was found - we send to the default route instead. */ if(route == NULL) { PRINTF("tcpip_ipv6_output: no route found, using default route\n"); nexthop = uip_ds6_defrt_choose(); if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } /* Inform the other end that the destination is not reachable. If it's * not informed routes might get lost unexpectedly until there's a need * to send a new packet to the peer */ if(UIP_FALLBACK_INTERFACE.output() < 0) { PRINTF("FALLBACK: output error. Reporting DST UNREACH\n"); uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); uip_flags = 0; tcpip_ipv6_output(); return; } #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_clear_buf(); return; } } else { /* A route was found, so we look up the nexthop neighbor for the route. */ nexthop = uip_ds6_route_nexthop(route); /* If the nexthop is dead, for example because the neighbor never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { #if UIP_CONF_IPV6_RPL /* If we are running RPL, and if we are the root of the network, we'll trigger a global repair berfore we remove the route. */ rpl_dag_t *dag; rpl_instance_t *instance; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { instance = dag->instance; rpl_repair_root(instance->instance_id); } #endif /* UIP_CONF_IPV6_RPL */ uip_ds6_route_rm(route); /* We don't have a nexthop to send the packet to, so we drop it. */ return; } } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { static uint8_t annotate_last; static uint8_t annotate_has_last = 0; if(annotate_has_last) { printf("#L %u 0; red\n", annotate_last); } printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1]; annotate_has_last = 1; } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_clear_buf(); return; } #endif /* UIP_CONF_IPV6_RPL */ nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_clear_buf(); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_clear_buf(); }
/*-----------------------------------------------------------------------------*/ void uip_split_output(void) { u16_t tcplen, len1, len2; /* We only try to split maximum sized TCP segments. */ if(BUF->proto == UIP_PROTO_TCP && uip_len == UIP_BUFSIZE - UIP_LLH_LEN) { tcplen = uip_len - UIP_TCPIP_HLEN; /* Split the segment in two. If the original packet length was odd, we make the second packet one byte larger. */ len1 = len2 = tcplen / 2; if(len1 + len2 < tcplen) { ++len2; } /* Create the first packet. This is done by altering the length field of the IP header and updating the checksums. */ uip_len = len1 + UIP_TCPIP_HLEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* UIP_CONF_IPV6 */ BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* UIP_CONF_IPV6 */ /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !UIP_CONF_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* UIP_CONF_IPV6 */ /* Transmit the first packet. */ /* uip_fw_output();*/ tcpip_output(); /* Now, create the second packet. To do this, it is not enough to just alter the length field, but we must also update the TCP sequence number and point the uip_appdata to a new place in memory. This place is detemined by the length of the first packet (len1). */ uip_len = len2 + UIP_TCPIP_HLEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* UIP_CONF_IPV6 */ BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* UIP_CONF_IPV6 */ /* uip_appdata += len1;*/ memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2); uip_add32(BUF->seqno, len1); BUF->seqno[0] = uip_acc32[0]; BUF->seqno[1] = uip_acc32[1]; BUF->seqno[2] = uip_acc32[2]; BUF->seqno[3] = uip_acc32[3]; /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !UIP_CONF_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* UIP_CONF_IPV6 */ /* Transmit the second packet. */ /* uip_fw_output();*/ tcpip_output(); } else {
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; uip_ds6_route_t *route = NULL; if(uip_len == 0) { return; } PRINTF("IPv6 packet send from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_clear_buf(); return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_clear_buf(); return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); /* No route was found - we send to the default route instead. */ if(route == NULL) { #if CETIC_6LBR_SMARTBRIDGE if (uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { /* In smart-bridge mode, there is no route towards hosts on the Ethernet side Therefore we have to check the destination and assume the host is on-link */ nexthop = &UIP_IP_BUF->destipaddr; } else #endif #if CETIC_6LBR_ROUTER && UIP_CONF_IPV6_RPL if (is_dodag_root() && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { //In router mode, we drop packets towards unknown mote PRINTF("Dropping wsn packet with no route\n"); uip_len = 0; return; } else #endif #if CETIC_6LBR_IP64 if(ip64_addr_is_ip64(&UIP_IP_BUF->destipaddr)) { #if UIP_CONF_IPV6_RPL rpl_remove_header(); #endif IP64_CONF_UIP_FALLBACK_INTERFACE.output(); uip_len = 0; uip_ext_len = 0; return; } else #endif { PRINTF("tcpip_ipv6_output: no route found, using default route\n"); nexthop = uip_ds6_defrt_choose(); } if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_clear_buf(); return; } } else { /* A route was found, so we look up the nexthop neighbor for the route. */ nexthop = uip_ds6_route_nexthop(route); /* If the nexthop is dead, for example because the neighbor never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { #if UIP_CONF_IPV6_RPL /* If we are running RPL, and if we are the root of the network, we'll trigger a DIO before we remove the route. */ rpl_dag_t *dag; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { rpl_reset_dio_timer(dag->instance); } #endif /* UIP_CONF_IPV6_RPL */ uip_ds6_route_rm(route); /* We don't have a nexthop to send the packet to, so we drop it. */ return; } } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { static uint8_t annotate_last; static uint8_t annotate_has_last = 0; if(annotate_has_last) { printf("#L %u 0; red\n", annotate_last); } printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1]; annotate_has_last = 1; } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_clear_buf(); return; } #endif /* UIP_CONF_IPV6_RPL */ nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA #if CETIC_6LBR && UIP_CONF_IPV6_RPL /* Don't perform NUD if it has been disabled for WSN */ if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) != 0 && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) && route != NULL) { uip_clear_buf(); return; } #endif if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_clear_buf(); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */ #if CETIC_6LBR && UIP_CONF_IPV6_RPL /* Don't update nbr state if we don't want to perform NUD for WSN */ if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) == 0 || !uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) || route == NULL) #endif if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_clear_buf(); }
/* ----------------------------------------------------------------------------- * Process periodical stuff. * * In contiki, this is handlet by the eventhandler of the tcpip.c file * with the process event "PROCESS_EVENT_TIMER". * -------------------------------------------------------------------------- */ void xtcp_process_timer(chanend mac_tx, xtcp_tmr_event_type_t event) { #if UIP_IGMP igmp_periodic(); if(uip_len > 0) { xtcp_tx_buffer(mac_tx); } #endif if(event == XTCP_TMR_PERIODIC) { #if UIP_TCP for(int i = 0; i < UIP_CONNS; ++i) { if(uip_conn_active(i)) { uip_periodic(i); #if UIP_CONF_IPV6 xtcpip_ipv6_output(mac_tx); #else if(uip_len > 0) { PRINTF("tcpip_output from periodic len %d\n", uip_len); tcpip_output(); PRINTF("tcpip_output after periodic len %d\n", uip_len); } #endif /* UIP_CONF_IPV6 */ } } #endif /* UIP_TCP */ #if UIP_CONF_IP_FORWARD uip_fw_periodic(); #endif /* UIP_CONF_IP_FORWARD */ } /*XXX CHSC HACK*/ #if UIP_CONF_IPV6 #if UIP_CONF_IPV6_REASSEMBLY /* * check the timer for reassembly */ if(etimer_expired(&uip_reass_timer)) { uip_reass_over(); tcpip_ipv6_output(); } #endif /* UIP_CONF_IPV6_REASSEMBLY */ /* * check the different timers for neighbor discovery and * stateless autoconfiguration */ /*if(data == &uip_ds6_timer_periodic && etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); tcpip_ipv6_output(); }*/ #if !UIP_CONF_ROUTER if(etimer_expired(&uip_ds6_timer_rs)) { uip_ds6_send_rs(); xtcpip_ipv6_output(mac_tx); } #endif /* !UIP_CONF_ROUTER */ if(etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); xtcpip_ipv6_output(mac_tx); } #endif /* UIP_CONF_IPV6 */ }
void tcpip_ipv6_output(void) { struct uip_nd6_neighbor *nbc = NULL; struct uip_nd6_defrouter *dr = NULL; if(uip_len == 0) return; if(uip_len > UIP_LINK_MTU){ UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /*If destination is on link */ nbc = NULL; if(uip_nd6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nbc = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->destipaddr); } else { #if UIP_CONF_ROUTER /*destination is not on link*/ uip_ipaddr_t ipaddr; uip_ipaddr_t *next_hop; /* Try to find the next hop address in the local routing table. */ next_hop = uip_router != NULL ? uip_router->lookup(&UIP_IP_BUF->destipaddr, &ipaddr) : NULL; if(next_hop != NULL) { /* Look for the next hop of the route in the neighbor cache. Add a cache entry if we can't find it. */ nbc = uip_nd6_nbrcache_lookup(next_hop); if(nbc == NULL) { nbc = uip_nd6_nbrcache_add(next_hop, NULL, 1, NO_STATE); } } else { #endif /* UIP_CONF_ROUTER */ /* No route found, check if a default router exists and use it then. */ dr = uip_nd6_choose_defrouter(); if(dr != NULL){ nbc = dr->nb; } else { /* shall we send a icmp error message destination unreachable ?*/ UIP_LOG("tcpip_ipv6_output: Destination off-link but no router"); uip_len = 0; return; } #if UIP_CONF_ROUTER } #endif /* UIP_CONF_ROUTER */ } /* there are two cases where the entry logically does not exist: * 1 it really does not exist. 2 it is in the NO_STATE state */ if (nbc == NULL || nbc->state == NO_STATE) { if (nbc == NULL) { /* create neighbor cache entry, original packet is replaced by NS*/ nbc = uip_nd6_nbrcache_add(&UIP_IP_BUF->destipaddr, NULL, 0, INCOMPLETE); } else { nbc->state = INCOMPLETE; } #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit */ memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); nbc->queue_buf_len = uip_len; #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_netif_is_addr_my_unicast(&UIP_IP_BUF->srcipaddr)){ uip_nd6_io_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbc->ipaddr); } else { uip_nd6_io_ns_output(NULL, NULL, &nbc->ipaddr); } stimer_set(&(nbc->last_send), uip_netif_physical_if.retrans_timer / 1000); nbc->count_send = 1; } else { if (nbc->state == INCOMPLETE){ PRINTF("tcpip_ipv6_output: neighbor cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit and set the destination neighbor to nbc */ memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); nbc->queue_buf_len = uip_len; uip_len = 0; #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ return; } /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ if (nbc->state == STALE){ nbc->state = DELAY; stimer_set(&(nbc->reachable), UIP_ND6_DELAY_FIRST_PROBE_TIME); PRINTF("tcpip_ipv6_output: neighbor cache entry stale moving to delay\n"); } stimer_set(&(nbc->last_send), uip_netif_physical_if.retrans_timer / 1000); tcpip_output(&(nbc->lladdr)); #if UIP_CONF_IPV6_QUEUE_PKT /* Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves *to STALE, and you must both send a NA and the queued packet */ if(nbc->queue_buf_len != 0) { uip_len = nbc->queue_buf_len; memcpy(UIP_IP_BUF, nbc->queue_buf, uip_len); nbc->queue_buf_len = 0; tcpip_output(&(nbc->lladdr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } } /*multicast IP destination address */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
/** * \brief Take a packet received over the ethernet link, and send it * out over 802.15.4 */ void mac_ethernetToLowpan(uint8_t * ethHeader) { //Dest address uip_lladdr_t destAddr; uip_lladdr_t *destAddrPtr = NULL; PRINTF("Packet type: 0x%04x\n\r", uip_ntohs(((struct uip_eth_hdr *) ethHeader)->type)); //RUM doesn't support sending data #if UIP_CONF_USE_RUM return; #endif /* In sniffer or sneezr mode we don't ever send anything */ if ((usbstick_mode.sendToRf == 0) || (usbstick_mode.sneeze != 0)) { uip_len = 0; return; } /* If not IPv6 we don't do anything. Disable ipv4 on the interface to prevent possible hangs from discovery packet flooding */ if (((struct uip_eth_hdr *) ethHeader)->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) { PRINTF("eth2low: Dropping packet w/type=0x%04x\n",uip_ntohs(((struct uip_eth_hdr *) ethHeader)->type)); // printf("!ipv6"); #if !RF230BB && !RF212BB usb_eth_stat.txbad++; #endif uip_len = 0; return; } /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0x33) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0x33) ) { PRINTF("eth2low: Ethernet multicast packet received\n\r"); ;//Do Nothing } else if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[2] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[3] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) { /* IPv6 does not use broadcast addresses, hence this should not happen */ PRINTF("eth2low: Dropping broadcast packet\n\r"); #if !RF230BB && !RF212BB usb_eth_stat.txbad++; #endif uip_len = 0; return; } else { /* Simple Address Translation */ if(memcmp((uint8_t *)&simple_trans_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) { #if UIP_CONF_IPV6 //Addressed to us: make 802.15.4 address from IPv6 Address destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[8] ^ 0x02; destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[9]; destAddr.addr[2] = UIP_IP_BUF->destipaddr.u8[10]; destAddr.addr[3] = UIP_IP_BUF->destipaddr.u8[11]; destAddr.addr[4] = UIP_IP_BUF->destipaddr.u8[12]; destAddr.addr[5] = UIP_IP_BUF->destipaddr.u8[13]; destAddr.addr[6] = UIP_IP_BUF->destipaddr.u8[14]; destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[15]; #else //Not intended to be functional, but allows ip4 build without errors. destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[0] ^ 0x02; destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[1]; destAddr.addr[2] = UIP_IP_BUF->destipaddr.u8[2]; destAddr.addr[3] = UIP_IP_BUF->destipaddr.u8[3]; destAddr.addr[4] = UIP_IP_BUF->destipaddr.u8[0]; destAddr.addr[5] = UIP_IP_BUF->destipaddr.u8[1]; destAddr.addr[6] = UIP_IP_BUF->destipaddr.u8[2]; destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[3]; #endif destAddrPtr = &destAddr; } #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS else { //Not addressed to us uip_len = 0; return; } #else /* Complex Address Translation */ PRINTF("eth2low: Addressed packet received... "); //Check this returns OK if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) { PRINTF(" translation failed\n\r"); #if !RF230BB && !RF212BB usb_eth_stat.txbad++; #endif uip_len = 0; return; } PRINTF(" translated OK\n\r"); destAddrPtr = &destAddr; #endif /* UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS */ } //Remove header from length before passing onward uip_len -= UIP_LLH_LEN; //Some IP packets have link layer in them, need to change them around! if (usbstick_mode.translate) { #if DEBUG uint8_t transReturn = mac_translateIPLinkLayer(ll_802154_type); PRINTF("IPTranslation: returns %d\n\r", transReturn); #else mac_translateIPLinkLayer(ll_802154_type); #endif } #if UIP_CONF_IPV6 /* Send the packet to the uip6 stack if it exists, else send to 6lowpan */ #if UIP_CONF_IPV6_RPL /* Save the destination address, to trap ponging it back to the interface */ uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); tcpip_input(); tcpip_output(destAddrPtr); #else // PRINTF("Input from %x %x %x %x %x %x %x %x\n",UIP_IP_BUF->srcipaddr.u8[0],UIP_IP_BUF->srcipaddr.u8[1],UIP_IP_BUF->srcipaddr.u8[2],UIP_IP_BUF->srcipaddr.u8[3],UIP_IP_BUF->srcipaddr.u8[4],UIP_IP_BUF->srcipaddr.u8[5],UIP_IP_BUF->srcipaddr.u8[6],UIP_IP_BUF->srcipaddr.u8[7]); // PRINTF("Output to %x %x %x %x %x %x %x %x\n",destAddr.addr[0],destAddr.addr[1],destAddr.addr[2],destAddr.addr[3],destAddr.addr[4],destAddr.addr[5],destAddr.addr[6],destAddr.addr[7]); tcpip_output(destAddrPtr); #endif #else /* UIP_CONF_IPV6 */ tcpip_output(); //Allow non-ipv6 builds (Hello World) #endif /* UIP_CONF_IPV6 */ #if !RF230BB && !RF212BB usb_eth_stat.txok++; #endif uip_len = 0; }
void tcpip_ipv6_output(void) { static uip_ds6_nbr_t *nbr = NULL; static uip_ipaddr_t* nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)) { UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) { nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif uip_len = 0; return; } } else { nexthop = &locrt->nexthop; } } /* end of next hop determination */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { // printf("add1 %d\n", nexthop->u8[15]); if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { // printf("add n\n"); uip_len = 0; return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; } } else { if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit and set the destination nbr to nbr */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } /* memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len); nbr->queue_buf_len = uip_len;*/ uip_len = 0; #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ return; } /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&(nbr->reachable), UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000); tcpip_output(&(nbr->lladdr)); #if UIP_CONF_IPV6_QUEUE_PKT /* Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves *to STALE, and you must both send a NA and the queued packet */ /* if(nbr->queue_buf_len != 0) { uip_len = nbr->queue_buf_len; memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); nbr->queue_buf_len = 0; tcpip_output(&(nbr->lladdr)); }*/ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(&(nbr->lladdr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } } /*multicast IP destination address */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
void netMainThread(void* arg) { uint8_t i; #if !NETSTACK_CONF_WITH_IPV6 POSTIMER_t arpTimer; #endif POSTIMER_t periodicTimer; int sendRequested; bool packetSeen; #if !NETSTACK_CONF_WITH_IPV6 arpTimer = posTimerCreate(); P_ASSERT("netMainThread1", arpTimer != NULL); posTimerSet(arpTimer, uipGiant, MS(10000), MS(10000)); posTimerStart(arpTimer); #endif periodicTimer = posTimerCreate(); P_ASSERT("netMainThread2", periodicTimer != NULL); posTimerSet(periodicTimer, uipGiant, MS(500), MS(500)); posTimerStart(periodicTimer); posMutexLock(uipMutex); packetSeen = false; while(1) { posMutexUnlock(uipMutex); // Using semaphore here is not fully optimal. // As it is a counting one, it can get bumped // to larger value than 1 by upper or interrupt // layer. However, not much harm is done, // this loop just spins extra times without // doing nothing useful. // A Pico]OS Flag object would be perfect, // but it doesn't work with posTimer* functions. if (!packetSeen || pollTicks == INFINITE) posSemaWait(uipGiant, pollTicks); posMutexLock(uipMutex); sendRequested = dataToSend; dataToSend = 0; packetSeen = false; if (sendRequested) { for(i = 0; i < UIP_CONNS; i++) { uip_len = 0; uip_poll_conn(&uip_conns[i]); if(uip_len > 0) { #if NETCFG_UIP_SPLIT == 1 uip_split_output(); #else #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif #endif } } #if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) { uip_len = 0; uip_udp_periodic(i); if(uip_len > 0) { #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif } } #endif /* UIP_UDP */ } packetSeen = netInterfacePoll(); if (posTimerFired(periodicTimer)) { for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); if(uip_len > 0) { #if NETCFG_UIP_SPLIT == 1 uip_split_output(); #else #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif #endif } } #if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) { uip_udp_periodic(i); if(uip_len > 0) { #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif } } #endif /* UIP_UDP */ } #if NETSTACK_CONF_WITH_IPV6 == 0 if (posTimerFired(arpTimer)) { uip_arp_timer(); } #endif // Run contiki-style timers. // Instead of posting events to process like // contiki does, it just calls common callback function // to do the work. etimer_request_poll(); } }
/*---------------------------------------------------------------------------*/ static void packet_input(void) { #if FORWARDER rpl_instance_t *instance; uint8_t octet; uint8_t ip6id; int rssi_temp; uint8_t send_rssi; rimeaddr_t packet_from_addr; packet_from_addr = *packetbuf_addr(PACKETBUF_ADDR_SENDER); instance = &instance_table[0]; octet = packet_from_addr.u8[7]; ip6id = (octet & 0b00111111) << 2; tcp_rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI); if(is_mobile_node(octet) == 1) { packet_input_count++; rssi_temp = tcp_rssi - 45; if(tcp_rssi > 200) { rssi_temp = tcp_rssi - 255 - 46; } rssi_sum += rssi_temp; if(packet_input_count == WINDOW_SIZE) { rssi_sum = rssi_sum / WINDOW_SIZE; PRINTF("RSSI = %d\n", rssi_sum); PRINTF("packet input count = %d\n", packet_input_count); if(rssi_sum <= -90) { send_rssi = rssi_sum + 255 + 46; dis_output(NULL, 1, 0, send_rssi, ip6id); } rssi_sum = 0; packet_input_count = 0; } } #endif #if UIP_CONF_IP_FORWARD if(uip_len > 0) { tcpip_is_forwarding = 1; if(uip_fw_forward() == UIP_FW_LOCAL) { tcpip_is_forwarding = 0; check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input forward output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } tcpip_is_forwarding = 0; } #else /* UIP_CONF_IP_FORWARD */ if(uip_len > 0) { check_for_tcp_syn(); uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else PRINTF("tcpip packet_input output len %d\n", uip_len); tcpip_output(); #endif #endif /* UIP_CONF_TCP_SPLIT */ } } #endif /* UIP_CONF_IP_FORWARD */ }
/** * \brief Take a packet received over the ethernet link, and send it * out over 802.15.4 */ void mac_ethernetToLowpan(uint8_t * ethHeader) { //Dest address uip_lladdr_t destAddr; uip_lladdr_t *destAddrPtr = NULL; PRINTF("Packet type: %x\n", ((struct uip_eth_hdr *) ethHeader)->type); //RUM doesn't support sending data #if UIP_CONF_USE_RUM return; #endif //If not IPv6 we don't do anything if (((struct uip_eth_hdr *) ethHeader)->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) { PRINTF("eth2low: Packet is not IPv6, dropping\n"); /* rndis_stat.txbad++; */ uip_len = 0; return; } // In sniffer mode we don't ever send anything if (usbstick_mode.sendToRf == 0) { uip_len = 0; return; } /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0x33) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0x33) ) { PRINTF("eth2low: Ethernet multicast packet received\n"); ;//Do Nothing } else if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[2] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[3] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) { /* IPv6 does not use broadcast addresses, hence this should not happen */ PRINTF("eth2low: Ethernet broadcast address received, should not happen?\n"); /* rndis_stat.txbad++; */ uip_len = 0; return; } else { PRINTF("eth2low: Addressed packet received... "); //Check this returns OK if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) { PRINTF(" translation failed\n"); /* rndis_stat.txbad++; */ uip_len = 0; return; } PRINTF(" translated OK\n"); destAddrPtr = &destAddr; } //Remove header from length before passing onward uip_len -= UIP_LLH_LEN; //Some IP packets have link layer in them, need to change them around! if (usbstick_mode.translate) { uint8_t transReturn = mac_translateIPLinkLayer(ll_802154_type); PRINTF("IPTranslation: returns %d\n", transReturn); } if (usbstick_mode.sendToRf){ tcpip_output(destAddrPtr); /* rndis_stat.txok++; */ } uip_len = 0; }
smcp_status_t smcp_plat_outbound_finish(smcp_t self,const uint8_t* data_ptr, coap_size_t data_len, int flags) { SMCP_EMBEDDED_SELF_HOOK; smcp_status_t ret = SMCP_STATUS_FAILURE; assert(uip_udp_conn == self->plat.udp_conn); uip_slen = data_len; require_action(uip_slen<SMCP_MAX_PACKET_LENGTH, bail, ret = SMCP_STATUS_MESSAGE_TOO_BIG); if (data_ptr != uip_sappdata) { memmove( uip_sappdata, data_ptr, uip_slen ); data_ptr = (const uint8_t*)uip_sappdata; } #if 0 // TODO: For some reason this isn't working anymore. Investigate. if(self->is_responding) { // We are responding, let uIP handle preparing the packet. } else #endif { // Here we explicitly tickle UIP to send the packet. // Change the remote IP address temporarily. uip_ipaddr_copy(&uip_udp_conn->ripaddr, &self->plat.sockaddr_remote.smcp_addr); smcp_get_current_instance()->plat.udp_conn->rport = self->plat.sockaddr_remote.smcp_port; uip_process(UIP_UDP_SEND_CONN); #if UIP_CONF_IPV6_MULTICAST /* Let the multicast engine process the datagram before we send it */ if (uip_is_addr_mcast_routable(&uip_udp_conn->ripaddr)) { UIP_MCAST6.out(); } #endif /* UIP_IPV6_MULTICAST */ // TODO: This next part is somewhat contiki-ish. Abstract somehow? #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif // Since we just sent out packet, we need to zero out uip_slen // to prevent uIP from trying to send out a packet. uip_slen = 0; // Make our remote address unspecified again, so that we can continue // to receive traffic. memset(&smcp_get_current_instance()->plat.udp_conn->ripaddr, 0, sizeof(uip_ipaddr_t)); smcp_get_current_instance()->plat.udp_conn->rport = 0; } ret = SMCP_STATUS_OK; bail: return ret; }