Merge pull request #3675 from authmillenon/gnrc_ipv6/fix/check-mtu
gnrc_ipv6: check link MTU before sending
This commit is contained in:
commit
8977cc1175
@ -28,6 +28,7 @@
|
|||||||
#include "kernel_macros.h"
|
#include "kernel_macros.h"
|
||||||
#include "kernel_types.h"
|
#include "kernel_types.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
|
#include "net/ipv6.h"
|
||||||
#include "net/ipv6/addr.h"
|
#include "net/ipv6/addr.h"
|
||||||
#include "vtimer.h"
|
#include "vtimer.h"
|
||||||
|
|
||||||
@ -51,11 +52,19 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief Default MTU
|
* @brief Default MTU
|
||||||
*
|
*
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc2460#section-5">
|
* An interface will choose this MTU if the link-layer's maximum packet size
|
||||||
* RFC 2460, section 5
|
* (see @ref NETOPT_MAX_PACKET_SIZE) is lesser than the @ref IPV6_MIN_MTU or if it just not
|
||||||
* </a>
|
* provide it. For RFC-compatible communication it must be at least @ref IPV6_MIN_MTU.
|
||||||
|
*
|
||||||
|
* @note If the scenario the node is used in allows for it and the packet size is predictable,
|
||||||
|
* a user might choose to set @ref GNRC_IPV6_NETIF_DEFAULT_MTU to a lesser value than
|
||||||
|
* @ref IPV6_MIN_MTU to optimize for code size (e.g. because it is then possible to omit
|
||||||
|
* @ref net_gnrc_sixlowpan_frag) and memory usage (e.g. because @ref GNRC_PKTBUF_SIZE
|
||||||
|
* can be much smaller).
|
||||||
*/
|
*/
|
||||||
#define GNRC_IPV6_NETIF_DEFAULT_MTU (1280)
|
#ifndef GNRC_IPV6_NETIF_DEFAULT_MTU
|
||||||
|
#define GNRC_IPV6_NETIF_DEFAULT_MTU (IPV6_MIN_MTU)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default hop limit
|
* @brief Default hop limit
|
||||||
|
|||||||
@ -32,6 +32,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief minimum **M**aximum **T**ransition **U**nit
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc4944#section-5.3">
|
||||||
|
* RFC 2460, section 5.3
|
||||||
|
* </a>
|
||||||
|
*/
|
||||||
|
#define IPV6_MIN_MTU (1280)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -223,7 +223,7 @@ static inline int _get_max_pkt_sz(uint16_t *value, size_t max_len)
|
|||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
*value = ETHERNET_MAX_LEN;
|
*value = ETHERNET_DATA_LEN;
|
||||||
|
|
||||||
return sizeof(uint16_t);
|
return sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
*
|
*
|
||||||
* @file
|
* @file
|
||||||
*/
|
*/
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -205,31 +206,29 @@ static void *_event_loop(void *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN
|
|
||||||
static void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt)
|
static void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt)
|
||||||
{
|
{
|
||||||
|
((gnrc_netif_hdr_t *)pkt->data)->if_pid = iface;
|
||||||
gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);
|
gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);
|
||||||
|
|
||||||
((gnrc_netif_hdr_t *)pkt->data)->if_pid = iface;
|
assert(if_entry != NULL);
|
||||||
|
if (gnrc_pkt_len(pkt->next) > if_entry->mtu) {
|
||||||
|
DEBUG("ipv6: packet too big\n");
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef MODULE_GNRC_SIXLOWPAN
|
||||||
if ((if_entry != NULL) && (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
|
if ((if_entry != NULL) && (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
|
||||||
DEBUG("ipv6: send to 6LoWPAN instead\n");
|
DEBUG("ipv6: send to 6LoWPAN instead\n");
|
||||||
if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
|
if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
|
||||||
DEBUG("ipv6: no 6LoWPAN thread found");
|
DEBUG("ipv6: no 6LoWPAN thread found");
|
||||||
gnrc_pktbuf_release(pkt);
|
gnrc_pktbuf_release(pkt);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
gnrc_netapi_send(iface, pkt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt)
|
|
||||||
{
|
|
||||||
((gnrc_netif_hdr_t *)pkt->data)->if_pid = iface;
|
|
||||||
gnrc_netapi_send(iface, pkt);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
gnrc_netapi_send(iface, pkt);
|
||||||
|
}
|
||||||
|
|
||||||
/* functions for sending */
|
/* functions for sending */
|
||||||
static void _send_unicast(kernel_pid_t iface, uint8_t *dst_l2addr,
|
static void _send_unicast(kernel_pid_t iface, uint8_t *dst_l2addr,
|
||||||
|
|||||||
@ -695,6 +695,7 @@ void gnrc_ipv6_netif_init_by_dev(void)
|
|||||||
for (size_t i = 0; i < ifnum; i++) {
|
for (size_t i = 0; i < ifnum; i++) {
|
||||||
ipv6_addr_t addr;
|
ipv6_addr_t addr;
|
||||||
eui64_t iid;
|
eui64_t iid;
|
||||||
|
uint16_t mtu;
|
||||||
gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);
|
gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);
|
||||||
|
|
||||||
if (ipv6_if == NULL) {
|
if (ipv6_if == NULL) {
|
||||||
@ -730,6 +731,7 @@ void gnrc_ipv6_netif_init_by_dev(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* set link-local address */
|
||||||
if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid,
|
if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid,
|
||||||
sizeof(eui64_t)) < 0)) {
|
sizeof(eui64_t)) < 0)) {
|
||||||
mutex_unlock(&ipv6_if->mutex);
|
mutex_unlock(&ipv6_if->mutex);
|
||||||
@ -740,6 +742,16 @@ void gnrc_ipv6_netif_init_by_dev(void)
|
|||||||
ipv6_addr_set_link_local_prefix(&addr);
|
ipv6_addr_set_link_local_prefix(&addr);
|
||||||
_add_addr_to_entry(ipv6_if, &addr, 64, 0);
|
_add_addr_to_entry(ipv6_if, &addr, 64, 0);
|
||||||
|
|
||||||
|
/* set link MTU */
|
||||||
|
if ((gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE, 0, &mtu,
|
||||||
|
sizeof(uint16_t)) >= 0)) {
|
||||||
|
if (mtu >= IPV6_MIN_MTU) {
|
||||||
|
ipv6_if->mtu = mtu;
|
||||||
|
}
|
||||||
|
/* otherwise leave at GNRC_IPV6_NETIF_DEFAULT_MTU as initialized in
|
||||||
|
* gnrc_ipv6_netif_add() */
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&ipv6_if->mutex);
|
mutex_unlock(&ipv6_if->mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,6 +89,11 @@ static void _set_usage(char *cmd_name)
|
|||||||
" * \"state\" - set the device state\n");
|
" * \"state\" - set the device state\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _mtu_usage(char *cmd_name)
|
||||||
|
{
|
||||||
|
printf("usage: %s <if_id> mtu <n>\n", cmd_name);
|
||||||
|
}
|
||||||
|
|
||||||
static void _flag_usage(char *cmd_name)
|
static void _flag_usage(char *cmd_name)
|
||||||
{
|
{
|
||||||
printf("usage: %s <if_id> [-]{promisc|autoack|preload|6lo|iphc}\n", cmd_name);
|
printf("usage: %s <if_id> [-]{promisc|autoack|preload|6lo|iphc}\n", cmd_name);
|
||||||
@ -259,8 +264,11 @@ static void _netif_list(kernel_pid_t dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GNRC_IPV6_NETIF
|
#ifdef MODULE_GNRC_IPV6_NETIF
|
||||||
if ((entry != NULL) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
|
if (entry != NULL) {
|
||||||
|
printf("MTU:%" PRIu16 " ", entry->mtu);
|
||||||
|
if (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
|
||||||
printf("6LO ");
|
printf("6LO ");
|
||||||
|
}
|
||||||
linebreak = true;
|
linebreak = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -683,6 +691,33 @@ static int _netif_del(kernel_pid_t dev, char *addr_str)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _netif_mtu(kernel_pid_t dev, char *mtu_str)
|
||||||
|
{
|
||||||
|
#ifdef MODULE_GNRC_IPV6_NETIF
|
||||||
|
int mtu;
|
||||||
|
gnrc_ipv6_netif_t *entry;
|
||||||
|
if (((mtu = atoi(mtu_str)) < IPV6_MIN_MTU) || (mtu > UINT16_MAX)) {
|
||||||
|
printf("error: MTU must be between %" PRIu16 " and %" PRIu16 "\n",
|
||||||
|
IPV6_MIN_MTU, UINT16_MAX);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((entry = gnrc_ipv6_netif_get(dev)) == NULL) {
|
||||||
|
puts("error: unable to set MTU.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
entry->mtu = IPV6_MIN_MTU;
|
||||||
|
printf("success: set MTU %" PRIu16 " interface %" PRIkernel_pid "\n", mtu,
|
||||||
|
dev);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
(void)dev;
|
||||||
|
(void)mtu_str;
|
||||||
|
puts("error: unable to set MTU.");
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* shell commands */
|
/* shell commands */
|
||||||
int _netif_send(int argc, char **argv)
|
int _netif_send(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -777,6 +812,14 @@ int _netif_config(int argc, char **argv)
|
|||||||
|
|
||||||
return _netif_del((kernel_pid_t)dev, argv[3]);
|
return _netif_del((kernel_pid_t)dev, argv[3]);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(argv[2], "mtu") == 0) {
|
||||||
|
if (argc < 4) {
|
||||||
|
_mtu_usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _netif_mtu((kernel_pid_t)dev, argv[3]);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return _netif_flag(argv[0], dev, argv[2]);
|
return _netif_flag(argv[0], dev, argv[2]);
|
||||||
}
|
}
|
||||||
@ -789,6 +832,7 @@ int _netif_config(int argc, char **argv)
|
|||||||
|
|
||||||
printf("usage: %s [<if_id>]\n", argv[0]);
|
printf("usage: %s [<if_id>]\n", argv[0]);
|
||||||
_set_usage(argv[0]);
|
_set_usage(argv[0]);
|
||||||
|
_mtu_usage(argv[0]);
|
||||||
_flag_usage(argv[0]);
|
_flag_usage(argv[0]);
|
||||||
_add_usage(argv[0]);
|
_add_usage(argv[0]);
|
||||||
_del_usage(argv[0]);
|
_del_usage(argv[0]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user