Exemplo n.º 1
0
/*---------------------------------------------------------------------------*/
static void
rpl_set_preferred_parent(rpl_dag_t *dag, rpl_parent_t *p)
{
  if(dag != NULL && dag->preferred_parent != p) {
    PRINTF("RPL: rpl_set_preferred_parent ");
    if(p != NULL) {
      PRINT6ADDR(rpl_get_parent_ipaddr(p));
    } else {
      PRINTF("NULL");
    }
    PRINTF(" used to be ");
    if(dag->preferred_parent != NULL) {
      PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
    } else {
      PRINTF("NULL");
    }
    PRINTF("\n");

    /* Always keep the preferred parent locked, so it remains in the
     * neighbor table. */
    nbr_table_unlock(rpl_parents, dag->preferred_parent);
    nbr_table_lock(rpl_parents, p);
    dag->preferred_parent = p;
  }
}
Exemplo n.º 2
0
static rpl_parent_t *
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
{
  rpl_rank_t r1, r2;
  rpl_dag_t *dag;

  PRINTF("RPL: Comparing parent ");
  PRINT6ADDR(rpl_get_parent_ipaddr(p1));
  PRINTF(" (confidence %d, rank %d) with parent ",
        p1->link_metric, p1->rank);
  PRINT6ADDR(rpl_get_parent_ipaddr(p2));
  PRINTF(" (confidence %d, rank %d)\n",
        p2->link_metric, p2->rank);


  r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC  +
         p1->link_metric;
  r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC  +
         p2->link_metric;
  /* Compare two parents by looking both and their rank and at the ETX
     for that parent. We choose the parent that has the most
     favourable combination. */

  dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */
  if(r1 < r2 + MIN_DIFFERENCE &&
     r1 > r2 - MIN_DIFFERENCE) {
    return dag->preferred_parent;
  } else if(r1 < r2) {
    return p1;
  } else {
    return p2;
  }
}
Exemplo n.º 3
0
/*---------------------------------------------------------------------------*/
void
rpl_nullify_parent(rpl_parent_t *parent)
{
  rpl_dag_t *dag = parent->dag;
  /* This function can be called when the preferred parent is NULL, so we
     need to handle this condition in order to trigger uip_ds6_defrt_rm. */
  if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
    dag->rank = INFINITE_RANK;
    if(dag->joined) {
      if(dag->instance->def_route != NULL) {
        PRINTF("RPL: Removing default route ");
        PRINT6ADDR(rpl_get_parent_ipaddr(parent));
        PRINTF("\n");
        uip_ds6_defrt_rm(dag->instance->def_route);
        dag->instance->def_route = NULL;
      }
      /* Send No-Path DAO only to preferred parent, if any */
      if(parent == dag->preferred_parent) {
        dao_output(parent, RPL_ZERO_LIFETIME);
        rpl_set_preferred_parent(dag, NULL);
      }
    }
  }

  PRINTF("RPL: Nullifying parent ");
  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
  PRINTF("\n");
}
Exemplo n.º 4
0
/*---------------------------------------------------------------------------*/
void
rpl_nullify_parent(rpl_parent_t *parent)
{
  rpl_dag_t *dag = parent->dag;

#if WITH_ORPL
  /* We don't have a preferred parent in ORPL.
   * We simply recalculate our EDC. */
  dag->instance->of->calculate_rank(parent, 0);
  return;
#endif /* WITH_ORPL */

  /* This function can be called when the preferred parent is NULL, so we
     need to handle this condition in order to trigger uip_ds6_defrt_rm. */
  if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
    rpl_set_preferred_parent(dag, NULL);
    dag->rank = INFINITE_RANK;
    if(dag->joined) {
      if(dag->instance->def_route != NULL) {
        PRINTF("RPL: Removing default route ");
        PRINT6ADDR(rpl_get_parent_ipaddr(parent));
        PRINTF("\n");
        uip_ds6_defrt_rm(dag->instance->def_route);
        dag->instance->def_route = NULL;
      }
      dao_output(parent, RPL_ZERO_LIFETIME);
    }
  }

  PRINTF("RPL: Nullifying parent ");
  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
  PRINTF("\n");
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------------*/
void
rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
{
  if(parent == dag_src->preferred_parent) {
      rpl_set_preferred_parent(dag_src, NULL);
      dag_src->rank = INFINITE_RANK;
    if(dag_src->joined && dag_src->instance->def_route != NULL) {
      PRINTF("RPL: Removing default route ");
      PRINT6ADDR(rpl_get_parent_ipaddr(parent));
      PRINTF("\n");
      PRINTF("rpl_move_parent\n");
      uip_ds6_defrt_rm(dag_src->instance->def_route);
      dag_src->instance->def_route = NULL;
    }
  } else if(dag_src->joined) {
    /* Remove uIPv6 routes that have this parent as the next hop. */
    rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src);
  }

  PRINTF("RPL: Moving parent ");
  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
  PRINTF("\n");

  parent->dag = dag_dst;
}
Exemplo n.º 6
0
uint16_t
create_parent_msg(char *buf,rpl_parent_t *parent, uint8_t preferred)
{
	uint8_t n = 0;
	uip_ds6_nbr_t *nbr;

	uip_ipaddr_t * addr = rpl_get_parent_ipaddr(parent);

	n += sprintf(&(buf[n]), "{\"eui\":\"%04x%04x%04x%04x\",",
					UIP_HTONS(addr->u16[4]),
					UIP_HTONS(addr->u16[5]),
					UIP_HTONS(addr->u16[6]),
					UIP_HTONS(addr->u16[7]));
	
	n += sprintf(&(buf[n]), "\"pref\":");

	if(preferred == 1)
	{
		n += sprintf(&(buf[n]), "true,");
	}else
	{
		n += sprintf(&(buf[n]), "false,");
	}

	nbr = rpl_get_nbr(parent); // Estimated Retransmission part (ETX) value

	n += sprintf(&(buf[n]), "\"etx\":%d}",nbr->link_metric);

	buf[n] = 0; // clear next buffer value
	PRINTF("buf: %s\n", buf); // print the buffer value
	return n;
}
Exemplo n.º 7
0
/*---------------------------------------------------------------------------*/
static void res_rpl_parent_get_handler(void *request, void *response,
  uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
  uint16_t length;
  rpl_instance_t *instance;
  char message[REST_MAX_CHUNK_SIZE];

  memset(message, 0, REST_MAX_CHUNK_SIZE);
  instance = rpl_get_instance(RPL_DEFAULT_INSTANCE);
  /* Print the parent */
  if(instance != NULL &&
    instance->current_dag != NULL &&
    instance->current_dag->preferred_parent != NULL) {
    sprintf(&message[0], "RPL Parent: ");
    sprint_addr6(&message[0],
      rpl_get_parent_ipaddr(instance->current_dag->preferred_parent));
  } else {
    sprintf(&message[0], "No parent yet\n");
  }
  length = strlen(&message[0]);
  memcpy(buffer, message, length);

  REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
  REST.set_header_etag(response, (uint8_t *)&length, 1);
  REST.set_response_payload(response, buffer, length);
}
Exemplo n.º 8
0
/*---------------------------------------------------------------------------*/
void monitor_parents(void)
{
	rpl_parent_t *p;
	uip_ipaddr_t *dest;
 uint16_t temp1,temp2;

//counter++;
	rpl_parent_t *pref_parent =(&instance_table[0])->current_dag->preferred_parent;
//	rpl_instance_t *instance=&instance_table[0];
temp1 = ((((&instance_table[0])->current_dag->rank)%256)*100)/256;
	printf("rank= %u.%u:{", (((&instance_table[0])->current_dag->rank)/256), temp1);
	for(p = nbr_table_head(rpl_parents); p != NULL ;     p = nbr_table_next(rpl_parents, p))
	{	dest=rpl_get_parent_ipaddr(p);
		printf("(");
		if(p==pref_parent)
			printf("pref-prnt ");
		printf("%02x ", ((uint8_t *)dest)[15]);
temp1 = ((p->link_metric%128)*100)/128;
temp2 = ((p->rank%256)*100)/256;
		printf(" etx=%d.%2d,rank=%u.%2u)", p->link_metric/128, temp1 ,p->rank/256 , temp2);
//printf("%d- etx=%d.%2d,rank=%u.%2u)", counter, p->link_metric/128, temp1 ,p->rank/256 , temp2);
//printf("%d   %d.%2d \n", counter, p->link_metric/128, temp1);
		  /*PRINTF("RPL: My path ETX to the root is %u.%u\n",
			instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
			(instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) /
			 RPL_DAG_MC_ETX_DIVISOR);*/
		}
	printf("}\n");

}
Exemplo n.º 9
0
/*---------------------------------------------------------------------------*/
const uip_ipaddr_t *
simple_rpl_parent(void)
{
    rpl_dag_t *dag;

    dag = rpl_get_any_dag();
    if(dag != NULL && dag->preferred_parent != NULL) {
        return rpl_get_parent_ipaddr(dag->preferred_parent);
    }
    return NULL;
}
Exemplo n.º 10
0
/*---------------------------------------------------------------------------*/
void
rpl_remove_parent(rpl_parent_t *parent)
{
  PRINTF("RPL: Removing parent ");
  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
  PRINTF("\n");

  rpl_nullify_parent(parent);

  nbr_table_remove(rpl_parents, parent);
}
Exemplo n.º 11
0
/*---------------------------------------------------------------------------*/
static void
handle_probing_timer(void *ptr)
{
  rpl_instance_t *instance = (rpl_instance_t *)ptr;
  rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag);

  /* Perform probing */
  if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) {
    PRINTF("RPL: probing %3u\n",
        nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]);
    /* Send probe, e.g. unicast DIO or DIS */
    RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target));
  }

  /* Schedule next probing */
  rpl_schedule_probing(instance);

