Giter Site home page Giter Site logo

wicked's Introduction

Presenting wicked network configuration
=======================================

This tool and library provides a new framework for network
configuration.

One of the bigger problems with network interface management today,
and with the ifup scripts in general, is that different layers of
network management get jumbled together into one single script,
or at most two different scripts, that interact with each other in a
not-really-well-defined way, with side effects that are difficult to
be aware of, obscure constraints and conventions, etc.  Several layers
of special hacks for a variety of different scenarios cover them like
barnacles.  Address configuration protocols are being used that are
implemented via daemons like dhcpcd, which interact rather poorly with
the rest of the infrastructure. Funky interface naming schemes that
require heavy udev support are introduced to achieve persistent
identification of interfaces.

In other words, a maintenance nightmare.

The idea of wicked is to decompose the problem in several ways. None
of them is entirely novel, but trying to put ideas from different
other projects together is hopefully going to create a better solution
overall.

One approach is to use a client/server model. This allows wicked to define
standardized facilities for things like address configuration that
are well integrated with the overall framework. For instance, with
address configuration, the admin may request that an interface should
be configured via dhcp or ipv4 zeroconf, and all the respective
addrconf service does is obtain the lease from its server, and pass it
on to the wicked server process, which installs the requested addresses
and routes.

The other approach to decomposing the problem is to enforce the layering
aspect. For any type of network interface, it is possible to define
a dbus service that configures the network interface's device layer -
be it a vlan, a bridge, a bond, or an paravirtualized NIC. Common
functionality, such as address configuration, is implemented by joint
services that are layered on top of these device specific services,
without having to implement them specifically.

The wicked framework implements these two aspects by using a variety
of dbus services, which get attached to a network interface depending
on its type.

To illustrate this point, here's a rough overview of the current
object hierarchy in wicked.

Each network interface is represented via a child object of
/org/opensuse/Network/Interfaces. The name of the child object is given
by its ifindex, so e.g. the loopback interface, which usually gets
ifindex 1, is /org/opensuse/Network/Interfaces/1, the first ethernet
interface registered is /org/opensuse/Network/Interfaces/2, etc.

Each network interface has a "class" associated with it, which is
used to select the dbus interfaces it supports. By default, each
network interface is of class "netif", and wickedd will automatically
attach all interfaces compatible with this class. In the current
implementation, this includes the following interfaces

org.opensuse.Network.Interface
        Generic network interface functions, such as taking the link
        up or down, assigning an MTU, etc.

org.opensuse.Network.Addrconf.ipv4.dhcp
org.opensuse.Network.Addrconf.ipv6.dhcp
org.opensuse.Network.Addrconf.ipv4.auto
org.opensuse.Network.Addrconf.ipv6.auto
        Address configuration services for DHCP, ipv6 autoconf, ipv4
        zeroconf, etc.

Beyond this, network interfaces may require/offer special configuration
mechanisms. For instance, for an Ethernet device, you may want to be
able to control the link speed, offloading of checksumming, etc. To
achieve this, ethernet devices have a class of their own, called
netif-ethernet, which is a subclass of netif. As a consequence, the dbus
interfaces assigned to an ethernet interface include all the services
listed above, plus org.opensuse.Network.Ethernet, which is a service
available only to objects belonging to the netif-ethernet class.

Similarly, there exist classes for interface types like bridges, vlans,
bonds, or infiniband.

Obviously, this begs the question, how do you interact with an interface
that needs to be created first - such as a VLAN, which is really a
virtual network interface that sits on top of an ethernet device.

For these, wicked defines factory interfaces, such as
org.opensuse.Network.VLAN.Factory. Such a factory interface offers a
single function that lets you create an interface of the requested type.
These factory interfaces are attached to the
/org/opensuse/Network/Interfaces list node.

Frequently Asked Questions
==========================

We have a FAQ section hosted in our GitHub's wiki, be sure to check that
out for common questions about usage or Wicked in general:

        https://github.com/openSUSE/wicked/wiki/FAQ

