/* * Copyright (C) 2015 Freie Universität Berlin * * 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. */ /** * @defgroup net_gnrc Generic (GNRC) network stack * @ingroup net * @brief RIOT's modular default IP network stack. * @see [Martine Lenders' master thesis](http://doc.riot-os.org/mlenders_msc.pdf) * about GNRC's design and evaluation and the slide set of * [its defense](http://doc.riot-os.org/mlenders_msc_def.pdf). * * About * ===== * * This module is currently the default network stack for RIOT and includes * many components ranging from a @ref net_gnrc_nomac "simple MAC protocol" * through a fully-featured @ref net_gnrc_ipv6 implementation with @ref * net_gnrc_sixlowpan "6LowPAN" extensions to an @ref net_gnrc_udp "UDP" * implementation and @ref net_gnrc_rpl. * * A list of all features contained in the @ref net_gnrc is available in the * `Modules` section above. * * Integration into RIOT * ===================== * * From the application layer the @ref net_gnrc can be accessed through the * @ref net_conn, while the interface to the @ref drivers_netdev_netdev2 is * defined by the @ref net_gnrc_netdev2. * * Architecture * ============ * * ![GNRC Network Stack](riot-gnrc.svg) * * Each layer of the network stack runs in its own thread and each lower layer * thread has a higher priority than any upper layer thread. In this regard, * the thread of the MAC layer implementation has the highest priority and * threads on the application layer have the lowest priority. The communication * between threads is handled by the kernel's @ref core_msg functionality and * by the @ref net_gnrc_netapi. Most of the times IPC will take place between * threads of neighboring layers for packets that traverse the network stack up * or down. * * Due to the design of @ref net_gnrc "GNRC" and the nature of inter-process * communication, it is crucial for a new module that introduces a new thread * to follow a certain programming construct if it desires to interact with * other threads without blocking the system: Utilizing an `event loop`. * * Hence, a thread for @ref net_gnrc "GNRC" will usually consist of four basic * steps. * * 1. Initialize a message queue (note that its size **must** be a power of two, * see @ref msg_init_queue()) * 2. register for a @ref net_gnrc_nettype * 3. wait for a message * 4. react appropriately to a message and return to 3. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c} * void *_event_loop(void *arg) * { * static msg_t _msg_q[Q_SZ]; * (void)arg; * msg_init_queue(_msg_q, Q_SZ); * gnrc_netreg_entry me_reg = GNRC_NETREG_ENTRY_INIT_PID( * GNRC_NETREG_DEMUX_CTX_ALL, * sched_active_pid); * gnrc_netreg_register(GNRC_NETTYPE_IPV6, &me_reg); * while (1) { * msg_receive(&msg); * switch (msg.type) { * case TYPE1: * callback1(); * break; * ... * } * } * * return NULL; * } * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * @note As an example have a look at the event loops of @ref net_gnrc_ipv6 and * @ref net_gnrc_rpl * * Receiving / Transmitting Packets * ================================ * * Packets can be received or transmitted by interacting with the @ref * net_gnrc_netapi. * * Receiving Packets * ----------------- * * The reception of a @ref net_gnrc_pkt from another thread is handled by the * @ref net_gnrc_netapi module. In order to receive a @ref net_gnrc_pkt of a * specific type, it is necessary to register for the appropriate @ref * net_gnrc_nettype first. Your thread will then be able to receive certain * commands defined in the @ref net_gnrc_netapi module (e.g. @ref * net_gnrc_netapi::GNRC_NETAPI_MSG_TYPE_RCV) for all @ref net_gnrc_pkt * "Packets" that your thread registered for. * * The following example will sketch how to receive incoming and outgoing UDP * traffic on port 80. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c} * void *_event_loop(void *arg) * { * static msg_t _msg_q[Q_SZ]; * msg_t msg, reply; * reply.type = GNRC_NETAPI_MSG_TYPE_ACK; * reply.content.value = -ENOTSUP; * msg_init_queue(_msg_q, Q_SZ); * gnrc_pktsnip_t *pkt = NULL; * gnrc_netreg_entry me_reg = { .demux_ctx = 80, .pid = thread_getpid() }; * gnrc_netreg_register(GNRC_NETTYPE_UDP, &me_reg); * * while (1) { * msg_receive(&msg); * switch (msg.type) { * case GNRC_NETAPI_MSG_TYPE_RCV: * pkt = msg.content.ptr; * _handle_incoming_pkt(pkt); * break; * case GNRC_NETAPI_MSG_TYPE_SND: * pkt = msg.content.ptr; * _handle_outgoing_pkt(pkt); * break; * case GNRC_NETAPI_MSG_TYPE_SET: * case GNRC_NETAPI_MSG_TYPE_GET: * msg_reply(&msg, &reply); * break; * default: * break; * } * } * * return NULL; * } * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * @note When receiving a message of type @ref GNRC_NETAPI_MSG_TYPE_SET or * @ref GNRC_NETAPI_MSG_TYPE_GET, it is necessary to acknowledge it by * calling @ref msg_reply() with a message of type * @ref GNRC_NETAPI_MSG_TYPE_ACK which contains the actual size of the * GET message's content on success or an error code otherwise. * * @note Do not forget to unregister with @ref gnrc_netreg_unregister() if you * leave the function * context * * Transmitting Packets * -------------------- * * A packet is transmitted by relaying it to threads interested in handling (and * dispatching) packets of its type. To do this, the @ref net_gnrc_netapi * offers dispatch helper functions called @ref gnrc_netapi_dispatch_send() * and gnrc_netapi_dispatch_receive(). * * The following example sketches the usage and assumes a valid @ref * net_gnrc_pkt named `pkt`. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c} * gnrc_pktsnip_t *pkt; * * pkt = gnrc_pktbuf_add(NULL, data, size, GNRC_NETTYPE_UNDEF); * if (pkt == NULL) { * puts("Error: unable to copy data to packet buffer\n"); * return; * } * if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, 80, pkt)) { * puts("Error: no thread is interested"); * gnrc_pktbuf_release(pkt); * return; * } * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * First, the data to be sent is added to the @ref net_gnrc_pktbuf "packet buffer". * This ensures its intactness during the sending process. After the data to be * sent has been added to the packet buffer, its parent data structure can safely * be freed or re-used. * * Then, the @ref net_gnrc_pkt "pkt" will be sent to all threads that registered * for @ref GNRC_NETTYPE_UDP and the demux context `80`. Every registered thread * will receive a @ref GNRC_NETAPI_MSG_TYPE_SND command and can access the @ref * net_gnrc_pkt. Note that at this point, the threads receiving pkt act as its * owners, so please don't modify pkt after calling any dispatch function. * * If @ref gnrc_netapi_dispatch_send() is replaced by @ref * gnrc_netapi_dispatch_receive() then threads will receive the @ref * GNRC_NETAPI_MSG_TYPE_RCV command instead, again with access to the @ref * net_gnrc_pkt. * * @note If the data to be sent requires extra headers to be added for successful * transmission (in the example, this would be IP and UDP headers), these * have to be built manually before calling @ref gnrc_netapi_dispatch_send(). * In the interest of conciseness, this is omitted in this tutorial; * please refer to @ref gnrc_udp_hdr_build(), @ref gnrc_ipv6_hdr_build() * etc. for more information. * * How To Use * ========== * @ref net_gnrc is highly modular and can be adjusted to include only the * desired features. In the following several of the available modules will be * stated that you can include in your application's Makefile. * * - To include the default network device(s) on your board: * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_netdev_default * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * - To auto-initialize these network devices as GNRC network interfaces * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += auto_init_gnrc_netif * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * - You may choose to build either as an IPv6 Node * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_ipv6_default * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * or as an IPv6 Router * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_ipv6_router_default * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * An IPv6 Router can forward packets, while an IPv6 Node will simply drop * packets not targeted to it. If an IEEE 802.15.4 network device is present * @ref net_gnrc_sixlowpan (with @ref net_gnrc_sixlowpan_frag and @ref * net_gnrc_sixlowpan_iphc) will be included automatically. * - For basic IPv6 (and 6LoWPAN) functionalities choose instead * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_ipv6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * or * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_ipv6_router * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * respectively. Those modules provide the bare minimum of IPv6 * functionalities (no @ref net_gnrc_icmpv6, no @ref net_gnrc_ndp). Because * of that, the @ref net_gnrc_ipv6_nc needs to be configured manually. If an * IEEE 802.15.4 device is present @ref net_gnrc_sixlowpan will be included * automatically, but no fragmentation or header compression support will be * provided. * * - For @ref net_gnrc_icmpv6_echo "ICMPv6 echo request/reply (ping)" * functionality: * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_icmpv6_echo * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * - For @ref net_gnrc_udp support include * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_udp * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * - To use @ref net_conn_udp with GNRC include * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_conn_udp * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * - To include the @ref net_gnrc_rpl module * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} * USEMODULE += gnrc_rpl * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * This will include the @ref net_gnrc_rpl module. To provide forwarding * capabilities it is necessary to build the application with * `gnrc_ipv6_router_default` (or `gnrc_ipv6_router`), not * `gnrc_ipv6_default` (or `gnrc_ipv6`). * * @{ * * @file * @brief Includes all essential GNRC network stack base modules * * @author Hauke Petersen */ #ifndef GNRC_NETBASE_H_ #define GNRC_NETBASE_H_ #include "net/netopt.h" #include "net/gnrc/netdev.h" #include "net/gnrc/netapi.h" #include "net/gnrc/netreg.h" #include "net/gnrc/nettype.h" #include "net/gnrc/netif.h" #include "net/gnrc/netif/hdr.h" #include "net/gnrc/pktbuf.h" #include "net/gnrc/pkt.h" #ifdef __cplusplus extern "C" { #endif /* this file does not provide anything on it's own */ #ifdef __cplusplus } #endif #endif /* GNRC_NETBASE_H_ */ /** @} */