#if DEBUG
  rpl_print_neighbor_list();
#endif
}
Exemplo n.º 12
0
/*---------------------------------------------------------------------------*/
int
rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
{
  int return_value;

#if DEBUG
  rpl_rank_t old_rank;

  old_rank = instance->current_dag->rank;
#endif /* DEBUG */

  return_value = 1;

  if(!acceptable_rank(p->dag, p->rank)) {
    /* The candidate parent is no longer valid: the rank increase resulting
       from the choice of it as a parent would be too high. */
    PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank);
    rpl_nullify_parent(p);
    if(p != instance->current_dag->preferred_parent) {
      return 0;
    } else {
      return_value = 0;
    }
  }

  if(rpl_select_dag(instance, p) == NULL) {
    /* No suitable parent; trigger a local repair. */
    PRINTF("RPL: No parents found in any DAG\n");
    rpl_local_repair(instance);
    return 0;
  }
#if DEBUG
  if(DAG_RANK(old_rank, instance) !=
     DAG_RANK(instance->current_dag->rank, instance)) {
    PRINTF("RPL: Moving in the instance from rank %hu to %hu\n",
           DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank,
                                                  instance));
    if(instance->current_dag->rank != INFINITE_RANK) {
      PRINTF("RPL: The preferred parent is ");
      PRINT6ADDR(rpl_get_parent_ipaddr
                   (instance->current_dag->preferred_parent));
      PRINTF(" (rank %u)\n",
             (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank,
                                instance));
    } else {
      PRINTF("RPL: We don't have any parent");
    }
  }