For any questions not answered on the FAQ, please read our section
below: "Where to discuss or report bugs"

What's currently supported
==========================

wicked currently supports

 -	configuration file backends to parse SUSE style
	/etc/sysconfig/network files.

 -	an internal configuration backend to represent network
	interface configuration in XML. The syntax evolved out
	of what netcf uses.

 -	bring-up and shutdown of "normal" network interfaces
	such as Ethernet, Infiniband etc, as well as VLAN,
	bridges, bonds, tun, tap, dummy, macvlan, macvtap, hsi,
	qeth, iucv and wireless (currently limited to one
	wpa-psk/eap network) devices.

 -	A built-in DHCPv4 client
 -	A built-in DHCPv6 client

 -	The nanny daemon (if enabled) helps to automatically
	bring up configured interfaces as soon as the device
	is available (interface hotplugging) and set up IP
	configuration when a link (carrier) is detected.


Where to get the sources/binaries
=================================

The git source repository is hosted at:

	https://github.com/openSUSE/wicked

Binary packages are build in the openSUSE build service in
the network:wicked project tree and can be found via:

	http://software.opensuse.org/package/wicked

The actual git master is built in the network:wicked:master
project automatically.

To build wicked from sources, try following commands:

	zypper in git-core rpm-build gcc make pkg-config \
		autoconf automake libtool systemd-devel \
		libnl3-devel dbus-1-devel libgcrypt-devel \
		pandoc
	git clone https://github.com/openSUSE/wicked.git
	cd wicked
	./autogen.sh
	make rpmbuild

and then install the RPMs.


Where to discuss or report bugs
===============================

Please take a look at:

	http://bugs.opensuse.org

where you can find links to bugzilla and user forums.

There are currently two mailing lists:

	[email protected]

for discussions about development and

	[email protected]

to monitor git repository commits.

GitHub offers also an issue tracker, where you can discuss pull
requests and report git master issues, which are not yet in
openSUSE:Factory or any repository for released products.


What you can do
===============

Enable wicked using:

        systemctl enable --force wicked

This enables the wicked services, creates the
	network.service -> wicked.service
alias link and causes to start the network at the next boot.

To manually start the server process (again, as root), use:

        systemctl start wickedd.service

which starts wickedd (main server) and associated supplicants:

	/usr/lib/wicked/bin/wickedd-auto4 --systemd --foreground
	/usr/lib/wicked/bin/wickedd-dhcp4 --systemd --foreground
	/usr/lib/wicked/bin/wickedd-dhcp6 --systemd --foreground
	/usr/sbin/wickedd --systemd --foreground
	/usr/sbin/wickedd-nanny --systemd --foreground

You may then bring up the network using:

        systemctl start wicked.service

also using the network.service alias:

        systemctl start network.service

These commands are using default/system configuration sources as
defined in the /etc/wicked/client.xml file.

To enable debugging, you can currently set the WICKED_DEBUG variable
in /etc/sysconfig/network/config file, e.g. WICKED_DEBUG="all" or
to omit some, WICKED_DEBUG="all,-dbus,-objectmodel,-xpath,-xml"
before the wickedd service is started.


Showing interface status
========================

You can use the client utility to display interface information (xml):

        wicked show-xml all
        wicked show-xml <ifname>


Bringing up one interface
=========================

You can set up single interfaces, too. The easiest way is to call:

        wicked ifup eth0
        wicked ifup wlan0
        ...

since there is no configuration source specified, wicked client checks
its default sources of configuration defined in /etc/wicked/client.xml
that is:

        1) firmware:    ibft firmware
        2) compat:      ifcfg files - implemented for compatibility

whatever it gets from those sources for a given interface is applied.
The intended order of importance is firmware > compat. But this may be
changed in the future.

Please refer to the wicked(8) manpage for details.


Bringing up multiple interfaces
===============================

For bonds and bridges, it may make sense to define the entire device
topology in one file (ifcfg-bondX), and bring it up in one go.

