/*---------------------------------------------------------------------------*/ rpl_parent_t * rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) { rpl_parent_t *p = NULL; /* Is the parent known by ds6? Drop this request if not. * Typically, the parent is added upon receiving a DIO. */ uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr); PRINTF("RPL: rpl_add_parent lladdr %p\n", lladdr); if(lladdr != NULL) { /* Add parent in rpl_parents */ p = nbr_table_add_lladdr(rpl_parents, (rimeaddr_t *)lladdr); p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; #if WITH_ORPL p->bc_ackcount = 0; #endif /* WITH_ORPL */ #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ } return p; }
/*---------------------------------------------------------------------------*/ rpl_parent_t * rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) { rpl_parent_t *p = NULL; /* Is the parent known by ds6? Drop this request if not. * Typically, the parent is added upon receiving a DIO. */ uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr); // PRINTF("RPL: rpl_add_parent lladdr %p\n", lladdr); if(lladdr != NULL) { /* Add parent in rpl_parents */ p = nbr_table_add_lladdr(rpl_parents, (rimeaddr_t *)lladdr); p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; p->rssi= cc2420_last_rssi-45; p->update_time = clock_seconds(); if(dag->rank > p->rank) p->flag= PRNT; else p->flag=NBR; p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ } return p; }
/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop) { /* Get routing entry list of this neighbor */ const uip_lladdr_t *nexthop_lladdr; struct uip_ds6_route_neighbor_routes *routes; nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop); routes = nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); rm_routelist(routes); }
/*---------------------------------------------------------------------------*/ int uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr) { const uip_lladdr_t *lladdr; lladdr = uip_ds6_nbr_lladdr_from_ipaddr(ipaddr); if(lladdr == NULL) { return 0; } return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL; }
/*---------------------------------------------------------------------------*/ rpl_parent_t * rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) { rpl_parent_t *p = NULL; /* Is the parent known by ds6? Drop this request if not. * Typically, the parent is added upon receiving a DIO. */ const uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr); PRINTF("RPL: rpl_add_parent lladdr %p ", lladdr); PRINTLLADDR(lladdr); PRINTF(" "); PRINT6ADDR(addr); PRINTF("\n"); if(lladdr != NULL) { /* Add parent in rpl_parents */ p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr); if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { uip_ds6_nbr_t *nbr; nbr = rpl_get_nbr(p); p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; /* Check whether we have a neighbor that has not gotten a link metric yet */ if(nbr != NULL && nbr->link_metric == 0) { nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; } #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ } } return p; }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop) { uip_ds6_route_t *r; #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 "); PRINT6ADDR(ipaddr); 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 just update the old one. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { PRINTF("uip_ds6_route_add: old route already found, updating this one instead: "); PRINT6ADDR(ipaddr); PRINTF("\n"); } else { struct uip_ds6_route_neighbor_routes *routes; /* If there is no routing entry, create one */ /* 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, (rimeaddr_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, (rimeaddr_t *)nexthop_lladdr); if(routes == NULL) { PRINTF("uip_ds6_route_add: could not allocate a neighbor table entri for new route to "); PRINT6ADDR(ipaddr); PRINTF(", dropping it\n"); return NULL; } LIST_STRUCT_INIT(routes, route_list); } /* Allocate a routing entry and populate it. */ r = memb_alloc(&routememb); if(r == NULL) { PRINTF("uip_ds6_route_add: could not allocate memory for new route to "); PRINT6ADDR(ipaddr); PRINTF(", dropping it\n"); return NULL; } /* Add the route to this neighbor */ list_add(routes->route_list, r); num_routes++; PRINTF("uip_ds6_route_add num %d\n", num_routes); r->routes = 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; }