/*---------------------------------------------------------------------------*/ void uip_ds6_send_rs(void) { #if CONF_6LOWPAN_ND uint16_t r; #endif /* CONF_6LOWPAN_ND */ if((uip_ds6_defrt_choose() == NULL) && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) { PRINTF("Sending RS %u\n", rscount); uip_nd6_rs_output(); rscount++; etimer_set(&uip_ds6_timer_rs, UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND); #if CONF_6LOWPAN_ND } else if(uip_ds6_defrt_choose() == NULL) { /* Slower retransmissions */ PRINTF("Sending RS slower %u\n", rscount); uip_nd6_rs_output(); rscount++; r = (((uint16_t)random_rand()) % ((2 << (rscount - 1) - 1) + 1)) * UIP_ND6_RTR_SOLICITATION_INTERVAL; if(r >= UIP_ND6_MAX_RTR_SOLICITATION_INTERVAL) { r = UIP_ND6_MAX_RTR_SOLICITATION_INTERVAL; } etimer_set(&uip_ds6_timer_rs, r * CLOCK_SECOND); #endif /* CONF_6LOWPAN_ND */ } else { PRINTF("Router found ? (boolean): %u\n", (uip_ds6_defrt_choose() != NULL)); etimer_stop(&uip_ds6_timer_rs); } return; }
/*---------------------------------------------------------------------------*/ void uip_ds6_send_rs(void) { if((uip_ds6_defrt_choose() == NULL) && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) { PRINTF("Sending RS %u\n", rscount); uip_nd6_rs_output(); rscount++; etimer_set(&uip_ds6_timer_rs, UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND); } else { PRINTF("Router found ? (boolean): %u\n", (uip_ds6_defrt_choose() != NULL)); etimer_stop(&uip_ds6_timer_rs); } return; }
/*---------------------------------------------------------------------------*/ static void echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen) { if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) { def_rt_rssi = sicslowpan_get_last_rssi(); } }
/* Useful for debugging so allow external calls */ void raven_ping6(void) { #define PING_GOOGLE 0 UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; #if PING_GOOGLE if (seqno==1) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router } else if (seqno==2) { uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x4860,0x800f,0x0000,0x0000,0x0000,0x0000,0x0093); //ipv6.google.com } else if (seqno==3) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router } else { // uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x5FFF,0x007D,0x02D0,0xB7FF,0xFE23,0xE6DB); //?.cisco.com uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x0000,0x0010,0x0250,0x8bff,0xfee8,0xf800); //six.cisco.com } #else uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router #endif uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING6_DATALEN); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); tcpip_ipv6_output(); }
/*---------------------------------------------------------------------------*/ static void ping_parent(void) { if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) { return; } uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0, CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN); }
void uip_ds6_send_rs(uip_ds6_defrt_t *defrt) { u8_t unicast_rs = 0; if (!timer_expired(&uip_ds6_timer_rs)) { return; } locdefrt = NULL; /* First check whether we can unicast the RS to a specific router rather than * multicasting it. */ if ((defrt != NULL) && (defrt->isused)){ /* Mark this router as "sending_rs" in case it wasn't marked already */ defrt->sending_rs = 1; locdefrt = defrt; unicast_rs = 1; } else { for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { if((locdefrt->isused) && (locdefrt->sending_rs)) { unicast_rs = 1; break; } } } if (unicast_rs) { if (locdefrt->rscount < UIP_ND6_MAX_RTR_SOLICITATIONS) { /* Unicast RS and update count and timer */ uip_nd6_rs_output(&locdefrt->ipaddr); locdefrt->rscount = locdefrt->rscount > 10 ? locdefrt->rscount : locdefrt->rscount + 1; timer_set(&uip_ds6_timer_rs, rs_rtx_time(locdefrt->rscount) * CLOCK_SECOND); return; } else { /* Switch to multicast */ locdefrt->sending_rs = 0; rscount = locdefrt->rscount; locdefrt->rscount = 0; } } /* Multicast RS and update RS count and timer */ uip_nd6_rs_output(NULL); if(uip_ds6_defrt_choose() == NULL) { rscount = rscount > 10 ? rscount : rscount + 1; } else { rscount = 0; } /* Make sure we do not send rs more frequently than UIP_ND6_RTR_SOLICITATION_INTERVAL */ timer_set(&uip_ds6_timer_rs, rs_rtx_time(rscount) * CLOCK_SECOND); }
/*---------------------------------------------------------------------------*/ static void print_network_status(void) { int i; uint8_t state; uip_ds6_defrt_t *default_route; uip_ds6_route_t *route; PRINTA("--- Network status ---\n"); /* Our IPv6 addresses */ PRINTA("- Server IPv6 addresses:\n"); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { PRINTA("-%d- ",i); uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); PRINTA("\n"); } } /* Our default route */ PRINTA("- Default route:\n"); default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); if(default_route != NULL) { PRINTA("-- "); uip_debug_ipaddr_print(&default_route->ipaddr);; PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); } else { PRINTA("-- None\n"); } /* Our routing entries */ PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes()); route = uip_ds6_route_head(); while(route != NULL) { PRINTA("-- "); uip_debug_ipaddr_print(&route->ipaddr); PRINTA(" via "); uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); route = uip_ds6_route_next(route); } PRINTA("----------------------\n"); }
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; }
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(); }
static void timeout_handler(void) { static int seq_id; char buf[MAX_PAYLOAD_LEN]; int i; uip_ipaddr_t *globaladdr = NULL; uip_ipaddr_t newdest_addr; uint16_t dest_port = use_user_dest_addr ? user_dest_port : 3000; int has_dest=0; if ( use_user_dest_addr ) { uip_ipaddr_copy(&newdest_addr, &user_dest_addr); has_dest=1; } else if((globaladdr = &uip_ds6_get_global(-1)->ipaddr) != NULL) { #if UIP_CONF_IPV6_RPL rpl_dag_t *dag = rpl_get_any_dag(); uip_ipaddr_copy(&newdest_addr, globaladdr); memcpy(&newdest_addr.u8[8], &dag->dag_id.u8[8], sizeof(uip_ipaddr_t) / 2); has_dest = dag == NULL ? 0 : 1; #else uip_ipaddr_t * defrt = uip_ds6_defrt_choose(); if ( defrt != NULL ) { uip_ipaddr_copy(&newdest_addr, defrt); has_dest=1; } #endif } if (client_conn == NULL) { if (has_dest) { /* At least one prefix announced : building of the global address to reach using prefixes */ memcpy(dest_addr, &newdest_addr, sizeof(uip_ipaddr_t)); PRINTF("UDP-CLIENT: address destination: "); PRINT6ADDR(dest_addr); PRINTF("\n"); client_conn = udp_new(dest_addr, UIP_HTONS(dest_port), NULL); udp_bind(client_conn, UIP_HTONS(3001)); PRINTF("Created a connection with the server "); PRINT6ADDR(&client_conn->ripaddr); PRINTF(" local/remote port %u/%u\n", UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); print_local_addresses(); } else { PRINTF("No address configured yet\n"); } } if (client_conn != NULL) { if(memcmp(&client_conn->ripaddr, &newdest_addr, sizeof(uip_ipaddr_t)) != 0) { PRINTF("UPD-CLIENT : new address, connection changed\n"); memcpy(dest_addr, &newdest_addr, sizeof(uip_ipaddr_t)); client_conn = udp_new(dest_addr, UIP_HTONS(3000), NULL); udp_bind(client_conn, UIP_HTONS(3001)); PRINTF("Created a connection with the server "); PRINT6ADDR(&client_conn->ripaddr); PRINTF(" local/remote port %u/%u\n", UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); print_local_addresses(); } if ( udp_client_run ) { PRINTF("Client sending to: "); PRINT6ADDR(&client_conn->ripaddr); i = sprintf(buf, "%d | ", ++seq_id); #if UIP_CONF_IPV6_RPL rpl_dag_t *dag = rpl_get_any_dag(); add_ipaddr(buf + i, &dag->instance->def_route->ipaddr); #endif PRINTF(" (msg: %s)\n", buf); #if SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION uip_udp_packet_send(client_conn, buf, UIP_APPDATA_SIZE); #else /* SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION */ uip_udp_packet_send(client_conn, buf, strlen(buf)); #endif /* SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION */ } } }
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(); }
/*---------------------------------------------------------------------------*/ void uip_ds6_periodic(void) { /* This flag signals whether we allow or not to send a packet in the current * invocation. */ u8_t allow_output = 1; /* minimum lifetime */ min_lifetime = 0xFFFFFFFF; /* router with minimum lifetime */ min_defrt = NULL; /* Periodic processing on registrations */ for(locreg = uip_ds6_reg_list; locreg < uip_ds6_reg_list + UIP_DS6_REG_LIST_SIZE; locreg++) { if (locreg->isused) { if (stimer_expired(&locreg->reg_lifetime)) { uip_ds6_reg_rm(locreg); } else if (allow_output) { /* If no output is allowed, it is pointless to enter here in this invocation */ if (uip_ds6_if.registration_in_progress) { /* There is a registration in progress */ if ((locreg == uip_ds6_if.registration_in_progress) && (timer_expired(&locreg->registration_timer))) { /* We already sent a NS message for this address but there has been no response */ if(locreg->reg_count >= UIP_ND6_MAX_UNICAST_SOLICIT) { /* NUD failed. Signal the need for next-hop determination by deleting the * NCE (RFC 4861) */ uip_ds6_reg_rm(locreg); /* And then, delete neighbor and corresponding router (as hosts only keep * NCEs for routers in 6lowpan-nd) */ locnbr = uip_ds6_nbr_lookup(&locreg->defrt->ipaddr); uip_ds6_nbr_rm(locnbr); uip_ds6_defrt_rm(locreg->defrt); /* Since we are deleting a default router, we must delete also all * registrations with that router. * Be careful here, uip_ds6_reg_cleanup_defrt() modifies the value of locreg!*/ uip_ds6_reg_cleanup_defrt(locreg->defrt); /* We will also need to start sending RS, as specified in I-D.ietf-6lowpan-nd * for NUD failure case */ uip_ds6_send_rs(NULL); uip_ds6_if.registration_in_progress = NULL; } else { locreg->reg_count++; timer_restart(&locreg->registration_timer); uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, &locreg->defrt->ipaddr, 1, UIP_ND6_REGISTRATION_LIFETIME); } allow_output = 0; /* Prevent this invocation from sending anything else */ } } else { /* There are no registrations in progress, let's see this entry needs (re)registration * or deletion */ if ((locreg->state == REG_GARBAGE_COLLECTIBLE) || (locreg->state == REG_TO_BE_UNREGISTERED) || ((locreg->state == REG_REGISTERED) && (stimer_remaining(&locreg->reg_lifetime) < stimer_elapsed(&locreg->reg_lifetime)))) { /* Issue (re)registration */ uip_ds6_if.registration_in_progress = locreg; locreg->reg_count++; timer_set(&locreg->registration_timer, (uip_ds6_if.retrans_timer / 1000) * (CLOCK_SECOND /* FIXME @@@jwg!!!!*/+250)); if (locreg->state == REG_TO_BE_UNREGISTERED) { uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, &locreg->defrt->ipaddr, 1, 0); } else { uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, &locreg->defrt->ipaddr, 1, UIP_ND6_REGISTRATION_LIFETIME); } allow_output = 0; /* Prevent this invocation from sending anything else */ } } } } } /* Periodic processing on unicast addresses */ for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { if(locaddr->isused) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { uip_ds6_addr_rm(locaddr); } else if (allow_output) { if (stimer_remaining(&locaddr->vlifetime) < min_lifetime) { min_lifetime = stimer_remaining(&locaddr->vlifetime); min_defrt = locaddr->defrt; } } } } /* Periodic processing on default routers */ if (uip_ds6_defrt_choose() == NULL) { if (allow_output) { /* If default router list is empty, start sending RS */ uip_ds6_send_rs(NULL); allow_output = 0; /* Prevent this invocation from sending anything else */ } } else { for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { if((locdefrt->isused) && (!locdefrt->isinfinite)) { if (stimer_expired(&(locdefrt->lifetime))) { uip_ds6_defrt_rm(locdefrt); /* If default router list is empty, we will start sending RS in * the next invocation of ds6_periodic() */ } else { if (allow_output) { if (stimer_remaining(&locdefrt->lifetime) < min_lifetime) { min_lifetime = stimer_remaining(&locdefrt->lifetime); min_defrt = locdefrt; } } } } } } #if !UIP_CONF_ROUTER /* Periodic processing on prefixes */ for (locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if((locprefix->isused) && (!locprefix->isinfinite)) { if (stimer_expired(&locprefix->vlifetime)) { uip_ds6_prefix_rm(locprefix); } else if (allow_output) { if (stimer_remaining(&locprefix->vlifetime) < min_lifetime) { min_lifetime = stimer_remaining(&locprefix->vlifetime); min_defrt = locprefix->defrt; } } } } #endif /* !UIP_CONF_ROUTER */ #if CONF_6LOWPAN_ND_6CO /* Periodic processing on contexts */ for(loccontext = uip_ds6_addr_context_table; loccontext < uip_ds6_addr_context_table + SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; loccontext++) { if(loccontext->state != NOT_IN_USE) { if (stimer_expired(&loccontext->vlifetime)) { if (loccontext->state != EXPIRED) { loccontext->state = IN_USE_UNCOMPRESS_ONLY; stimer_set(&loccontext->vlifetime, 2 * loccontext->defrt_lifetime); } else { uip_ds6_context_rm(loccontext); } } else if (allow_output) { if (stimer_remaining(&loccontext->vlifetime) < min_lifetime) { min_lifetime = stimer_remaining(&loccontext->vlifetime); min_defrt = loccontext->defrt; } } } } #endif /* CONF_6LOWPAN_ND_6CO */ /* Start sending RS well before the minimum of the lifetimes (def. router, * context, or prefix) expires */ if ((allow_output) && (min_lifetime < UIP_DS6_LIFETIME_THRESHOLD)) { /* Start sending RSs to the router with minimum lifetime (if possible) */ uip_ds6_send_rs(min_defrt); allow_output = 0; } /* Periodic processing on neighbors */ for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB; locnbr++) { if(locnbr->isused) { switch (locnbr->state) { #if UIP_CONF_ROUTER /* There can not be INCOMPLETE NCEs in a host in 6lowpan-nd */ case NBR_INCOMPLETE: if (allow_output) { if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { uip_ds6_nbr_rm(locnbr); } else if(stimer_expired(&(locnbr->sendns))) { locnbr->nscount++; PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); allow_output = 0; } } break; #endif /* UIP_CONF_ROUTER */ case NBR_REACHABLE: if(stimer_expired(&(locnbr->reachable))) { PRINTF("REACHABLE: moving to STALE ("); PRINT6ADDR(&locnbr->ipaddr); PRINTF(")\n"); locnbr->state = NBR_STALE; NEIGHBOR_STATE_CHANGED(locnbr); } break; case NBR_DELAY: if (allow_output) { if(stimer_expired(&(locnbr->reachable))) { locnbr->state = NBR_PROBE; locnbr->nscount = 1; NEIGHBOR_STATE_CHANGED(locnbr); PRINTF("DELAY: moving to PROBE + NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr, 0, 0); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); allow_output = 0; } } break; case NBR_PROBE: if (allow_output) { if(locnbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) { PRINTF("PROBE END \n"); if((locdefrt = uip_ds6_defrt_lookup(&locnbr->ipaddr)) != NULL) { uip_ds6_defrt_rm(locdefrt); } uip_ds6_nbr_rm(locnbr); } else if(stimer_expired(&(locnbr->sendns))) { locnbr->nscount++; PRINTF("PROBE: NS %u\n", locnbr->nscount); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr, 0, 0); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); allow_output = 0; } } break; default: break; } } } #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA /* Periodic RA sending */ if(stimer_expired(&uip_ds6_timer_ra)) { uip_ds6_send_ra_periodic(); } #endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */ etimer_reset(&uip_ds6_timer_periodic); return; }
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; }
/*---------------------------------------------------------------------------*/ static void publish(void) { /* Publish MQTT topic in IBM quickstart format */ int len; int remaining = APP_BUFFER_SIZE; seq_nr_value++; buf_ptr = app_buffer; len = snprintf(buf_ptr, remaining, "{" "\"d\":{" "\"Seq #\":%d," "\"Uptime (sec)\":%lu", seq_nr_value, clock_seconds()); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); return; } remaining -= len; buf_ptr += len; /* Put our Default route's string representation in a buffer */ char def_rt_str[64]; memset(def_rt_str, 0, sizeof(def_rt_str)); ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d", def_rt_str, def_rt_rssi); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); return; } remaining -= len; buf_ptr += len; len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (deg.C)\":%d", temperature_sensor.value(0)); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); return; } remaining -= len; buf_ptr += len; len = snprintf(buf_ptr, remaining, "}}"); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); return; } mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer, strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF); DBG("APP - Publish!\n"); }
void device_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *uri_path = NULL; uint8_t uri_len = REST.get_url(request, &uri_path); if (uri_len == 1) { if (*offset >= LEN_D_CORE) { coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); return; } flash_getVar(buffer, RES_D_CORE + *offset, preferred_size); if (LEN_D_CORE - *offset < preferred_size) { preferred_size = LEN_D_CORE - *offset; *offset = -1; } else { *offset += preferred_size; } REST.set_header_content_type(response, APPLICATION_LINK_FORMAT); REST.set_response_payload(response, buffer, preferred_size); return; } //************************************************************************* //* DEVICE NAME * //************************************************************************* if (uri_path[2] == 'n' && uri_path[3] == 'a') { flash_getVar(buffer, RES_NAME, LEN_NAME); REST.set_header_content_type(response, TEXT_PLAIN); REST.set_response_payload(response, buffer, strlen(buffer)); } //************************************************************************* //* DEVICE MODEL * //************************************************************************* if (uri_path[2] == 'm') { flash_getVar(buffer, RES_MODEL, LEN_MODEL); REST.set_header_content_type(response, TEXT_PLAIN); REST.set_response_payload(response, buffer, strlen(buffer)); return; } //************************************************************************* //* DEVICE IDENTIFIER * //************************************************************************* if (uri_path[2] == 'u') { leds_on(LEDS_GREEN); send_hello = 0; flash_getVar(buffer, RES_UUID, LEN_UUID); REST.set_header_content_type(response, APPLICATION_OCTET_STREAM); REST.set_response_payload(response, buffer, LEN_UUID); } //************************************************************************* //* DEVICE TIME * //************************************************************************* if (uri_path[2] == 't') { uint32_t time = uip_htonl(clock_seconds()); memcpy(buffer, &time, 4); REST.set_header_content_type(response, APPLICATION_OCTET_STREAM); REST.set_response_payload(response, buffer, 4); } //************************************************************************* //* DEVICE PSK * //************************************************************************* if (uri_path[2] == 'p') { getPSK(buffer); REST.set_header_content_type(response, APPLICATION_OCTET_STREAM); REST.set_response_payload(response, buffer, LEN_PSK); } //************************************************************************* //* DEVICE DEFAULT ROUTE * //************************************************************************* if (uri_path[2] == 'r') { uip_ipaddr_t *addr = uip_ds6_defrt_choose(); memcpy(buffer, addr, 16); REST.set_header_content_type(response, APPLICATION_OCTET_STREAM); REST.set_response_payload(response, buffer, 16); } //************************************************************************* //* DEVICE NEIGHBOURS * //************************************************************************* if (uri_path[2] == 'n' && uri_path[3] == 'b') { uint32_t o = *offset / 16; uint32_t bfr_ptr = 0; uint32_t i; uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors); for (i = 0; i < (o+2); i++) { if (i >= o) { memcpy(buffer + bfr_ptr, &nbr->ipaddr, 16); bfr_ptr += 16; } nbr = nbr_table_next(ds6_neighbors, nbr); if (nbr == NULL) { if (bfr_ptr == 0) { coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); return; } break; } } if (nbr == NULL) { *offset = -1; } else { *offset += bfr_ptr; } REST.set_header_content_type(response, APPLICATION_OCTET_STREAM); REST.set_response_payload(response, buffer, bfr_ptr); } }