For these, you simply define the device topology in one file, and tell
wicked to bring up the whole configuration by specifying the top level
interface names (of the bridge or bond):

	wicked ifup br0

which automatically sets up the bridge and its dependencies in the
appropriate order without a need to list the dependencies (ports, ...)
separately.

You can also bring up multiple interfaces in one call:

	wicked ifup bond0 br0 br1 br2

or also all interfaces:

	wicked ifup all

As an example, take a look at samples/suse/host5/ directory.
This configuration defines an Ethernet Bridge (ifcfg-bridge42)
with a Dummy port (ifcfg-dummy42).

Assuming you copy the files to standard ifcfg config directory
(that is to /etc/sysconfig/network/), simply call:

	wicked ifup bridge42

and the client will create and bring up the dummy42 first, create
the bridge and add the dummy interface as a port to the bridge.


For testing purposes, you can even use the --ifconfig parameter:

	wicked ifup --ifconfig compat:samples/suse/host5 bridge42

which will bring up the bridge using the config files directly
from the sample directory, but please note: --ifconfig parameter
list disables (overrides) the default configuration search path
and all following commands like "wicked ifstatus" have to use
the same --ifconfig parameter list.


Handling incremental changes
============================

With wicked, there is no need to actually take down an interface
to reconfigure it (unless it's required by the kernel). For instance,
in order to add another IP address or route to a statically configured
network interface, simply add it to the interface definition, and do
another "ifup" operation. The server will try hard to update only
those settings that changed. This applies to link-level options such as
the device mtu or the MAC address, as well as network level settings,
such as addresses, routes, or even address configuration mode (when
moving from a static configuration to, say, DHCP).

Things get tricky of course with virtual interfaces combining several
real devices, like bridges or bonds. For bonded devices, it's not
possible to change certain parameters while the device is up. Doing
that will result in an error.

However, what should still work, is the act of adding or removing the
child devices of a bond or bridge, or choosing a bond's primary interface.


Wicked extensions - address configuration
=========================================

It's not useful to require support for all interface types to be coded in
C. Languages like C are useful when you want to do slightly complex things,
but for many mundane tasks of system configuration, using shell scripts
is still the most natural thing to do.

For that reason, wicked is designed to be extensible via shell scripts.
These extensions can be defined in the config.xml file.

Currently, several diffent classes of extensions are supported:

 *      link configuration: these are scripts responsible for setting
        up a device's link layer according to the configuration
        provided by the client, and for tearing it down again.

 *      address configruation: these are scripts responsible for
        managing a device's address configuration.
        Usually address configuration and DHCP are managed by wicked
        itself, but can be implemented via extensions.

 *      firewall extension: these scripts can apply firewall rules

Typically, extensions have a start and a stop command, an optional
"pid file", and a set of environment variables that get passed to
the script.

To illustrate how this is supposed to work, let's look at how a
firewall extension is defined in etc/server.xml:

  <dbus-service interface="org.opensuse.Network.Firewall">
     <action name="firewallUp"   command="/etc/wicked/extensions/firewall up"/>
     <action name="firewallDown" command="/etc/wicked/extensions/firewall down"/>

     <!-- default environment for all calls to this extension script -->
     <putenv name="WICKED_OBJECT_PATH" value="$object-path"/>
     <putenv name="WICKED_INTERFACE_NAME" value="$property:name"/>
     <putenv name="WICKED_INTERFACE_INDEX" value="$property:index"/>
  </dbus-service>

The extension is attached to dbus-service interface and defines
commands to execute for the actions of this interface. Further,
the declaration can define and initialize environment variables
passed to the actions.

Wicked extensions - configuration files
=======================================

You can extend the handling of configuration files with scripts as well.
For example, DNS updates from leases are ultimately handled by the
extensions/resolver script, with behavior configured in server.xml:

        <system-updater name="resolver">
          <action name="backup" command="/etc/wicked/extensions/resolver backup"/>
          <action name="restore" command="/etc/wicked/extensions/resolver restore"/>
          <action name="install" command="/etc/wicked/extensions/resolver install"/>
          <action name="remove" command="/etc/wicked/extensions/resolver remove"/>
        </system-updater>

When an update arrives in wickedd, the system updater routines parse
the lease and call the appropriate commands (ie. backup, install, etc)
in the resolver script. This in turn configures the DNS settings
using /sbin/netconfig (if it exists on the system), or by manually writing
/etc/resolv.conf as a fallback.

Future wickedness
=================

In the future, it may be useful to extend what wicked supports beyond
the configuration of network interfaces itself.


A Note on the name
==================

Only after I started to show my code to a bunch of people, I found out that
there's a project called WICD, which aims to provide... a network connection
manager :-)

