From 95841fb56d70349b469b182e0aacf8bf2067e806 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 16 Jan 2015 16:43:14 +0100 Subject: [PATCH 01/35] Remove all the DODAG from the instance when the node is set as Root --- core/net/rpl/rpl-dag.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index cbbf0764a1..22af410882 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -253,6 +253,7 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) rpl_dag_t *dag; rpl_instance_t *instance; uint8_t version; + int i; #if CETIC_6LBR version = nvm_data.rpl_version_id; @@ -263,19 +264,28 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) #else version = RPL_LOLLIPOP_INIT; #endif - dag = get_dag(instance_id, dag_id); - if(dag != NULL) { - version = dag->version; - RPL_LOLLIPOP_INCREMENT(version); + instance = rpl_get_instance(instance_id); + if(instance != NULL) { + for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) { + dag = &instance->dag_table[i]; + if(dag->used) { + if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) { + version = dag->version; + RPL_LOLLIPOP_INCREMENT(version); #if CETIC_6LBR nvm_data.rpl_version_id = version; store_nvm_config(); #endif - PRINTF("RPL: Dropping a joined DAG when setting this node as root"); - if(dag == dag->instance->current_dag) { - dag->instance->current_dag = NULL; + } + if(dag == dag->instance->current_dag) { + PRINTF("RPL: Dropping a joined DAG when setting this node as root"); + dag->instance->current_dag = NULL; + } else { + PRINTF("RPL: Dropping a DAG when setting this node as root"); + } + rpl_free_dag(dag); + } } - rpl_free_dag(dag); } dag = rpl_alloc_dag(instance_id, dag_id); From 33fccf76a6a96b24d3b74e6f9cddb42e0e6959eb Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 16 Jan 2015 16:43:31 +0100 Subject: [PATCH 02/35] Fix indentation --- core/net/rpl/rpl-dag.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 22af410882..8430f4e769 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -273,8 +273,8 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) version = dag->version; RPL_LOLLIPOP_INCREMENT(version); #if CETIC_6LBR - nvm_data.rpl_version_id = version; - store_nvm_config(); + nvm_data.rpl_version_id = version; + store_nvm_config(); #endif } if(dag == dag->instance->current_dag) { From 1c27755a11f4a648d471812c5335003100736942 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 16 Jan 2015 16:44:19 +0100 Subject: [PATCH 03/35] Do not delete instance when a new DODAG can not be created --- core/net/rpl/rpl-dag.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 8430f4e769..2cfa2ca049 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -522,7 +522,6 @@ rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id) } RPL_STAT(rpl_stats.mem_overflows++); - rpl_free_instance(instance); return NULL; } /*---------------------------------------------------------------------------*/ From 678ed3033bab94e0bd90649ee7e20124933a9cf0 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 16 Jan 2015 16:45:51 +0100 Subject: [PATCH 04/35] Do not priotirize new packets in sicslowpan --- core/net/ipv6/sicslowpan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index d4d9c1a866..f0e2492eeb 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -1676,7 +1676,7 @@ input(void) * We discard the previous packet, and start reassembling the new packet. * This lessens the negative impacts of too high SICSLOWPAN_REASS_MAXAGE. */ -#define PRIORITIZE_NEW_PACKETS 1 +#define PRIORITIZE_NEW_PACKETS 0 #if PRIORITIZE_NEW_PACKETS if(!is_fragment) { From 507a1b0b524819529d135e96f3b7374db8c0fb03 Mon Sep 17 00:00:00 2001 From: Maciej Wasilak Date: Fri, 19 Dec 2014 22:43:09 +0100 Subject: [PATCH 05/35] Set uip_ext_len to 0 after dropping packet --- core/net/ip/tcpip.c | 7 +++++++ core/net/ipv6/multicast/smrf.c | 3 +++ core/net/ipv6/uip-nd6.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index 6d6b80a694..f2ac16a978 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -589,12 +589,14 @@ tcpip_ipv6_output(void) if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; + uip_ext_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; + uip_ext_len = 0; return; } @@ -649,6 +651,7 @@ tcpip_ipv6_output(void) PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_len = 0; + uip_ext_len = 0; return; } @@ -698,6 +701,7 @@ tcpip_ipv6_output(void) #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_len = 0; + uip_ext_len = 0; return; } #endif /* UIP_CONF_IPV6_RPL */ @@ -706,6 +710,7 @@ tcpip_ipv6_output(void) #if UIP_ND6_SEND_NA if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_len = 0; + uip_ext_len = 0; return; } else { #if UIP_CONF_IPV6_QUEUE_PKT @@ -744,6 +749,7 @@ tcpip_ipv6_output(void) } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; + uip_ext_len = 0; return; } /* Send in parallel if we are running NUD (nbc state is either STALE, @@ -774,6 +780,7 @@ tcpip_ipv6_output(void) #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; + uip_ext_len = 0; return; } return; diff --git a/core/net/ipv6/multicast/smrf.c b/core/net/ipv6/multicast/smrf.c index 8a80a41425..13abb48725 100644 --- a/core/net/ipv6/multicast/smrf.c +++ b/core/net/ipv6/multicast/smrf.c @@ -81,6 +81,9 @@ mcast_fwd(void *p) UIP_IP_BUF->ttl--; tcpip_output(NULL); uip_len = 0; +#if NETSTACK_CONF_WITH_IPV6 + uip_ext_len = 0; +#endif /*NETSTACK_CONF_WITH_IPV6*/ } /*---------------------------------------------------------------------------*/ static uint8_t diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 9d0055e388..3e2f4639e1 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -356,6 +356,7 @@ ns_input(void) discard: uip_len = 0; + uip_ext_len = 0; return; } @@ -608,6 +609,7 @@ na_input(void) discard: uip_len = 0; + uip_ext_len = 0; return; } @@ -744,6 +746,7 @@ rs_input(void) discard: uip_len = 0; + uip_ext_len = 0; return; } @@ -1126,6 +1129,7 @@ ra_input(void) discard: uip_len = 0; + uip_ext_len = 0; return; } #endif /* !UIP_CONF_ROUTER */ From 7d7cd0059310e355f540cf153bbb5ba493516350 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Fri, 24 Oct 2014 15:13:27 +0200 Subject: [PATCH 06/35] fixed so that trickle timer rpl config is updated at global repair --- core/net/rpl/rpl-dag.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 2cfa2ca049..4dacdf0dc8 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -1079,6 +1079,14 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) remove_parents(dag, 0); dag->version = dio->version; + + /* copy parts of the configuration so that it propagates in the network */ + dag->instance->dio_intdoubl = dio->dag_intdoubl; + dag->instance->dio_intmin = dio->dag_intmin; + dag->instance->dio_redundancy = dio->dag_redund; + dag->instance->default_lifetime = dio->default_lifetime; + dag->instance->lifetime_unit = dio->lifetime_unit; + dag->instance->of->reset(dag); dag->min_rank = INFINITE_RANK; RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out); From f680514bf7bba3a256a8cc173588852d52ba1c44 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 27 Mar 2015 16:08:00 +0100 Subject: [PATCH 07/35] Use debuild to create debian package --- examples/6lbr/Makefile | 15 +------ .../6lbr/{control-ipk => angstrom}/control | 0 .../6lbr/{control-ipk => angstrom}/postinst | 0 .../6lbr/{control-ipk => angstrom}/postrm | 0 examples/6lbr/{control-ipk => angstrom}/prerm | 0 examples/6lbr/control-deb/control | 8 ---- examples/6lbr/control-deb/postinst | 12 ------ examples/6lbr/control-deb/postrm | 6 --- examples/6lbr/control-deb/prerm | 8 ---- examples/6lbr/debian/changelog | 5 +++ examples/6lbr/debian/compat | 1 + examples/6lbr/debian/control | 13 +++++++ examples/6lbr/debian/copyright | 39 +++++++++++++++++++ examples/6lbr/debian/docs | 0 examples/6lbr/debian/rules | 21 ++++++++++ examples/6lbr/debian/source/format | 1 + 16 files changed, 81 insertions(+), 48 deletions(-) rename examples/6lbr/{control-ipk => angstrom}/control (100%) rename examples/6lbr/{control-ipk => angstrom}/postinst (100%) rename examples/6lbr/{control-ipk => angstrom}/postrm (100%) rename examples/6lbr/{control-ipk => angstrom}/prerm (100%) delete mode 100644 examples/6lbr/control-deb/control delete mode 100755 examples/6lbr/control-deb/postinst delete mode 100755 examples/6lbr/control-deb/postrm delete mode 100755 examples/6lbr/control-deb/prerm create mode 100644 examples/6lbr/debian/changelog create mode 100644 examples/6lbr/debian/compat create mode 100644 examples/6lbr/debian/control create mode 100644 examples/6lbr/debian/copyright create mode 100644 examples/6lbr/debian/docs create mode 100755 examples/6lbr/debian/rules create mode 100644 examples/6lbr/debian/source/format diff --git a/examples/6lbr/Makefile b/examples/6lbr/Makefile index ac685517a1..34bbcdcb1b 100644 --- a/examples/6lbr/Makefile +++ b/examples/6lbr/Makefile @@ -366,19 +366,6 @@ ifneq ($(PLUGINS_FILES),) install $(PLUGINS_FILES) /usr/lib/6lbr/plugins endif install tools/nvm_tool /usr/lib/6lbr/bin - update-rc.d 6lbr defaults - -rpi_deb: - rm -rf $(DEB) - cp -R package $(DEB) - cp -R control-deb $(DEB)/DEBIAN - mkdir -p $(DEB)/usr/lib/6lbr/bin - cp bin/* $(DEB)/usr/lib/6lbr/bin -ifneq ($(PLUGINS_FILES),) - cp $(PLUGINS_FILES) $(DEB)/usr/lib/6lbr/plugins -endif - cp tools/nvm_tool $(DEB)/usr/lib/6lbr/bin - dpkg --build $(DEB) . ipk: rm -rf $(IPK) @@ -391,7 +378,7 @@ ifneq ($(PLUGINS_FILES),) endif cp tools/nvm_tool $(IPK)/usr/lib/6lbr/bin cd $(IPK) && tar zcvf ../$(IPK)/data.tar.gz --exclude='*~' * - cd control-ipk && tar zcvfh ../$(IPK)/control.tar.gz --exclude='*~' * + cd angstrom && tar zcvfh ../$(IPK)/control.tar.gz --exclude='*~' * echo 2.0 > $(IPK)/debian-binary cd $(IPK) && ar rc ../cetic-6lbr_$(VERSION)-$(PKG_VERSION)_armv7a.ipk debian-binary data.tar.gz control.tar.gz diff --git a/examples/6lbr/control-ipk/control b/examples/6lbr/angstrom/control similarity index 100% rename from examples/6lbr/control-ipk/control rename to examples/6lbr/angstrom/control diff --git a/examples/6lbr/control-ipk/postinst b/examples/6lbr/angstrom/postinst similarity index 100% rename from examples/6lbr/control-ipk/postinst rename to examples/6lbr/angstrom/postinst diff --git a/examples/6lbr/control-ipk/postrm b/examples/6lbr/angstrom/postrm similarity index 100% rename from examples/6lbr/control-ipk/postrm rename to examples/6lbr/angstrom/postrm diff --git a/examples/6lbr/control-ipk/prerm b/examples/6lbr/angstrom/prerm similarity index 100% rename from examples/6lbr/control-ipk/prerm rename to examples/6lbr/angstrom/prerm diff --git a/examples/6lbr/control-deb/control b/examples/6lbr/control-deb/control deleted file mode 100644 index 412662e2f2..0000000000 --- a/examples/6lbr/control-deb/control +++ /dev/null @@ -1,8 +0,0 @@ -Package: cetic-6lbr -Version: 1.3.2 -Architecture: armhf -Maintainer: CETIC <6lbr@cetic.be> -Section: network -Priority: optional -Installed-Size: 350000 -Description: CETIC 6LoWPAN Border Router diff --git a/examples/6lbr/control-deb/postinst b/examples/6lbr/control-deb/postinst deleted file mode 100755 index 56fa25ad0a..0000000000 --- a/examples/6lbr/control-deb/postinst +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -set -e - -action="$1" - -if [ "$action" != configure ]; then - exit 0 -fi - -if [ -x "/etc/init.d/6lbr" ]; then - update-rc.d 6lbr defaults >/dev/null -fi diff --git a/examples/6lbr/control-deb/postrm b/examples/6lbr/control-deb/postrm deleted file mode 100755 index 6ebae0a984..0000000000 --- a/examples/6lbr/control-deb/postrm +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -e - -if [ "$1" = "purge" ] ; then - update-rc.d 6lbr remove >/dev/null -fi diff --git a/examples/6lbr/control-deb/prerm b/examples/6lbr/control-deb/prerm deleted file mode 100755 index d87f204332..0000000000 --- a/examples/6lbr/control-deb/prerm +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -e - -if [ -x "/etc/init.d/6lbr" ]; then - invoke-rc.d 6lbr stop || exit $? -fi - - diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog new file mode 100644 index 0000000000..bf5801d292 --- /dev/null +++ b/examples/6lbr/debian/changelog @@ -0,0 +1,5 @@ +cetic-6lbr (1.3.3) unstable; urgency=low + + * Initial Release. + + -- 6LBR Team <6lbr@cetic.be> Wed, 25 Mar 2015 13:27:37 +0000 diff --git a/examples/6lbr/debian/compat b/examples/6lbr/debian/compat new file mode 100644 index 0000000000..45a4fb75db --- /dev/null +++ b/examples/6lbr/debian/compat @@ -0,0 +1 @@ +8 diff --git a/examples/6lbr/debian/control b/examples/6lbr/debian/control new file mode 100644 index 0000000000..bd2d26ce31 --- /dev/null +++ b/examples/6lbr/debian/control @@ -0,0 +1,13 @@ +Source: cetic-6lbr +Section: network +Priority: extra +Maintainer: 6LBR Team <6lbr@cetic.be> +Build-Depends: debhelper (>= 8.0.0) +Standards-Version: 3.9.3 +Homepage: https://github.com/cetic/6lbr + +Package: cetic-6lbr +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: CETIC 6LoWPAN Border Router + CETIC 6LBR is an enhanced version of Contiki's 6LoWPAN Border Router solution. rIit provides network configuration and monitoring and support out of the box redundant and distributed operating modes. diff --git a/examples/6lbr/debian/copyright b/examples/6lbr/debian/copyright new file mode 100644 index 0000000000..53556d41fb --- /dev/null +++ b/examples/6lbr/debian/copyright @@ -0,0 +1,39 @@ +License: BSD-3-clause +CETIC-6LBR is licensed under the 3-clause BSD license. This license gives +everyone the right to use and distribute the code, either in binary or +source code format, as long as the copyright license is retained in +the source code. + +The copyright for different parts of the code is held by different +people and organizations, but the code is licensed under the same type +of license. The license text is: + + * Copyright (c) (Year), (Name of copyright holder) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/examples/6lbr/debian/docs b/examples/6lbr/debian/docs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/6lbr/debian/rules b/examples/6lbr/debian/rules new file mode 100755 index 0000000000..4456cf852c --- /dev/null +++ b/examples/6lbr/debian/rules @@ -0,0 +1,21 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +export DH_VERBOSE=1 + +%: + dh $@ + +override_dh_auto_build: + make all_native + make plugins + make tools + +override_dh_installinit: + dh_installinit --onlyscripts --name 6lbr diff --git a/examples/6lbr/debian/source/format b/examples/6lbr/debian/source/format new file mode 100644 index 0000000000..89ae9db8f8 --- /dev/null +++ b/examples/6lbr/debian/source/format @@ -0,0 +1 @@ +3.0 (native) From a30daa53c5eeec30adacff32f41899b4ad49f703 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 25 Mar 2015 13:48:01 +0100 Subject: [PATCH 08/35] Check node existence first in add route notification in node-info --- examples/6lbr/apps/node-info/node-info.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/apps/node-info/node-info.c b/examples/6lbr/apps/node-info/node-info.c index a2e5faea9f..d81c0cc7d4 100644 --- a/examples/6lbr/apps/node-info/node-info.c +++ b/examples/6lbr/apps/node-info/node-info.c @@ -50,8 +50,13 @@ node_info_route_notification_cb(int event, { if(event == UIP_DS6_NOTIFICATION_ROUTE_ADD) { node_info_t *node = NULL; - node = node_info_add(route); - node->last_seen = clock_time(); + node = node_info_lookup(route); + if(node == NULL) { + node = node_info_add(route); + } + if(node != NULL) { + node->last_seen = clock_time(); + } } else if(event == UIP_DS6_NOTIFICATION_ROUTE_RM) { node_info_rm(route); } From 81cbab73de6fde9dbcd20289de26e7764f6d2e57 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 1 Apr 2015 14:34:42 +0200 Subject: [PATCH 09/35] Allow more baudrates for slip-radio interface --- examples/6lbr/platform/native/slip-config.c | 156 ++++++++++++++++---- 1 file changed, 130 insertions(+), 26 deletions(-) diff --git a/examples/6lbr/platform/native/slip-config.c b/examples/6lbr/platform/native/slip-config.c index 53ad64b1d9..13876ca328 100644 --- a/examples/6lbr/platform/native/slip-config.c +++ b/examples/6lbr/platform/native/slip-config.c @@ -69,6 +69,45 @@ char const *slip_config_plugins = NULL; char const *ip_config_file_name = NULL; char const * node_config_file_name = NULL; +#if __APPLE__ +#ifndef B460800 +#define B460800 460800 +#endif +#ifndef B500000 +#define B500000 500000 +#endif +#ifndef B576000 +#define B576000 576000 +#endif +#ifndef B921600 +#define B921600 921600 +#endif +#ifndef B1000000 +#define B1000000 1000000 +#endif +#ifndef B1152000 +#define B1152000 1152000 +#endif +#ifndef B1500000 +#define B1500000 1500000 +#endif +#ifndef B2000000 +#define B2000000 2000000 +#endif +#ifndef B2500000 +#define B2500000 2500000 +#endif +#ifndef B3000000 +#define B3000000 3000000 +#endif +#ifndef B3500000 +#define B3500000 3500000 +#endif +#ifndef B4000000 +#define B4000000 4000000 +#endif +#endif + #ifndef BAUDRATE #define BAUDRATE B115200 #endif @@ -196,13 +235,8 @@ slip_config_handle_arguments(int argc, char **argv) fprintf(stderr, "usage: %s [options] ipaddress\n", prog); fprintf(stderr, "example: %s -L -v2 -s ttyUSB1\n", prog); fprintf(stderr, "Options are:\n"); -#ifdef linux - fprintf(stderr, - " -B baudrate 9600,19200,38400,57600,115200,921600 (default 115200)\n"); -#else fprintf(stderr, - " -B baudrate 9600,19200,38400,57600,115200 (default 115200)\n"); -#endif + " -B baudrate Slip-radio baudrate (default 115200)\n"); fprintf(stderr, " -H Hardware CTS/RTS flow control (default disabled)\n"); fprintf(stderr, @@ -242,26 +276,96 @@ slip_config_handle_arguments(int argc, char **argv) switch (baudrate) { case -2: break; /* Use default. */ - case 9600: - slip_config_b_rate = B9600; - break; - case 19200: - slip_config_b_rate = B19200; - break; - case 38400: - slip_config_b_rate = B38400; - break; - case 57600: - slip_config_b_rate = B57600; - break; - case 115200: - slip_config_b_rate = B115200; - break; -#ifdef linux - case 921600: - slip_config_b_rate = B921600; - break; -#endif + #ifdef B50 + case 50: slip_config_b_rate = B50; break; + #endif + #ifdef B75 + case 75: slip_config_b_rate = B75; break; + #endif + #ifdef B110 + case 110: slip_config_b_rate = B110; break; + #endif + #ifdef B134 + case 134: slip_config_b_rate = B134; break; + #endif + #ifdef B150 + case 150: slip_config_b_rate = B150; break; + #endif + #ifdef B200 + case 200: slip_config_b_rate = B200; break; + #endif + #ifdef B300 + case 300: slip_config_b_rate = B300; break; + #endif + #ifdef B600 + case 600: slip_config_b_rate = B600; break; + #endif + #ifdef B1200 + case 1200: slip_config_b_rate = B1200; break; + #endif + #ifdef B1800 + case 1800: slip_config_b_rate = B1800; break; + #endif + #ifdef B2400 + case 2400: slip_config_b_rate = B2400; break; + #endif + #ifdef B4800 + case 4800: slip_config_b_rate = B4800; break; + #endif + #ifdef B9600 + case 9600: slip_config_b_rate = B9600; break; + #endif + #ifdef B19200 + case 19200: slip_config_b_rate = B19200; break; + #endif + #ifdef B38400 + case 38400: slip_config_b_rate = B38400; break; + #endif + #ifdef B57600 + case 57600: slip_config_b_rate = B57600; break; + #endif + #ifdef B115200 + case 115200: slip_config_b_rate = B115200; break; + #endif + #ifdef B230400 + case 230400: slip_config_b_rate = B230400; break; + #endif + #ifdef B460800 + case 460800: slip_config_b_rate = B460800; break; + #endif + #ifdef B500000 + case 500000: slip_config_b_rate = B500000; break; + #endif + #ifdef B576000 + case 576000: slip_config_b_rate = B576000; break; + #endif + #ifdef B921600 + case 921600: slip_config_b_rate = B921600; break; + #endif + #ifdef B1000000 + case 1000000: slip_config_b_rate = B1000000; break; + #endif + #ifdef B1152000 + case 1152000: slip_config_b_rate = B1152000; break; + #endif + #ifdef B1500000 + case 1500000: slip_config_b_rate = B1500000; break; + #endif + #ifdef B2000000 + case 2000000: slip_config_b_rate = B2000000; break; + #endif + #ifdef B2500000 + case 2500000: slip_config_b_rate = B2500000; break; + #endif + #ifdef B3000000 + case 3000000: slip_config_b_rate = B3000000; break; + #endif + #ifdef B3500000 + case 3500000: slip_config_b_rate = B3500000; break; + #endif + #ifdef B4000000 + case 4000000: slip_config_b_rate = B4000000; break; + #endif default: err(1, "unknown baudrate %d", baudrate); break; From 76fa87d1d417630a750efd11e60084877eb6f2c5 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 17 Apr 2015 13:06:19 +0200 Subject: [PATCH 10/35] Force bridge mac address to eth0 mac address in example interface files --- .../6lbr/package/etc/6lbr/interfaces.dhcp.example | 11 ++++------- .../6lbr/package/etc/6lbr/interfaces.static.example | 12 ++++-------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/examples/6lbr/package/etc/6lbr/interfaces.dhcp.example b/examples/6lbr/package/etc/6lbr/interfaces.dhcp.example index 780b3cd2a3..95a5a69e26 100644 --- a/examples/6lbr/package/etc/6lbr/interfaces.dhcp.example +++ b/examples/6lbr/package/etc/6lbr/interfaces.dhcp.example @@ -7,16 +7,13 @@ address 0.0.0.0 auto br0 iface br0 inet dhcp - pre-up brctl addbr br0 - pre-up brctl addif br0 eth0 - pre-up ip addr flush dev eth0 + bridge_ports eth0 + bridge_stp off up echo 0 > /sys/devices/virtual/net/br0/bridge/multicast_snooping - post-down ip link set eth0 down - post-down ip link set br0 down - post-down brctl delif br0 eth0 - post-down brctl delbr br0 + post-up ip link set br0 address `ip link show eth0 | grep ether | awk '{print $2}'` allow-hotplug wlan0 iface wlan0 inet manual wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf + iface default inet dhcp diff --git a/examples/6lbr/package/etc/6lbr/interfaces.static.example b/examples/6lbr/package/etc/6lbr/interfaces.static.example index 2d68bd935c..647805a06c 100644 --- a/examples/6lbr/package/etc/6lbr/interfaces.static.example +++ b/examples/6lbr/package/etc/6lbr/interfaces.static.example @@ -7,22 +7,18 @@ address 0.0.0.0 auto br0 iface br0 inet static - pre-up brctl addbr br0 - pre-up brctl addif br0 eth0 - pre-up ip addr flush dev eth0 + bridge_ports eth0 + bridge_stp off up echo 0 > /sys/devices/virtual/net/br0/bridge/multicast_snooping - post-down ip link set eth0 down - post-down ip link set br0 down - post-down brctl delif br0 eth0 - post-down brctl delbr br0 + post-up ip link set br0 address `ip link show eth0 | grep ether | awk '{print $2}'` address 192.168.2.100 netmask 255.255.255.0 network 192.168.2.0 broadcast 192.168.2.255 gateway 192.168.2.254 - allow-hotplug wlan0 iface wlan0 inet manual wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf + iface default inet dhcp From d7be65234fb505e3ecb3681802c75a4daead5e31 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 17 Apr 2015 16:19:52 +0200 Subject: [PATCH 11/35] Fix webserver formatting --- examples/6lbr/apps/webserver/webserver.c | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/6lbr/apps/webserver/webserver.c b/examples/6lbr/apps/webserver/webserver.c index 9d514483f5..623008b431 100644 --- a/examples/6lbr/apps/webserver/webserver.c +++ b/examples/6lbr/apps/webserver/webserver.c @@ -487,7 +487,7 @@ PT_THREAD(generate_index(struct httpd_state *s)) #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; - add("
This page sent %u times", ++numtimes); + add("
This page sent %u times", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME @@ -537,14 +537,14 @@ PT_THREAD(generate_sensors(struct httpd_state *s)) if ( node_config_loaded ) { add("%s (", node_config_get_name(node_config_find_from_ip(&node_info_table[i].ipaddr))); ipaddr_add(&node_info_table[i].ipaddr); - add(")"); + add(")"); } else { ipaddr_add(&node_info_table[i].ipaddr); - add(""); + add(""); } #else ipaddr_add(&node_info_table[i].ipaddr); - add(""); + add(""); #endif if(0) { @@ -597,12 +597,12 @@ PT_THREAD(generate_sensors(struct httpd_state *s)) } SEND_STRING(&s->sout, buf); reset_buf(); - add("web"); - add("web"); + add("coap"); + add("]:5683\">coap"); if(node_info_table[i].messages_count > 0) { add("%d", node_info_table[i].sequence); #if CETIC_NODE_CONFIG @@ -633,7 +633,7 @@ PT_THREAD(generate_sensors(struct httpd_state *s)) add ("
" - "
"); + add("}\" alt=\"\" />"); SEND_STRING(&s->sout, buf); reset_buf(); @@ -695,7 +695,7 @@ PT_THREAD(generate_sensors(struct httpd_state *s)) #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; - add("
This page sent %u times", ++numtimes); + add("
This page sent %u times", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME @@ -820,7 +820,7 @@ PT_THREAD(generate_rpl(struct httpd_state *s)) #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; - add("
This page sent %u times", ++numtimes); + add("
This page sent %u times", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME @@ -1030,7 +1030,7 @@ PT_THREAD(generate_network(struct httpd_state *s)) #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; - add("
This page sent %u times", ++numtimes); + add("
This page sent %u times", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME @@ -1210,7 +1210,7 @@ PT_THREAD(generate_config(struct httpd_state *s)) #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; - add("
This page sent %u times", ++numtimes); + add("
This page sent %u times", ++numtimes); #endif #if WEBSERVER_CONF_LOADTIME From f41cc9222bcaf1248010675b56377897201d50b2 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 29 Apr 2015 22:04:46 +0200 Subject: [PATCH 12/35] Add support for non constant Ethernet padding --- examples/6lbr/6lbr/packet-filter.c | 17 +++++++++++++++++ examples/6lbr/platform/native/raw-tap-dev.c | 7 +------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/6lbr/6lbr/packet-filter.c b/examples/6lbr/6lbr/packet-filter.c index 15386a02c8..310a9410de 100644 --- a/examples/6lbr/6lbr/packet-filter.c +++ b/examples/6lbr/6lbr/packet-filter.c @@ -51,6 +51,9 @@ #include "nvm-config.h" #include "platform-init.h" #include "log-6lbr.h" +#if CONTIKI_TARGET_NATIVE +#include "slip-config.h" +#endif #include "eth-drv.h" @@ -233,6 +236,20 @@ eth_input(void) uip_len = 0; return; } + if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40 < uip_len) { +#if CONTIKI_TARGET_NATIVE + if(ethernet_has_fcs) { + uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40; + } else +#endif + { + LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: packet size different than reported in IPv6 header, %d vs %d\n", uip_len, (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40); + } + } else if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40 > uip_len) { + LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: packet shorter than reported in IPv6 header, %d vs %d\n", uip_len, (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40); + uip_len = 0; + return; + } //Packet source Filtering //----------------------- /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ diff --git a/examples/6lbr/platform/native/raw-tap-dev.c b/examples/6lbr/platform/native/raw-tap-dev.c index f15d6023c4..cf9eb050f8 100644 --- a/examples/6lbr/platform/native/raw-tap-dev.c +++ b/examples/6lbr/platform/native/raw-tap-dev.c @@ -407,12 +407,7 @@ handle_fd(fd_set * rset, fd_set * wset) if(FD_ISSET(tunfd, rset)) { size = tun_input(tmp_tap_buf, sizeof(tmp_tap_buf)); - if(ethernet_has_fcs) { - //Remove extra data from packet capture - uip_len = size - ETHERNET_LLH_LEN - 4; - } else { - uip_len = size - ETHERNET_LLH_LEN; - } + uip_len = size - ETHERNET_LLH_LEN; memcpy(ll_header, tmp_tap_buf, ETHERNET_LLH_LEN); memcpy(uip_buf, tmp_tap_buf + ETHERNET_LLH_LEN, uip_len); eth_drv_input(); From ebf770743e815f4be8f825cc47e0cc84fe5c0aef Mon Sep 17 00:00:00 2001 From: Ioannis Glaropoulos Date: Mon, 9 Mar 2015 19:41:25 +0100 Subject: [PATCH 13/35] Send the first NS attempt inside tcpip_ipv6_output() --- core/net/ip/tcpip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index f2ac16a978..2e6661d640 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -734,7 +734,11 @@ tcpip_ipv6_output(void) stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; + /* Send the first NS try from here (multicast destination IP address). */ } +#else /* UIP_ND6_SEND_NA */ + uip_len = 0; + return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA @@ -783,7 +787,6 @@ tcpip_ipv6_output(void) uip_ext_len = 0; return; } - return; } /* Multicast IP destination address. */ tcpip_output(NULL); From 7d591c3724faf988c00f0045b059bb02007ca81d Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Tue, 5 May 2015 09:15:01 +0000 Subject: [PATCH 14/35] Add DESTDIR to install target and fix 6lbr startup script --- examples/6lbr/Makefile | 25 +++++++++++++------------ examples/6lbr/package/etc/init.d/6lbr | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/examples/6lbr/Makefile b/examples/6lbr/Makefile index 34bbcdcb1b..03017151b8 100644 --- a/examples/6lbr/Makefile +++ b/examples/6lbr/Makefile @@ -350,22 +350,23 @@ VERSION=$(shell echo $(word 3,$(shell awk '/CETIC_6LBR_VERSION/' project-conf.h) DEB=6lbr-$(VERSION)-$(PKG_VERSION)-deb IPK=6lbr-$(VERSION)-$(PKG_VERSION)-ipk +DESTDIR= install: - install -d /etc/6lbr - cp -r package/etc/6lbr /etc - install -d /etc/init.d - install package/etc/init.d/* /etc/init.d - install -d /usr/bin - install package/usr/bin/* /usr/bin - install -d /usr/lib/6lbr - cp -r package/usr/lib/6lbr /usr/lib - install -d /usr/lib/6lbr/bin - install bin/* /usr/lib/6lbr/bin + install -d $(DESTDIR)/etc/6lbr + cp -r package/etc/6lbr $(DESTDIR)/etc + install -d $(DESTDIR)/etc/init.d + install package/etc/init.d/* $(DESTDIR)/etc/init.d + install -d $(DESTDIR)/usr/bin + install package/usr/bin/* $(DESTDIR)/usr/bin + install -d $(DESTDIR)/usr/lib/6lbr + cp -r package/usr/lib/6lbr $(DESTDIR)/usr/lib + install -d $(DESTDIR)/usr/lib/6lbr/bin + install bin/* $(DESTDIR)/usr/lib/6lbr/bin ifneq ($(PLUGINS_FILES),) - install $(PLUGINS_FILES) /usr/lib/6lbr/plugins + install $(PLUGINS_FILES) $(DESTDIR)/usr/lib/6lbr/plugins endif - install tools/nvm_tool /usr/lib/6lbr/bin + install tools/nvm_tool $(DESTDIR)/usr/lib/6lbr/bin ipk: rm -rf $(IPK) diff --git a/examples/6lbr/package/etc/init.d/6lbr b/examples/6lbr/package/etc/init.d/6lbr index 14afd90088..7ef0eff121 100755 --- a/examples/6lbr/package/etc/init.d/6lbr +++ b/examples/6lbr/package/etc/init.d/6lbr @@ -3,7 +3,7 @@ ### BEGIN INIT INFO # Provides: 6lbr # Required-Start: $network $remote_fs -# Required-Stop: +# Required-Stop: $network $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: 6LoWPAN Border Router From 28377c1dfc8f04e0f523a2f632271b54f898c5d8 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 6 May 2015 06:59:07 +0000 Subject: [PATCH 15/35] Add usb scanning workaround for BB --- examples/6lbr/package/usr/lib/6lbr/6lbr | 2 ++ examples/6lbr/package/usr/lib/6lbr/bb-scan-usb.sh | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100755 examples/6lbr/package/usr/lib/6lbr/bb-scan-usb.sh diff --git a/examples/6lbr/package/usr/lib/6lbr/6lbr b/examples/6lbr/package/usr/lib/6lbr/6lbr index 1ba1c02c09..9c2e121ac0 100755 --- a/examples/6lbr/package/usr/lib/6lbr/6lbr +++ b/examples/6lbr/package/usr/lib/6lbr/6lbr @@ -176,9 +176,11 @@ fi while ((1)); do if [ "$MODE" != 'RPL-ROOT' -a "$SOCK_RADIO" = "" ]; then + $SCAN_DEVICE while [ ! -e "$DEV_RADIO" ]; do echo "Waiting for $DEV_RADIO" sleep 10 + $SCAN_DEVICE done fi TIMESTAMP=`date`" : Starting 6LBR " diff --git a/examples/6lbr/package/usr/lib/6lbr/bb-scan-usb.sh b/examples/6lbr/package/usr/lib/6lbr/bb-scan-usb.sh new file mode 100755 index 0000000000..2bdfed0d4f --- /dev/null +++ b/examples/6lbr/package/usr/lib/6lbr/bb-scan-usb.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +echo "Reset and scan USB devices..." + +#Rebind USB controller +echo "usb1" > /sys/bus/usb/drivers/usb/unbind +sleep 1 +echo "usb1" > /sys/bus/usb/drivers/usb/bind +sleep 1 + +#Disable auto-suspend +echo "on" > /sys/bus/usb/devices/usb1/power/control + +#Force USB controller scan +cat /dev/bus/usb/001/001 > /dev/null From 6ca958aba2e7fbefe6f17df8b6724af1ff1e1562 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 6 May 2015 09:12:42 +0200 Subject: [PATCH 16/35] Update documentation --- examples/6lbr/package/etc/6lbr/6lbr.conf.example | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/6lbr/package/etc/6lbr/6lbr.conf.example b/examples/6lbr/package/etc/6lbr/6lbr.conf.example index bca61f701d..5548b54751 100644 --- a/examples/6lbr/package/etc/6lbr/6lbr.conf.example +++ b/examples/6lbr/package/etc/6lbr/6lbr.conf.example @@ -51,6 +51,11 @@ #ETH_JOIN_BRIDGE=1 +#Multicast snooping is broken in several versions of the Linux kernel, it drops +#multicast traffic after a while. + +#BRIDGE_DISABLE_SNOOPING=1 + ################################################################################ #SLIP Radio configuration # These parameters define the SLIP Radio device and the Baudrate to be used to From ac97c549fa0f85a50d823e29904579bf352dd7e7 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 6 May 2015 09:13:06 +0200 Subject: [PATCH 17/35] Add protection on MacOS-X --- examples/6lbr/package/etc/6lbr/ifup.d/20link | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/6lbr/package/etc/6lbr/ifup.d/20link b/examples/6lbr/package/etc/6lbr/ifup.d/20link index cdebed241a..37eac62c2b 100755 --- a/examples/6lbr/package/etc/6lbr/ifup.d/20link +++ b/examples/6lbr/package/etc/6lbr/ifup.d/20link @@ -32,9 +32,11 @@ case $OS in ifconfig $DEV link $DEV_TAP_MAC fi - #On MacOS 10.6, IPv6 stack is not always correctly started on tap device - ip6 -d $DEV - ip6 -u $DEV + if [ -x /usr/sbin/ip6 ]; then + #On MacOS 10.6, IPv6 stack is not always correctly started on tap device + ip6 -d $DEV + ip6 -u $DEV + fi ifconfig $DEV inet6 up ;; From f034d3cbfd08dbbf5aeccfb474b263fb1bea07fd Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 6 May 2015 10:22:07 +0200 Subject: [PATCH 18/35] Add forward compatibility in node-info --- examples/6lbr/apps/node-info/node-info.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/6lbr/apps/node-info/node-info.c b/examples/6lbr/apps/node-info/node-info.c index d81c0cc7d4..e0a6fd58f4 100644 --- a/examples/6lbr/apps/node-info/node-info.c +++ b/examples/6lbr/apps/node-info/node-info.c @@ -107,6 +107,10 @@ node_info_update(uip_ipaddr_t * ipaddr, char * info) if (*info == ' ') { info++; } + sep = index(info, '|'); + if (sep != NULL) { + *sep = 0; + } if (uiplib_ipaddrconv(info, &node->ip_parent) == 0) { uip_create_unspecified(&node->ip_parent); } From 0102f69ead0c3520fc46f86d7525f16e2bde5af6 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 24 Apr 2015 10:41:19 +0200 Subject: [PATCH 19/35] Check mac address message size --- examples/6lbr/platform/native/slip-cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/6lbr/platform/native/slip-cmds.c b/examples/6lbr/platform/native/slip-cmds.c index 47fbb86f58..cfa23fb6cd 100644 --- a/examples/6lbr/platform/native/slip-cmds.c +++ b/examples/6lbr/platform/native/slip-cmds.c @@ -66,7 +66,7 @@ border_router_cmd_handler(const uint8_t * data, int len) if(data[0] == '!') { LOG6LBR_TRACE("Got configuration message of type %c\n", data[1]); if(0) { - } else if(data[1] == 'M' && command_context == CMD_CONTEXT_RADIO) { + } else if(data[1] == 'M' && command_context == CMD_CONTEXT_RADIO && len == 10) { LOG6LBR_DEBUG("Setting MAC address\n"); slip_got_mac(&data[2]); return 1; From 49aa5153f5fa27e19aec7c7623374d898815587c Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 7 May 2015 13:54:00 +0200 Subject: [PATCH 20/35] Split up install target --- examples/6lbr/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/6lbr/Makefile b/examples/6lbr/Makefile index 03017151b8..37b4a8dba7 100644 --- a/examples/6lbr/Makefile +++ b/examples/6lbr/Makefile @@ -363,10 +363,12 @@ install: cp -r package/usr/lib/6lbr $(DESTDIR)/usr/lib install -d $(DESTDIR)/usr/lib/6lbr/bin install bin/* $(DESTDIR)/usr/lib/6lbr/bin + install tools/nvm_tool $(DESTDIR)/usr/lib/6lbr/bin + +install_plugins: ifneq ($(PLUGINS_FILES),) install $(PLUGINS_FILES) $(DESTDIR)/usr/lib/6lbr/plugins endif - install tools/nvm_tool $(DESTDIR)/usr/lib/6lbr/bin ipk: rm -rf $(IPK) From 574eaffa77d8689f10caa6b3f620b41585891fbe Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 7 May 2015 14:01:38 +0200 Subject: [PATCH 21/35] Add documentation on SCAN_DEVICE --- examples/6lbr/package/etc/6lbr/6lbr.conf.beaglebone | 3 +++ examples/6lbr/package/etc/6lbr/6lbr.conf.example | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/examples/6lbr/package/etc/6lbr/6lbr.conf.beaglebone b/examples/6lbr/package/etc/6lbr/6lbr.conf.beaglebone index 921e75621c..5e09a0cc1e 100644 --- a/examples/6lbr/package/etc/6lbr/6lbr.conf.beaglebone +++ b/examples/6lbr/package/etc/6lbr/6lbr.conf.beaglebone @@ -20,4 +20,7 @@ RAW_ETH_FCS=1 DEV_RADIO=/dev/ttyUSB0 BAUDRATE=115200 +#Enable this line if radio device is not detected +#SCAN_DEVICE=/usr/lib/6lbr/bb-scan-usb.sh + LOG_LEVEL=3 #INFO and above only diff --git a/examples/6lbr/package/etc/6lbr/6lbr.conf.example b/examples/6lbr/package/etc/6lbr/6lbr.conf.example index 5548b54751..db5695fdea 100644 --- a/examples/6lbr/package/etc/6lbr/6lbr.conf.example +++ b/examples/6lbr/package/etc/6lbr/6lbr.conf.example @@ -71,6 +71,13 @@ #SLIP Radio baudrate #BAUDRATE=115200 +#Scan operation to be performed before checking the radio availability +#SCAN_DEVICE= + +#On BeagleBone, the USB Host does not always scan and detect properly the slip +#radio. +#SCAN_DEVICE=/usr/lib/6lbr/bb-scan-usb.sh + ################################################################################ #NVM File # The NVM file contains the user configuration, like the network prefixes, the From b13c95d783b060728bb297b84963fe31b9a15802 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 7 May 2015 14:02:23 +0200 Subject: [PATCH 22/35] Add interfaces example file for debian Beaglebone --- .../etc/6lbr/interfaces.beaglebone.example | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 examples/6lbr/package/etc/6lbr/interfaces.beaglebone.example diff --git a/examples/6lbr/package/etc/6lbr/interfaces.beaglebone.example b/examples/6lbr/package/etc/6lbr/interfaces.beaglebone.example new file mode 100644 index 0000000000..8a407b81f2 --- /dev/null +++ b/examples/6lbr/package/etc/6lbr/interfaces.beaglebone.example @@ -0,0 +1,41 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +auto lo +iface lo inet loopback + +# The primary network interface +#auto eth0 +#iface eth0 inet dhcp +# Example to keep MAC address between reboots +#hwaddress ether DE:AD:BE:EF:CA:FE + +# The secondary network interface +#auto eth1 +#iface eth1 inet dhcp + +iface eth0 inet static +address 0.0.0.0 + +auto br0 +iface br0 inet dhcp + bridge_ports eth0 + bridge_stp off + up echo 0 > /sys/devices/virtual/net/br0/bridge/multicast_snooping + post-up ip link set br0 address `ip link show eth0 | grep ether | awk '{print $2}'` + +# WiFi Example +#auto wlan0 +#iface wlan0 inet dhcp +# wpa-ssid "essid" +# wpa-psk "password" + +# Ethernet/RNDIS gadget (g_ether) +# ... or on host side, usbnet and random hwaddr +# Note on some boards, usb0 is automaticly setup with an init script +iface usb0 inet static + address 192.168.7.2 + netmask 255.255.255.0 + network 192.168.7.0 + gateway 192.168.7.1 From 68bc940db921532ba4392fa291b2ffb1811fe833 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Wed, 6 May 2015 13:17:42 +0200 Subject: [PATCH 23/35] Bump version to 1.3.3 --- examples/6lbr/angstrom/control | 2 +- examples/6lbr/project-conf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/angstrom/control b/examples/6lbr/angstrom/control index 6284f9791f..f558747c89 100644 --- a/examples/6lbr/angstrom/control +++ b/examples/6lbr/angstrom/control @@ -1,5 +1,5 @@ Package: cetic-6lbr -Version: 1.3.2 +Version: 1.3.3 Architecture: armv7a Maintainer: CETIC <6lbr@cetic.be> Section: network diff --git a/examples/6lbr/project-conf.h b/examples/6lbr/project-conf.h index d77ea29dcc..b962d48023 100644 --- a/examples/6lbr/project-conf.h +++ b/examples/6lbr/project-conf.h @@ -405,7 +405,7 @@ /*------------------------------------------------------------------*/ /* Do not change lines below */ -#define CETIC_6LBR_VERSION "1.3.2" +#define CETIC_6LBR_VERSION "1.3.3" #define CETIC_6LBR_ETH_EXT_A 0xFF #define CETIC_6LBR_ETH_EXT_B 0xFF From 3715b49b1121c0770f4a064753680cf315977ae9 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 8 May 2015 16:38:15 +0200 Subject: [PATCH 24/35] Update 1.3.3 changelog --- examples/6lbr/debian/changelog | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog index bf5801d292..d839acc0d9 100644 --- a/examples/6lbr/debian/changelog +++ b/examples/6lbr/debian/changelog @@ -1,5 +1,19 @@ cetic-6lbr (1.3.3) unstable; urgency=low - * Initial Release. + * 6LoWPAN/RPL + Multi DODAG bugfixes + Support DAG parameter updates + Do not drop partially received segmented packets + * Slip-Radio + Better Z1 and CC2538 support + Check message format + Add more baud rates + * Network + Fix multicast snooping on bridge interface + Fix bridge hw address + Fix tap interface down issue + * BeagleBone + Add Debian support + Add USB scanning issue workaround - -- 6LBR Team <6lbr@cetic.be> Wed, 25 Mar 2015 13:27:37 +0000 + -- 6lbr-team <6lbr@cetic.be> Fri, 08 May 2015 12:23:54 +0000 From 4f7a1cd9240da51f93c33ad77a0b288acd35a1f1 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 8 May 2015 16:38:15 +0200 Subject: [PATCH 25/35] Update 1.4.0 changelog --- apps/tinydtls | 2 +- examples/6lbr/debian/changelog | 75 +++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/apps/tinydtls b/apps/tinydtls index 6c4757caea..a6fa96c9f6 160000 --- a/apps/tinydtls +++ b/apps/tinydtls @@ -1 +1 @@ -Subproject commit 6c4757caea14bedc4e398ea1a774040f2c351bc4 +Subproject commit a6fa96c9f6cf242660574f32794709ef39367770 diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog index bf5801d292..6da08882fa 100644 --- a/examples/6lbr/debian/changelog +++ b/examples/6lbr/debian/changelog @@ -1,5 +1,76 @@ +cetic-6lbr (1.4.O) unstable; urgency=low + + * Features + Link layer Security + NAT 64 / Dual stack + RDNSS + DNS Forwarder + mDNS advertising + Static port mapping + Node Info (PRR, Hop Count, Parent Switch, ...) + * Platform + Zolertia Zoul/RE-Mote + OpenMote + CC26xx (experimental) + OpenWRT + * Network + 6lowpan context configuration (limited) + RPL stability bugfixes + Static route support + Tap/bridge interface autoconfiguration + RFC 4193 configuration script + * Updates + Rebased on Contiki 3.0 + TinyDTLS 1.9 + RFC CoAP + * Development + User plugins + Out of tree development + Modular webserver + New configuration file + * 6lbr-demo + Simple Core Interface library + CC26xx support + * Simple Core Interface library ([draft-ietf-core-interfaces](https://tools.ietf.org/html/draft-ietf-core-interfaces-03)) + Observe binding support + CoAP push binding support + Runtime configurable binding + Text, JSON, XML and SenML encoding + Linked list, batch and linked batch support + Simple Resource Directory client + IPSO Application Framework demo + LWM2M demo + * Bugfixes + Slip-Radio throughput improvements + Fix CRC when Adress overriding is enabled + CC2538DK alignment issues solved + Loss of connectivity in SmartBridge mode + Big Endian platform support + Multi-dodag bugfixes + Fix CSMA infinite retransmissions + Various webserver glitches fixed + Wrong month in logs fixed + LLSEC reboot workaround + Global DODAG id correction + + -- 6lbr-team <6lbr@cetic.be> Thu, 12 May 2016 16:32:25 +0200 + cetic-6lbr (1.3.3) unstable; urgency=low - * Initial Release. + * 6LoWPAN/RPL + Multi DODAG bugfixes + Support DAG parameter updates + Do not drop partially received segmented packets + * Slip-Radio + Better Z1 and CC2538 support + Check message format + Add more baud rates + * Network + Fix multicast snooping on bridge interface + Fix bridge hw address + Fix tap interface down issue + * BeagleBone + Add Debian support + Add USB scanning issue workaround - -- 6LBR Team <6lbr@cetic.be> Wed, 25 Mar 2015 13:27:37 +0000 + -- 6lbr-team <6lbr@cetic.be> Fri, 08 May 2015 12:23:54 +0000 From c33493fb84349022aade9ca4a735938cce8bcc2a Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 12 May 2016 16:40:51 +0200 Subject: [PATCH 26/35] Bump version to 1.4.0 --- examples/6lbr/angstrom/control | 2 +- examples/6lbr/project-conf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/angstrom/control b/examples/6lbr/angstrom/control index f558747c89..4a0023c722 100644 --- a/examples/6lbr/angstrom/control +++ b/examples/6lbr/angstrom/control @@ -1,5 +1,5 @@ Package: cetic-6lbr -Version: 1.3.3 +Version: 1.4.0 Architecture: armv7a Maintainer: CETIC <6lbr@cetic.be> Section: network diff --git a/examples/6lbr/project-conf.h b/examples/6lbr/project-conf.h index 20769dd0fb..0f9cb7b693 100644 --- a/examples/6lbr/project-conf.h +++ b/examples/6lbr/project-conf.h @@ -255,7 +255,7 @@ /*------------------------------------------------------------------*/ /* Do not change lines below */ -#define CETIC_6LBR_VERSION "1.4.x" +#define CETIC_6LBR_VERSION "1.4.0" #define CETIC_6LBR_ETH_EXT_A 0xFF #define CETIC_6LBR_ETH_EXT_B 0xFF From fc76af7480fc4ff82d48446a7623a2d4edad0603 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 13 May 2016 10:46:01 +0200 Subject: [PATCH 27/35] Update package creation rules --- examples/6lbr/debian/control | 7 ++++--- examples/6lbr/debian/rules | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/6lbr/debian/control b/examples/6lbr/debian/control index bd2d26ce31..214bf9d5e2 100644 --- a/examples/6lbr/debian/control +++ b/examples/6lbr/debian/control @@ -1,5 +1,5 @@ Source: cetic-6lbr -Section: network +Section: net Priority: extra Maintainer: 6LBR Team <6lbr@cetic.be> Build-Depends: debhelper (>= 8.0.0) @@ -8,6 +8,7 @@ Homepage: https://github.com/cetic/6lbr Package: cetic-6lbr Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, bridge-utils Description: CETIC 6LoWPAN Border Router - CETIC 6LBR is an enhanced version of Contiki's 6LoWPAN Border Router solution. rIit provides network configuration and monitoring and support out of the box redundant and distributed operating modes. + CETIC 6LBR is an enhanced version of Contiki's 6LoWPAN Border Router solution. + It provides network configuration and monitoring, and supports out of the box redundant and distributed operating modes. diff --git a/examples/6lbr/debian/rules b/examples/6lbr/debian/rules index 4456cf852c..1d476de94f 100755 --- a/examples/6lbr/debian/rules +++ b/examples/6lbr/debian/rules @@ -13,9 +13,13 @@ export DH_VERBOSE=1 dh $@ override_dh_auto_build: - make all_native + make TARGET=native all make plugins make tools +# Add extra installation target for plugins +override_dh_auto_install: + dh_auto_install -- plugins-install + override_dh_installinit: dh_installinit --onlyscripts --name 6lbr From 58c673660f0943869ed48c56d727d095a9ea0c23 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Tue, 17 May 2016 14:33:49 +0200 Subject: [PATCH 28/35] Fix version in debian/changelog --- examples/6lbr/debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog index 6da08882fa..68fd6da7f9 100644 --- a/examples/6lbr/debian/changelog +++ b/examples/6lbr/debian/changelog @@ -1,4 +1,4 @@ -cetic-6lbr (1.4.O) unstable; urgency=low +cetic-6lbr (1.4.0) unstable; urgency=low * Features Link layer Security From d780fe037baab609c23d9091fffac732bc58378d Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 22 Dec 2016 13:18:15 +0100 Subject: [PATCH 29/35] Update changelog --- examples/6lbr/debian/changelog | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog index 68fd6da7f9..7d1af801a8 100644 --- a/examples/6lbr/debian/changelog +++ b/examples/6lbr/debian/changelog @@ -1,3 +1,29 @@ +cetic-6lbr (1.4.1) unstable; urgency=low + + * Features + Node info export + Improved multi-dodag support + Better endianness detection + TinyDTLS stability fixes + Slip-radio configuration + Add Slip-radio retries + Non-root support + Improved plugin build and support + * Platform + CC26xx/CC13xx full support + Cooja support + OpenWRT feed + * Bugfixes + Fix anti-replay flag inversion + Fix max rank increase + Fix loss of address in SmartBridge mode + Fix route deletion after time update + Fix random crashes in udp-server + Fix uip_buf buffer overflow and packet with wrong size + Fix PAN-ID configuration on CC2538/CC26xx/CC13xx + + -- 6lbr-team <6lbr@cetic.be> Thu, 22 Dec 2016 13:15:40 +0100 + cetic-6lbr (1.4.0) unstable; urgency=low * Features From 5fdd8a4d464a68c1ffd8db0af5d2701006a995f2 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 22 Dec 2016 13:20:26 +0100 Subject: [PATCH 30/35] Bump version to 1.4.1 --- examples/6lbr/angstrom/control | 2 +- examples/6lbr/project-conf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/angstrom/control b/examples/6lbr/angstrom/control index 4a0023c722..2dbd8f4dda 100644 --- a/examples/6lbr/angstrom/control +++ b/examples/6lbr/angstrom/control @@ -1,5 +1,5 @@ Package: cetic-6lbr -Version: 1.4.0 +Version: 1.4.1 Architecture: armv7a Maintainer: CETIC <6lbr@cetic.be> Section: network diff --git a/examples/6lbr/project-conf.h b/examples/6lbr/project-conf.h index 56a041d90d..df3ddb8bb9 100644 --- a/examples/6lbr/project-conf.h +++ b/examples/6lbr/project-conf.h @@ -255,7 +255,7 @@ /*------------------------------------------------------------------*/ /* Do not change lines below */ -#define CETIC_6LBR_VERSION "1.4.0" +#define CETIC_6LBR_VERSION "1.4.1" #define CETIC_6LBR_ETH_EXT_A 0xFF #define CETIC_6LBR_ETH_EXT_B 0xFF From b981b83cb4f74b545547f8a984ac4e03a2124cfb Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 24 Nov 2017 09:31:06 +0100 Subject: [PATCH 31/35] Update changelog --- examples/6lbr/debian/changelog | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog index 7d1af801a8..7131b20bc9 100644 --- a/examples/6lbr/debian/changelog +++ b/examples/6lbr/debian/changelog @@ -1,3 +1,27 @@ +cetic-6lbr (1.4.2) unstable; urgency=low + + * Features + Multi SLIP-Radio support + Add CRC for SLIP-Radio + Runtime configuration of NUD + Add Per-Node statistics + Add set PAN ID command in slip radio + Add RPL hooks and delayed RPL initialisation + Replace abbreviations in status pages + New demo framework and demos for the main features of 6LBR + * Bugfixes + 6lbr.ip4 is not updated when using DHCP + SLIP retransmit callback not scheduled + Node tree graph is sometimes corrupted + TCP RST are observed on BBB and RPi + Buffer overflow when saving 6lbr.ip + gettimeofday() is still used in handle_fd() + Loss of access to web server due to wrong source address selection + Global repair is not properly triggered at BR startup + Infinite loop in node config + + -- 6lbr-team <6lbr@cetic.be> Fri, 24 Nov 2017 9:30:10 +0100 + cetic-6lbr (1.4.1) unstable; urgency=low * Features From e865b8c74be46ca9a678733beaf164587c493ec9 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Fri, 24 Nov 2017 09:37:53 +0100 Subject: [PATCH 32/35] Bump version to 1.4.2 --- examples/6lbr/angstrom/control | 2 +- examples/6lbr/project-conf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/angstrom/control b/examples/6lbr/angstrom/control index 2dbd8f4dda..2721ba9c4d 100644 --- a/examples/6lbr/angstrom/control +++ b/examples/6lbr/angstrom/control @@ -1,5 +1,5 @@ Package: cetic-6lbr -Version: 1.4.1 +Version: 1.4.2 Architecture: armv7a Maintainer: CETIC <6lbr@cetic.be> Section: network diff --git a/examples/6lbr/project-conf.h b/examples/6lbr/project-conf.h index 2e840af070..51abd38e2a 100644 --- a/examples/6lbr/project-conf.h +++ b/examples/6lbr/project-conf.h @@ -255,7 +255,7 @@ /*------------------------------------------------------------------*/ /* Do not change lines below */ -#define CETIC_6LBR_VERSION "1.4.1" +#define CETIC_6LBR_VERSION "1.4.2" #define CETIC_6LBR_ETH_EXT_A 0xFF #define CETIC_6LBR_ETH_EXT_B 0xFF From 491a1d8c1f784951bfd460e780daf2e3679fe3b9 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 14 Dec 2017 12:34:17 +0100 Subject: [PATCH 33/35] Update changelog --- examples/6lbr/debian/changelog | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/6lbr/debian/changelog b/examples/6lbr/debian/changelog index 7131b20bc9..bf72ed2347 100644 --- a/examples/6lbr/debian/changelog +++ b/examples/6lbr/debian/changelog @@ -1,3 +1,15 @@ +cetic-6lbr (1.5.0) unstable; urgency=low + + * Features + Multicast routing + RPL Non-Storing mode + DAO-Ack support + AdaptiveSec integration + TSCH SLIP-Radio support + Rebased on latest Contiki (11-Oct-2017) + + -- 6lbr-team <6lbr@cetic.be> Thu, 14 Nov 2017 12:30:10 +0100 + cetic-6lbr (1.4.2) unstable; urgency=low * Features From 7397a1650876298055c30afdc969f7a5ec697711 Mon Sep 17 00:00:00 2001 From: Laurent Deru Date: Thu, 14 Dec 2017 12:37:33 +0100 Subject: [PATCH 34/35] Bump version to 1.5.0 --- examples/6lbr/angstrom/control | 2 +- examples/6lbr/project-conf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/6lbr/angstrom/control b/examples/6lbr/angstrom/control index 2721ba9c4d..4ac64b969f 100644 --- a/examples/6lbr/angstrom/control +++ b/examples/6lbr/angstrom/control @@ -1,5 +1,5 @@ Package: cetic-6lbr -Version: 1.4.2 +Version: 1.5.0 Architecture: armv7a Maintainer: CETIC <6lbr@cetic.be> Section: network diff --git a/examples/6lbr/project-conf.h b/examples/6lbr/project-conf.h index bc3f5cd5c9..50da6c1b62 100644 --- a/examples/6lbr/project-conf.h +++ b/examples/6lbr/project-conf.h @@ -213,7 +213,7 @@ /* Do not change lines below */ /*------------------------------------------------------------------*/ -#define CETIC_6LBR_VERSION "1.4.2" +#define CETIC_6LBR_VERSION "1.5.0" /* Activate CETIC 6LBR specific code in Contiki */ #define CETIC_6LBR 1 From 32fbbab77eb249b6a6cabcd20a1520f0a9d76855 Mon Sep 17 00:00:00 2001 From: aloCetic Date: Wed, 17 Sep 2025 12:27:57 +0200 Subject: [PATCH 35/35] =?UTF-8?q?Cr=C3=A9=C3=A9=20=C3=A0=20l'aide=20de=20C?= =?UTF-8?q?olab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notebooks/video_predictor_example.ipynb | 1156 +++++++++++++++++++++++ 1 file changed, 1156 insertions(+) create mode 100644 notebooks/video_predictor_example.ipynb diff --git a/notebooks/video_predictor_example.ipynb b/notebooks/video_predictor_example.ipynb new file mode 100644 index 0000000000..2a5f74f66e --- /dev/null +++ b/notebooks/video_predictor_example.ipynb @@ -0,0 +1,1156 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "3c3b1c46-9f5c-41c1-9101-85db8709ec0d", + "metadata": { + "id": "3c3b1c46-9f5c-41c1-9101-85db8709ec0d" + }, + "outputs": [], + "source": [ + "# Copyright (c) Meta Platforms, Inc. and affiliates." + ] + }, + { + "cell_type": "markdown", + "id": "6e7a0db5-7f04-4845-8b11-684fe6e9f7f2", + "metadata": { + "id": "6e7a0db5-7f04-4845-8b11-684fe6e9f7f2" + }, + "source": [ + "# Video segmentation with SAM 2" + ] + }, + { + "cell_type": "markdown", + "id": "73ba7875-35e5-478b-b8ba-4b48e121dec7", + "metadata": { + "id": "73ba7875-35e5-478b-b8ba-4b48e121dec7" + }, + "source": [ + "This notebook shows how to use SAM 2 for interactive segmentation in videos. It will cover the following:\n", + "\n", + "- adding clicks (or box) on a frame to get and refine _masklets_ (spatio-temporal masks)\n", + "- propagating clicks (or box) to get _masklets_ throughout the video\n", + "- segmenting and tracking multiple objects at the same time\n", + "\n", + "We use the terms _segment_ or _mask_ to refer to the model prediction for an object on a single frame, and _masklet_ to refer to the spatio-temporal masks across the entire video." + ] + }, + { + "cell_type": "markdown", + "id": "a887b90f-6576-4ef8-964e-76d3a156ccb6", + "metadata": { + "id": "a887b90f-6576-4ef8-964e-76d3a156ccb6" + }, + "source": [ + "\n", + " \"Open\n", + "" + ] + }, + { + "cell_type": "markdown", + "id": "26616201-06df-435b-98fd-ad17c373bb4a", + "metadata": { + "id": "26616201-06df-435b-98fd-ad17c373bb4a" + }, + "source": [ + "## Environment Set-up" + ] + }, + { + "cell_type": "markdown", + "id": "8491a127-4c01-48f5-9dc5-f148a9417fdf", + "metadata": { + "id": "8491a127-4c01-48f5-9dc5-f148a9417fdf" + }, + "source": [ + "If running locally using jupyter, first install `sam2` in your environment using the [installation instructions](https://github.com/facebookresearch/sam2#installation) in the repository.\n", + "\n", + "If running from Google Colab, set `using_colab=True` below and run the cell. In Colab, be sure to select 'GPU' under 'Edit'->'Notebook Settings'->'Hardware accelerator'. Note that it's recommended to use **A100 or L4 GPUs when running in Colab** (T4 GPUs might also work, but could be slow and might run out of memory in some cases)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f74c53be-aab1-46b9-8c0b-068b52ef5948", + "metadata": { + "id": "f74c53be-aab1-46b9-8c0b-068b52ef5948" + }, + "outputs": [], + "source": [ + "using_colab = True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d824a4b2-71f3-4da3-bfc7-3249625e6730", + "metadata": { + "id": "d824a4b2-71f3-4da3-bfc7-3249625e6730", + "outputId": "75533e67-dbc1-4f41-cfcc-8c58b6b2973a", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "PyTorch version: 2.8.0+cu126\n", + "Torchvision version: 0.23.0+cu126\n", + "CUDA is available: False\n", + "Requirement already satisfied: opencv-python in /usr/local/lib/python3.12/dist-packages (4.12.0.88)\n", + "Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/dist-packages (3.10.0)\n", + "Requirement already satisfied: numpy<2.3.0,>=2 in /usr/local/lib/python3.12/dist-packages (from opencv-python) (2.0.2)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.3.3)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (4.59.2)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.4.9)\n", + "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (25.0)\n", + "Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (11.3.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (3.2.3)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (2.9.0.post0)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.7->matplotlib) (1.17.0)\n", + "Collecting git+https://github.com/facebookresearch/sam2.git\n", + " Cloning https://github.com/facebookresearch/sam2.git to /tmp/pip-req-build-jjwg63u9\n", + " Running command git clone --filter=blob:none --quiet https://github.com/facebookresearch/sam2.git /tmp/pip-req-build-jjwg63u9\n", + " Resolved https://github.com/facebookresearch/sam2.git to commit 2b90b9f5ceec907a1c18123530e92e794ad901a4\n" + ] + } + ], + "source": [ + "if using_colab:\n", + " import torch\n", + " import torchvision\n", + " print(\"PyTorch version:\", torch.__version__)\n", + " print(\"Torchvision version:\", torchvision.__version__)\n", + " print(\"CUDA is available:\", torch.cuda.is_available())\n", + " import sys\n", + " !{sys.executable} -m uv pip install opencv-python matplotlib\n", + " !{sys.executable} -m uv pip install 'git+https://github.com/facebookresearch/sam2.git'\n", + "\n", + " !mkdir -p videos\n", + " !wget -P videos https://dl.fbaipublicfiles.com/segment_anything_2/assets/bedroom.zip\n", + " !unzip -d videos videos/bedroom.zip\n", + "\n", + " !mkdir -p ../checkpoints/\n", + " !wget -P ../checkpoints/ https://dl.fbaipublicfiles.com/segment_anything_2/092824/sam2.1_hiera_large.pt" + ] + }, + { + "cell_type": "markdown", + "id": "22e6aa9d-487f-4207-b657-8cff0902343e", + "metadata": { + "id": "22e6aa9d-487f-4207-b657-8cff0902343e" + }, + "source": [ + "## Set-up" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e5318a85-5bf7-4880-b2b3-15e4db24d796", + "metadata": { + "id": "e5318a85-5bf7-4880-b2b3-15e4db24d796" + }, + "outputs": [], + "source": [ + "import os\n", + "# if using Apple MPS, fall back to CPU for unsupported ops\n", + "os.environ[\"PYTORCH_ENABLE_MPS_FALLBACK\"] = \"1\"\n", + "import numpy as np\n", + "import torch\n", + "import matplotlib.pyplot as plt\n", + "from PIL import Image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08ba49d8-8c22-4eba-a2ab-46eee839287f", + "metadata": { + "id": "08ba49d8-8c22-4eba-a2ab-46eee839287f" + }, + "outputs": [], + "source": [ + "# select the device for computation\n", + "if torch.cuda.is_available():\n", + " device = torch.device(\"cuda\")\n", + "elif torch.backends.mps.is_available():\n", + " device = torch.device(\"mps\")\n", + "else:\n", + " device = torch.device(\"cpu\")\n", + "print(f\"using device: {device}\")\n", + "\n", + "if device.type == \"cuda\":\n", + " # use bfloat16 for the entire notebook\n", + " torch.autocast(\"cuda\", dtype=torch.bfloat16).__enter__()\n", + " # turn on tfloat32 for Ampere GPUs (https://pytorch.org/docs/stable/notes/cuda.html#tensorfloat-32-tf32-on-ampere-devices)\n", + " if torch.cuda.get_device_properties(0).major >= 8:\n", + " torch.backends.cuda.matmul.allow_tf32 = True\n", + " torch.backends.cudnn.allow_tf32 = True\n", + "elif device.type == \"mps\":\n", + " print(\n", + " \"\\nSupport for MPS devices is preliminary. SAM 2 is trained with CUDA and might \"\n", + " \"give numerically different outputs and sometimes degraded performance on MPS. \"\n", + " \"See e.g. https://github.com/pytorch/pytorch/issues/84936 for a discussion.\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "ae8e0779-751f-4224-9b04-ed0f0b406500", + "metadata": { + "id": "ae8e0779-751f-4224-9b04-ed0f0b406500" + }, + "source": [ + "### Loading the SAM 2 video predictor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5f3245e-b4d6-418b-a42a-a67e0b3b5aec", + "metadata": { + "id": "f5f3245e-b4d6-418b-a42a-a67e0b3b5aec" + }, + "outputs": [], + "source": [ + "from sam2.build_sam import build_sam2_video_predictor\n", + "\n", + "sam2_checkpoint = \"../checkpoints/sam2.1_hiera_large.pt\"\n", + "model_cfg = \"configs/sam2.1/sam2.1_hiera_l.yaml\"\n", + "\n", + "predictor = build_sam2_video_predictor(model_cfg, sam2_checkpoint, device=device)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a5320fe-06d7-45b8-b888-ae00799d07fa", + "metadata": { + "id": "1a5320fe-06d7-45b8-b888-ae00799d07fa" + }, + "outputs": [], + "source": [ + "def show_mask(mask, ax, obj_id=None, random_color=False):\n", + " if random_color:\n", + " color = np.concatenate([np.random.random(3), np.array([0.6])], axis=0)\n", + " else:\n", + " cmap = plt.get_cmap(\"tab10\")\n", + " cmap_idx = 0 if obj_id is None else obj_id\n", + " color = np.array([*cmap(cmap_idx)[:3], 0.6])\n", + " h, w = mask.shape[-2:]\n", + " mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1)\n", + " ax.imshow(mask_image)\n", + "\n", + "\n", + "def show_points(coords, labels, ax, marker_size=200):\n", + " pos_points = coords[labels==1]\n", + " neg_points = coords[labels==0]\n", + " ax.scatter(pos_points[:, 0], pos_points[:, 1], color='green', marker='*', s=marker_size, edgecolor='white', linewidth=1.25)\n", + " ax.scatter(neg_points[:, 0], neg_points[:, 1], color='red', marker='*', s=marker_size, edgecolor='white', linewidth=1.25)\n", + "\n", + "\n", + "def show_box(box, ax):\n", + " x0, y0 = box[0], box[1]\n", + " w, h = box[2] - box[0], box[3] - box[1]\n", + " ax.add_patch(plt.Rectangle((x0, y0), w, h, edgecolor='green', facecolor=(0, 0, 0, 0), lw=2))" + ] + }, + { + "cell_type": "markdown", + "id": "f22aa751-b7cd-451e-9ded-fb98bf4bdfad", + "metadata": { + "id": "f22aa751-b7cd-451e-9ded-fb98bf4bdfad" + }, + "source": [ + "#### Select an example video" + ] + }, + { + "cell_type": "markdown", + "id": "1c4c6af6-e18d-4939-beaf-2bc00f94a724", + "metadata": { + "id": "1c4c6af6-e18d-4939-beaf-2bc00f94a724" + }, + "source": [ + "We assume that the video is stored as a list of JPEG frames with filenames like `.jpg`.\n", + "\n", + "For your custom videos, you can extract their JPEG frames using ffmpeg (https://ffmpeg.org/) as follows:\n", + "```\n", + "ffmpeg -i .mp4 -q:v 2 -start_number 0 /'%05d.jpg'\n", + "```\n", + "where `-q:v` generates high-quality JPEG frames and `-start_number 0` asks ffmpeg to start the JPEG file from `00000.jpg`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b94c87ca-fd1a-4011-9609-e8be1cbe3230", + "metadata": { + "id": "b94c87ca-fd1a-4011-9609-e8be1cbe3230" + }, + "outputs": [], + "source": [ + "# `video_dir` a directory of JPEG frames with filenames like `.jpg`\n", + "video_dir = \"./videos/bedroom\"\n", + "\n", + "# scan all the JPEG frame names in this directory\n", + "frame_names = [\n", + " p for p in os.listdir(video_dir)\n", + " if os.path.splitext(p)[-1] in [\".jpg\", \".jpeg\", \".JPG\", \".JPEG\"]\n", + "]\n", + "frame_names.sort(key=lambda p: int(os.path.splitext(p)[0]))\n", + "\n", + "# take a look the first video frame\n", + "frame_idx = 0\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[frame_idx])))" + ] + }, + { + "cell_type": "markdown", + "id": "dff46b10-c17a-4a26-8004-8c6d80806b0a", + "metadata": { + "id": "dff46b10-c17a-4a26-8004-8c6d80806b0a" + }, + "source": [ + "#### Initialize the inference state" + ] + }, + { + "cell_type": "markdown", + "id": "f594ac71-a6b9-461d-af27-500fa1d1a420", + "metadata": { + "id": "f594ac71-a6b9-461d-af27-500fa1d1a420" + }, + "source": [ + "SAM 2 requires stateful inference for interactive video segmentation, so we need to initialize an **inference state** on this video.\n", + "\n", + "During initialization, it loads all the JPEG frames in `video_path` and stores their pixels in `inference_state` (as shown in the progress bar below)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8967aed3-eb82-4866-b8df-0f4743255c2c", + "metadata": { + "id": "8967aed3-eb82-4866-b8df-0f4743255c2c" + }, + "outputs": [], + "source": [ + "inference_state = predictor.init_state(video_path=video_dir)" + ] + }, + { + "cell_type": "markdown", + "id": "edb1f3f6-d74d-4016-934c-8d2a14d1a543", + "metadata": { + "id": "edb1f3f6-d74d-4016-934c-8d2a14d1a543" + }, + "source": [ + "### Example 1: Segment & track one object" + ] + }, + { + "cell_type": "markdown", + "id": "aa2d3127-67b2-45d2-9f32-8fe3e10dc5eb", + "metadata": { + "id": "aa2d3127-67b2-45d2-9f32-8fe3e10dc5eb" + }, + "source": [ + "Note: if you have run any previous tracking using this `inference_state`, please reset it first via `reset_state`.\n", + "\n", + "(The cell below is just for illustration; it's not needed to call `reset_state` here as this `inference_state` is just freshly initialized above.)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2646a1d-3401-438c-a653-55e0e56b7d9d", + "metadata": { + "id": "d2646a1d-3401-438c-a653-55e0e56b7d9d" + }, + "outputs": [], + "source": [ + "predictor.reset_state(inference_state)" + ] + }, + { + "cell_type": "markdown", + "id": "26aeb04d-8cba-4f57-95da-6e5a1796003e", + "metadata": { + "id": "26aeb04d-8cba-4f57-95da-6e5a1796003e" + }, + "source": [ + "#### Step 1: Add a first click on a frame" + ] + }, + { + "cell_type": "markdown", + "id": "695c7749-b523-4691-aad0-7558c5d1d68c", + "metadata": { + "id": "695c7749-b523-4691-aad0-7558c5d1d68c" + }, + "source": [ + "To get started, let's try to segment the child on the left.\n", + "\n", + "Here we make a **positive click** at (x, y) = (210, 350) with label `1`, by sending their coordinates and labels into the `add_new_points_or_box` API.\n", + "\n", + "Note: label `1` indicates a *positive click (to add a region)* while label `0` indicates a *negative click (to remove a region)*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e749bab-0f36-4173-bf8d-0c20cd5214b3", + "metadata": { + "id": "3e749bab-0f36-4173-bf8d-0c20cd5214b3" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 1 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's add a positive click at (x, y) = (210, 350) to get started\n", + "points = np.array([[210, 350]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([1], np.int32)\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_points(points, labels, plt.gca())\n", + "show_mask((out_mask_logits[0] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_ids[0])" + ] + }, + { + "cell_type": "markdown", + "id": "89457875-93fa-40ed-b6dc-4e1c971a27f9", + "metadata": { + "id": "89457875-93fa-40ed-b6dc-4e1c971a27f9" + }, + "source": [ + "#### Step 2: Add a second click to refine the prediction" + ] + }, + { + "cell_type": "markdown", + "id": "a75eb21b-1413-452c-827b-a04093c30c78", + "metadata": { + "id": "a75eb21b-1413-452c-827b-a04093c30c78" + }, + "source": [ + "Hmm, it seems that although we wanted to segment the child on the left, the model predicts the mask for only the shorts -- this can happen since there is ambiguity from a single click about what the target object should be. We can refine the mask on this frame via another positive click on the child's shirt.\n", + "\n", + "Here we make a **second positive click** at (x, y) = (250, 220) with label `1` to expand the mask.\n", + "\n", + "Note: we need to send **all the clicks and their labels** (i.e. not just the last click) when calling `add_new_points_or_box`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1ab3ec7-2537-4158-bf98-3d0977d8908d", + "metadata": { + "id": "e1ab3ec7-2537-4158-bf98-3d0977d8908d" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 1 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's add a 2nd positive click at (x, y) = (250, 220) to refine the mask\n", + "# sending all clicks (and their labels) to `add_new_points_or_box`\n", + "points = np.array([[210, 350], [250, 220]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([1, 1], np.int32)\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_points(points, labels, plt.gca())\n", + "show_mask((out_mask_logits[0] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_ids[0])" + ] + }, + { + "cell_type": "markdown", + "id": "df4ab457-d91d-4ac8-b350-fbcd549fd3fd", + "metadata": { + "id": "df4ab457-d91d-4ac8-b350-fbcd549fd3fd" + }, + "source": [ + "With this 2nd refinement click, now we get a segmentation mask of the entire child on frame 0." + ] + }, + { + "cell_type": "markdown", + "id": "f52015ac-1b7b-4c59-bca3-c2b28484cf46", + "metadata": { + "id": "f52015ac-1b7b-4c59-bca3-c2b28484cf46" + }, + "source": [ + "#### Step 3: Propagate the prompts to get the masklet across the video" + ] + }, + { + "cell_type": "markdown", + "id": "30b025bd-cd58-4bfb-9572-c8d2fd0a02ef", + "metadata": { + "id": "30b025bd-cd58-4bfb-9572-c8d2fd0a02ef" + }, + "source": [ + "To get the masklet throughout the entire video, we propagate the prompts using the `propagate_in_video` API." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ab45e932-b0d5-4983-9718-6ee77d1ac31b", + "metadata": { + "id": "ab45e932-b0d5-4983-9718-6ee77d1ac31b" + }, + "outputs": [], + "source": [ + "# run propagation throughout the video and collect the results in a dict\n", + "video_segments = {} # video_segments contains the per-frame segmentation results\n", + "for out_frame_idx, out_obj_ids, out_mask_logits in predictor.propagate_in_video(inference_state):\n", + " video_segments[out_frame_idx] = {\n", + " out_obj_id: (out_mask_logits[i] > 0.0).cpu().numpy()\n", + " for i, out_obj_id in enumerate(out_obj_ids)\n", + " }\n", + "\n", + "# render the segmentation results every few frames\n", + "vis_frame_stride = 30\n", + "plt.close(\"all\")\n", + "for out_frame_idx in range(0, len(frame_names), vis_frame_stride):\n", + " plt.figure(figsize=(6, 4))\n", + " plt.title(f\"frame {out_frame_idx}\")\n", + " plt.imshow(Image.open(os.path.join(video_dir, frame_names[out_frame_idx])))\n", + " for out_obj_id, out_mask in video_segments[out_frame_idx].items():\n", + " show_mask(out_mask, plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "3e801b70-72df-4a72-b3fe-84f145e5e3f6", + "metadata": { + "id": "3e801b70-72df-4a72-b3fe-84f145e5e3f6" + }, + "source": [ + "#### Step 4: Add new prompts to further refine the masklet" + ] + }, + { + "cell_type": "markdown", + "id": "478958ab-29b4-4a75-bba4-adb1b03d0a2b", + "metadata": { + "id": "478958ab-29b4-4a75-bba4-adb1b03d0a2b" + }, + "source": [ + "It appears that in the output masklet above, there are some small imperfections in boundary details on frame 150.\n", + "\n", + "With SAM 2 we can fix the model predictions interactively. We can add a **negative click** at (x, y) = (82, 415) on this frame with label `0` to refine the masklet. Here we call the `add_new_points_or_box` API with a different `frame_idx` argument to indicate the frame index we want to refine." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a572ea9-5b7e-479c-b30c-93c38b121131", + "metadata": { + "id": "1a572ea9-5b7e-479c-b30c-93c38b121131" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 150 # further refine some details on this frame\n", + "ann_obj_id = 1 # give a unique id to the object we interact with (it can be any integers)\n", + "\n", + "# show the segment before further refinement\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx} -- before refinement\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_mask(video_segments[ann_frame_idx][ann_obj_id], plt.gca(), obj_id=ann_obj_id)\n", + "\n", + "# Let's add a negative click on this frame at (x, y) = (82, 415) to refine the segment\n", + "points = np.array([[82, 410]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([0], np.int32)\n", + "_, _, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + ")\n", + "\n", + "# show the segment after the further refinement\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx} -- after refinement\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_points(points, labels, plt.gca())\n", + "show_mask((out_mask_logits > 0.0).cpu().numpy(), plt.gca(), obj_id=ann_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "50a3950a-acf1-435c-bd64-94297267b5e9", + "metadata": { + "id": "50a3950a-acf1-435c-bd64-94297267b5e9" + }, + "source": [ + "#### Step 5: Propagate the prompts (again) to get the masklet across the video" + ] + }, + { + "cell_type": "markdown", + "id": "b1954ecf-c2ec-4f9c-8d10-c4f527a10cd2", + "metadata": { + "id": "b1954ecf-c2ec-4f9c-8d10-c4f527a10cd2" + }, + "source": [ + "Let's get an updated masklet for the entire video. Here we call `propagate_in_video` again to propagate all the prompts after adding the new refinement click above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "baa96690-4a38-4a24-aa17-fd2f4db0e232", + "metadata": { + "id": "baa96690-4a38-4a24-aa17-fd2f4db0e232" + }, + "outputs": [], + "source": [ + "# run propagation throughout the video and collect the results in a dict\n", + "video_segments = {} # video_segments contains the per-frame segmentation results\n", + "for out_frame_idx, out_obj_ids, out_mask_logits in predictor.propagate_in_video(inference_state):\n", + " video_segments[out_frame_idx] = {\n", + " out_obj_id: (out_mask_logits[i] > 0.0).cpu().numpy()\n", + " for i, out_obj_id in enumerate(out_obj_ids)\n", + " }\n", + "\n", + "# render the segmentation results every few frames\n", + "vis_frame_stride = 30\n", + "plt.close(\"all\")\n", + "for out_frame_idx in range(0, len(frame_names), vis_frame_stride):\n", + " plt.figure(figsize=(6, 4))\n", + " plt.title(f\"frame {out_frame_idx}\")\n", + " plt.imshow(Image.open(os.path.join(video_dir, frame_names[out_frame_idx])))\n", + " for out_obj_id, out_mask in video_segments[out_frame_idx].items():\n", + " show_mask(out_mask, plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "607507e3-6a2b-4fd7-944c-2371bdab9d01", + "metadata": { + "id": "607507e3-6a2b-4fd7-944c-2371bdab9d01" + }, + "source": [ + "The segments now look good on all frames." + ] + }, + { + "cell_type": "markdown", + "id": "2502bb5a-3e1f-43d0-9f58-33f8676fff0d", + "metadata": { + "id": "2502bb5a-3e1f-43d0-9f58-33f8676fff0d" + }, + "source": [ + "### Example 2: Segment an object using box prompt" + ] + }, + { + "cell_type": "markdown", + "id": "8e2d26c8-0432-48c6-997e-4a3b77bb5f6d", + "metadata": { + "id": "8e2d26c8-0432-48c6-997e-4a3b77bb5f6d" + }, + "source": [ + "Note: if you have run any previous tracking using this `inference_state`, please reset it first via `reset_state`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6dbe9183-abbb-4283-b0cb-d24f3d7beb34", + "metadata": { + "id": "6dbe9183-abbb-4283-b0cb-d24f3d7beb34" + }, + "outputs": [], + "source": [ + "predictor.reset_state(inference_state)" + ] + }, + { + "cell_type": "markdown", + "id": "ceb6eae9-0f4c-434f-8089-a46c9ca59da5", + "metadata": { + "id": "ceb6eae9-0f4c-434f-8089-a46c9ca59da5" + }, + "source": [ + "In addition to using clicks as inputs, SAM 2 also supports segmenting and tracking objects in a video via **bounding boxes**.\n", + "\n", + "In the example below, we segment the child on the right using a **box prompt** of (x_min, y_min, x_max, y_max) = (300, 0, 500, 400) on frame 0 as input into the `add_new_points_or_box` API." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cbfb273-4e14-495b-bd89-87a8baf52ae7", + "metadata": { + "id": "1cbfb273-4e14-495b-bd89-87a8baf52ae7" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 4 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's add a box at (x_min, y_min, x_max, y_max) = (300, 0, 500, 400) to get started\n", + "box = np.array([300, 0, 500, 400], dtype=np.float32)\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " box=box,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_box(box, plt.gca())\n", + "show_mask((out_mask_logits[0] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_ids[0])" + ] + }, + { + "cell_type": "markdown", + "id": "bd3f9ba7-bf4d-47e5-9b02-8a424cab42cc", + "metadata": { + "id": "bd3f9ba7-bf4d-47e5-9b02-8a424cab42cc" + }, + "source": [ + "Here, SAM 2 gets a pretty good segmentation mask of the entire child, even though the input bounding box is not perfectly tight around the object.\n", + "\n", + "Similar to the previous example, if the returned mask from is not perfect when using a box prompt, we can also further **refine** the output using positive or negative clicks. To illustrate this, here we make a **positive click** at (x, y) = (460, 60) with label `1` to expand the segment around the child's hair.\n", + "\n", + "Note: to refine the segmentation mask from a box prompt, we need to send **both the original box input and all subsequent refinement clicks and their labels** when calling `add_new_points_or_box`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54906315-ab4c-4088-b866-4c22134d5b66", + "metadata": { + "id": "54906315-ab4c-4088-b866-4c22134d5b66" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 4 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's add a positive click at (x, y) = (460, 60) to refine the mask\n", + "points = np.array([[460, 60]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([1], np.int32)\n", + "# note that we also need to send the original box input along with\n", + "# the new refinement click together into `add_new_points_or_box`\n", + "box = np.array([300, 0, 500, 400], dtype=np.float32)\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + " box=box,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_box(box, plt.gca())\n", + "show_points(points, labels, plt.gca())\n", + "show_mask((out_mask_logits[0] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_ids[0])" + ] + }, + { + "cell_type": "markdown", + "id": "73128cd6-dbfa-49f7-8d79-1a8e19835f7f", + "metadata": { + "id": "73128cd6-dbfa-49f7-8d79-1a8e19835f7f" + }, + "source": [ + "Then, to get the masklet throughout the entire video, we propagate the prompts using the `propagate_in_video` API." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cd90557-a0dc-442e-b091-9c74c831bef8", + "metadata": { + "id": "9cd90557-a0dc-442e-b091-9c74c831bef8" + }, + "outputs": [], + "source": [ + "# run propagation throughout the video and collect the results in a dict\n", + "video_segments = {} # video_segments contains the per-frame segmentation results\n", + "for out_frame_idx, out_obj_ids, out_mask_logits in predictor.propagate_in_video(inference_state):\n", + " video_segments[out_frame_idx] = {\n", + " out_obj_id: (out_mask_logits[i] > 0.0).cpu().numpy()\n", + " for i, out_obj_id in enumerate(out_obj_ids)\n", + " }\n", + "\n", + "# render the segmentation results every few frames\n", + "vis_frame_stride = 30\n", + "plt.close(\"all\")\n", + "for out_frame_idx in range(0, len(frame_names), vis_frame_stride):\n", + " plt.figure(figsize=(6, 4))\n", + " plt.title(f\"frame {out_frame_idx}\")\n", + " plt.imshow(Image.open(os.path.join(video_dir, frame_names[out_frame_idx])))\n", + " for out_obj_id, out_mask in video_segments[out_frame_idx].items():\n", + " show_mask(out_mask, plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "e023f91f-0cc5-4980-ae8e-a13c5749112b", + "metadata": { + "id": "e023f91f-0cc5-4980-ae8e-a13c5749112b" + }, + "source": [ + "Note that in addition to clicks or boxes, SAM 2 also supports directly using a **mask prompt** as input via the `add_new_mask` method in the `SAM2VideoPredictor` class. This can be helpful in e.g. semi-supervised VOS evaluations (see [tools/vos_inference.py](https://github.com/facebookresearch/sam2/blob/main/tools/vos_inference.py) for an example)." + ] + }, + { + "cell_type": "markdown", + "id": "da018be8-a4ae-4943-b1ff-702c2b89cb68", + "metadata": { + "id": "da018be8-a4ae-4943-b1ff-702c2b89cb68" + }, + "source": [ + "### Example 3: Segment multiple objects simultaneously" + ] + }, + { + "cell_type": "markdown", + "id": "dea6c04c-3072-4876-b394-879321a48c4a", + "metadata": { + "id": "dea6c04c-3072-4876-b394-879321a48c4a" + }, + "source": [ + "Note: if you have run any previous tracking using this `inference_state`, please reset it first via `reset_state`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29b874c8-9f39-42d3-a667-54a0bd696410", + "metadata": { + "id": "29b874c8-9f39-42d3-a667-54a0bd696410" + }, + "outputs": [], + "source": [ + "predictor.reset_state(inference_state)" + ] + }, + { + "cell_type": "markdown", + "id": "48f3f7e6-4821-468c-84e4-f3a0435c9149", + "metadata": { + "id": "48f3f7e6-4821-468c-84e4-f3a0435c9149" + }, + "source": [ + "#### Step 1: Add two objects on a frame" + ] + }, + { + "cell_type": "markdown", + "id": "95158714-86d7-48a9-8365-b213f97cc9ca", + "metadata": { + "id": "95158714-86d7-48a9-8365-b213f97cc9ca" + }, + "source": [ + "SAM 2 can also segment and track two or more objects at the same time. One way, of course, is to do them one by one. However, it would be more efficient to batch them together (e.g. so that we can share the image features between objects to reduce computation costs).\n", + "\n", + "This time, let's focus on object parts and segment **the shirts of both childen** in this video. Here we add prompts for these two objects and assign each of them a unique object id." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e22d896d-3cd5-4fa0-9230-f33e217035dc", + "metadata": { + "id": "e22d896d-3cd5-4fa0-9230-f33e217035dc" + }, + "outputs": [], + "source": [ + "prompts = {} # hold all the clicks we add for visualization" + ] + }, + { + "cell_type": "markdown", + "id": "59d9ac57-b14a-4237-828d-927e422c518b", + "metadata": { + "id": "59d9ac57-b14a-4237-828d-927e422c518b" + }, + "source": [ + "Add the first object (the left child's shirt) with a **positive click** at (x, y) = (200, 300) on frame 0.\n", + "\n", + "We assign it to object id `2` (it can be arbitrary integers, and only needs to be unique for each object to track), which is passed to the `add_new_points_or_box` API to distinguish the object we are clicking upon." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d13432fc-f467-44d8-adfe-3e0c488046b7", + "metadata": { + "id": "d13432fc-f467-44d8-adfe-3e0c488046b7" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 2 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's add a positive click at (x, y) = (200, 300) to get started on the first object\n", + "points = np.array([[200, 300]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([1], np.int32)\n", + "prompts[ann_obj_id] = points, labels\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_points(points, labels, plt.gca())\n", + "for i, out_obj_id in enumerate(out_obj_ids):\n", + " show_points(*prompts[out_obj_id], plt.gca())\n", + " show_mask((out_mask_logits[i] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "1bbbd51b-e1e2-4c36-99ec-1d9a1b49b0cd", + "metadata": { + "id": "1bbbd51b-e1e2-4c36-99ec-1d9a1b49b0cd" + }, + "source": [ + "Hmm, this time we just want to select the child's shirt, but the model predicts the mask for the entire child. Let's refine the prediction with a **negative click** at (x, y) = (275, 175)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "95ecf61d-662b-4f98-ae62-46557b219842", + "metadata": { + "id": "95ecf61d-662b-4f98-ae62-46557b219842" + }, + "outputs": [], + "source": [ + "# add the first object\n", + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 2 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's add a 2nd negative click at (x, y) = (275, 175) to refine the first object\n", + "# sending all clicks (and their labels) to `add_new_points_or_box`\n", + "points = np.array([[200, 300], [275, 175]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([1, 0], np.int32)\n", + "prompts[ann_obj_id] = points, labels\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_points(points, labels, plt.gca())\n", + "for i, out_obj_id in enumerate(out_obj_ids):\n", + " show_points(*prompts[out_obj_id], plt.gca())\n", + " show_mask((out_mask_logits[i] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "194718c1-734d-446c-a3ef-361057de2f31", + "metadata": { + "id": "194718c1-734d-446c-a3ef-361057de2f31" + }, + "source": [ + "After the 2nd negative click, now we get the left child's shirt as our first object.\n", + "\n", + "Let's move on to the second object (the right child's shirt) with a positive click at (x, y) = (400, 150) on frame 0. Here we assign object id `3` to this second object (it can be arbitrary integers, and only needs to be unique for each object to track).\n", + "\n", + "Note: when there are multiple objects, the `add_new_points_or_box` API will return a list of masks for each object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86ca1bde-62a4-40e6-98e4-15606441e52f", + "metadata": { + "id": "86ca1bde-62a4-40e6-98e4-15606441e52f" + }, + "outputs": [], + "source": [ + "ann_frame_idx = 0 # the frame index we interact with\n", + "ann_obj_id = 3 # give a unique id to each object we interact with (it can be any integers)\n", + "\n", + "# Let's now move on to the second object we want to track (giving it object id `3`)\n", + "# with a positive click at (x, y) = (400, 150)\n", + "points = np.array([[400, 150]], dtype=np.float32)\n", + "# for labels, `1` means positive click and `0` means negative click\n", + "labels = np.array([1], np.int32)\n", + "prompts[ann_obj_id] = points, labels\n", + "\n", + "# `add_new_points_or_box` returns masks for all objects added so far on this interacted frame\n", + "_, out_obj_ids, out_mask_logits = predictor.add_new_points_or_box(\n", + " inference_state=inference_state,\n", + " frame_idx=ann_frame_idx,\n", + " obj_id=ann_obj_id,\n", + " points=points,\n", + " labels=labels,\n", + ")\n", + "\n", + "# show the results on the current (interacted) frame on all objects\n", + "plt.figure(figsize=(9, 6))\n", + "plt.title(f\"frame {ann_frame_idx}\")\n", + "plt.imshow(Image.open(os.path.join(video_dir, frame_names[ann_frame_idx])))\n", + "show_points(points, labels, plt.gca())\n", + "for i, out_obj_id in enumerate(out_obj_ids):\n", + " show_points(*prompts[out_obj_id], plt.gca())\n", + " show_mask((out_mask_logits[i] > 0.0).cpu().numpy(), plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "a1f7add8-d577-4597-ae2f-654b8c7b05e0", + "metadata": { + "id": "a1f7add8-d577-4597-ae2f-654b8c7b05e0" + }, + "source": [ + "This time the model predicts the mask of the shirt we want to track in just one click. Nice!" + ] + }, + { + "cell_type": "markdown", + "id": "448733b8-ea8b-4078-995f-b676c3b558ba", + "metadata": { + "id": "448733b8-ea8b-4078-995f-b676c3b558ba" + }, + "source": [ + "#### Step 2: Propagate the prompts to get masklets across the video" + ] + }, + { + "cell_type": "markdown", + "id": "60bd73de-d669-41c8-b6ba-943883f0caa2", + "metadata": { + "id": "60bd73de-d669-41c8-b6ba-943883f0caa2" + }, + "source": [ + "Now, we propagate the prompts for both objects to get their masklets throughout the video.\n", + "\n", + "Note: when there are multiple objects, the `propagate_in_video` API will return a list of masks for each object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17737191-d62b-4611-b2c6-6d0418a9ab74", + "metadata": { + "id": "17737191-d62b-4611-b2c6-6d0418a9ab74" + }, + "outputs": [], + "source": [ + "# run propagation throughout the video and collect the results in a dict\n", + "video_segments = {} # video_segments contains the per-frame segmentation results\n", + "for out_frame_idx, out_obj_ids, out_mask_logits in predictor.propagate_in_video(inference_state):\n", + " video_segments[out_frame_idx] = {\n", + " out_obj_id: (out_mask_logits[i] > 0.0).cpu().numpy()\n", + " for i, out_obj_id in enumerate(out_obj_ids)\n", + " }\n", + "\n", + "# render the segmentation results every few frames\n", + "vis_frame_stride = 30\n", + "plt.close(\"all\")\n", + "for out_frame_idx in range(0, len(frame_names), vis_frame_stride):\n", + " plt.figure(figsize=(6, 4))\n", + " plt.title(f\"frame {out_frame_idx}\")\n", + " plt.imshow(Image.open(os.path.join(video_dir, frame_names[out_frame_idx])))\n", + " for out_obj_id, out_mask in video_segments[out_frame_idx].items():\n", + " show_mask(out_mask, plt.gca(), obj_id=out_obj_id)" + ] + }, + { + "cell_type": "markdown", + "id": "18a0b9d7-c78f-432b-afb0-11f2ea5b652a", + "metadata": { + "id": "18a0b9d7-c78f-432b-afb0-11f2ea5b652a" + }, + "source": [ + "Looks like both children's shirts are well segmented in this video.\n", + "\n", + "Now you can try SAM 2 on your own videos and use cases!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file