/* * Unknown Protocol Handler, sends reject */ static void ppp_reject_protocol(u16_t protocol, u8_t *buffer, u16_t count) { u16_t i; u8_t *dptr, *sptr; LCPPKT *pkt; /* first copy rejected packet back, start from end and work forward, +++ Pay attention to buffer managment when updated. Assumes fixed PPP blocks. */ ANNOTATE("Rejecting Protocol\n"); if((count + 6) > PPP_RX_BUFFER_SIZE) { /* This is a fatal error +++ do somthing about it. */ ANNOTATE("Cannot Reject Protocol, PKT to big\n"); return; } dptr = buffer + count + 6; sptr = buffer + count; for(i = 0; i < count; ++i) { *dptr-- = *sptr--; } pkt = (LCPPKT *)buffer; pkt->code = PROT_REJ; /* Write Conf_rej */ /*pkt->id = tid++;*/ /* write tid */ pkt->len = uip_htons(count + 6); *((u16_t *)(&pkt->data)) = uip_htons(protocol); ahdlc_tx(LCP, buffer, 0, (u16_t)(count + 6), 0); }
/* scan_packet(list,buffer,len) * * list = list of supported ID's * *buffer pointer to the first code in the packet * length of the codespace */ u16_t scan_packet(u16_t protocol, u8_t *list, u8_t *buffer, u8_t *options, u16_t len) { u8_t *tlist, *bptr; u8_t *tptr; u8_t bad = 0; u8_t i, j, good; bptr = tptr = options; /* scan through the packet and see if it has any unsupported codes */ while(bptr < options + len) { /* get code and see if it matches somwhere in the list, if not we don't support it */ i = *bptr++; /* ANNOTATE("%x - ",i);*/ tlist = list; good = 0; while(*tlist) { /* ANNOTATE("%x ",*tlist);*/ if(i == *tlist++) { good = 1; break; } } if(!good) { /* we don't understand it, write it back */ bad = 1; *tptr++ = i; j = *tptr++ = *bptr++; for(i = 0; i < j - 2; ++i) { *tptr++ = *bptr++; } } else { /* advance over to next option */ bptr += *bptr - 1; } } /* Bad? if we we need to send a config Reject */ if(bad) { /* write the config Rej packet we've built above, take on the header */ bptr = buffer; *bptr++ = CONF_REJ; /* Write Conf_rej */ bptr++; /* skip over ID */ *bptr++ = 0; *bptr = tptr - buffer; /* length right here? */ /* write the reject frame */ ANNOTATE("Writing Reject frame --\n"); ahdlc_tx(protocol, buffer, 0, (u16_t)(tptr - buffer), 0); ANNOTATE("\nEnd writing reject \n"); } return bad; }
void dump_ppp_packet(u8_t *buffer, u16_t len) { int i; ANNOTATE("\n"); for(i = 0;i < len; ++i) { if((i & 0x1f) == 0x10) { ANNOTATE("\n"); } ANNOTATE("0x%02x ",buffer[i]); } ANNOTATE("\n\n"); }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop, uint8_t metric) { if(uip_ds6_list_loop ((uip_ds6_element_t *)uip_ds6_routing_table, UIP_DS6_ROUTE_NB, sizeof(uip_ds6_route_t), ipaddr, length, (uip_ds6_element_t **)&locroute) == FREESPACE) { locroute->isused = 1; uip_ipaddr_copy(&(locroute->ipaddr), ipaddr); locroute->length = length; uip_ipaddr_copy(&(locroute->nexthop), nexthop); locroute->metric = metric; #ifdef UIP_DS6_ROUTE_STATE_TYPE memset(&locroute->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("DS6: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); PRINT6ADDR(nexthop); PRINTF("\n"); ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } return locroute; }
/*---------------------------------------------------------------------------*/ void uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt) { uip_ds6_defrt_t *d; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ /* Make sure that the defrt is in the list before we remove it. */ for(d = list_head(defaultrouterlist); d != NULL; d = list_item_next(d)) { if(d == defrt) { PRINTF("Removing default route\n"); list_remove(defaultrouterlist, defrt); memb_free(&defaultroutermemb, defrt); ANNOTATE("#L %u 0\n", defrt->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_RM, &defrt->ipaddr, &defrt->ipaddr); #endif return; } } #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ }
/*---------------------------------------------------------------------------*/ void rpl_remove_routes_by_nexthop(struct in6_addr *nexthop, rpl_dag_t *dag) { /* uip_ds6_route_t *r; r = uip_ds6_route_list_head(); while(r != NULL) { if(uip_ipaddr_cmp(&r->nexthop, nexthop) && r->state.dag == dag) { uip_ds6_route_rm(r); r = uip_ds6_route_list_head(); } else { r = list_item_next(r); } } ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); */ #if 0 uip_ds6_route_t *locroute; for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { if(locroute->isused && uip_ipaddr_cmp(&locroute->nexthop, nexthop) && locroute->state.dag == dag) { locroute->isused = 0; } } ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]); #endif /* 0 */ }
/*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { if(uip_ds6_list_loop ((uip_ds6_element_t *)uip_ds6_defrt_list, UIP_DS6_DEFRT_NB, sizeof(uip_ds6_defrt_t), ipaddr, 128, (uip_ds6_element_t **)&locdefrt) == FREESPACE) { locdefrt->isused = 1; uip_ipaddr_copy(&locdefrt->ipaddr, ipaddr); if(interval != 0) { stimer_set(&locdefrt->lifetime, interval); locdefrt->isinfinite = 0; } else { locdefrt->isinfinite = 1; } PRINTF("Adding defrouter with ip addr "); PRINT6ADDR(&locdefrt->ipaddr); PRINTF("\n"); ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]); return locdefrt; } return NULL; }
/*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { uip_ds6_defrt_t *d; #if _DEBUG_ != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* _DEBUG_ != DEBUG_NONE */ PRINTF("uip_ds6_defrt_add\n"); d = uip_ds6_defrt_lookup(ipaddr); if(d == NULL) { d = memb_alloc(&defaultroutermemb); if(d == NULL) { PRINTF("uip_ds6_defrt_add: could not add default route to "); PRINT6ADDR(ipaddr); PRINTF(", out of memory\n"); return NULL; } else { PRINTF("uip_ds6_defrt_add: adding default route to "); PRINT6ADDR(ipaddr); PRINTF("\n"); } list_push(defaultrouterlist, d); } if(ipaddr == NULL) { /* A special case: if uip_ds6_defrt_add() is called with a NULL route, this is an indication that we want to force packets to go out to the fallback interface. If so, we add an unspecified route to the list of default routes. uip_ds6_defrt_choose() will trap this and ensure that packets go to the fallback interface. */ uip_create_unspecified(&d->ipaddr); ipaddr = &d->ipaddr; } else { uip_ipaddr_copy(&d->ipaddr, ipaddr); } if(interval != 0) { stimer_set(&d->lifetime, interval); d->isinfinite = 0; } else { d->isinfinite = 1; } ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr); #endif #if _DEBUG_ != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* _DEBUG_ != DEBUG_NONE */ return d; }
void printip(uip_ipaddr_t ip2) { #if (UIP_LOGGING == 1) && (DEBUG & DEBUG_ANNOTATE) unsigned char *ip = (unsigned char *)ip2.u8; ANNOTATE(" %d:%d:%d:%d ",ip[0],ip[1],ip[2],ip[3]); #endif }
/*---------------------------------------------------------------------------*/ void uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt) { if(defrt != NULL) { defrt->isused = 0; ANNOTATE("#L %u 0\n", defrt->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]); } return; }
/*---------------------------------------------------------------------------*/ void ipv6cp_init(void) { ANNOTATE("ipv6cp init\n"); ipv6cp_state = 0; ppp_retry = 0; pppif.ipaddr.u16[0] = pppif.ipaddr.u16[1] = 0; TIMER_expire(); }
/*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { uip_ds6_defrt_t *d; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ PRINTF("uip_ds6_defrt_add\n"); d = uip_ds6_defrt_lookup(ipaddr); if(d == NULL) { d = memb_alloc(&defaultroutermemb); if(d == NULL) { PRINTF("uip_ds6_defrt_add: could not add default route to "); PRINT6ADDR(ipaddr); PRINTF(", out of memory\n"); return NULL; } else { PRINTF("uip_ds6_defrt_add: adding default route to "); PRINT6ADDR(ipaddr); PRINTF("\n"); } list_push(defaultrouterlist, d); } uip_ipaddr_copy(&d->ipaddr, ipaddr); //ADILA EDIT 03/11/14 //d->parentCh = cc2420_get_channel(); /*if(d->parentCh == 0) { d->parentCh = 26; }*/ //printf("\n\nINITIALISE D->PARENTCH %d\n\n", d->parentCh); //------------------- if(interval != 0) { stimer_set(&d->lifetime, interval); d->isinfinite = 0; } else { d->isinfinite = 1; } ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr); #endif #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return d; }
/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm(uip_ds6_route_t *route) { #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ if(route != NULL && route->routes != NULL) { PRINTF("uip_ds6_route_rm: removing route: "); PRINT6ADDR(&route->ipaddr); PRINTF("\n"); list_remove(route->routes->route_list, route); if(list_head(route->routes->route_list) == NULL) { /* If this was the only route using this neighbor, remove the neibhor from the table */ PRINTF("uip_ds6_route_rm: removing neighbor too\n"); nbr_table_remove(nbr_routes, route->routes->route_list); } memb_free(&routememb, route); num_routes--; PRINTF("uip_ds6_route_rm num %d\n", num_routes); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM, &route->ipaddr, uip_ds6_route_nexthop(route)); #endif #if 0 //(DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE /* we need to check if this was the last route towards "nexthop" */ /* if so - remove that link (annotation) */ uip_ds6_route_t *r; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { uip_ipaddr_t *nextr, *nextroute; nextr = uip_ds6_route_nexthop(r); nextroute = uip_ds6_route_nexthop(route); if(nextr != NULL && nextroute != NULL && uip_ipaddr_cmp(nextr, nextroute)) { /* we found another link using the specific nexthop, so keep the #L */ return; } } ANNOTATE("#L %u 0\n", uip_ds6_route_nexthop(route)->u8[sizeof(uip_ipaddr_t) - 1]); #endif } #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return; }
/*---------------------------------------------------------------------------*/ static void new_dio_interval(rpl_instance_t *instance, int isReset) { uint32_t time; clock_time_t ticks; /* TODO: too small timer intervals for many cases */ time = 1UL << instance->dio_intcurrent; /* Convert from milliseconds to CLOCK_TICKS. */ ticks = (time * CLOCK_SECOND) / 1000; instance->dio_next_delay = ticks; /* random number between I/2 and I */ ticks = ticks / 2 + (ticks / 2 * (uint32_t)random_rand()) / RANDOM_RAND_MAX; /* opt trickle*/ /* if (isReset == 1) { ticks * (uint32_t)random_rand() / RANDOM_RAND_MAX; } else { ticks = ticks / 2 + (ticks / 2 * (uint32_t)random_rand()) / RANDOM_RAND_MAX; } */ /* * The intervals must be equally long among the nodes for Trickle to * operate efficiently. Therefore we need to calculate the delay between * the randomized time and the start time of the next interval. */ instance->dio_next_delay -= ticks; instance->dio_send = 1; #if RPL_CONF_STATS /* keep some stats */ instance->dio_totint++; instance->dio_totrecv += instance->dio_counter; ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n", DAG_RANK(instance->current_dag->rank, instance), (10 * (instance->current_dag->rank % instance->min_hoprankinc)) / instance->min_hoprankinc, instance->current_dag->version, instance->dio_totint, instance->dio_totsend, instance->dio_totrecv,instance->dio_intcurrent, instance->current_dag->rank == ROOT_RANK(instance) ? "BLUE" : "ORANGE"); #endif /* RPL_CONF_STATS */ /* reset the redundancy counter */ instance->dio_counter = 0; /* schedule the timer */ PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", ticks); ctimer_set(&instance->dio_timer, ticks, &handle_dio_timer, instance); }
rpl_dag_t * rpl_set_root(uip_ipaddr_t *dag_id) { rpl_dag_t *dag; int version; version = -1; dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); if(dag != NULL) { PRINTF("RPL: Dropping a joined DAG when setting this node as root"); version = dag->version; rpl_free_dag(dag); } dag = rpl_alloc_dag(RPL_DEFAULT_INSTANCE); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG\n"); return NULL; } dag->joined = 1; dag->version = version + 1; dag->grounded = RPL_GROUNDED; dag->mop = RPL_MOP_DEFAULT; dag->of = &RPL_OF; dag->preferred_parent = NULL; dag->dtsn_out = 1; /* Trigger DAOs from the beginning. */ memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); dag->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; dag->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; dag->dio_redundancy = DEFAULT_DIO_REDUNDANCY; dag->max_rankinc = DEFAULT_MAX_RANKINC; dag->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; dag->default_lifetime = RPL_DEFAULT_LIFETIME; dag->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; dag->rank = ROOT_RANK(dag); dag->of->update_metric_container(dag); PRINTF("RPL: Node set to be a DAG root with DAG ID "); PRINT6ADDR(&dag->dag_id); PRINTF("\n"); ANNOTATE("#A root=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(dag, 1); return dag; }
/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop) { for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { if(locroute->isused && uip_ipaddr_cmp(&locroute->nexthop, nexthop)) { locroute->isused = 0; } } ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]); }
/*---------------------------------------------------------------------------*/ void rpl_remove_parent(rpl_dag_t *dag, rpl_parent_t *parent) { rpl_nullify_parent(dag, parent); PRINTF("RPL: Removing parent "); PRINT6ADDR(&parent->addr); PRINTF("\n"); ANNOTATE("#L %u 0\n", parent->addr.u8[sizeof(uip_ipaddr_t) - 1]); list_remove(dag->parents, parent); memb_free(&parent_memb, parent); }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop, uint8_t metric) { loc_loop_state = uip_ds6_list_loop ((uip_ds6_element_t *)uip_ds6_routing_table, UIP_DS6_ROUTE_NB, sizeof(uip_ds6_route_t), ipaddr, length, (uip_ds6_element_t **)&locroute); #ifdef UIP_DS6_ROUTE_STATE_CLEAN if (loc_loop_state == NOSPACE) { for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; ++locroute) { if(locroute->isused && (UIP_DS6_ROUTE_STATE_CLEAN(&locroute->state))) { uip_ds6_route_rm(locroute); loc_loop_state = FREESPACE; break; } } } if (loc_loop_state == NOSPACE) { locroute = NULL; } #endif /* UIP_DS6_ROUTE_STATE_TYPE */ if (loc_loop_state == FREESPACE) { locroute->isused = 1; uip_ipaddr_copy(&(locroute->ipaddr), ipaddr); locroute->length = length; uip_ipaddr_copy(&(locroute->nexthop), nexthop); locroute->metric = metric; #ifdef UIP_DS6_ROUTE_STATE_TYPE memset (&(locroute->state),0,sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("DS6: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); PRINT6ADDR(nexthop); PRINTF("\n"); ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } return locroute; }
/*---------------------------------------------------------------------------*/ void rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) { uip_ds6_route_t *r; r = uip_ds6_route_head(); while(r != NULL) { if(uip_ipaddr_cmp(uip_ds6_route_nexthop(r), nexthop) && r->state.dag == dag) { r->state.lifetime = 0; } r = uip_ds6_route_next(r); } ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); }
/* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) { rpl_parent_t *p, *p2; PRINTF("RPL: Removing parents (minimum rank %u)\n", minimum_rank); for(p = list_head(dag->parents); p != NULL; p = p2) { p2 = p->next; if(p->rank >= minimum_rank) { rpl_remove_parent(dag, p); ANNOTATE("#L %u 0\n", p->addr.u8[sizeof(uip_ipaddr_t) - 1]); } } }
/*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { uip_ds6_defrt_t *d; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ PRINTF("uip_ds6_defrt_add\n"); d = uip_ds6_defrt_lookup(ipaddr); if(d == NULL) { d = memb_alloc(&defaultroutermemb); if(d == NULL) { PRINTF("uip_ds6_defrt_add: could not add default route to "); PRINT6ADDR(ipaddr); PRINTF(", out of memory\n"); return NULL; } else { PRINTF("uip_ds6_defrt_add: adding default route to "); PRINT6ADDR(ipaddr); PRINTF("\n"); } list_push(defaultrouterlist, d); } uip_ipaddr_copy(&d->ipaddr, ipaddr); if(interval != 0) { stimer_set(&d->lifetime, interval); d->isinfinite = 0; } else { d->isinfinite = 1; } ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr); #endif #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return d; }
/*---------------------------------------------------------------------------*/ void ipcp_init(void) { ANNOTATE("ipcp init\n"); ipcp_state = 0; ppp_retry = 0; pppif.ipaddr.u16[0] = pppif.ipaddr.u16[1] = 0; //disable for gprs modem #if 0 pppif.ipaddr.u8[0]=UIP_IPADDR0; pppif.ipaddr.u8[1]=UIP_IPADDR1; pppif.ipaddr.u8[2]=UIP_IPADDR2; pppif.ipaddr.u8[3]=UIP_IPADDR3; #endif TIMER_expire(); }
/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm(uip_ds6_route_t *route) { route->isused = 0; #if (DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE /* we need to check if this was the last route towards "nexthop" */ /* if so - remove that link (annotation) */ for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { if(locroute->isused && uip_ipaddr_cmp(&locroute->nexthop, &route->nexthop)) { /* we found another link using the specific nexthop, so keep the #L */ return; } } ANNOTATE("#L %u 0\n",route->nexthop.u8[sizeof(uip_ipaddr_t) - 1]); #endif }
static void new_dio_interval(rpl_dag_t *dag) { uint32_t time; /* TODO: too small timer intervals for many cases */ time = 1UL << dag->dio_intcurrent; /* Convert from milliseconds to CLOCK_TICKS. */ time = (time * CLOCK_SECOND) / 1000; dag->dio_next_delay = time; /* random number between I/2 and I */ time = time >> 1; time += (time * random_rand()) / RANDOM_RAND_MAX; /* * The intervals must be equally long among the nodes for Trickle to * operate efficiently. Therefore we need to calculate the delay between * the randomized time and the start time of the next interval. */ dag->dio_next_delay -= time; dag->dio_send = 1; #if RPL_CONF_STATS /* keep some stats */ dag->dio_totint++; dag->dio_totrecv += dag->dio_counter; ANNOTATE("#A rank=Xu.Xu(Xu),stats=Xd Xd Xd Xd,color=Xs");//, DAG_RANK(dag->rank, dag), (10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc, dag->version, dag->dio_totint, dag->dio_totsend, dag->dio_totrecv,dag->dio_intcurrent, dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE"); #endif /* RPL_CONF_STATS */ /* reset the redundancy counter */ dag->dio_counter = 0; /* schedule the timer */ PRINTF("RPL: Scheduling DIO timer Xlu ticks in future (Interval)"); PRINTF_DEC(time); ctimer_set(&dag->dio_timer, time, &handle_dio_timer, dag); }
/*---------------------------------------------------------------------------*/ rpl_parent_t * rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) { rpl_parent_t *p; if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DAG) { return NULL; } p = memb_alloc(&parent_memb); if(p == NULL) { RPL_STAT(rpl_stats.mem_overflows++); return NULL; } memcpy(&p->addr, addr, sizeof(p->addr)); p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; p->link_metric = INITIAL_LINK_METRIC; memcpy(&p->mc, &dio->mc, sizeof(p->mc)); list_add(dag->parents, p); ANNOTATE("#L %u 1\n", p->addr.u8[sizeof(uip_ipaddr_t) - 1]); return p; }
/*---------------------------------------------------------------------------*/ void ipv6cp_task(u8_t *buffer) { u8_t *bptr; u16_t t; IPCPPKT *pkt; /* IPCP tx not up and hasn't timed out then lets see if we need to send a request */ if(!(ipv6cp_state & IPV6CP_TX_UP) && !(ipv6cp_state & IPV6CP_TX_TIMEOUT)) { /* Check if we have a request pending */ /*t=get_seconds()-ipv6cp_tx_time;*/ #if 1//0//phlb modify if(TIMER_timeout(IPV6CP_TIMEOUT)) { #else if((clock_seconds() - prev_ipv6cp_seconds) > IPV6CP_TIMEOUT) { prev_ipv6cp_seconds = clock_seconds(); #endif /* * No pending request, lets build one */ pkt=(IPCPPKT *)buffer; /* Configure-Request only here, write id */ pkt->code = CONF_REQ; pkt->id = ppp_id; bptr = (u8_t*)&pkt->data; /* * Write options, we want IP address, and DNS addresses if set. */ /* Write zeros for IP address the first time */ *bptr++ = 0x01;//IPV6CP_IPADDRESS; *bptr++ = 0x0a;//10 *bptr++ = ((u8_t*)uip_hostaddr.u8)[8]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[9]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[10]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[11]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[12]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[13]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[14]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[15]; #ifdef IPV6CP_GET_PRI_DNS if(!(ipv6cp_state & IPCP_PRI_DNS_BIT)) { /* Write zeros for IP address the first time */ *bptr++ = IPV6CP_PRIMARY_DNS; *bptr++ = 0x6; *bptr++ = ((u8_t*)pri_dns_addr.u8)[0]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[1]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[2]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[3]; } #endif #ifdef IPV6CP_GET_SEC_DNS if(!(ipv6cp_state & IPV6CP_SEC_DNS_BIT)) { /* Write zeros for IP address the first time */ *bptr++ = IPV6CP_SECONDARY_DNS; *bptr++ = 0x6; *bptr++ = ((u8_t*)sec_dns_addr)[0]; *bptr++ = ((u8_t*)sec_dns_addr)[1]; *bptr++ = ((u8_t*)sec_dns_addr)[2]; *bptr++ = ((u8_t*)sec_dns_addr)[3]; } #endif /* Write length */ t = bptr - buffer; /* length here - code and ID + */ pkt->len = uip_htons(t); ANNOTATE("\n**Sending IPV6CP Request packet\n"); /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ ahdlc_tx(IPV6CP, 0, buffer, 0, t); /* Set timer */ /*ipv6cp_tx_time=get_seconds();*/ TIMER_set(); /* Inc retry */ /*ipv6cp_retry++;*/ // ppp_retry++; /* * Have we timed out? (combide the timers?) */ if(ppp_retry > IPV6CP_RETRY_COUNT) ipv6cp_state |= IPV6CP_TX_TIMEOUT; } } }
/* * IPCP RX protocol Handler */ void ipv6cp_rx(u8_t *buffer, u16_t count) { u8_t *bptr = buffer; // IPCPPKT *pkt=(IPCPPKT *)buffer; u16_t len; ANNOTATE("IPV6CP len %d\n",count); switch(*bptr++) { case CONF_REQ: /* parce request and see if we can ACK it */ ++bptr; len = (*bptr++ << 8); len |= *bptr++; /* len-=2; */ ANNOTATE("check lcplist\n"); if(scan_packet(IPV6CP, ipv6cplist, buffer, bptr, (u16_t)(len - 4))) { UIP_LOG("option was bad\n"); } else { ANNOTATE("IPV6CP options are good\n"); /* * Parse out the results */ /* lets try to implement what peer wants */ /* Reject any protocol not */ /* Error? if we we need to send a config Reject ++++ this is good for a subroutine*/ //GD-2011-09-15 None of the IPv6CP options are supported with current implementation. #if 0 #warning option implementation example based on IPCP IPv4 address configuration. /* All we should get is the peer IP address */ if(IPV6CP_IPADDRESS == *bptr++) { /* dump length */ ++bptr; #ifdef IPV6CP_GET_PEER_IP ((u8_t*)peer_ip_addr.u8)[0] = *bptr++; ((u8_t*)peer_ip_addr.u8)[1] = *bptr++; ((u8_t*)peer_ip_addr.u8)[2] = *bptr++; ((u8_t*)peer_ip_addr.u8)[3] = *bptr++; ANNOTATE("Peer IP "); /* printip(peer_ip_addr);*/ ANNOTATE("\n"); #else bptr += 18; #endif } else { UIP_LOG("HMMMM this shouldn't happen IPV6CP1\n"); } #endif #if 0 if(error) { /* write the config NAK packet we've built above, take on the header */ bptr = buffer; *bptr++ = CONF_NAK; /* Write Conf_rej */ *bptr++; /*tptr++;*/ /* skip over ID */ /* Write new length */ *bptr++ = 0; *bptr = tptr - buffer; /* write the reject frame */ UIP_LOG("Writing NAK frame \n"); ahdlc_tx(IPV6CP, buffer, (u16_t)(tptr - buffer)); ANNOTATE("- End NAK Write frame\n"); } else { } #endif /* * If we get here then we are OK, lets send an ACK and tell the rest * of our modules our negotiated config. */ ipv6cp_state |= IPV6CP_RX_UP; ipv6cp_state &= ~IPV6CP_TX_UP;//phlb force send request with ipv6cp task ANNOTATE("Send IPV6CP ACK!\n"); bptr = buffer; *bptr++ = CONF_ACK; /* Write Conf_ACK */ bptr++; /* Skip ID (send same one) */ /* * Set stuff */ ppp_flags |= tflag; ANNOTATE("SET- stuff -- are we up? c=%d dif=%d \n", count, (u16_t)(bptr-buffer)); /* write the ACK frame */ ANNOTATE("Writing ACK frame \n"); /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ ahdlc_tx(IPV6CP, 0, buffer, 0, count /*bptr-buffer*/); ANNOTATE("- End ACK Write frame\n"); /* expire the timer to make things happen after a state change */ TIMER_expire(); //timer_expire(); //modify phlb uncomment /* } */ } break; // case CONF_ACK: /* config Ack */ ANNOTATE("CONF ACK\n"); /* * Parse out the results * * Dump the ID and get the length. */ /* dump the ID */ bptr++; /* get the length */ len = (*bptr++ << 8); len |= *bptr++; #if 0 //modify phlb /* Parse ACK and set data */ while(bptr < buffer + len) { switch(*bptr++) { case IPV6CP_IPADDRESS: /* dump length */ bptr++; ((u8_t*)ipaddr)[0] = *bptr++; ((u8_t*)ipaddr)[1] = *bptr++; ((u8_t*)ipaddr)[2] = *bptr++; ((u8_t*)ipaddr)[3] = *bptr++; break; case IPV6CP_PRIMARY_DNS: bptr++; ((u8_t*)pri_dns_addr)[0] = *bptr++; ((u8_t*)pri_dns_addr)[1] = *bptr++; ((u8_t*)pri_dns_addr)[2] = *bptr++; ((u8_t*)pri_dns_addr)[3] = *bptr++; break; case IPV6CP_SECONDARY_DNS: bptr++; ((u8_t*)sec_dns_addr)[0] = *bptr++; ((u8_t*)sec_dns_addr)[1] = *bptr++; ((u8_t*)sec_dns_addr)[2] = *bptr++; ((u8_t*)sec_dns_addr)[3] = *bptr++; break; default: UIP_LOG("IPV6CP CONFIG_ACK problem1\n"); } } #endif ipv6cp_state |= IPV6CP_TX_UP; //ipv6cp_state &= ~IPV6CP_RX_UP; ANNOTATE("were up! \n"); printip(pppif.ipaddr); #ifdef IPV6CP_GET_PRI_DNS printip(pri_dns_addr); #endif #ifdef IPV6CP_GET_SEC_DNS printip(sec_dns_addr); #endif ANNOTATE("\n"); /* expire the timer to make things happen after a state change */ TIMER_expire(); break; // case CONF_NAK: /* Config Nack */ UIP_LOG("CONF NAK\n"); /* dump the ID */ bptr++; /* get the length */ len = (*bptr++ << 8); len |= *bptr++; /* Parse ACK and set data */ while(bptr < buffer + len) { switch(*bptr++) { #if 0 #warning option implementation example based on IPCP IPv4 address configuration. case IPV6CP_IPADDRESS: /* dump length */ bptr++; ((u8_t*)pppif.ipaddr.u8)[0] = *bptr++; ((u8_t*)pppif.ipaddr.u8)[1] = *bptr++; ((u8_t*)pppif.ipaddr.u8)[2] = *bptr++; ((u8_t*)pppif.ipaddr.u8)[3] = *bptr++; uip_fw_register( &pppif ); ANNOTATE("My PPP-ipno: (%d.%d.%d.%d)\n", ((u8_t*)pppif.ipaddr.u8)[0], ((u8_t*)pppif.ipaddr.u8)[1], ((u8_t*)pppif.ipaddr.u8)[2], ((u8_t*)pppif.ipaddr.u8)[3]); break; #endif #ifdef IPV6CP_GET_PRI_DNS case IPV6CP_PRIMARY_DNS: bptr++; ((u8_t*)pri_dns_addr)[0] = *bptr++; ((u8_t*)pri_dns_addr)[1] = *bptr++; ((u8_t*)pri_dns_addr)[2] = *bptr++; ((u8_t*)pri_dns_addr)[3] = *bptr++; break; #endif #ifdef IPV6CP_GET_SEC_DNS case IPV6CP_SECONDARY_DNS: bptr++; ((u8_t*)sec_dns_addr)[0] = *bptr++; ((u8_t*)sec_dns_addr)[1] = *bptr++; ((u8_t*)sec_dns_addr)[2] = *bptr++; ((u8_t*)sec_dns_addr)[3] = *bptr++; break; #endif // default: UIP_LOG("IPCP CONFIG_ACK problem 2\n"); } } ppp_id++; printip(pppif.ipaddr); #ifdef IPV6CP_GET_PRI_DNS printip(pri_dns_addr); #endif #ifdef IPV6CP_GET_PRI_DNS printip(sec_dns_addr); #endif ANNOTATE("\n"); /* expire the timer to make things happen after a state change */ TIMER_expire(); break; case CONF_REJ: /* Config Reject */ ANNOTATE("CONF REJ\n"); /* Remove the offending options*/ ppp_id++; /* dump the ID */ bptr++; /* get the length */ len = (*bptr++ << 8); len |= *bptr++; /* Parse ACK and set data */ while(bptr < buffer + len) { switch(*bptr++) { #if 0 #warning option implementation example based on IPCP IPv4 address configuration. case IPV6CP_IPADDRESS: ipv6cp_state |= IPV6CP_IP_BIT; bptr += 5; break; #endif #ifdef IPV6CP_GET_PRI_DNS case IPV6CP_PRIMARY_DNS: ipv6cp_state |= IPV6CP_PRI_DNS_BIT; bptr += 5; break; #endif #ifdef IPV6CP_GET_PRI_DNS case IPV6CP_SECONDARY_DNS: ipv6cp_state |= IPV6CP_SEC_DNS_BIT; bptr += 5; break; #endif default: UIP_LOG("IPV6CP this shoudln't happen 3\n"); } } /* expire the timer to make things happen after a state change */ /*timer_expire(); */ break; default: UIP_LOG("-Unknown 4\n"); } }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop) { uip_ds6_route_t *r; struct uip_ds6_route_neighbor_route *nbrr; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ /* Get link-layer address of next hop, make sure it is in neighbor table */ const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop); if(nexthop_lladdr == NULL) { PRINTF("uip_ds6_route_add: neighbor link-local address unknown for "); PRINT6ADDR(nexthop); PRINTF("\n"); return NULL; } /* First make sure that we don't add a route twice. If we find an existing route for our destination, we'll delete the old one first. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { PRINTF("uip_ds6_route_add: old route for "); PRINT6ADDR(ipaddr); PRINTF(" found, deleting it\n"); uip_ds6_route_rm(r); } { struct uip_ds6_route_neighbor_routes *routes; /* If there is no routing entry, create one. We first need to check if we have room for this route. If not, we remove the least recently used one we have. */ if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) { /* Removing the oldest route entry from the route table. The least recently used route is the first route on the list. */ uip_ds6_route_t *oldest; oldest = list_tail(routelist); /* uip_ds6_route_head(); */ PRINTF("uip_ds6_route_add: dropping route to "); PRINT6ADDR(&oldest->ipaddr); PRINTF("\n"); uip_ds6_route_rm(oldest); } /* Every neighbor on our neighbor table holds a struct uip_ds6_route_neighbor_routes which holds a list of routes that go through the neighbor. We add our route entry to this list. We first check to see if we already have this neighbor in our nbr_route table. If so, the neighbor already has a route entry list. */ routes = nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); if(routes == NULL) { /* If the neighbor did not have an entry in our neighbor table, we create one. The nbr_table_add_lladdr() function returns a pointer to a pointer that we may use for our own purposes. We initialize this pointer with the list of routing entries that are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); if(routes == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n"); return NULL; } LIST_STRUCT_INIT(routes, route_list); } /* Allocate a routing entry and populate it. */ r = memb_alloc(&routememb); if(r == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate route\n"); return NULL; } /* add new routes first - assuming that there is a reason to add this and that there is a packet coming soon. */ list_push(routelist, r); nbrr = memb_alloc(&neighborroutememb); if(nbrr == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n"); memb_free(&routememb, r); return NULL; } nbrr->route = r; /* Add the route to this neighbor */ list_add(routes->route_list, nbrr); r->neighbor_routes = routes; num_routes++; PRINTF("uip_ds6_route_add num %d\n", num_routes); } uip_ipaddr_copy(&(r->ipaddr), ipaddr); r->length = length; #ifdef UIP_DS6_ROUTE_STATE_TYPE memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("uip_ds6_route_add: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); PRINT6ADDR(nexthop); PRINTF("\n"); ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop); #endif #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return r; }
/*---------------------------------------------------------------------------*/ void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_instance_t *instance; rpl_dag_t *dag; rpl_parent_t *p; rpl_of_t *of; dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG object!\n"); return; } instance = dag->instance; p = rpl_add_parent(dag, dio, from); PRINTF("RPL: Adding "); PRINT6ADDR(from); PRINTF(" as a parent: "); if(p == NULL) { PRINTF("failed\n"); instance->used = 0; return; } p->dtsn = dio->dtsn; PRINTF("succeeded\n"); /* Determine the objective function by using the objective code point of the DIO. */ of = rpl_find_of(dio->ocp); if(of == NULL) { PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n", dio->instance_id); rpl_remove_parent(p); instance->used = 0; return; } /* Autoconfigure an address if this node does not already have an address with this prefix. */ if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(NULL, &dio->prefix_info); } dag->joined = 1; dag->preference = dio->preference; dag->grounded = dio->grounded; dag->version = dio->version; instance->of = of; instance->mop = dio->mop; instance->current_dag = dag; instance->dtsn_out = RPL_LOLLIPOP_INIT; instance->max_rankinc = dio->dag_max_rankinc; instance->min_hoprankinc = dio->dag_min_hoprankinc; instance->dio_intdoubl = dio->dag_intdoubl; instance->dio_intmin = dio->dag_intmin; instance->dio_intcurrent = instance->dio_intmin + instance->dio_intdoubl; instance->dio_redundancy = dio->dag_redund; instance->default_lifetime = dio->default_lifetime; instance->lifetime_unit = dio->lifetime_unit; memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); /* Copy prefix information from the DIO into the DAG object. */ memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); rpl_set_preferred_parent(dag, p); instance->of->update_metric_container(instance); dag->rank = instance->of->calculate_rank(p, 0); /* So far this is the lowest rank we are aware of. */ dag->min_rank = dag->rank; if(default_instance == NULL) { default_instance = instance; } PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", dio->instance_id, dag->rank); PRINT6ADDR(&dag->dag_id); PRINTF("\n"); ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(instance); rpl_set_default_route(instance, from); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { rpl_schedule_dao(instance); } else { PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } }
/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) { rpl_dag_t *dag; rpl_instance_t *instance; uint8_t version; int i; #if CETIC_6LBR version = nvm_data.rpl_version_id; RPL_LOLLIPOP_INCREMENT(version); nvm_data.rpl_version_id = version; store_nvm_config(); #else version = RPL_LOLLIPOP_INIT; #endif instance = rpl_get_instance(instance_id); if(instance != NULL) { for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) { dag = &instance->dag_table[i]; if(dag->used) { if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) { version = dag->version; RPL_LOLLIPOP_INCREMENT(version); #if CETIC_6LBR nvm_data.rpl_version_id = version; store_nvm_config(); #endif } if(dag == dag->instance->current_dag) { PRINTF("RPL: Dropping a joined DAG when setting this node as root"); rpl_set_default_route(instance, NULL); dag->instance->current_dag = NULL; } else { PRINTF("RPL: Dropping a DAG when setting this node as root"); } rpl_free_dag(dag); } } } dag = rpl_alloc_dag(instance_id, dag_id); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG\n"); return NULL; } instance = dag->instance; dag->version = version; dag->joined = 1; dag->grounded = RPL_GROUNDED; dag->preference = RPL_PREFERENCE; instance->mop = RPL_MOP_DEFAULT; instance->of = &RPL_OF; rpl_set_preferred_parent(dag, NULL); memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS; instance->dio_intmin = RPL_DIO_INTERVAL_MIN; /* The current interval must differ from the minimum interval in order to trigger a DIO timer reset. */ instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN + RPL_DIO_INTERVAL_DOUBLINGS; instance->dio_redundancy = RPL_DIO_REDUNDANCY; instance->max_rankinc = RPL_MAX_RANKINC; instance->min_hoprankinc = RPL_MIN_HOPRANKINC; instance->default_lifetime = RPL_DEFAULT_LIFETIME; instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; dag->rank = ROOT_RANK(instance); if(instance->current_dag != dag && instance->current_dag != NULL) { /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); instance->current_dag->joined = 0; } instance->current_dag = dag; instance->dtsn_out = RPL_LOLLIPOP_INIT; instance->of->update_metric_container(instance); default_instance = instance; PRINTF("RPL: Node set to be a DAG root with DAG ID "); PRINT6ADDR(&dag->dag_id); PRINTF("\n"); ANNOTATE("#A root=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(instance); return dag; }