To make this absolutely plain, wicked is in no way related to WICD, for good
or bad. It's just coincidence.

wicked's People

Contributors

boomer41 avatar bytesbymike avatar cfconrad avatar coderliss avatar conan-kudo avatar dzejrou avatar gjuroski avatar hreinecke avatar janzerebecki avatar jcronenberg avatar jimfunk avatar ken23421 avatar kmroz avatar lnussel avatar madanyang avatar mikhailkasimov avatar mmnelemane avatar mtomaschewski avatar mvidner avatar mwilck avatar okirch avatar olafhering avatar pevik avatar pzirnik avatar rma-x avatar rtorrero avatar thkukuk avatar vadorovsky avatar wipawel avatar yadan-fan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wicked's Issues

TODO: network/ifndpproxy

From TODO file:

network/ifndpproxy

  • Currently no ifndp-proxy(5) support in the converter at all [virtualization@ISP != bridged(eth0), “routed” VM IP from same network as the IP assigned to eth0 interface]

TODO: LLDP and DCBX

From TODO file:

  • LLDP and DCBX:
    • Basic LLDP code is there, as well as DCBX TLV encoding/decoding
    • Above all, this needs testing
    • There should be a global setting for enabling/disabling LLDP tx and rx.
    • When a NIC does not support DCB, we spit out an ugly error message. We should not do this
    • When receiving a DCBX message, we currently update the operating params, but never write them back to the kernel.

TODO: interface match

From TODO file:

  • Wicked implements matching by other references than name, AFAIR by mac and by pci bus id currently [as alternative to udev rules]. How complete is the current “match” implementation [e.g. s390 specific things]?

TODO: network/routes

From TODO file:

  • Fix routes / ifroutes parsing [incomplete, see libnetcontrol]

TODO: network/ifsysctl

From TODO file:

network/ifsysctl

  • Currently no ifsysctl(5) support in the converter at all

TODO: hotplugging

From TODO file:

  • hotplugging: there are some parts/mechanisms, status unknown. as wickedd does not read and execute interface configs itself, I suppose this has to be addressed (ifup supports physical interfaces & bonding slaves).

TODO: ifplugd

From TODO file:

  • ifplugd: we could support this in the wicked client using some element.

    For each interface marked this way, wicked would background itself, and monitor linkUp/linkDown events.

TODO: support ppp

From TODO file:

  • support ppp: have a deviceNew method that associates a pppN and use deviceChange to bring up pppd.

TODO: route tables and improve routing support

From TODO file:

  • route tables and improve routing support, implement routing tables/rules rules support to configure simple multihoming.
    Note: Our productive servers (dist.suse.de) require this.

TODO: dhcpv6 renew iBFT adress

From TODO file:

  • try to request (renew) iBFT provided address in iBFT-dhcp mode, but do newer remove it from the interface, even dhcp server suggests other one as this could break mouted iSCSI volumes.

TODO: ifcfg config file converter

From TODO file:

  • ifcfg config file converter

    • Enable the use of the converter by default [by explicit config, … anyhow], so it works out of the box using ifcfg files
    • Currently there are two calls needed:
      • wicked convert --format suse --output /some/path/bond0.xml /etc/sysconfig/network/ifcfg-bond0
      • wicked ifup --ifconfig /some/path/bond0.xml bond0

    Update:

    • wicked ifup compat:/etc/sysconfig/network was recently added