#endif /* DEBUG */

  return return_value;
}
Exemplo n.º 13
0
static void
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
	rpl_dag_t *dag;
	rpl_parent_t *parent;
	int32_t strpos = 0;
	const uip_ipaddr_t *addr;
	addr = &uip_ds6_if.addr_list[1].ipaddr;
	dag = rpl_get_any_dag();

	parent_index = 0;

	if (dag != NULL)
	{
		/* seek to the parents entry and return it */
		strpos += sprintf(&(buffer[strpos]),"{\"node\":\"n%x\"",addr->u8[15]); // last addr byte of mote
		strpos += sprintf(&(buffer[strpos]),",\"nbr\":{");
		parent = nbr_table_head(rpl_parents);  // addr of first neighbor
		while (parent != NULL)
		{
			etx_table[parent_index].nbr_addr = rpl_get_parent_ipaddr(parent)->u8[15];
			etx_table[parent_index].nbr_etx = rpl_get_parent_link_metric(parent);
			etx_table[parent_index].p = parent;
			strpos += sprintf(&(buffer[strpos]),"\"n%x\":%u,",etx_table[parent_index].nbr_addr, etx_table[parent_index].nbr_etx);
			parent = nbr_table_next(rpl_parents, parent);
			parent_index++;
		}
		PRINTF("parent_index:%d\n",parent_index);
	}
	else
	{ /* no DAG */
		strpos += sprintf(&(buffer[strpos]),"{}\n");
	}
	//PRINTF("strpos: %ld\n", strpos);
	//rpl_print_neighbor_list(); // get parents for debug purposes
	//PRINTF("buf_parents: %s\n", buffer);
	strpos += sprintf(&(buffer[strpos-1]),"}}\n"); //replace the last comma
	//PRINTF("strpos-after: %ld\n", strpos);
	REST.set_header_content_type(response, APPLICATION_JSON);
	REST.set_header_max_age(response, res_etx.periodic->period / CLOCK_SECOND);
	//*offset = -1;  // try to fix Copper response
	REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%s", buffer));

	/* The REST.subscription_handler() will be called for observable resources by the REST framework. */
}
void
collect_common_net_print(void)
{
  rpl_dag_t *dag;
  uip_ds6_route_t *r;

  /* Let's suppose we have only one instance */
  dag = rpl_get_any_dag();
  if(dag->preferred_parent != NULL) {
    PRINTF("Preferred parent: ");
    PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
    PRINTF("\n");
  }
  for(r = uip_ds6_route_head();
      r != NULL;
      r = uip_ds6_route_next(r)) {
    PRINT6ADDR(&r->ipaddr);
  }
  PRINTF("---\n");
}
Exemplo n.º 15
0
/* length of an neighbor entry, must be fixed width */
uint16_t create_parent_msg(char *buf, rpl_parent_t *parent, uint8_t preferred)
{
	uint8_t n = 0;

	uip_ipaddr_t * addr = rpl_get_parent_ipaddr(parent);

	n += sprintf(&(buf[n]), "{\"eui\":\"%04x%04x%04x%04x\",",
		     UIP_HTONS(addr->u16[4]),
		     UIP_HTONS(addr->u16[5]),
		     UIP_HTONS(addr->u16[6]),
		     UIP_HTONS(addr->u16[7]));
	n += sprintf(&(buf[n]), "\"pref\":");
	if(preferred == 1) {
		n += sprintf(&(buf[n]), "true,");
	} else {
		n += sprintf(&(buf[n]), "false,");
	}
	n += sprintf(&(buf[n]), "\"etx\":%d}", rpl_get_parent_link_metric(parent));

	buf[n] = 0;
	PRINTF("buf: %s\n", buf);
	return n;
}
Exemplo n.º 16
0
void
collect_common_send()
{
  /* Send the query reply back to the sink */
  rpl_parent_t *preferred_parent;
  rpl_dag_t *dag;

  query_reply_t qrpkt;
  dag = rpl_get_any_dag();
  if(dag != NULL) {
    preferred_parent = dag->preferred_parent;
  if(preferred_parent != NULL) {
    uip_ds6_nbr_t *nbr;
  nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent));
  if(nbr != NULL) {
    // Use parts of the IPv6 address as the parent address, in reversed byte order. 
        qrpkt.parent_etx = (uint16_t)preferred_parent->link_metric + preferred_parent->rank;
      }
    }
  }
  uip_udp_packet_sendto(client_conn, &qrpkt, sizeof(qrpkt),
      &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT));
}
Exemplo n.º 17
0
/*---------------------------------------------------------------------------*/
void
collect_common_send(void)
{
  static uint8_t seqno;
  struct {
    uint8_t seqno;
    uint8_t for_alignment;
    struct collect_view_data_msg msg;
  } msg;
  /* struct collect_neighbor *n; */
  uint16_t parent_etx;
  uint16_t rtmetric;
  uint16_t num_neighbors;
  uint16_t beacon_interval;
  rpl_parent_t *preferred_parent;
  rimeaddr_t parent;
  rpl_dag_t *dag;

  if(client_conn == NULL) {
    /* Not setup yet */
    return;
  }
  memset(&msg, 0, sizeof(msg));
  seqno++;
  if(seqno == 0) {
    /* Wrap to 128 to identify restarts */
    seqno = 128;
  }
  msg.seqno = seqno;

  rimeaddr_copy(&parent, &rimeaddr_null);
  parent_etx = 0;

  /* Let's suppose we have only one instance */
  dag = rpl_get_any_dag();
  if(dag != NULL) {
    preferred_parent = dag->preferred_parent;
    if(preferred_parent != NULL) {
      uip_ds6_nbr_t *nbr;
      nbr = uip_ds6_nbr_lookup(rpl_get_parent_ipaddr(preferred_parent));
      if(nbr != NULL) {
        /* Use parts of the IPv6 address as the parent address, in reversed byte order. */
        parent.u8[RIMEADDR_SIZE - 1] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 2];
        parent.u8[RIMEADDR_SIZE - 2] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 1];
        parent_etx = rpl_get_parent_rank((rimeaddr_t *) uip_ds6_nbr_get_ll(nbr)) / 2;
      }
    }
    rtmetric = dag->rank;
    beacon_interval = (uint16_t) ((2L << dag->instance->dio_intcurrent) / 1000);
    num_neighbors = RPL_PARENT_COUNT(dag);
  } else {
    rtmetric = 0;
    beacon_interval = 0;
    num_neighbors = 0;
  }

  /* num_neighbors = collect_neighbor_list_num(&tc.neighbor_list); */
  collect_view_construct_message(&msg.msg, &parent,
                                 parent_etx, rtmetric,
                                 num_neighbors, beacon_interval);

  uip_udp_packet_sendto(client_conn, &msg, sizeof(msg),
                        &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT));
}
Exemplo n.º 18
0
/*---------------------------------------------------------------------------*/
rpl_dag_t *
rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
{
  rpl_parent_t *last_parent;
  rpl_dag_t *dag, *end, *best_dag;
  rpl_rank_t old_rank;

  old_rank = instance->current_dag->rank;
  last_parent = instance->current_dag->preferred_parent;

  if(instance->current_dag->rank != ROOT_RANK(instance)) {
    rpl_select_parent(p->dag);
  }

  best_dag = NULL;
  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
    if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != INFINITE_RANK) {
      if(best_dag == NULL) {
        best_dag = dag;
      } else {
        best_dag = instance->of->best_dag(best_dag, dag);
      }
    }
  }

  if(best_dag == NULL) {
    /* No parent found: the calling function handle this problem. */
    return NULL;
  }

  if(instance->current_dag != best_dag) {
    /* Remove routes installed by DAOs. */
    rpl_remove_routes(instance->current_dag);

    PRINTF("RPL: New preferred DAG: ");
    PRINT6ADDR(&best_dag->dag_id);
    PRINTF("\n");

    if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
      check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info);
    } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
      check_prefix(&instance->current_dag->prefix_info, NULL);
    }

    best_dag->joined = 1;
    instance->current_dag->joined = 0;
    instance->current_dag = best_dag;
  }

  instance->of->update_metric_container(instance);
  /* Update the DAG rank. */
  best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0);
  if(last_parent == NULL || best_dag->rank < best_dag->min_rank) {
    best_dag->min_rank = best_dag->rank;
  } else if(!acceptable_rank(best_dag, best_dag->rank)) {
    PRINTF("RPL: New rank unacceptable!\n");
    rpl_set_preferred_parent(instance->current_dag, NULL);
    if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) {
      /* Send a No-Path DAO to the removed preferred parent. */
      dao_output(last_parent, RPL_ZERO_LIFETIME);
    }
    return NULL;
  }

  if(best_dag->preferred_parent != last_parent) {
    rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent));
    PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",
  	(unsigned)old_rank, best_dag->rank);
    RPL_STAT(rpl_stats.parent_switch++);
    if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
      if(last_parent != NULL) {
        /* Send a No-Path DAO to the removed preferred parent. */
        dao_output(last_parent, RPL_ZERO_LIFETIME);
      }
      /* The DAO parent set changed - schedule a DAO transmission. */
      RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
      rpl_schedule_dao(instance);
    }
    rpl_reset_dio_timer(instance);
