diff --git a/include/net/net_l2.h b/include/net/net_l2.h index a5f3369312ff4..6d06209295233 100644 --- a/include/net/net_l2.h +++ b/include/net/net_l2.h @@ -83,11 +83,13 @@ NET_L2_DECLARE_PUBLIC(IEEE802154_L2); #ifdef CONFIG_NET_L2_BT #define BLUETOOTH_L2 BLUETOOTH #define BLUETOOTH_L2_CTX_TYPE void* +NET_L2_DECLARE_PUBLIC(BLUETOOTH_L2); #endif /* CONFIG_NET_L2_BT */ #ifdef CONFIG_NET_OFFLOAD #define OFFLOAD_IP_L2 OFFLOAD_IP #define OFFLOAD_IP_L2_CTX_TYPE void* +NET_L2_DECLARE_PUBLIC(OFFLOAD_IP); #endif /* CONFIG_NET_OFFLOAD */ extern struct net_l2 __net_l2_end[]; diff --git a/subsys/net/ip/Kconfig.rpl b/subsys/net/ip/Kconfig.rpl index 53e9da550532d..b18923044353f 100644 --- a/subsys/net/ip/Kconfig.rpl +++ b/subsys/net/ip/Kconfig.rpl @@ -18,6 +18,30 @@ menuconfig NET_RPL if NET_RPL +config NET_RPL_PREFIX + string "Network IPv6 prefix" + help + What is the DAG id (prefix) of the RPL network. This is only used + if you are creating a root node. You should specify here the full + IPv6 address as that is used as a root node address. + Example: 2001:db8::1/64 + +choice + prompt "Network type" + default NET_RPL_L2_ANY + default NET_RPL_L2_IEEE802154 if NET_L2_IEEE802154 + help + The type of the network that this RPL device is supporting. + Currently all the nodes in the network need to be the same type + like IEEE 802.15.4. + +config NET_RPL_L2_ANY + bool "Any network type" + +config NET_RPL_L2_IEEE802154 + bool "IEEE 802.15.4" +endchoice + choice prompt "Objective function" default NET_RPL_MRHOF @@ -99,6 +123,12 @@ config NET_RPL_MAX_DAG_PER_INSTANCE help This determines how many DAG to allocate within one RPL instance. +config NET_RPL_MAX_PARENTS + int "Maximum number of parents for one node" + default NET_IPV6_MAX_NEIGHBORS + help + This determines how many RPL parents each node can have. + config NET_RPL_DAO_SPECIFY_DAG bool "Specify DAG when sending a DAO message." depends on NET_RPL diff --git a/subsys/net/ip/nbr.c b/subsys/net/ip/nbr.c index 5eac43f3070af..4fcd09e125783 100644 --- a/subsys/net/ip/nbr.c +++ b/subsys/net/ip/nbr.c @@ -72,7 +72,7 @@ struct net_nbr *net_nbr_get(struct net_nbr_table *table) { int i; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < table->nbr_count; i++) { struct net_nbr *nbr = get_nbr(table->nbr, i); if (!nbr->ref) { @@ -164,7 +164,7 @@ struct net_nbr *net_nbr_lookup(struct net_nbr_table *table, { int i; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < table->nbr_count; i++) { struct net_nbr *nbr = get_nbr(table->nbr, i); if (nbr->ref && nbr->iface == iface && @@ -191,7 +191,7 @@ void net_nbr_clear_table(struct net_nbr_table *table) { int i; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < table->nbr_count; i++) { struct net_nbr *nbr = get_nbr(table->nbr, i); struct net_linkaddr lladdr = { .addr = net_neighbor_lladdr[i].lladdr.addr, @@ -211,7 +211,7 @@ void net_nbr_print(struct net_nbr_table *table) { int i; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < table->nbr_count; i++) { struct net_nbr *nbr = get_nbr(table->nbr, i); if (!nbr->ref) { diff --git a/subsys/net/ip/nbr.h b/subsys/net/ip/nbr.h index 77865bccdeac1..ee17af9ed6008 100644 --- a/subsys/net/ip/nbr.h +++ b/subsys/net/ip/nbr.h @@ -94,6 +94,9 @@ struct net_nbr_table { /** Function to be called when the table is cleared. */ void (*const clear)(struct net_nbr_table *table); + + /** Max number of neighbors in the pool */ + const u16_t nbr_count; }; #define NET_NBR_LOCAL static @@ -108,6 +111,7 @@ struct net_nbr_table { .table = { \ .clear = _clear, \ .nbr = (struct net_nbr *)_pool, \ + .nbr_count = ARRAY_SIZE(_pool), \ } \ } diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index fb73d87b81978..42d8f5b369682 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -11,7 +11,7 @@ */ #if defined(CONFIG_NET_DEBUG_NET_PKT) -#define SYS_LOG_DOMAIN "net/net_pkt" +#define SYS_LOG_DOMAIN "net/pkt" #define NET_LOG_ENABLED 1 #endif diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c index bfb1e28d003f7..ca13de7c5a4d0 100644 --- a/subsys/net/ip/net_shell.c +++ b/subsys/net/ip/net_shell.c @@ -91,6 +91,65 @@ static inline const char *addrstate2str(enum net_addr_state addr_state) return ""; } +static const char *iface2str(struct net_if *iface, const char **extra) +{ +#ifdef CONFIG_NET_L2_IEEE802154 + if (iface->l2 == &NET_L2_GET_NAME(IEEE802154)) { + if (extra) { + *extra = "============="; + } + + return "IEEE 802.15.4"; + } +#endif + +#ifdef CONFIG_NET_L2_ETHERNET + if (iface->l2 == &NET_L2_GET_NAME(ETHERNET)) { + if (extra) { + *extra = "========"; + } + + return "Ethernet"; + } +#endif + +#ifdef CONFIG_NET_L2_DUMMY + if (iface->l2 == &NET_L2_GET_NAME(DUMMY)) { + if (extra) { + *extra = "====="; + } + + return "Dummy"; + } +#endif + +#ifdef CONFIG_NET_L2_BT + if (iface->l2 == &NET_L2_GET_NAME(BLUETOOTH)) { + if (extra) { + *extra = "========="; + } + + return "Bluetooth"; + } +#endif + +#ifdef CONFIG_NET_L2_OFFLOAD + if (iface->l2 == &NET_L2_GET_NAME(OFFLOAD_IP)) { + if (extra) { + *extra = "=========="; + } + + return "IP Offload"; + } +#endif + + if (extra) { + *extra = "=============="; + } + + return ""; +} + static void iface_cb(struct net_if *iface, void *user_data) { #if defined(CONFIG_NET_IPV6) @@ -99,12 +158,13 @@ static void iface_cb(struct net_if *iface, void *user_data) #endif struct net_if_addr *unicast; struct net_if_mcast_addr *mcast; + const char *extra; int i, count; ARG_UNUSED(user_data); - printk("Interface %p\n", iface); - printk("====================\n"); + printk("Interface %p (%s)\n", iface, iface2str(iface, &extra)); + printk("=======================%s\n", extra); if (!net_if_is_up(iface)) { printk("Interface is down.\n"); @@ -304,10 +364,13 @@ static void route_cb(struct net_route_entry *entry, void *user_data) static void iface_per_route_cb(struct net_if *iface, void *user_data) { + const char *extra; + ARG_UNUSED(user_data); - printk("IPv6 routes for interface %p\n", iface); - printk("====================================\n"); + printk("IPv6 routes for interface %p (%s)\n", iface, + iface2str(iface, &extra)); + printk("=======================================%s\n", extra); net_route_foreach(route_cb, iface); } @@ -318,13 +381,16 @@ static void route_mcast_cb(struct net_route_entry_mcast *entry, void *user_data) { struct net_if *iface = user_data; + const char *extra; if (entry->iface != iface) { return; } - printk("IPv6 multicast route %p for interface %p\n", entry, iface); - printk("========================================================\n"); + printk("IPv6 multicast route %p for interface %p (%s)\n", entry, + iface, iface2str(iface, &extra)); + printk("===========================================================" + "%s\n", extra); printk("IPv6 group : %s\n", net_sprint_ipv6_addr(&entry->group)); printk("Lifetime : %u\n", entry->lifetime); @@ -1673,16 +1739,31 @@ static void rpl_parent(struct net_rpl_parent *parent, void *user_data) int *count = user_data; if (*count == 0) { - printk(" Parent Last TX Rank DTSN Flags\tAddress\n"); + printk(" Parent Last TX Rank DTSN Flags DAG\t\t\t" + "Address\n"); } (*count)++; if (parent->dag) { - printk("[%2d] %p %10d %2d %d 0x%08x %s\n", - *count, parent, parent->last_tx_time, parent->rank, + struct net_ipv6_nbr_data *data; + char addr[NET_IPV6_ADDR_LEN]; + + data = net_rpl_get_ipv6_nbr_data(parent); + if (data) { + snprintk(addr, sizeof(addr), "%s", + net_sprint_ipv6_addr(&data->addr)); + } else { + snprintk(addr, sizeof(addr), ""); + } + + printk("[%2d]%s %p %7d %5d %3d 0x%02x %s\t%s\n", + *count, + parent->dag->preferred_parent == parent ? "*" : " ", + parent, parent->last_tx_time, parent->rank, parent->dtsn, parent->flags, - net_sprint_ipv6_addr(&parent->dag->dag_id)); + net_sprint_ipv6_addr(&parent->dag->dag_id), + addr); } } @@ -1783,7 +1864,7 @@ int net_shell_cmd_rpl(int argc, char *argv[]) instance, instance->is_used ? "active" : "disabled"); if (instance->default_route) { - printk("Default route : %s\n", + printk("Default route : %s\n", net_sprint_ipv6_addr( &instance->default_route->address.in6_addr)); } diff --git a/subsys/net/ip/rpl.c b/subsys/net/ip/rpl.c index fa6c6e9439bb6..d8cb09b4db9b2 100644 --- a/subsys/net/ip/rpl.c +++ b/subsys/net/ip/rpl.c @@ -109,6 +109,7 @@ static struct net_rpl_instance rpl_instances[CONFIG_NET_RPL_MAX_INSTANCES]; static struct net_rpl_instance *rpl_default_instance; +static struct net_if *rpl_default_iface; static enum net_rpl_mode rpl_mode = NET_RPL_MODE_MESH; static net_rpl_join_callback_t rpl_join_callback; static u8_t rpl_dao_sequence; @@ -208,7 +209,7 @@ static void net_rpl_neighbor_table_clear(struct net_nbr_table *table) NET_DBG("Neighbor table %p cleared", table); } -NET_NBR_POOL_INIT(net_rpl_neighbor_pool, CONFIG_NET_IPV6_MAX_NEIGHBORS, +NET_NBR_POOL_INIT(net_rpl_neighbor_pool, CONFIG_NET_RPL_MAX_PARENTS, sizeof(struct net_rpl_parent), net_rpl_neighbor_data_remove, 0); @@ -270,7 +271,7 @@ struct net_nbr *net_rpl_get_nbr(struct net_rpl_parent *data) { int i; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); if (nbr->data == (u8_t *)data) { @@ -349,7 +350,7 @@ int net_rpl_foreach_parent(net_rpl_parent_cb_t cb, void *user_data) { int i, ret = 0; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); if (!nbr->ref) { @@ -377,7 +378,7 @@ static void net_rpl_print_neighbors(void) NET_DBG("rank %u DIO interval %u", curr_rank, curr_interval); - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *ipv6_nbr, *nbr = get_nbr(i); struct in6_addr *parent_addr; @@ -388,10 +389,10 @@ static void net_rpl_print_neighbors(void) parent = nbr_data(nbr); parent_addr = - net_rpl_get_parent_addr(net_if_get_default(), + net_rpl_get_parent_addr(rpl_default_iface, parent); - ipv6_nbr = net_ipv6_nbr_lookup(net_if_get_default(), + ipv6_nbr = net_ipv6_nbr_lookup(rpl_default_iface, parent_addr); NET_DBG("[%d] nbr %s %5u %5u => %5u %c " @@ -590,12 +591,13 @@ int net_rpl_dio_send(struct net_if *iface, ret = net_send_data(pkt); if (ret >= 0) { if (!dst) { - NET_DBG("Sent a multicast DIO with rank %d", - instance->current_dag->rank); + NET_DBG("Sent a multicast DIO with rank %d (iface %p)", + instance->current_dag->rank, iface); } else { - NET_DBG("Sent a unicast DIO with rank %d to %s", + NET_DBG("Sent a unicast DIO with rank %d to %s " + "(iface %p)", instance->current_dag->rank, - net_sprint_ipv6_addr(dst)); + net_sprint_ipv6_addr(dst), iface); } net_stats_update_icmp_sent(); @@ -638,12 +640,12 @@ static void dio_timer(struct k_work *work) if (instance->dio_send) { if (instance->dio_redundancy && instance->dio_counter < instance->dio_redundancy) { - struct net_if *iface; struct in6_addr *addr = - net_if_ipv6_get_ll_addr(NET_ADDR_PREFERRED, - &iface); + net_if_ipv6_get_ll(rpl_default_iface, + NET_ADDR_PREFERRED); - net_rpl_dio_send(iface, instance, addr, NULL); + net_rpl_dio_send(rpl_default_iface, instance, addr, + NULL); #if defined(CONFIG_NET_STATISTICS_RPL) instance->dio_send_pkt++; @@ -787,8 +789,9 @@ int net_rpl_dis_send(struct in6_addr *dst, struct net_if *iface) ret = net_send_data(pkt); if (ret >= 0) { - NET_DBG("Sent a %s DIS to %s", dst ? "unicast" : "multicast", - net_sprint_ipv6_addr(dst_addr)); + NET_DBG("Sent a %s DIS to %s (iface %p)", + dst ? "unicast" : "multicast", + net_sprint_ipv6_addr(dst_addr), iface); net_stats_update_icmp_sent(); net_stats_update_rpl_dis_sent(); @@ -890,7 +893,7 @@ static struct net_rpl_parent *get_probing_target(struct net_rpl_dag *dag) * for NET_RPL_PROBING_EXPIRATION_TIME */ if (!probing_target && (sys_rand32_get() % 2) == 0) { - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); parent = nbr_data(nbr); @@ -911,7 +914,7 @@ static struct net_rpl_parent *get_probing_target(struct net_rpl_dag *dag) /* The default probing target is the least recently updated parent */ if (!probing_target) { - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); parent = nbr_data(nbr); @@ -1550,7 +1553,7 @@ static void remove_parents(struct net_if *iface, NET_DBG("Removing parents minimum rank %u", minimum_rank); - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); struct net_rpl_parent *parent; @@ -1793,7 +1796,7 @@ static struct net_rpl_parent *best_parent(struct net_if *iface, struct net_rpl_parent *best = NULL; int i; - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); struct net_rpl_parent *parent; @@ -1962,7 +1965,7 @@ static void nullify_parents(struct net_if *iface, NET_DBG("Nullifying parents (minimum rank %u)", minimum_rank); - for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) { + for (i = 0; i < CONFIG_NET_RPL_MAX_PARENTS; i++) { struct net_nbr *nbr = get_nbr(i); struct net_rpl_parent *parent; @@ -3612,9 +3615,11 @@ static enum net_verdict handle_dao(struct net_pkt *pkt) net_pkt_iface(pkt), instance, sequence, 0); if (r >= 0) { - NET_DBG("Sending DAO-ACK to %s", + NET_DBG("Sending DAO-ACK to %s " + "(iface %p)", net_sprint_ipv6_addr( - &NET_IPV6_HDR(pkt)->src)); + &NET_IPV6_HDR(pkt)->src), + net_pkt_iface(pkt)); net_pkt_unref(pkt); return NET_OK; } @@ -4192,7 +4197,7 @@ static void dis_timeout(struct k_work *work) NET_DBG("DIS Timer triggered at %u", k_uptime_get_32()); - net_rpl_dis_send(NULL, NULL); + net_rpl_dis_send(NULL, rpl_default_iface); dis_interval = CONFIG_NET_RPL_DIS_INTERVAL * MSEC_PER_SEC; @@ -4229,8 +4234,8 @@ void net_rpl_init(void) static struct net_if_link_cb link_cb; struct in6_addr addr; - NET_DBG("Allocated %d routing entries (%zu bytes)", - CONFIG_NET_IPV6_MAX_NEIGHBORS, + NET_DBG("Allocated %d parent routing entries (%zu bytes)", + CONFIG_NET_RPL_MAX_PARENTS, sizeof(net_rpl_neighbor_pool)); #if defined(CONFIG_NET_STATISTICS_RPL) @@ -4241,8 +4246,18 @@ void net_rpl_init(void) net_rpl_init_timers(); +#if defined(CONFIG_NET_RPL_L2_IEEE802154) + rpl_default_iface = net_if_get_ieee802154(); +#endif + + if (!rpl_default_iface) { + rpl_default_iface = net_if_get_default(); + } + + NET_DBG("Default interface is %p", rpl_default_iface); + create_linklocal_rplnodes_mcast(&addr); - if (!net_if_ipv6_maddr_add(net_if_get_default(), &addr)) { + if (!net_if_ipv6_maddr_add(rpl_default_iface, &addr)) { NET_ERR("Cannot create RPL multicast address"); /* Ignore error at this point */ diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 61bc3e1c3a5b3..6acf90612b081 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -131,18 +131,21 @@ static inline u32_t retry_timeout(const struct net_tcp *tcp) (IS_ENABLED(CONFIG_NET_L2_IEEE802154) && \ net_pkt_ll_dst(pkt)->type == NET_LINK_IEEE802154))) -static inline void do_ref_if_needed(struct net_pkt *pkt) -{ - /* The ref should not be done for Bluetooth and IEEE 802.15.4 which use - * IPv6 header compression (6lo). For BT and 802.15.4 we copy the pkt - * chain we are about to send so it is fine if the network driver - * releases it. As we have our own copy of the sent data, we do not - * need to take a reference of it. See also net_tcp_send_pkt(). - */ - if (!is_6lo_technology(pkt)) { - pkt = net_pkt_ref(pkt); - } -} +/* The ref should not be done for Bluetooth and IEEE 802.15.4 which use + * IPv6 header compression (6lo). For BT and 802.15.4 we copy the pkt + * chain we are about to send so it is fine if the network driver + * releases it. As we have our own copy of the sent data, we do not + * need to take a reference of it. See also net_tcp_send_pkt(). + * + * Note that this is macro so that we get information who called the + * net_pkt_ref() if memory debugging is active. + */ +#define do_ref_if_needed(pkt) \ + do { \ + if (!is_6lo_technology(pkt)) { \ + pkt = net_pkt_ref(pkt); \ + } \ + } while (0) static void abort_connection(struct net_tcp *tcp) { diff --git a/subsys/net/lib/app/init.c b/subsys/net/lib/app/init.c index f24d58b96b453..dca8289e1ad14 100644 --- a/subsys/net/lib/app/init.c +++ b/subsys/net/lib/app/init.c @@ -103,6 +103,11 @@ static void setup_ipv4(struct net_if *iface) #endif struct in_addr addr; + if (sizeof(CONFIG_NET_APP_MY_IPV4_ADDR) == 1) { + /* Empty address, skip setting ANY address in this case */ + return; + } + if (net_addr_pton(AF_INET, CONFIG_NET_APP_MY_IPV4_ADDR, &addr)) { NET_ERR("Invalid address: %s", CONFIG_NET_APP_MY_IPV4_ADDR); return; @@ -182,6 +187,11 @@ static void setup_ipv6(struct net_if *iface, u32_t flags) struct net_if_addr *ifaddr; u32_t mask = NET_EVENT_IPV6_DAD_SUCCEED; + if (sizeof(CONFIG_NET_APP_MY_IPV6_ADDR) == 1) { + /* Empty address, skip setting ANY address in this case */ + return; + } + if (net_addr_pton(AF_INET6, CONFIG_NET_APP_MY_IPV6_ADDR, &laddr)) { NET_ERR("Invalid address: %s", CONFIG_NET_APP_MY_IPV6_ADDR); /* some interfaces may add IP address later */