TODO: use reetrant function variants

From TODO file:

  • Fix to use reetrant function variants. Most other code (yast2, libvirt, …) are threaded; the use of some functions or own nonreetrant helper-functions (like ni_sockaddr_print) breaks the use of libwicked to implement e.g. libvirt driver or the use in yast2.

TODO: if-{up,down].d

From TODO file:

if-{up,down].d

  • What about all the “ifup” hooks installed by another software (e.g. samba-client with its MODIFY_SMB_CONF, xen, ...)? I don't think it makes sense to try to call as they are; it would not work because:
    • sysconfig scripts/funcions are not available/installed,
    • different dhcp client in use, … ifup state is not available
    • perhaps they're not needed at all, e.g. samba-client hook needs to be adopted, xen too.

TODO: sysctl

From TODO file:

sysctl: Implemented are: disable_ipv6, autoconf, forwarding, accept_redirects, use_tempaddr. Support more: for IPv6, there are more useful to e.g. to catch corner cases, e.g.: accept_ra, proxy-ndp, ...

TODO: Support all sorts of trigger scripts

From TODO file:

  • Support all sorts of trigger scripts when interfaces are brought up and down. execute scripts from ifup.d and ifdown.d execute {ifup,ifdown}-connections

TODO: source tree

From TODO file:

source tree:
- Cleanup the code and carefully refactor a bit.

TODO: multipath routes

From TODO file:

  • multipath routes nexthop routes over multiple links/gateways + weight

TODO: network/dhcp

From TODO file:

network/dhcp

  • Handle more global dhcp options? I don't see the need now except of SET_HOSTNAME (IMO crap). Currently parsed DHCLIENT_* options are:
    HOSTNAME_OPTION, CLIENT_ID, VENDOR_CLASS_ID, WAIT_AT_BOOT, LEASE_TIME.

TODO: Support for network-root (IBFT / ISCSI, FcoE, NFS)

From TODO file:

  • Support for IBFT / ISCSI, FcoE, NFS, ...
    - Reading/using iBFT firmware as config is incomplete. fw parsing is implemented (shell/extension script) and contains config generation from firmware already, but is incomplete and IMO never tested; no support for e.g. iBFT dns servers yet.
    - Some mechanisms for “nfsroot” are there, IMO untested/incomplete
    - Provide solution for remote-device shutdown order problem:
    There is an shutdown order problem, especially with remotedevices, which are using e.g. LVM which is used also by local disks as well. Current “ifup solution” is that the ISCSI / FcoE scripts are putting interfaces into “nfsroot” mode “on the fly” until shutdown and overriding any STARTMODE setting in the ifcfg configs. This causes to: start the dhcp clients in “persistent” mode, that is never remove any IP address from interface and reject to set link down.

TODO: wicked-nanny

From TODO file:
wicked-nanny:

  • policy daemon (provides NM like functionality)
  • Discover how to deal with it / interview Olaf about ;-) I've looked at it, but have not much idea about / never really tried to effectively use it until now.
    Required to support multiple wlan networks per interface and ifplugd sets?

TODO: firewall

From TODO file:

firewall

  • Integrate SuSEfirewall2 as firewall extension script
  • Currently there is an empty wicked extension script called with “up” and “down” similar as in ifup case [which has also “lock/unlock” batch stuff to save some CPU).
    • just call SuSEfirewall2 from the extension hook.
  • There are also another things in the schema, but seems to be “how we could make more” examples only.
    • Cleanup/Remove the additional examples from firewall schema for now

TODO: dhcpv6

From TODO file:

  • dhcpv6 support
    • It is an initial implementation, not all features complete & enabled yet: currently requesting (and delivering back to wickedd) only non-temporary address and a very minimalistic set of options. Add/enable some important, DHCPv6 specific options and deliver to wicked. The dhcp client <-> server exchange is implemented in most cases, but then data gets discarded.
    • Code reading the netlink info from kernel is already there, but I've not finished it / events data is not processed at the moment: Finish “auto” mode to follow router-advertisment [network admin suggestion] and “info-only” mode [just options, no address needed for tahi?].