#if DEBUG
    rpl_print_neighbor_list();
#endif
  } else if(best_dag->rank != old_rank) {
    PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n",
  	(unsigned)old_rank, best_dag->rank);
  }
  return best_dag;
}
/*simple-udp-rpl---------------------------------------------------------------------------*/
static void
receiver(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{
// #ifdef WITH_LEAPFROG //for packet elimination
//   int leapfrog_elimination_flag = 0;
    
//   if(data[0] == LEAPFROG_DATA_HEADER){
//     char tmp_lf_pc = data[1] - LEAPFROG_BEACON_OFFSET;
//     int tmp_sid = sender_addr->u8[15];
//     char tmp_lf_an = leapfrog_elimination_id_array[tmp_sid];

//     if(tmp_lf_an <= LEAPFROG_DATA_COUNTER_WIDTH){
//       if(tmp_lf_pc <= tmp_lf_an || LEAPFROG_DATA_COUNTER_MAX - (LEAPFROG_DATA_COUNTER_WIDTH - tmp_lf_an ) <= tmp_lf_pc) leapfrog_elimination_flag = 1; 
//     }else{
//       if(tmp_lf_an - LEAPFROG_DATA_COUNTER_WIDTH <= tmp_lf_pc && tmp_lf_pc <= tmp_lf_an) leapfrog_elimination_flag = 1;
//     }

//     if(leapfrog_elimination_flag == 1){
//       PRINTF("LEAPFROG: Elimination discard data\n");
//     }else{
//       PRINTF("LEAPFROG: ");
//       leapfrog_elimination_id_array[tmp_sid] = tmp_lf_pc;
//     }
//   }

//   if(leapfrog_elimination_flag != 1){
// #endif /*WITH_LEAPFROG*/

  printf("DATA: received from ");
  uip_debug_ipaddr_print(sender_addr);
  printf(" on port %d from port %d with length %d: '%s'\n",
         receiver_port, sender_port, datalen, data);

#ifdef WITH_LEAPFROG //for beaconing
  if(data[0] == LEAPFROG_BEACON_HEADER){
    char temp_sid = 0; //sender id of packet
    char temp_pid = 0; //sender's parent id
    char temp_gid = 0; //sender's grand parent id
    char temp_aid = 0; //sender's alt parent id
    temp_sid = sender_addr->u8[15]; //get most least byte. must be modified to store whole address
    temp_pid = data[2] - LEAPFROG_BEACON_OFFSET;
    temp_gid = data[4] - LEAPFROG_BEACON_OFFSET;
    temp_aid = data[6] - LEAPFROG_BEACON_OFFSET;
    char temp_pps_num;
    char temp_pps_str[LEAPFROG_NUM_NEIGHBOR_NODE];
    int temp_pps_itr;
    temp_pps_num = data[8] - LEAPFROG_BEACON_OFFSET;
    for(temp_pps_itr = 0; temp_pps_itr < (int)temp_pps_num; temp_pps_itr++){ //do nothing if temp_pps_num = 0
      temp_pps_str[temp_pps_itr] = data[8 + 1 + temp_pps_itr];
    }
    temp_pps_str[temp_pps_itr] = '\0';

    printf("LEAPFROG: receive beacon S %d P %d GP %d AP %d PPs #%d %s\n", temp_sid, temp_pid, temp_gid, temp_aid, temp_pps_num, temp_pps_str);
    
    //judge and registor parent, grandparent, alt parent 
    uip_ipaddr_t * addr;
    #ifdef WITH_LEAPFROG_TSCH
    char my_id = 0;
    addr = &uip_ds6_if.addr_list[2].ipaddr; //get own ID. [2] seems to be default
    if(addr != NULL){
      my_id = addr->u8[15];
    }
    #endif //WITH_LEAPFROG_TSCH
    addr = rpl_get_parent_ipaddr(default_instance->current_dag->preferred_parent);
    if(addr != NULL){
      char my_pid = addr->u8[15];
//      if(leapfrog_parent_id == 0){ //registor parent
//        leapfrog_parent_id = my_pid;
//      }else 
      //new parent and reset P, GP, AP
      if(leapfrog_parent_id != my_pid){ //new parent and reset P, GP, AP
        leapfrog_parent_id = my_pid;
        leapfrog_grand_parent_id = 0;
        leapfrog_alt_parent_id = 0;
        printf("LEAPFROG: reset P GP AP\n");
      }
      //judge Grand Parent
      if(leapfrog_parent_id > 0 && leapfrog_parent_id == my_pid){ //judge Grand Parent
        if(temp_sid == my_pid){
          if(temp_pid > 0 && temp_pid != my_pid){
            leapfrog_grand_parent_id = temp_pid; //get grand parent
          }
        }
      }
      //judge Alternate Parent
      if(leapfrog_grand_parent_id > 0 && temp_pid > 0 && leapfrog_grand_parent_id == temp_pid && leapfrog_parent_id != temp_sid){ //judge Alt Parent
        if(leapfrog_alt_parent_id != temp_sid){
          leapfrog_alt_parent_id = temp_sid; //get alt parent
#ifdef WITH_LEAPFROG_TSCH //add unicast tx link to AP based on own(child) ID
          linkaddr_copy(&alt_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_SENDER));
          //alt_parent_linkaddr.u8[7] = leapfrog_alt_parent_id; //for tsch
          //printf("LEAPFROG-TSCH: update AP %d %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 
          //  leapfrog_alt_parent_id,
          //  alt_parent_linkaddr.u8[0],
          //  alt_parent_linkaddr.u8[1],
          //  alt_parent_linkaddr.u8[2],
          //  alt_parent_linkaddr.u8[3],
          //  alt_parent_linkaddr.u8[4],
          //  alt_parent_linkaddr.u8[5],
          //  alt_parent_linkaddr.u8[6],
          //  alt_parent_linkaddr.u8[7]);

          printf("LEAPFROG-TSCH: update alt tx normally -> AP %d\n", leapfrog_alt_parent_id);
          
          orchestra_leapfrog_add_uc_tx_link(leapfrog_alt_parent_id);
#endif /*WITH_LEAPFROG_TSCH*/
        }
      }else{ //judge Alternate Parent by Possible Parent
        if(my_pid != temp_sid){
          for(temp_pps_itr = 0; temp_pps_itr < (int)temp_pps_num; temp_pps_itr++){ //do nothing if temp_pps_num = 0
            if(leapfrog_grand_parent_id == data[8 + 1 + temp_pps_itr] - LEAPFROG_BEACON_OFFSET){
              leapfrog_alt_parent_id = temp_sid;
#ifdef WITH_LEAPFROG_TSCH
              linkaddr_copy(&alt_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_SENDER));
              printf("LEAPFROG-TSCH: update alt tx by PP -> AP %d\n", leapfrog_alt_parent_id);
          
              orchestra_leapfrog_add_uc_tx_link(leapfrog_alt_parent_id);
#endif //WITH_LEAPFROG_TSCH
              break;
            }
          }
        }
      }

      for(temp_pps_itr = 0; temp_pps_itr < leapfrog_possible_parent_num; temp_pps_itr++){
        temp_pps_str[temp_pps_itr] = leapfrog_possible_parent_id_array[temp_pps_itr] + LEAPFROG_BEACON_OFFSET;
      }
      temp_pps_str[temp_pps_itr] = '\0';
      printf("LEAPFROG: own P %d GP %d AP %d PPs #%d %s\n", leapfrog_parent_id, leapfrog_grand_parent_id, leapfrog_alt_parent_id, leapfrog_possible_parent_num, temp_pps_str);

      //judge I am sender's Alt Parent and prepare Rx link for alt child
#ifdef WITH_LEAPFROG_TSCH //judge I am sender's Alt Parent
      if(temp_aid != 0 && my_id == temp_aid){
        printf("LEAPFROG-TSCH: update rx s <- (alt)C %d\n", temp_sid);

        orchestra_leapfrog_add_uc_rx_link(temp_sid);
      }
#endif /*WITH_LEAPFROG_TSCH*/      
    }
  }

  // }else{
  //   //receiving processes is skipped because of elimination
  // }
