void rpl_send_DIO_mode(ipv6_addr_t *destination) { if (i_am_leaf) { return; } rpl_dodag_t *mydodag; icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); mydodag = rpl_get_my_dodag(); if (mydodag == NULL) { DEBUGF("Error - trying to send DIO without being part of a dodag.\n"); return; } icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIO; rpl_send_dio_buf = get_rpl_send_dio_buf(); memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf)); DEBUGF("Sending DIO with "); rpl_send_dio_buf->rpl_instanceid = mydodag->instance->id; DEBUG("instance %02X ", rpl_send_dio_buf->rpl_instanceid); rpl_send_dio_buf->version_number = mydodag->version; rpl_send_dio_buf->rank = mydodag->my_rank; DEBUG("rank %04X\n", rpl_send_dio_buf->rank); rpl_send_dio_buf->g_mop_prf = (mydodag->grounded << RPL_GROUNDED_SHIFT) | (mydodag->mop << RPL_MOP_SHIFT) | mydodag->prf; rpl_send_dio_buf->dtsn = mydodag->dtsn; rpl_send_dio_buf->flags = 0; rpl_send_dio_buf->reserved = 0; rpl_send_dio_buf->dodagid = mydodag->dodag_id; int opt_hdr_len = 0; /* DODAG configuration option */ rpl_send_opt_dodag_conf_buf = get_rpl_send_opt_dodag_conf_buf(DIO_BASE_LEN); rpl_send_opt_dodag_conf_buf->type = RPL_OPT_DODAG_CONF; rpl_send_opt_dodag_conf_buf->length = RPL_OPT_DODAG_CONF_LEN; rpl_send_opt_dodag_conf_buf->flags_a_pcs = 0; rpl_send_opt_dodag_conf_buf->DIOIntDoubl = mydodag->dio_interval_doubling; rpl_send_opt_dodag_conf_buf->DIOIntMin = mydodag->dio_min; rpl_send_opt_dodag_conf_buf->DIORedun = mydodag->dio_redundancy; rpl_send_opt_dodag_conf_buf->MaxRankIncrease = mydodag->maxrankincrease; rpl_send_opt_dodag_conf_buf->MinHopRankIncrease = mydodag->minhoprankincrease; rpl_send_opt_dodag_conf_buf->ocp = mydodag->of->ocp; DEBUGF("Building done.\n"); rpl_send_opt_dodag_conf_buf->reserved = 0; rpl_send_opt_dodag_conf_buf->default_lifetime = mydodag->default_lifetime; rpl_send_opt_dodag_conf_buf->lifetime_unit = mydodag->lifetime_unit; opt_hdr_len += RPL_OPT_DODAG_CONF_LEN; uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void send_DIO(ipv6_addr_t *destination) { mutex_lock(&rpl_send_mutex); rpl_dodag_t *mydodag; icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); mydodag = rpl_get_my_dodag(); if(mydodag == NULL) { printf("Error, trying to send DIO without being part of a dodag. This should not happen\n"); mutex_unlock(&rpl_send_mutex, 0); return; } icmp_send_buf->type = ICMP_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIO; icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); rpl_send_dio_buf = get_rpl_send_dio_buf(); memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf)); rpl_send_dio_buf->rpl_instanceid = mydodag->instance->id; rpl_send_dio_buf->version_number = mydodag->version; rpl_send_dio_buf->rank = mydodag->my_rank; rpl_send_dio_buf->g_mop_prf = (mydodag->grounded << RPL_GROUNDED_SHIFT) | (mydodag->mop << RPL_MOP_SHIFT) | mydodag->prf; rpl_send_dio_buf->dtsn = mydodag->dtsn; rpl_send_dio_buf->flags = 0; rpl_send_dio_buf->reserved = 0; rpl_send_dio_buf->dodagid = mydodag->dodag_id; int opt_hdr_len = 0; /* DODAG Configuration Option! */ rpl_send_opt_dodag_conf_buf = get_rpl_send_opt_dodag_conf_buf(DIO_BASE_LEN); rpl_send_opt_dodag_conf_buf->type = RPL_OPT_DODAG_CONF; rpl_send_opt_dodag_conf_buf->length = RPL_OPT_DODAG_CONF_LEN; rpl_send_opt_dodag_conf_buf->flags_a_pcs = 0; rpl_send_opt_dodag_conf_buf->DIOIntDoubl = mydodag->dio_interval_doubling; rpl_send_opt_dodag_conf_buf->DIOIntMin = mydodag->dio_min; rpl_send_opt_dodag_conf_buf->DIORedun = mydodag->dio_redundancy; rpl_send_opt_dodag_conf_buf->MaxRankIncrease = mydodag->maxrankincrease; rpl_send_opt_dodag_conf_buf->MinHopRankIncrease = mydodag->minhoprankincrease; rpl_send_opt_dodag_conf_buf->ocp = mydodag->of->ocp; rpl_send_opt_dodag_conf_buf->reserved = 0; rpl_send_opt_dodag_conf_buf->default_lifetime = mydodag->default_lifetime; rpl_send_opt_dodag_conf_buf->lifetime_unit = mydodag->lifetime_unit; opt_hdr_len += RPL_OPT_LEN + RPL_OPT_DODAG_CONF_LEN; uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL); mutex_unlock(&rpl_send_mutex, 0); }
void rpl_send_DIO(rpl_dodag_t *mydodag, ipv6_addr_t *destination) { #if ENABLE_DEBUG if (destination) { DEBUGF("Send DIO to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination)); } #endif icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); if (mydodag == NULL) { DEBUGF("Error - trying to send DIO without being part of a dodag.\n"); return; } icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIO; rpl_send_dio_buf = get_rpl_send_dio_buf(); memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf)); DEBUGF("Sending DIO with "); rpl_send_dio_buf->rpl_instanceid = mydodag->instance->id; DEBUG("instance %02X ", rpl_send_dio_buf->rpl_instanceid); rpl_send_dio_buf->version_number = mydodag->version; rpl_send_dio_buf->rank = byteorder_htons(mydodag->my_rank); DEBUG("rank %04X\n", byteorder_ntohs(rpl_send_dio_buf->rank)); rpl_send_dio_buf->g_mop_prf = (mydodag->grounded << RPL_GROUNDED_SHIFT) | (mydodag->mop << RPL_MOP_SHIFT) | mydodag->prf; rpl_send_dio_buf->dtsn = mydodag->dtsn; rpl_send_dio_buf->flags = 0; rpl_send_dio_buf->reserved = 0; rpl_send_dio_buf->dodagid = mydodag->dodag_id; int opt_hdr_len = 0; /* DODAG configuration option */ rpl_send_opt_dodag_conf_buf = get_rpl_send_opt_dodag_conf_buf(DIO_BASE_LEN); rpl_send_opt_dodag_conf_buf->type = RPL_OPT_DODAG_CONF; rpl_send_opt_dodag_conf_buf->length = RPL_OPT_DODAG_CONF_LEN; rpl_send_opt_dodag_conf_buf->flags_a_pcs = 0; rpl_send_opt_dodag_conf_buf->DIOIntDoubl = mydodag->dio_interval_doubling; rpl_send_opt_dodag_conf_buf->DIOIntMin = mydodag->dio_min; rpl_send_opt_dodag_conf_buf->DIORedun = mydodag->dio_redundancy; rpl_send_opt_dodag_conf_buf->MaxRankIncrease = byteorder_htons(mydodag->maxrankincrease); rpl_send_opt_dodag_conf_buf->MinHopRankIncrease = byteorder_htons(mydodag->minhoprankincrease); rpl_send_opt_dodag_conf_buf->ocp = byteorder_htons(mydodag->of->ocp); rpl_send_opt_dodag_conf_buf->reserved = 0; rpl_send_opt_dodag_conf_buf->default_lifetime = mydodag->default_lifetime; rpl_send_opt_dodag_conf_buf->lifetime_unit = byteorder_htons(mydodag->lifetime_unit); opt_hdr_len += RPL_OPT_DODAG_CONF_LEN_WITH_OPT_LEN; if (!ipv6_addr_is_unspecified(&mydodag->prefix)) { rpl_send_opt_prefix_information_buf = get_rpl_send_opt_prefix_information_buf(DIO_BASE_LEN + opt_hdr_len); rpl_send_opt_prefix_information_buf->type = RPL_OPT_PREFIX_INFO; rpl_send_opt_prefix_information_buf->length = RPL_OPT_PREFIX_INFO_LEN; rpl_send_opt_prefix_information_buf->flags = mydodag->prefix_flags; rpl_send_opt_prefix_information_buf->prefix = mydodag->prefix; rpl_send_opt_prefix_information_buf->prefix_length = mydodag->prefix_length; rpl_send_opt_prefix_information_buf->preferred_lifetime = byteorder_htonl(mydodag->prefix_preferred_lifetime); rpl_send_opt_prefix_information_buf->valid_lifetime = byteorder_htonl(mydodag->prefix_valid_lifetime); opt_hdr_len += RPL_OPT_PREFIX_INFO_LEN_WITH_OPT_LEN; } uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }