bmx-routing / bmx6 Goto Github PK
View Code? Open in Web Editor NEWBMX6 Mesh Networking Protocol
Home Page: http://bmx6.net
BMX6 Mesh Networking Protocol
Home Page: http://bmx6.net
@axn
Hi,
As mbed TLS 1.3 is EoL is there a chance if you could look into adding support for the 2.4+ versions instead for bmx7?
Best regards,
Daniel
I have two devices based on atheros and ralink chips.
The problem is if I try to send packets more than 1428 between hosts, packets more than 1428 bytes just drop. Meanwhile ipv6 works fine.
# ping -s 1500 10.202.0.94
PING 10.202.0.94 (10.202.0.94): 1500 data bytes
^C
--- 10.202.0.94 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
# ping -s 1428 10.202.0.94
PING 10.202.0.94 (10.202.0.94): 1428 data bytes
1436 bytes from 10.202.0.94: seq=0 ttl=64 time=6.061 ms
1436 bytes from 10.202.0.94: seq=1 ttl=64 time=1.446 ms
1436 bytes from 10.202.0.94: seq=2 ttl=64 time=1.398 ms
1436 bytes from 10.202.0.94: seq=3 ttl=64 time=1.458 ms
^C
--- 10.202.0.94 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 1.398/2.590/6.061 ms
# ping -s 1500 fd66:66:66:7:b2b2:dcff:fd3a:b35c
PING fd66:66:66:7:b2b2:dcff:fd3a:b35c (fd66:66:66:7:b2b2:dcff:fd3a:b35c): 1500 data bytes
1508 bytes from fd66:66:66:7:b2b2:dcff:fd3a:b35c: seq=0 ttl=64 time=1.528 ms
1508 bytes from fd66:66:66:7:b2b2:dcff:fd3a:b35c: seq=1 ttl=64 time=1.283 ms
1508 bytes from fd66:66:66:7:b2b2:dcff:fd3a:b35c: seq=2 ttl=64 time=1.254 ms
1508 bytes from fd66:66:66:7:b2b2:dcff:fd3a:b35c: seq=3 ttl=64 time=1.413 ms
^C
--- fd66:66:66:7:b2b2:dcff:fd3a:b35c ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 1.254/1.369/1.528 ms
that's the same node with ip 10.202.0.94 and fd66:66:66:7:b2b2:dcff:fd3a:b35c based on ralink:
# cat /proc/cpuinfo
system type : Ralink RT3352 id:1 rev:6
machine : D-Link DIR-620 D1
processor : 0
cpu model : MIPS 24KEc V4.12
BogoMIPS : 255.59
wait instruction : yes
microsecond timers : yes
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa : mips1 mips2 mips32r1 mips32r2
ASEs implemented : mips16 dsp
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
I came across with this problem only on ralink chip.
config switch
option name 'rt305x'
option reset '1'
option enable_vlan '1'
config switch_vlan
option device 'rt305x'
option vlan '1'
option ports '0 1 2 3 5 6t'
config device 'eth0_1_12'
option type '8021ad'
option name 'eth0_1_12'
option ifname 'eth0.1'
option vid '12'
option proto 'static'
option ip6addr 'FD02:0:0:B0B2:DC3A:B35C:0:212/128'
config interface 'eth0_1_12_ad'
option ifname 'eth0_1_12'
option auto '1'
I'm runnnig a few nodes with different versions of qMp which, in turn, run diverse versions of BMX6. Starting with version 5dc6678 , devices can not ping each other using their announced IPv4 address(es), but can do it using their IPv6 ones.
If I replace the /usr/sbin/bmx6 file from a non-functional node with that from a working one, which has version 4016a19 or older, IPv4 pings work fine.
At the moment I'm newbie with this, but we had race conditions issues during boot because of /etc/init.d/bmx6
file
question: what do you think about this issue => https://gitlab.com/guifi-exo/temba/issues/18
we are going to patch on temba "firmware", but probably this is useful for bmx6 in general (so should we patch it to upstream? where is it?)
Thanks for reading
hey axel!
we justed bumped into this bug:
on a mesh network made of around ~60 bmx6 nodes with sms_plugin enabled, trying to add one node with bmx6 but no sms_plugin enabled, makes that node crash with the following error
Wed Feb 24 09:24:07 2016 daemon.err bmx6[3792]: ERROR ip_flush_rules(): removed orphan IPv4 rule to table 60
Wed Feb 24 09:24:07 2016 daemon.err bmx6[3792]: ERROR ip_flush_rules(): removed orphan IPv6 rule to table 60
Wed Feb 24 09:24:07 2016 daemon.err bmx6[3792]: WARN dev_check(): detected valid but disabled dev=wlan1-adhoc_12 ! Activating now...
Wed Feb 24 09:24:07 2016 daemon.err bmx6[3792]: WARN dev_activate(): dev=wlan1-adhoc_12
Wed Feb 24 09:24:07 2016 daemon.err bmx6[3792]: INFO dev_reconfigure_soft(): enabled wireless umin=6222K umax=56000K umax=56000000 umax_conf=18446744073709551615 undef=18446744073709551615 dev=wlan1-adhoc_12 MAC: 6470023E9D2A link-local fe80::6670:2ff:fe3e:9d2a/64 global fd66:66:66:10:6670:2ff:fe3e:9d2a/64 brc ff02::2
Wed Feb 24 09:24:07 2016 daemon.err bmx6[3792]: INFO check_proc_sys_net(): changing /proc/sys/net/ipv4/conf/bmxtmain/accept_local from 0 to 1
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: WARN rx_frame_iterate(): process_description_tlvs - unknown type=16 ! check for updates
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR First SIGSEGV -501358 received, try cleaning up...
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 rx_frame_iterate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 process_description_tlv_hna()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 is_ip_valid()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 is_ip_valid()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 is_ip_valid()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 is_ip_valid()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 rx_frame_iterate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 process_description_tlv_tun6_adv()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 is_ip_valid()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 rx_frame_iterate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 process_description_tlv_tunXin6_net_adv()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 rx_frame_iterate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 process_description_tlv_tunXin6_net_adv()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 ip_netmask_validate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 process_description_tlvs()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 rx_frame_iterate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 process_description_tlv_metricalgo()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 metricalgo_tlv_to_host()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 fmetric_to_umetric()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 validate_metricalgo()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 fmetric_to_umetric()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 _add_tun_bit_node()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 eval_tun_bit_tree()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 task_remove()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 _recalc_tun_bit_tree()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 rx_frame_iterate()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 cleanup_all()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR debug_function_calls(): 3070 segmentation_fault()
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR Terminating with error code -501358 (BMX6-0.1-alpha-rev8f26909e8808ed7fab0359afc15a3e44563fbd40)! Please notify a developer
Wed Feb 24 09:24:10 2016 daemon.err bmx6[3792]: ERROR Second SIGSEGV -500234 received, giving up! core contains second SIGSEV!
simply enabling sms_plugin like this:
root@3e9d28:/etc/config# bmx6 -cp
plugin bmx6_sms.so
plugin bmx6_config.so
plugin bmx6_json.so
ipVersion 6
dev wlan1-adhoc_12
/linklayer 2
tunDev tmain
/tun4Address 10.1.29.1/28
/tun6Address 2012:0:1:c171::1/64
syncSms chat
makes the new node work properly
but without the "plugin=bmx6_json.so" it crashes as mentioned, and we believe this should not happen
sincerely,
pau, gio, rogerpueyo, and gui :)
Hi,
I'm using BMX7-0.1-alpha-rev41aabcb on a 802.11s mesh consisting of two nodes. The OS is OpenWRT 15.05 with the latest patches, and the configuration is the same for both nodes.
About every three minutes bmx7 would terminate with the following error:
daemon.err bmx7[9395]: ERROR First SIGSEGV -502124 received, try cleaning up...
daemon.err bmx7[9395]: ERROR Terminating with error code -502124 (BMX7-0.1-alpha-rev41aabcb)! Please notify a developer
The output of bmx7 -c parameters for one of the nodes is:
plugin bmx7_config.so (0)
plugin bmx7_sms.so (0)
plugin bmx7_iwinfo.so (0)
plugin bmx7_tun.so (0)
plugin bmx7_table.so (0)
ipVersion 6 (6)
dev wdmesh0 (0)
syncSms mdns (0)
tunOutTimeout 120000 (60000)
tunMtu 1528 (0)
tunDev dmesh (0)
/tun4Address 10.254.177.170/32 (0)
/tun6Address 2012:0:0:b1aa::1/64 (0)
tunOut sen4 (0)
/network 10.254.0.0/16 (0)
/hysteresis 30 (20)
tunOut sen6 (0)
/network 2012::/48 (0)
/hysteresis 30 (20)
tunOut inet4 (0)
/network 0.0.0.0/0 (0)
/maxPrefixLen 0 (128)
I'm pretty much at loss on how I can debug this further, but if you need more info please let me know.
Cheers,
Jan
Hello,
The subject line says it all. I'd have respective patches ready that introduce a PREFIX Makefile variable.
Cheers,
Steffen
Line 603 of the is_ip_valid function in the ip.c file:
if (ipXto4(*ip) != INADDR_LOOPBACK && ipXto4(*ip) != INADDR_NONE)
return YES;
It only works on a big endian device. On a little endian device, ipXto4(*ip)
of a loopback device has the value 0x100007f
while INADDR_LOOPBACK
has the value 0x7f000001
.
Should we use something like htonl
' to convert IP addresses from host order to network order before the comparison?
Also on line 592, for an IPv6 loopback address ::1, is_zero((void*) ip, sizeof ( IPX_T) - sizeof (IP4_T)
always evaluates TRUE but family is AF_INET6, so the condition (family != (is_zero((void*) ip, sizeof ( IPX_T) - sizeof (IP4_T)) ? AF_INET : AF_INET6)
is alway TRUE. Line 595 to 598 will always be skipped.
cc @dyangol
We are having issues because sometimes bmx6 crashes The most common issue in bmx6 mesh networks is that a bmx6 crashed, and the solution we apply is to restart bmx6 daemon. I think two actions are required:
Fix /etc/init.d/bmx6
to have a debug level of 0 (this way, and hopefully, we will know cleary when bmx6 crashed). By default/now is reporting too much. OK, debug level of 0 is like too much verbose. Probably we can find a grep
expression to reduce it even more
Start again automatically when it crashes
#!/bin/sh /etc/rc.common
# Copyright (C) 2011 Fundacio Privada per a la Xarxa Oberta, Lliure i Neutral guifi.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
START=99
BIN=/usr/sbin/bmx6
CONF=/etc/config/bmx6
PID=/var/run/bmx6/pid
start() {
cd /root/
while pgrep -f mac80211.sh ; do sleep 1; done
ulimit -c 20000
$BIN -f $CONF -d0 > /dev/null &
}
stop() {
start-stop-daemon -p $PID -K
}
restart() {
stop; sleep 3; start
}
I can send a logread
example privately (probably too much sensitive information)
Hi,
I am running BMX6 in qMp with 85 other network routers:
root@qMp-98d4:/# bmx6 -c --version
BMX6-0.1-alpha comPatibility=16 revision=0312168aaa384379ccbefd4b2d936fc698664d5b
and I've noticed that asking the JSON-formatted BMX6 tunnels list crashes the daemon (while the raw/plaintext list doesn't). For instance:
root@qMp-98d4:/# bmx6 -c tunnels | wc
184 2563 27825 <==== a nice number of tunnels
and
root@qMp-98d4:/# bmx6 -c --jshow tunnels; ps | grep bmx
10434 root 3088 S grep bmx <==== BMX6 crashed :(
The daemon does not crash when a small number of nodes is present (e.g. 4), but I don't know exactly what number of nodes/tunnels or which output message size makes the daemon crash.
Hello,
it is not ultimately required, a mere date plus hash would do, but it would nonetheless be nice to somehow have synchronised releases on github with what appears on the Linux distributions. I got positive initial vibes on axn/bmx6#3 (comment) about this idea. Just prime me on how you think an appearance on Debian would be supportive of what you are doing.
Best,
Steffen
I've tried to start the bmx6 daemon on my QNAP machine running on Debian Buster:
[6427 0] ERROR : First SIGSEGV -500650 received, try cleaning up...
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_tun_search()
[6427 0] ERROR debug_function_calls: 0 opt_status()
[6427 0] ERROR debug_function_calls: 0 create_ctrl_node()
[6427 0] ERROR debug_function_calls: 0 opt_dev()
[6427 0] ERROR debug_function_calls: 0 opt_dev()
[6427 0] ERROR debug_function_calls: 0 create_ctrl_node()
[6427 0] ERROR debug_function_calls: 0 opt_ip_version()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 ip_flush_routes()
[6427 0] ERROR debug_function_calls: 0 ip_flush_rules()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 iproute()
[6427 0] ERROR debug_function_calls: 0 ip_netmask_validate()
[6427 0] ERROR debug_function_calls: 0 iptrack()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 ip_flush_routes()
[6427 0] ERROR debug_function_calls: 0 ip_flush_rules()
[6427 0] ERROR debug_function_calls: 0 add_rtattr()
[6427 0] ERROR debug_function_calls: 0 iproute()
[6427 0] ERROR debug_function_calls: 0 is_ip_valid()
[6427 0] ERROR debug_function_calls: 0 cleanup_all()
[6427 0] ERROR debug_function_calls: 0 segmentation_fault()
[6427 0] ERROR : Terminating with error code -500650 (BMX6-0.1-alpha-revd8869ec)! Please notify a developer
[6427 0] ERROR : check up-to-dateness of bmx libs in default lib path /usr/lib or customized lib path defined by BMX6_LIB_PATH !
[6427 0] ERROR : raising SIGSEGV again ...
Segmentation fault
processor : 0
model name : Feroceon 88FR131 rev 1 (v5l)
BogoMIPS : 400.00
Features : swp half thumb fastmult edsp
CPU implementer : 0x56
CPU architecture: 5TE
CPU variant : 0x2
CPU part : 0x131
CPU revision : 1
Hardware : Marvell Kirkwood (Flattened Device Tree)
Revision : 0000
Serial : 0000000000000000
Linux host-8c828b 4.19.0-6-marvell #1 Debian 4.19.67-2+deb10u1 (2019-09-20) armv5tel GNU/Linux
tunnel mtu problems are being discussed/solved here: bmx-routing/bmx7#30
I see that the commits are very neat.
If the tunnel structure is the same from bmx6 to bmx7 would be possible to make it work on bmx6 or it would be a lot of work?
Thanks for reading
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.