From 4412c3806b1fdf68a2cbe8f90189711c0917a346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cenk=20G=C3=BCndo=C4=9Fan?= Date: Thu, 1 Oct 2015 16:30:06 +0200 Subject: [PATCH] rpl: refactor dao sending to use appropriate pktbuf functions --- .../routing/rpl/gnrc_rpl_control_messages.c | 112 ++++++++++++------ 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c index 1872ae6406..5d2b344d61 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c @@ -621,13 +621,44 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len) } } -void _dao_fill_target(gnrc_rpl_opt_target_t *target, ipv6_addr_t *addr) +gnrc_pktsnip_t *_dao_target_build(gnrc_pktsnip_t *pkt, ipv6_addr_t *addr) { + gnrc_rpl_opt_target_t *target; + gnrc_pktsnip_t *opt_snip; + if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_opt_target_t), + GNRC_NETTYPE_UNDEF)) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + gnrc_pktbuf_release(pkt); + return NULL; + } + target = opt_snip->data; target->type = GNRC_RPL_OPT_TARGET; target->length = sizeof(target->flags) + sizeof(target->prefix_length) + sizeof(target->target); target->flags = 0; target->prefix_length = 128; target->target = *addr; + return opt_snip; +} + +gnrc_pktsnip_t *_dao_transit_build(gnrc_pktsnip_t *pkt, uint8_t lifetime) +{ + gnrc_rpl_opt_transit_t *transit; + gnrc_pktsnip_t *opt_snip; + if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_opt_transit_t), + GNRC_NETTYPE_UNDEF)) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + gnrc_pktbuf_release(pkt); + return NULL; + } + transit = opt_snip->data; + transit->type = GNRC_RPL_OPT_TRANSIT; + transit->length = sizeof(transit->e_flags) + sizeof(transit->path_control) + + sizeof(transit->path_sequence) + sizeof(transit->path_lifetime); + transit->e_flags = 0; + transit->path_control = 0; + transit->path_sequence = 0; + transit->path_lifetime = lifetime; + return opt_snip; } void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_t lifetime) @@ -653,11 +684,8 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_ destination = &(dodag->parents->addr); } - gnrc_pktsnip_t *pkt; - icmpv6_hdr_t *icmp; + gnrc_pktsnip_t *pkt = NULL, *tmp = NULL; gnrc_rpl_dao_t *dao; - gnrc_rpl_opt_target_t *target; - gnrc_rpl_opt_transit_t *transit; /* find my address */ ipv6_addr_t *me = NULL; @@ -669,8 +697,8 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_ gnrc_ipv6_netif_addr_t *me_netif = gnrc_ipv6_netif_addr_get(me); if (me_netif == NULL) { - DEBUG("RPL: no netif address found for %s\n", ipv6_addr_to_str(addr_str, me, - sizeof(addr_str))); + DEBUG("RPL: no netif address found for %s\n", + ipv6_addr_to_str(addr_str, me, sizeof(addr_str))); return; } @@ -681,30 +709,49 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_ fib_get_destination_set(&gnrc_ipv6_fib_table, prefix.u8, sizeof(ipv6_addr_t), fib_dest_set, &dst_size); - int size = sizeof(icmpv6_hdr_t) + sizeof(gnrc_rpl_dao_t) + - (sizeof(gnrc_rpl_opt_target_t) * (dst_size + 1)) + sizeof(gnrc_rpl_opt_transit_t); - - bool local_instance = (dodag->instance->id & GNRC_RPL_INSTANCE_ID_MSB) ? true : false; - - if (local_instance) { - size += sizeof(ipv6_addr_t); - } - - if ((pkt = gnrc_icmpv6_build(NULL, ICMPV6_RPL_CTRL, GNRC_RPL_ICMPV6_CODE_DAO, size)) == NULL) { + /* add transit option for all target options */ + if ((pkt = _dao_transit_build(pkt, lifetime)) == NULL) { DEBUG("RPL: Send DAO - no space left in packet buffer\n"); return; } - icmp = (icmpv6_hdr_t *)pkt->data; - dao = (gnrc_rpl_dao_t *)(icmp + 1); - target = (gnrc_rpl_opt_target_t *) (dao + 1); + /* add children */ + for (size_t i = 0; i < dst_size; ++i) { + if ((pkt = _dao_target_build(pkt, ((ipv6_addr_t *) fib_dest_set[i].dest))) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + return; + } + } + /* add own address */ + if ((pkt = _dao_target_build(pkt, me)) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + return; + } + + bool local_instance = (dodag->instance->id & GNRC_RPL_INSTANCE_ID_MSB) ? true : false; + + if (local_instance) { + if ((tmp = gnrc_pktbuf_add(pkt, &dodag->dodag_id, sizeof(ipv6_addr_t), + GNRC_NETTYPE_UNDEF)) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + gnrc_pktbuf_release(pkt); + return; + } + pkt = tmp; + } + + if ((tmp = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_dao_t), GNRC_NETTYPE_UNDEF)) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + gnrc_pktbuf_release(pkt); + return; + } + pkt = tmp; + dao = pkt->data; dao->instance_id = dodag->instance->id; if (local_instance) { /* set the D flag to indicate that a DODAG id is present */ dao->k_d_flags = GNRC_RPL_DAO_D_BIT; - memcpy((dao + 1), &dodag->dodag_id, sizeof(ipv6_addr_t)); - target = (gnrc_rpl_opt_target_t *)(((uint8_t *) target) + sizeof(ipv6_addr_t)); } else { dao->k_d_flags = 0; @@ -715,23 +762,12 @@ void gnrc_rpl_send_DAO(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, uint8_ dao->dao_sequence = dodag->dao_seq; dao->reserved = 0; - /* add own address */ - _dao_fill_target(target, me); - - /* add children */ - for (size_t i = 0; i < dst_size; ++i) { - target = (target + 1); - _dao_fill_target(target, ((ipv6_addr_t *) fib_dest_set[i].dest)); + if ((tmp = gnrc_icmpv6_build(pkt, ICMPV6_RPL_CTRL, GNRC_RPL_ICMPV6_CODE_DAO, + sizeof(icmpv6_hdr_t))) == NULL) { + DEBUG("RPL: Send DAO - no space left in packet buffer\n"); + return; } - - transit = (gnrc_rpl_opt_transit_t *) (target + 1); - transit->type = GNRC_RPL_OPT_TRANSIT; - transit->length = sizeof(transit->e_flags) + sizeof(transit->path_control) + - sizeof(transit->path_sequence) + sizeof(transit->path_lifetime); - transit->e_flags = 0; - transit->path_control = 0; - transit->path_sequence = 0; - transit->path_lifetime = lifetime; + pkt = tmp; gnrc_rpl_send(pkt, NULL, destination, &dodag->dodag_id);