From cc9aa3550d3bcf0e8c56ce6e80f3d7ca617cb665 Mon Sep 17 00:00:00 2001 From: Martine Lenders <mlenders@inf.fu-berlin.de> Date: Mon, 31 Aug 2015 04:09:43 +0200 Subject: [PATCH] shell_commands: provide command for 6Lo context administration --- sys/shell/commands/Makefile | 5 + sys/shell/commands/sc_gnrc_6ctx.c | 173 ++++++++++++++++++++++++++++ sys/shell/commands/shell_commands.c | 11 ++ 3 files changed, 189 insertions(+) create mode 100644 sys/shell/commands/sc_gnrc_6ctx.c diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index 948529eeae..74a86b495f 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -56,6 +56,11 @@ endif ifneq (,$(filter gnrc_rpl,$(USEMODULE))) SRC += sc_gnrc_rpl.c endif +ifneq (,$(filter gnrc_sixlowpan_ctx,$(USEMODULE))) +ifneq (,$(filter gnrc_sixlowpan_nd_border_router,$(USEMODULE))) + SRC += sc_gnrc_6ctx.c +endif +endif # TODO # Conditional building not possible at the moment due to diff --git a/sys/shell/commands/sc_gnrc_6ctx.c b/sys/shell/commands/sc_gnrc_6ctx.c new file mode 100644 index 0000000000..17d3b72b59 --- /dev/null +++ b/sys/shell/commands/sc_gnrc_6ctx.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "net/ipv6/addr.h" +#include "net/gnrc/ipv6/netif.h" +#include "net/gnrc/ndp/internal.h" +#include "net/gnrc/sixlowpan/ctx.h" +#include "net/gnrc/sixlowpan/nd.h" +#include "timex.h" +#include "xtimer.h" + +static xtimer_t del_timer[GNRC_SIXLOWPAN_CTX_SIZE]; +static gnrc_sixlowpan_nd_router_abr_t *abr = NULL; + +void _del_cb(void *ptr) +{ + gnrc_sixlowpan_ctx_t *ctx = ptr; + uint8_t cid = ctx->flags_id & GNRC_SIXLOWPAN_CTX_FLAGS_CID_MASK; + ctx->prefix_len = 0; + gnrc_sixlowpan_nd_router_abr_rem_ctx(abr, cid); + del_timer[cid].callback = NULL; +} + +static void _usage(char *cmd_str) +{ + printf("usage: %s [{add <0-15> <prefix>/<prefix_len> <ltime in min>|del <ctx>}]\n", cmd_str); + puts(" `del` will only invalidate the context for compression. It can be"); + puts(" reassigned after 5 min."); +} + +int _gnrc_6ctx_list(void) +{ + puts("cid|prefix |C|ltime"); + puts("-----------------------------------------------------------"); + for (uint8_t i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) { + gnrc_sixlowpan_ctx_t *ctx = gnrc_sixlowpan_ctx_lookup_id(i); + if (ctx != NULL) { + char addr_str[IPV6_ADDR_MAX_STR_LEN]; + printf(" %2" PRIu8 "|%39s/%-3" PRIu8 "|%" PRIx8 "|%5" PRIu16 " min\n", i, + ipv6_addr_to_str(addr_str, &ctx->prefix, sizeof(addr_str)), ctx->prefix_len, + (ctx->flags_id & 0xf0) >> 4, ctx->ltime); + } + } + return 0; +} + +static void _adv_ctx(void) +{ + kernel_pid_t ifs[GNRC_NETIF_NUMOF]; + size_t ifnum = gnrc_netif_get(ifs); + for (size_t i = 0; i < ifnum; i++) { + gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(ifs[i]); + if ((iface != NULL) && (iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { + gnrc_ndp_internal_send_rtr_adv(ifs[i], NULL, NULL, false); + } + } +} + +int _gnrc_6ctx_add(char *cmd_str, char *ctx_str, char *prefix_str, char *ltime_str) +{ + ipv6_addr_t prefix; + char *addr_str, *prefix_len_str, *save_ptr; + unsigned prefix_len; + unsigned ltime; + unsigned ctx = (unsigned)atoi(ctx_str); + if (ctx >= GNRC_SIXLOWPAN_CTX_SIZE) { + _usage(cmd_str); + return 1; + } + addr_str = strtok_r(prefix_str, "/", &save_ptr); + if (addr_str == NULL) { + _usage(cmd_str); + return 1; + } + prefix_len_str = strtok_r(NULL, "/", &save_ptr); + if (addr_str == NULL) { + _usage(cmd_str); + return 1; + } + prefix_len = (unsigned)atoi(prefix_len_str); + if ((prefix_len - 1U) > 128U) { + puts("ERROR: prefix_len < 1 || prefix_len > 128"); + return 1; + } + ipv6_addr_from_str(&prefix, addr_str); + if (ipv6_addr_is_unspecified(&prefix)) { + puts("ERROR: prefix may not be ::"); + return 1; + } + if (abr == NULL) { + abr = gnrc_sixlowpan_nd_router_abr_get(); + } + if (gnrc_sixlowpan_nd_router_abr_add_ctx(abr, ctx) < 0) { + puts("ERROR: can not add context"); + return 1; + } + ltime = (unsigned)atoi(ltime_str); + if (gnrc_sixlowpan_ctx_update((uint8_t)ctx, &prefix, (uint8_t)prefix_len, ltime, + true) == NULL) { + puts("ERROR: can not add context"); + return 1; + } + /* advertise new/updated context */ + _adv_ctx(); + return 0; +} + +int _gnrc_6ctx_del(char *cmd_str, char *ctx_str) +{ + gnrc_sixlowpan_ctx_t *ctx; + unsigned cid = (unsigned)atoi(ctx_str); + if (cid >= GNRC_SIXLOWPAN_CTX_SIZE) { + _usage(cmd_str); + return 1; + } + else if (del_timer[cid].callback == NULL) { + ctx = gnrc_sixlowpan_ctx_lookup_id(cid); + if (ctx != NULL) { + ctx->flags_id &= ~GNRC_SIXLOWPAN_CTX_FLAGS_COMP; + ctx->ltime = 0; + del_timer[cid].callback = _del_cb; + del_timer[cid].arg = ctx; + xtimer_set(&del_timer[cid], GNRC_SIXLOWPAN_ND_RTR_MIN_CTX_DELAY * SEC_IN_USEC); + } + } + else { + printf("Context %u already marked for removal\n", cid); + return 1; + } + /* advertise updated context */ + _adv_ctx(); + return 0; +} + +int _gnrc_6ctx(int argc, char **argv) +{ + if (argc < 2) { + _gnrc_6ctx_list(); + } + else if (strcmp("add", argv[1]) == 0) { + if (argc < 5) { + _usage(argv[0]); + return 1; + } + return _gnrc_6ctx_add(argv[0], argv[2], argv[3], argv[4]); + } + else if (strcmp("del", argv[1]) == 0) { + return _gnrc_6ctx_del(argv[0], argv[2]); + } + else { + _usage(argv[0]); + return 1; + } + return 0; +} + +/** @} */ diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index e8a7340592..c4a3fd02cd 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -120,6 +120,12 @@ extern int _zep_init(int argc, char **argv); extern int _gnrc_rpl(int argc, char **argv); #endif +#ifdef MODULE_GNRC_SIXLOWPAN_CTX +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER +extern int _gnrc_6ctx(int argc, char **argv); +#endif +#endif + const shell_command_t _shell_command_list[] = { {"reboot", "Reboot the node", _reboot_handler}, #ifdef MODULE_CONFIG @@ -197,6 +203,11 @@ const shell_command_t _shell_command_list[] = { #endif #ifdef MODULE_GNRC_RPL {"rpl", "rpl configuration tool [help|init|rm|root|show]", _gnrc_rpl }, +#endif +#ifdef MODULE_GNRC_SIXLOWPAN_CTX +#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER + {"6ctx", "6LoWPAN context configuration tool", _gnrc_6ctx }, +#endif #endif {NULL, NULL, NULL} }; -- GitLab