#endif /*WITH_LEAPFROG*/
}
Exemplo n.º 20
0
/*---------------------------------------------------------------------------*/
static void
sendpacket(int mode)
{

    static uip_ipaddr_t *parent_ipaddr=NULL,tempadd;
    static rpl_dag_t *current_dag=NULL;
    	
    static int i=0;
    static rpl_instance_t * instance_id=NULL;
    for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
        if(instance_table[i].used && instance_table[i].current_dag->joined) {
            current_dag = instance_table[i].current_dag;
            instance_id = &instance_table[i];
            break;
        }
    }

    if(current_dag != NULL) {
        parent_ipaddr=rpl_get_parent_ipaddr(current_dag->preferred_parent);
    }else return; //if current dag is null return

    if(!parent_ipaddr->u8[15])// if parent is null return
	return;	    
	 		
    uip_ds6_nbr_t *nbr=NULL;
    int num = uip_ds6_nbr_num();
    int sizeof_buf = sizeof(int) + sizeof(uint8_t)  + sizeof(uint8_t) + sizeof(int) + sizeof(uint16_t) +sizeof(uint8_t) + sizeof(uint16_t)+ sizeof(int) + num * ( sizeof(uint8_t) + sizeof(uint16_t) );
    // code + node + id_of_intermediate + msg_instance + own rank + parent + rank + numof_nbr*(nbr+rank)
    unsigned char buf[sizeof_buf];
    unsigned char * buf_p = buf;
    i=2;myrank=current_dag->rank;
    MAPPER_ADD_PACKETDATA(buf_p, i);
    MAPPER_ADD_PACKETDATA(buf_p, myip.u8[15]);

	
    if(mode)		//for first time setting 
    msg_instance = 100*myip.u8[15]; 	
        		
    MAPPER_ADD_PACKETDATA(buf_p, myip.u8[15]);   //added to track limited boradcasting intermediate node id
    MAPPER_ADD_PACKETDATA(buf_p, msg_instance);        //added to track limited boradcasting
    msg_instance++;	

    
    MAPPER_ADD_PACKETDATA(buf_p, current_dag->rank);
    MAPPER_ADD_PACKETDATA(buf_p, parent_ipaddr->u8[15]);
    MAPPER_ADD_PACKETDATA(buf_p, current_dag->preferred_parent->rank);
    MAPPER_ADD_PACKETDATA(buf_p, num);

    printf(" %02x R %u P %u PR %u Bufsize %d msg_instance %d ",myip.u8[15],current_dag->rank,parent_ipaddr->u8[15],current_dag->preferred_parent->rank, sizeof_buf, msg_instance-1);

    num_nbrs=0;
    rpl_parent_t *p=NULL; 
    for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) {
        //p=find_parent_any_dag_any_instance(&nbr->ipaddr);
        p=rpl_find_parent_any_dag(instance_id, &nbr->ipaddr);
	
        MAPPER_ADD_PACKETDATA(buf_p,nbr->ipaddr.u8[15]);
        //rank = rpl_get_parent_rank(uip_ds6_nbr_get_ll(nbr));
        MAPPER_ADD_PACKETDATA(buf_p,p->rank);
        printf("No of nbrs %d : %02x rank %u ",num,nbr->ipaddr.u8[15],p->rank);
	
	nbrs[num_nbrs]=nbr->ipaddr.u8[15];
	num_nbrs++;

    }
    printf("\n");

    if(mode)	
    {
	uip_udp_packet_sendto(client_conn, buf, sizeof(buf), &server_ipaddr, UIP_HTONS(2345));
	uip_create_unspecified(&client_conn->ripaddr);    
	parent_change=0;
	printf("parent change info send via unicast 6BR\n");		
    }
    else
    {   
	

	//uip_udp_packet_sendto(client_conn, buf, sizeof(buf), &server_ipaddr, UIP_HTONS(2345));//temporaryly aadded
	//uip_create_unspecified(&client_conn->ripaddr);  
	
	//send_broadcast(buf,sizeof(buf)); ///*
	//uip_create_unspecified(&udp_bconn->ripaddr);

	int j=0;
	for(i=0,j=0;i<=num_nbrs*3;i++,j=0)
		for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) {        
		uip_ipaddr_copy(&tempadd, &nbr->ipaddr);
		j++;
		if(nbr->ipaddr.u8[15]!=myip.u8[15] && i==j){
			uip_udp_packet_sendto(client_conn, buf, sizeof(buf), &tempadd, UIP_HTONS(10000+(int)tempadd.u8[15]));
			printf("send to %u \n",tempadd.u8[15]);
			uip_create_unspecified(&client_conn->ripaddr);
		}
	}	
	printf("parent change info send via broadcast 6BR\n");		
    }		 	
}
Exemplo n.º 21
0
/*void start_no_data_timer() {
	etimer_set(&bad_etx_timer, NO_DATA_PERIOD);
}
void stop_no_data_timer(){
	etimer_stop(&bad_etx_timer);
}*/
void eventhandler(process_event_t ev, process_data_t data) {
	switch (ev) {

	case PARENT_UNREACHABLE: {
		instance = &instance_table[0];
		dag = instance->current_dag;
		if (dag->preferred_parent != NULL) {
			p = dag->preferred_parent;
			PRINT6ADDR(rpl_get_parent_ipaddr(p));
		} else {
			PRINTF("NULL");
		} PRINTF("\n");

		if (test_unreachable == 1 && hand_off_backoff_flag == 0) {
			PRINTF("Connection unstable\n");

			reliable = 0;
			if (wait_dio_flag == 0) {
				PRINTF("Sending DIS to current parent\n");
				dis_output(rpl_get_parent_ipaddr(p), 1, 0, 0, 0); /* Send DIS to assess parent */
				wait_dio_flag = 1;
				/*
				 * Wait DIO reply. If parent doesn't reply until timer finishes,
				 * he's considered unreachable.
				 */
				etimer_set(&dio_check, WAIT_DIO);
			} else {
				etimer_set(&dio_check, WAIT_DIO);
			}
		}
	}
		break;

	case PARENT_REACHABLE: {
		uint8_t *dis_rssi;

		/* We received the DIO reply from parent but we need to check the RSSI value */
		dis_rssi = data;
		rssi = dis_rssi - 45;
		if (dis_rssi > 200) {
			rssi = dis_rssi - 255 - 46;
		} PRINTF("RSSI response from parent = %d ->", rssi);
		if (rssi <= -85) {
			PRINTF(" Unreliable\n");
			mobility_flag = 1;
			leds_on(LEDS_ALL);
			current_t = clock_time() * 1000 / CLOCK_SECOND;
			PRINTF("%u\n", current_t);
			dis_output(NULL, 1, counter, 0, 0);
			rpl_dis_burst();
		} else {
			PRINTF(" Reliable\n");
			reliable = 1;
			process_post(&tcpip_process, RESET_MOBILITY_FLAG, NULL);
		}
	}
		break;

	case DIS_BURST: {
		etimer_reset(&dis_timer);
	}
		break;

		/* DIO received when checking current parent, stop the timer */
	case STOP_DIO_CHECK: {
		printf("stopping DIO CHECK\n");
		etimer_stop(&dio_check);
		etimer_stop(&dis_timer);
	}
		break;

	case PROCESS_EVENT_TIMER: {
		/* Current parent Unreachable/Unreliable, print current time and start DIS_BURST */
		if (data == &dio_check && etimer_expired(&dio_check) && !reliable
				&& test_unreachable == 1) {
			mobility_flag = 1;
			if (dis_burst_flag == 0) {
				dis_burst_flag++;
				current_t = clock_time() * 1000 / CLOCK_SECOND;
				 printf("Start %u\n", current_t);
				dis_output(NULL, 1, counter, 0, 0);
				etimer_set(&dis_timer, SEND_TIME);
			} else {
				rpl_dis_burst();
			}
		}
		/* 1st DIS was sent above. Check for the backoff delay and keep sending (Total = 3DIS) */
		if (data == &dis_timer && etimer_expired(&dis_timer)) {
			counter++;
			dis_output(NULL, 1, counter, 0, 0);
			if (counter < 3) {
				etimer_reset(&dis_timer);
			} else {
				counter = 1;
				dis_burst_flag = 0;
			}
		}

	}break;
}
}
Exemplo n.º 22
0
/*-----------------------------------------------------------*/
static void
neighbor_link_callback(rpl_parent_t *p, int status, int numtx)
{
  uint16_t recorded_etx = p->link_metric;
  uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR;
  uint16_t new_etx;
uip_ipaddr_t *dest;
dest=rpl_get_parent_ipaddr(p);
unsigned int test;
//elnaz
unsigned long delta;
rpl_parent_t * pref;
//elnaz
  /* Do not penalize the ETX when collisions or transmission errors occur. */
p->msg_num++;
p->retransmission_num = p->retransmission_num + numtx;
if(set_tx_flag_char==1)
{
	retransmission_num = retransmission_num + numtx;
	return;
}

  if(status == MAC_TX_OK || status == MAC_TX_NOACK) {
    if(status == MAC_TX_NOACK) {
      packet_etx = MAX_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;

//printf("no ack %02x%02x \n",((uint8_t *)dest)[14], ((uint8_t *)dest)[15]);
    }
dest=rpl_get_parent_ipaddr(p);
//printf("numtx=%d ADDR=%02x%02x \n", numtx, ((uint8_t *)dest)[14], ((uint8_t *)dest)[15]);

    new_etx = ((uint32_t)recorded_etx * ETX_ALPHA +
               (uint32_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;

    PRINTF("RPL: ETX changed from %u to %u (packet ETX = %u)\n",
        (unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR),
        (unsigned)(new_etx  / RPL_DAG_MC_ETX_DIVISOR),
        (unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR));
    p->link_metric = new_etx;

//elnaz
//----------------------- PROBE 

   if(start_flag==1)
	{last_probe_time=clock_seconds();
	start_flag=0;
	set_ETX_th();}

//test = PROBE_NUM_THRESHOLD * PROBE_INTERVAL * 2;
//printf("%lu , test= %d, delta=%d ", (clock_seconds()-last_probe_time),  test, (PROBE_NUM_THRESHOLD * PROBE_INTERVAL * 2) );
  pref = p->dag->preferred_parent;
  if((p->link_metric)>ETX_THERESHOLD && p==pref)
	{	printf("pass threshhold ADDR=%02x etx=%u th=%u\n", ((uint8_t *)dest)[15],p->link_metric,ETX_THERESHOLD);
		delta = (clock_seconds()-last_probe_time);
		//printf("t=%lu , %lu,%lu, %lu \n",delta, delta*CLOCK_SECOND, 120, 120*CLOCK_SECOND);
	if(delta>(wait*60))
		{	//printf("pass time constraint");
			wait=5;
			if(etx_flag==1)
			{
				ETX_THERESHOLD = pref->link_metric;
				etx_flag=0;
				printf("adjust etx-th \n");
				
			}
			else if(rpl_pt_parents(0)==1)
			{	last_probe_time=clock_seconds();
				printf("update time\n");	
				
				//steps=0;	
			}

		}
//	if(delta>=)

	else
		{	/*steps++;
			if(steps==11)
			{ adjust_ETX_th(p->link_metric);
			  steps=0;
			 }*/
			//steps=0; 
			//printf("not if");	
		}
	}
   
  }
else
	{ printf("error ADDR= %02x%02x \n",((uint8_t *)dest)[14], ((uint8_t *)dest)[15]);
	}
monitor_parents();
}
Exemplo n.º 23
0
char rpl_pt_parents(char set_tx)
{	
	
	rpl_parent_t *p;
	struct ip_addr_list_struct test;
	uip_ipaddr_t *dest;
	unsigned long age;
	int timer;// jitter;
rpl_rank_t srank;
	rpl_parent_t * pref_parent;

/*if(flag==0)
{
	flag=1;
	memb_init(&pt_prnt_mem);
	list_init(ip_addr_list);
	
}*/
pt_parents[0].rank=INFINITE_RANK;
pt_parents[0].ipaddr=NULL;
pt_parents[1]=pt_parents[0];
pt_parents[2]=pt_parents[1];


//printf("\nP_T={");

//printf("rank= %u:{", (((&instance_table[0])->current_dag->rank)/256));
pref_parent =(&instance_table[0])->current_dag->preferred_parent;
p = nbr_table_head(rpl_parents);
srank = p->dag->rank;
  	for( ;p != NULL;p = nbr_table_next(rpl_parents, p)) 
	{			if(set_tx==1)
				{
					p->retransmission_num = 0;
					p->msg_num = 0;

				}
				if(p==pref_parent)
				{continue;}
				dest=rpl_get_parent_ipaddr(p);
				age = (clock_seconds()-(p->update_time))/2000;
				 printf("prnt rssi=%d,rank=%u\n",p->rssi, p->rank);
				if(p->rssi > RSSI_THRESHOLD && (p->rank)<srank)// age<AGE_THRESHOLD &&
				{	
				

					if(p->rank < pt_parents[0].rank)
						{	
							test=pt_parents[1];
							pt_parents[1]=pt_parents[0];
							pt_parents[2]=test;
							pt_parents[0].rank=p->rank;
							pt_parents[0].ipaddr=dest;
							continue;	
				
						}
					if(p->rank < pt_parents[1].rank)
						{	
							pt_parents[2]=pt_parents[1];
							pt_parents[1].rank=p->rank;
							pt_parents[1].ipaddr=dest;
							continue;
						}
					if(p->rank < pt_parents[2].rank)
						{	
							pt_parents[2].rank= p->rank;
							pt_parents[2].ipaddr= dest;
						}
				}
		
	}
		
	
printf("P_T={%02x, %02x, %02x}\n",((uint8_t *)pt_parents[0].ipaddr)[15],((uint8_t *)pt_parents[1].ipaddr)[15],((uint8_t *)pt_parents[2].ipaddr)[15]);
if(pt_parents[0].rank!=INFINITE_RANK)
{
	timer = (PROBE_INTERVAL * CLOCK_SECOND);

	//timer += (random_rand()*CLOCK_SECOND)/RANDOM_RAND_MAX;

	ctimer_set(&probe_timer, timer, &handle_probe_timer, pt_parents);

}
else 
{	
	//printf("there is no pt_pref_prnt\n");
	return 0;
}
return 1;
	
}
Exemplo n.º 24
0
/*---------------------------------------------------------------------------*/
static void
res_rpl_info_get_handler(void *request, void *response, uint8_t *buffer,
  uint16_t preferred_size, int32_t *offset)
{
  /*Return RPL information in JSON format */
  uint16_t length = 0;
  rpl_instance_t *instance;
  uip_ds6_nbr_t *nbr;
  char message[REST_MAX_CHUNK_SIZE];
  memset(message, 0, sizeof(message));

  instance = rpl_get_instance(RPL_DEFAULT_INSTANCE);
  if(instance != NULL &&
     instance->current_dag != NULL &&
     instance->current_dag->preferred_parent != NULL) {
    nbr = rpl_get_nbr(instance->current_dag->preferred_parent);
  } else {
    nbr = NULL;
  }

  /* Write all RPL info in JSON format */
  snprintf(message, sizeof(message) - 1, "{\"parent\":\"");
  length = strlen(message);

  if(instance != NULL &&
    instance->current_dag != NULL &&
    instance->current_dag->preferred_parent != NULL) {
    sprint_addr6(&message[length],
                 rpl_get_parent_ipaddr(instance->current_dag->preferred_parent));
    length = strlen(message);
    snprintf(&message[length], sizeof(message) - length - 1, "\"");
  } else {
    snprintf(&message[length], sizeof(message) - length - 1, "None\"");
  }
  length = strlen(message);

  snprintf(&message[length], sizeof(message) - length - 1, " ,\"rank\":\"");
  length = strlen(message);

  if(instance != NULL && instance->current_dag != NULL) {
    snprintf(&message[length], sizeof(message) - length - 1, "%u.%02u\"",
             (instance->current_dag->rank / RPL_DAG_MC_ETX_DIVISOR),
             (100 * (instance->current_dag->rank % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR);
  } else {
    snprintf(&message[length], sizeof(message) - length - 1, "inf\"");
  }
  length = strlen(message);

  snprintf(&message[length], sizeof(message) - length - 1, " ,\"link-metric\":\"");
  length = strlen(message);
  if(nbr != NULL) {
    snprintf(&message[length], sizeof(message) - length - 1, "%u.%02u\"",
             nbr->link_metric / RPL_DAG_MC_ETX_DIVISOR,
             (100 * (nbr->link_metric % RPL_DAG_MC_ETX_DIVISOR)) / RPL_DAG_MC_ETX_DIVISOR);
  } else {
    snprintf(&message[length], sizeof(message) - length - 1, "inf\"");
  }
  length = strlen(message);
  snprintf(&message[length], sizeof(message) - length - 1, "}");
  length = strlen(message);
  memcpy(buffer, message, length);

  REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
  REST.set_header_etag(response, (uint8_t *)&length, 1);
  REST.set_response_payload(response, buffer, length);
}