From f3d16b85a5e4630aae2bc5c07c4cf432c6b3f7c0 Mon Sep 17 00:00:00 2001 From: Oleg Hahm <oleg@hobbykeller.org> Date: Mon, 26 Oct 2015 17:41:52 +0100 Subject: [PATCH] ccn-lite: initial import of an example --- examples/ccn-lite-relay/Makefile | 39 ++++++++++ examples/ccn-lite-relay/README.md | 61 ++++++++++++++++ examples/ccn-lite-relay/content.c | 81 +++++++++++++++++++++ examples/ccn-lite-relay/interests.c | 82 +++++++++++++++++++++ examples/ccn-lite-relay/main.c | 109 ++++++++++++++++++++++++++++ pkg/ccn-lite/ccn-lite-riot.h | 25 +++++-- 6 files changed, 389 insertions(+), 8 deletions(-) create mode 100644 examples/ccn-lite-relay/Makefile create mode 100644 examples/ccn-lite-relay/README.md create mode 100644 examples/ccn-lite-relay/content.c create mode 100644 examples/ccn-lite-relay/interests.c create mode 100644 examples/ccn-lite-relay/main.c diff --git a/examples/ccn-lite-relay/Makefile b/examples/ccn-lite-relay/Makefile new file mode 100644 index 0000000000..cfb71c22dc --- /dev/null +++ b/examples/ccn-lite-relay/Makefile @@ -0,0 +1,39 @@ +APPLICATION = ccn-lite-relay + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +BOARD_WHITELIST := fox iotlab-m3 msba2 mulle native pba-d-01-kw2x samr21-xpro + + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +CFLAGS += -DDEVELHELP +CFLAGS += -DUSE_LINKLAYER +CFLAGS += -DUSE_IPV6 +CFLAGS += -DCCNL_UAPI_H_ +CFLAGS += -DUSE_SUITE_NDNTLV +CFLAGS += -DNEEDS_PREFIX_MATCHING +CFLAGS += -DNEEDS_PACKET_CRAFTING +CFLAGS += -DUSE_HMAC256 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +USEMODULE += ps +USEMODULE += shell +USEMODULE += shell_commands +# Include packages that pull up and auto-init the link layer. +# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present +USEMODULE += gnrc_netif_default +USEMODULE += auto_init_gnrc_netif +USEMODULE += timex +USEMODULE += xtimer +USEMODULE += random +USEMODULE += prng_minstd + +USEPKG += ccn-lite +USEMODULE += ccn-lite-utils + +include $(RIOTBASE)/Makefile.include diff --git a/examples/ccn-lite-relay/README.md b/examples/ccn-lite-relay/README.md new file mode 100644 index 0000000000..b053cba468 --- /dev/null +++ b/examples/ccn-lite-relay/README.md @@ -0,0 +1,61 @@ +# CCN-Lite on RIOT + +This application demonstrates how to use the Content-Centric Networking stack +from [CCN-Lite](http://www.ccn-lite.net/) on RIOT. In the current state you can +use only one packet format, `ndn2013`, and only relay over the link-layer +(Ethernet, IEEE~802.15.4 or what else is supported by your network device). + +## The shell commands + +RIOT provides three shell to interact with the CCN-Lite stack: +* `ccnl_open` - opens and configures a network device to be used for CCN-Lite. + It expects one parameter specifying the PID of the network + device. (You can figure out the PID of your network device(s) + by calling `ifconfig`.) In this example, this should always be + 3, hence, calling `ccnl_open 3` should work. (If you specify an + incorrect ID, you should get an error message.) You have to + call this command, before you can actually send or receive + anything. +* `ccnl_int` - generates and sends out an Interest. The command expects one + mandatory and one optional parameter. The first parameter + specifies the exact name (or a prefix) to request, the second + parameter specifies the link-layer address of the relay to use. + If the second parameter is omitted, the Interest will be + broadcasted. You may call it like this: + `ccnl_int /riot/peter/schmerzl b6:e5:94:26:ab:da` +* `ccnl_cont` - generates and populates Content. The command expects one + mandatory and one optional parameter. The first parameter + specifies the name of the content to be created, the second + parameter specifies the content itself. The second parameter may + include spaces, e.g. you can call: + `ccnl_cont /riot/peter/schmerzl Hello World! Hello RIOT!` + +## Example setup + +An example usage of this application could be setup like this: +1. Open a terminal window, navigate to the RIOT directory, and enter + `dist/tools/tapsetup/tapsetup -c`. +2. Open a second terminal window and navigate to this directory in both of + windows. +3. Call `make -B clean all term` in the first terminal and `PORT=tap1 make + term` in the second one. +4. Enter `open 3` in both terminals. +5. Enter `ccnl_cont /riot/peter/schmerzl Hello World! Hello RIOT!` on the first + terminal. +6. Enter `ccnl_int /riot/peter/schmerzl` in the second terminal. +7. See the content being displayed. Be happy! + +## Wireshark dissector + +One can use the Wireshark dissector from the named-data project +(https://github.com/named-data/ndn-tools/tree/master/tools/dissect-wireshark) +for analyzing the traffic in Wireshark. + +However, please note, that - in order to be compatible with the default +CCN-Lite upstream configuration - a different Ethertype (`0x0801` instead of +`0x8624`) is used. + +The simplest way to get this working is to copy the `ndn.lua` file into your +local Wireshark plugin directory (e.g. `$HOME/.wireshark/plugins`) and update +https://github.com/named-data/ndn-tools/blob/master/tools/dissect-wireshark/ndn.lua#L408 +to `0x0801). diff --git a/examples/ccn-lite-relay/content.c b/examples/ccn-lite-relay/content.c new file mode 100644 index 0000000000..0b081dec2f --- /dev/null +++ b/examples/ccn-lite-relay/content.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2015 Inria + * + * 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. + */ + +#include <stdio.h> +#include <string.h> + +#include "ccn-lite-riot.h" +#include "ccnl-pkt-ndntlv.h" +#include "ccnl-defs.h" +#include "ccnl-ext.h" + +#include "ccnl-pkt-ndntlv.h" + +#define MAX_CONTENT (64) + +static char *_default_content = "Start the RIOT!"; +static unsigned char _out[CCNL_MAX_PACKET_SIZE]; + +static void _usage(char *argv) +{ + printf("usage: %s <URI> [content]\n" + "%% %s /riot/peter/schmerzl (default content)\n" + "%% %s /riot/peter/schmerzl RIOT\n", + argv, argv, argv); +} + + +int _ccnl_content(int argc, char **argv) +{ + char *body = _default_content; + int arg_len = strlen(_default_content) + 1; + int offs = CCNL_MAX_PACKET_SIZE; + if (argc < 2) { + _usage(argv[0]); + return -1; + } + if (argc > 2) { + char buf[MAX_CONTENT]; + memset(buf, ' ', MAX_CONTENT); + char *buf_ptr = buf; + for (int i = 2; (i < argc) && (buf_ptr < (buf + MAX_CONTENT)); i++) { + arg_len = strlen(argv[i]); + if ((buf_ptr + arg_len) > (buf + MAX_CONTENT)) { + arg_len = (buf + MAX_CONTENT) - buf_ptr; + } + strncpy(buf_ptr, argv[i], arg_len); + buf_ptr += arg_len + 1; + } + *buf_ptr = '\0'; + body = buf; + arg_len = strlen(body); + } + + int suite = CCNL_SUITE_NDNTLV; + + struct ccnl_prefix_s *prefix = ccnl_URItoPrefix(argv[1], suite, NULL, NULL); + + arg_len = ccnl_ndntlv_prependContent(prefix, (unsigned char*) body, arg_len, NULL, NULL, &offs, _out); + + unsigned char *olddata; + unsigned char *data = olddata = _out + offs; + + int len; + unsigned typ; + if (ccnl_ndntlv_dehead(&data, &arg_len, (int*) &typ, &len) || + typ != NDN_TLV_Data) { + return -1; + } + struct ccnl_content_s *c = 0; + struct ccnl_pkt_s *pk = ccnl_ndntlv_bytes2pkt(typ, olddata, &data, &arg_len); + c = ccnl_content_new(&theRelay, &pk); + ccnl_content_add2cache(&theRelay, c); + c->flags |= CCNL_CONTENT_FLAGS_STATIC; + + return 0; +} diff --git a/examples/ccn-lite-relay/interests.c b/examples/ccn-lite-relay/interests.c new file mode 100644 index 0000000000..cebd8778ea --- /dev/null +++ b/examples/ccn-lite-relay/interests.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013-15, Christian Tschudin, University of Basel + * Copyright (C) 2015, Oliver Hahm, Inria + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * File history: + * 2015-11-09 created (based on ccn-lite-peek.c) + */ + + +#include <unistd.h> +#include "random.h" +#include "xtimer.h" +#include "timex.h" +#include "arpa/inet.h" +#include "net/packet.h" +#include "net/gnrc/netif.h" +#include "net/gnrc/netif/hdr.h" +#include "net/gnrc/netapi.h" + +#include "ccn-lite-riot.h" +#include "ccnl-core.h" +#include "ccnl-headers.h" +#include "ccnl-pkt-ndntlv.h" +#include "ccnl-defs.h" +#include "ccnl-ext.h" +#include "ccnl-pkt-ccntlv.h" + +/** + * Maximum number of Interest retransmissions + */ +#define CCNL_INTEREST_RETRIES (3) + +#define MAX_ADDR_LEN (8U) + +#define BUF_SIZE (128) +static unsigned char _int_buf[BUF_SIZE]; +static unsigned char _cont_buf[BUF_SIZE]; + +static void _usage(char *arg) +{ + printf("usage: %s <URI> [relay]\n" + "%% %s /riot/peter/schmerzl (classic lookup)\n", + arg, arg); +} + +int _ccnl_interest(int argc, char **argv) +{ + if (argc < 2) { + _usage(argv[0]); + return -1; + } + + /* XXX: https://xkcd.com/221/ */ + genrand_init(0x4); + + /* initialize address with 0xFF for broadcast */ + size_t addr_len = MAX_ADDR_LEN; + uint8_t relay_addr[MAX_ADDR_LEN]; + memset(relay_addr, UINT8_MAX, MAX_ADDR_LEN); + if (argc > 2) { + addr_len = gnrc_netif_addr_from_str(relay_addr, sizeof(relay_addr), argv[2]); + } + + for (int cnt = 0; cnt < CCNL_INTEREST_RETRIES; cnt++) { + ccnl_send_interest(CCNL_SUITE_NDNTLV, argv[1], relay_addr, addr_len, NULL, _int_buf, BUF_SIZE); + ccnl_wait_for_chunk(_cont_buf, BUF_SIZE); + } + + return 0; +} diff --git a/examples/ccn-lite-relay/main.c b/examples/ccn-lite-relay/main.c new file mode 100644 index 0000000000..15cf9b8b7c --- /dev/null +++ b/examples/ccn-lite-relay/main.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2015 Inria + * + * 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. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Basic ccn-lite relay example (produce and consumer via shell) + * + * @author Oliver Hahm <oliver.hahm@inria.fr> + * + * @} + */ + +#include <stdio.h> + +#include "thread.h" +#include "msg.h" +#include "timex.h" +#include "shell_commands.h" +#include "net/packet.h" +#include "net/netopt.h" +#include "net/gnrc/netif.h" +#include "net/gnrc/netapi.h" +#include "ccn-lite-riot.h" +#include "ccnl-core.h" +#include "ccnl-headers.h" +#include "ccnl-pkt-ndntlv.h" +#include "ccnl-defs.h" +#include "net/gnrc/nettype.h" + +/* main thread's message queue */ +#define MAIN_QUEUE_SIZE (8) +static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; + +/* check for one-time initialization */ +static bool started = false; + +/* shell command functions */ +static int _ccnl_open(int argc, char **argv); +extern int _ccnl_content(int argc, char **argv); +extern int _ccnl_interest(int argc, char **argv); + +static const shell_command_t shell_commands[] = { + { "open", "opens an interface or socket", _ccnl_open}, + { "interest", "sends an interest", _ccnl_interest}, + { "content", "create content and populated it", _ccnl_content}, + { NULL, NULL, NULL } +}; + +/* usage for open command */ +static void _usage(void) +{ + puts("ccnl <interface>"); +} + +static int _ccnl_open(int argc, char **argv) +{ + /* check if already running */ + if (started) { + puts("Already opened an interface for CCN!"); + return -1; + } + + /* check if parameter is given */ + if (argc != 2) { + _usage(); + return -1; + } + + /* check if given number is a valid netif PID */ + int pid = atoi(argv[1]); + if (!gnrc_netif_exist(pid)) { + printf("%i is not a valid interface!\n", pid); + return -1; + } + + ccnl_start(); + + /* set the relay's PID, configure the interface to interface to use CCN + * nettype */ + if (ccnl_open_netif(pid, GNRC_NETTYPE_CCN) < 0) { + puts("Error registering at network interface!"); + return -1; + } + + started = true; + + return 0; +} + +int main(void) +{ + msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); + + puts("Basic CCN-Lite example"); + + ccnl_core_init(); + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + return 0; +} diff --git a/pkg/ccn-lite/ccn-lite-riot.h b/pkg/ccn-lite/ccn-lite-riot.h index afb808e2a7..b9144dba8c 100644 --- a/pkg/ccn-lite/ccn-lite-riot.h +++ b/pkg/ccn-lite/ccn-lite-riot.h @@ -110,25 +110,34 @@ extern "C" { */ #define CONSTSTR(s) s +/** + * Stack size for CCN-Lite event loop + */ +#define CCNL_STACK_SIZE (THREAD_STACKSIZE_MAIN) + +/** + * Size of the message queue of CCN-Lite's event loop + */ +#define CCNL_QUEUE_SIZE (8) + /** * Struct holding CCN-Lite's central relay information */ extern struct ccnl_relay_s theRelay; /** - * @brief The main CCN-Lite event-loop - * - * @note This function does not terminate + * @brief Start the main CCN-Lite event-loop * - * @param[in] ccnl Reference to the CCN-Lite relay + * @return The PID of the event-loop's thread */ -void ccnl_event_loop(struct ccnl_relay_s *ccnl); +kernel_pid_t ccnl_start(void); /** - * @brief Opens a @ref gnrc_netif_t device for use with CCN-Lite + * @brief Opens a @ref net_gnrc_netif device for use with CCN-Lite * - * @param[in] if_pid The pid of the @ref gnrc_netif_t device driver - * @param[in] netreg_type The @ref gnrc_nettype_t @p if_pid should be configured to use + * @param[in] if_pid The pid of the @ref net_gnrc_netif device driver + * @param[in] netreg_type The @ref net_gnrc_nettype @p if_pid should be + * configured to use * * @return 0 on success, * @return -EINVAL if eventloop could not be registered for @p netreg_type -- GitLab