TODO: dhcpv4 renew iBFT adress

From TODO file:

  • try to request (renew) iBFT provided address in iBFT-dhcp mode (but do newer remove it from the interface, even the dhcp server suggests other IP; add additionally instead) to not break iSCSI[, ...] devices.

TODO: network/config

From TODO file:

network/config

  • Handle NETCONFIG_* variables somehow
    • Netconfig is currently used by all software to update dns/nis config in the system and add ntp servers to ntpd, that is by ifup(ibft,dhcp,ppp), NetworkManager, openvpn, … avahi [at least if configured].
    • All the variables, especially NETCONFIG_DNS_* and NETCONFIG_*_POLICY are used by yast2 and all sort of modules like yast2-network, yast2-{nis,dhcp,dns} which rely on them / the settings netconfig is applying [e.g. resolv + bind forwarders].
    • Netconfig(8) supports applying of static/static-asfallback and dynamic nis,ntp,dns settings it receives from dhcp/ppp/NM/avahi/VPN software and applying them to system configuration files (/etc/yp.conf, nisdomain, ntpd at runtime) according t destinations as /etc/resolv.conf and/or dnsmasq/bind [forwarder] and provides provides “priority” / “ranking” support , so e.g. nameserver provided by VPN are written to the front of resolv.conf list, before the settings provided by DHCP [same interface as VPN] and when enabled, also from avahi, but as fallback only.
  • Handle other global options? I don't see any now.

TODO: network/ifcfg-*

From TODO file:

  • network/ifcfg-*
    • Complete support of /etc/sysconfig/network/ifcfg-* files [many code has been “cloned+tweaked” for libnetcontrol]
    • Bonding options are IMO incomplete, but may be used in ifcfg files [see bond interface support]; ensure to at least ignore them properly
    • Fix some bridge variable parsing bugs (priority/path-cost parsing)
    • Support the VLAN_ID variable (custom interface names)
    • Support for TUNNEL variable (tun/tap/sit/gre/ipip/..)
    • Convert WIRELESS_* variables, currently dummy code
    • reading only the WIRELESS_ESSID variable
    • Convert also per-network WIRELESS_*[NET]
    • ETHTOOL_OPTIONS[SUFFIX] – it is an array on SLE11-SP2 mandatory
    • Convert BOOTPROTO=ifplugd + IFPLUGD_PRIORITY; Used by default on notebooks with eth+wlan interface to set up an “OR + priority” interfaces sets.
    • SEND_GRATUITOUS_ARP/CHECK_DUPLICATE_IP
    • ??? LABEL[SUFFIX], SCOPE[SUFFIX], IP_OPTIONS[SUFFIX]

TODO: disable parts of the source tree

From TODO file:

  • Beeing able to disable e.g. “ppp” or “wireless” support in the code would be very helpful and help to pass security audit. This would require some refactoring to have all e.g. ppp code in one place...

TODO: ethtool

From TODO file:
ethtool: Most are implemented (offload gso,gro,ufo,tso, …), but not all. Verify: Some (e.g. lro with netxen NIC) can be set after link is up only.

TODO: dhcpv4 fix broadcast vs. unicast

From TODO file:

  • Bug #657402: fix broadcast vs. unicast: dhcp renew is broadcasted [has to be unicast to server] are dropped on gateways/relays [e.g. isco routers], when the server is behind a router. Further, AFAIR other requests were not correctly addressed, too.

TODO: Autoipv6 Support

From TODO file:

  • Autoipv6 Support [in the kernel + daemon directly]
    • Kernel netlink events are received in the daemon
    • Currently “autoip” code feels responsible for IP addresses which were provided by dhcpv6 and causes some confusion/conflicts/error messages [DHCPv4/v6 does not write leases].
    • RDNSS support (nameservers via autoconf): receiving it from kernel is implemented, but currently never used (not written to resolv.conf)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.