FAUCET SDN Controller Documentation

repository·main·Indexed 20 days ago

https://github.com/faucetsdn/faucet

FAUCET is an SDN controller providing a programmable pipeline for OpenFlow switches, including integration for HPE-Aruba wired switches. It utilizes an OpenFlow 1.3 multi-table pipeline for L2/VLAN processing, L3 routing (IPv4/IPv6 FIB), and specialized handling via Coprocessors and VIPs. The documentation covers YAML-based configuration via faucet.yaml, datapath stacking, and deployment using Docker Compose with adapters for FaucetAgent and RabbitMQ (required for Poseidon).

Tokens
42.4K
Snippets
114
Records
156
Agent score
70%

What's inside FAUCET

  1. Overview of FAUCET OpenFlow Controller

    main

    FAUCET is an OpenFlow controller designed for multi-table OpenFlow 1.3 switches (both hardware and software). It implements a wide range of networking functions including:

    • Layer 2: Switching and VLANs (including mixed tagged/untagged ports).
    • Layer 3: IPv4 and IPv6 routing, supporting both static routing and BGP.
    • Security: ACLs matching layer 2 and layer 3 fields.
    • Advanced Networking: Policy-based forwarding to offload to external NFV applications (e.g., 802.1x via hostapd, DHCP via isc DHCPD).
    • Observability: Port and flow statistics via Grafana, and controller health/statistics via Prometheus.

    FAUCET is based on Waikato University's Valve and the Ryu OpenFlow Controller.

  2. Faucet Configuration Overview

    main

    Faucet is configured using a YAML-based file named faucet.yaml. This file defines the network topology, including datapaths (switches), interfaces, VLANs, routers, ACLs, and meters.

    Key Behaviors:

    • Datapath IDs: Can be specified as an integer or a hex string (e.g., 0x1).
    • Port Security: Any port not explicitly defined in the YAML configuration will be left in a 'down' state and will drop all incoming packets.
    • Default Listening Port: Faucet uses port 6653 by default.

    Customization Files: You can customize default settings in:

    • /etc/default/faucet
    • /etc/default/gauge
    • /etc/faucet/ryu.conf
  3. What is Faucet stacking (distributed switching)?

    main

    Faucet operates in two primary modes:

    1. Independent switching: Each decision (learning, routing, etc.) is made within the context of an individual switch.
    2. Distributed switching (Stacking): Decisions like switching and routing are made in the context of the entire network.

    Stacking allows for building resilient network topologies that can automatically recover from switch and port/cable failures by treating multiple physical or virtual switches as a single logical entity.

  4. What is Faucet and Gauge?

    main

    Faucet is an open-source OpenFlow 1.3 controller designed to move network control functions (routing, neighbor discovery, switching) from switch firmware to vendor-independent server software. It is designed to be compact, simple, and highly available.

    There are two main components in the Faucet ecosystem:

    1. Faucet: Controls all forwarding and switch state. It exposes its internal state (e.g., learned hosts) via Prometheus for monitoring with tools like Grafana.
    2. Gauge: An OpenFlow connection component that monitors port and flow state. It exports data to Prometheus or flat text log files. Crucially, Gauge does not modify switch state, allowing monitoring functions to be upgraded or restarted without impacting network forwarding.
  5. Understand FAUCET's architectural assumptions

    main

    FAUCET's design relies on several core assumptions to guarantee a consistent switch state and support high availability without state sharing between controllers:

    • Single Controller Ownership: FAUCET is assumed to be the only controller for the switch capable of adding or removing flows.
    • OpenFlow Uniformity: All supported dataplanes (hardware or software) must implement a functionally identical subset of OpenFlow 1.3. There is no switch-specific driver or TTP layer; the same messages are sent to OVS or hardware.
    • Default Deny Policy: FAUCET provisions default deny flows, meaning all traffic not explicitly programmed is dropped.
    • Minimized Packet-In: FAUCET minimizes the use of packet in messages to reduce competition for the OpenFlow control channel and protect the switch CPU. It achieves this by programming the dataplane to handle flooding where configured. Users are encouraged to use policy-based forwarding (e.g., ACLs) rather than relying on packet in.
  6. How the Faucet OpenFlow Switch Pipeline works

    main

    Faucet uses an OpenFlow 1.3 multi-table pipeline to process packets. The pipeline is modular: tables are only provisioned if the corresponding functionality (like routing) is configured. While table IDs are typically allocated sequentially, you should refer to them by their functional names.

    Key stages of the pipeline include:

    • L2/VLAN Processing: PORT_ACL (port-based ACLs), VLAN (VLAN tagging/untagging and L2 protocol filtering), and VLAN_ACL (VLAN-based ACLs).
    • L2 Learning & Switching: ETH_SRC (handles source MAC learning and routing decisions), ETH_DST_HAIRPIN (handles hairpinning/routing between VLANs on the same port), ETH_DST (standard L2 switching), and FLOOD (broadcast/multicast).
    • L3 Routing: IPV4_FIB and IPV6_FIB (handle IPv4/IPv6 routing, TTL decrement, and MAC rewriting).
    • Specialized Handling: Coprocessor (allows external NFV processors to intercept traffic) and VIP (handles traffic destined for Faucet Virtual IPs, including ARP/ND).
  7. How Faucet scales and achieves high availability

    main

    Faucet is designed for horizontal scaling and high availability through the following principles:

    • Statelessness/Independence: Faucet controllers are not interdependent. You achieve "hot/hot" high availability by provisioning multiple Faucets with the same configuration.
    • Distributed Deployment: A large network can run many Faucet instances spread across multiple machines. Controllers can be deployed as discrete functional units (e.g., one controller per rack) to reduce control plane complexity and latency.
    • Offloaded Forwarding: Faucet offloads all forwarding to the OpenFlow switch, including flooding. It programs the switch pre-emptively to minimize packet processing needs.
    • Multi-table Pipeline: Faucet uses a multi-table packet processing pipeline. This allows for complex flow-based logic while maintaining a smaller number of total flows and improving scalability by using dedicated tables with narrow match fields (e.g., IPv4 or IPv6 FIB tables).
  8. Configure switch stacking in faucet.yaml

    main

    To enable stacking, you must configure two main components in your faucet.yaml:

    1. Stack Priority: Define a stack block with a priority value for each datapath (DP). The datapath with the lowest priority value becomes the root switch of the stack.
    2. Stack Interfaces: For each interface acting as a link between switches, define a stack block specifying the remote datapath (dp) and the remote port (port).

    When configured, Faucet uses LLDP beacons to discover and connect the stack ports automatically.

    dps:
        br0:
            dp_id: 0x1
            hardware: "Open vSwitch"
            stack:
                priority: 1
            interfaces:
                1:
                    description: "host1 network namespace"
                    native_vlan: hosts
                2:
                    description: "br0 stack link to br1"
                    stack:
                        dp: br1
                        port: 2
        br1:
            dp_id: 0x2
            hardware: "Open vSwitch"
            interfaces:
                1:
                    description: "host2 network namespace"
                    native_vlan: hosts
                2:
                    description: "br1 stack link to br0"
                    stack:
                       dp: br0
                       port: 2
  9. Handle redundant stack links and loops

    main

    Faucet can manage stack topologies that contain loops (e.g., a ring topology) without requiring a traditional Spanning Tree Protocol (STP). When Faucet detects a topology change or brings up a stack for the first time, it calculates a spanning tree internally to prevent broadcast loops. This allows for fault-tolerant architectures where the network can survive single link or switch failures.

    To configure a ring topology, define the stack links for each switch in faucet.yaml so that they form a closed loop. Faucet will automatically manage the spanning tree to ensure connectivity while preventing loops.

    # /etc/faucet/faucet.yaml
    
    vlans:
        hosts:
           vid: 100
    dps:
        br0:
            dp_id: 0x1
            hardware: "Open vSwitch"
            stack:
                priority: 1
            interfaces:
                1:
                    description: "host1 network namespace"
                    native_vlan: hosts
                2:
                    description: "br0 stack link to br1"
                    stack:
                        dp: br1
                        port: 2
                3:
                    description: "br0 stack link to br2"
                    stack:
                        dp: br2
                        port: 2
        br1:
            dp_id: 0x2
            hardware: "Open vSwitch"
            interfaces:
                1:
                    description: "host2 network namespace"
                    native_vlan: hosts
                2:
                    description: "br1 stack link to br0"
                    stack:
                       dp: br0
                       port: 2
                3:
                    description: "br1 stack link to br2"
                    stack:
                       dp: br2
                       port: 3
        br2:
            dp_id: 0x3
            hardware: "Open vSwitch"
            interfaces:
                1:
                    description: "host3 network namespace"
                    native_vlan: hosts
                2:
                    description: "br2 stack link to br0"
                    stack:
                       dp: br0
                       port: 3
                3:
                    description: "br2 stack link to br1"
                    stack:
                       dp: br1
                       port: 3