Configuration examples

Example: creating veth interfaces

Everything described in this section — creating veth interfaces, starting BIRD, etc. — must be set in the system startup scripts and run before fastdpi starts.

Suppose the following devices are set in fastdpi.conf:

in_dev=41-00.0
out_dev=41-00.1

Suppose we need to configure the BGP protocol in BIRD for the uplink, that is, on device 41-00.1.

Shadow veth interfaces must be created for each in/out device whose traffic carries routing protocol packets; they require configuration in BIRD. If a device is not involved in routing (like in_dev=41-00.0 in this example), no veth pair is needed for it.

To redirect BGP traffic from 41-00.1 to the routing daemon (BIRD) running in the router netns, we need to create a veth pair of shadow interfaces for 41-00.1.

Create the router netns (the name router is chosen arbitrarily here, you can use another netns name) where BIRD will run:

ip netns add router

Create the veth pair:

ip link add bng-w type veth peer name rib-w netns router

The rib interface must have an IP address (and an IPv6 address if IPv6 is supported):

ip netns exec router ip address add 10.0.0.4/24 broadcast 10.0.0.255 dev rib-w
ip netns exec router ip address add 2098::4/124 dev rib-w
ip netns exec router ip link set dev rib-w arp on
ip netns exec router ethtool -K rib-w tx off

Where:

  • The first two commands assign IPv4 and IPv6 addresses to the rib-w interface. This address will be the BGP peer address for the BGP neighbor.
  • ip link set dev rib-w arp on enables ARP on the interface.
  • ethtool -K rib-w tx off disables hardware checksum calculation (tx checksum offload). On some kernel builds, at least in CentOS 8, the checksum on the interface may be calculated incorrectly.

All commands are run inside the router netns (via ip netns exec router).

The IP addresses of rib interfaces must differ from the SSG IP addresses set by the bras_arp_ip and bras_ipv6_address parameters. Moreover, to avoid unexpected behavior, the bras_arp_ip and bras_ipv6_address addresses must not belong to any subnet diverted to TAP interfaces.

The DPI interface must not have any IPv4 or IPv6 address, because SSG uses it as a TAP interface and does not need addresses on it (moreover, they may even interfere if the interface itself starts generating and sending packets):

ip link set dev bng-w arp off
# Disable IPv6 on bng-* interfaces (so that there is not even a link-local address)
echo 1 > /proc/sys/net/ipv6/conf/bng-w/disable_ipv6

Finally, bring up all the created interfaces:

ip link set bng-w up
ip netns exec router ip link set lo up
ip netns exec router ip link set rib-w up

Remember that the routing daemon (BIRD in this example) must run in the router netns:

ip netns exec router /usr/sbin/bird
By default, network namespaces and veth interfaces created in Linux do not persist after a system reboot. Therefore, create them with a startup script (for example, /usr/local/bin/bng_router.sh) that runs before the routing daemon and fastDPI start — for example, from the routing daemon systemd unit, as in the example below. Start the routing daemon (BIRD) itself with a systemd unit in the router netns.

Example script /usr/local/bin/bng_router.sh:

#!/bin/bash

# BIRD network namespace create and configuring process

/sbin/ip netns add router

# prepare BIRD interfaces
/sbin/ip link add bng-w type veth peer name rib-w
/sbin/ip link set rib-w netns router

# To border
/sbin/ip netns exec router ip link add link rib-w name vlan1111 type vlan id 1111
/sbin/ip netns exec router ip address add 192.168.27.8/28 broadcast 192.168.27.15 dev vlan1111

/sbin/ip netns exec router ip link set dev rib-w arp on

# set tx checksum offload off
/sbin/ip netns exec router ethtool -K rib-w tx off

/sbin/ip link set dev bng-w arp off
echo 1 > /proc/sys/net/ipv6/conf/bng-w/disable_ipv6

# LINKS UP
/sbin/ip netns exec router ip link set lo up
/sbin/ip netns exec router ip link set rib-w up
/sbin/ip netns exec router ip link set vlan1111 up
/sbin/ip link set bng-w up

Example BIRD unit (/etc/systemd/system/bird.netns.service). The unit itself runs the bng_router.sh script before starting BIRD (ExecStartPre), so there is no need to add the script to startup separately:

[Unit]
Description=BIRD Internet Routing Daemon executed in netns "router"
Wants=network.target
After=network.target
Before=fastdpi.service

[Service]
Type=simple
ExecStartPre=/usr/bin/bash /usr/local/bin/bng_router.sh
ExecStartPre=/sbin/ip netns exec router /usr/sbin/bird -p -c /etc/bird.netns.conf
ExecStart=/sbin/ip netns exec router /usr/sbin/bird -c /etc/bird.netns.conf -s /run/bird.netns.ctl -f -u bird -g bird
ExecStartPost=/bin/bash -c "while test ! -e /run/bird.netns.ctl; do sleep 0.5; done && chmod 666 /run/bird.netns.ctl"
ExecReload=/sbin/ip netns exec router /usr/sbin/birdc -s /run/bird.netns.ctl configure
ExecStopPost=/bin/rm -f /run/bird.netns.ctl
Restart=on-failure

[Install]
WantedBy=multi-user.target
When the unit restarts (Restart=on-failure), the bng_router.sh script runs again. The existing netns and veth interfaces are not changed, so no additional existence check is needed in the script.
SSG manages the link state of veth interfaces: if device 41-00.1 goes link down, SSG puts the veth interfaces of this device into link down; as soon as 41-00.1 link comes up, SSG puts the veth interfaces into link up.
What about VLAN?
SSG forwards packets to rib interfaces "as is", without any conversion. This means that if VLANs are present, you need to create VLAN interfaces on the rib interface using Linux tools and bind BIRD to these VLAN interfaces.
VLAN interfaces created on the rib interface must not appear anywhere in fastdpi.conf — specify the two ends of the veth pair as tap and peer.
In router mode, SSG terminates outgoing subscriber traffic into the required VLAN without additional configuration. To originate incoming traffic, enable VLAN traffic processing.
MTU
SSG does not set the MTU on veth interfaces. When configuring veth interfaces, set the MTU using standard Linux tools.

Full router setup (fastdpi.conf + bird.netns.conf + bng_router.sh)

Below is an end-to-end example: SSG with the router, LAG on the LAN and WAN sides, and five VRFs. The BIRD routing daemon runs in the router netns. The three files are consistent with each other: the veth pair names (bng-w/rib-w, bng-static/rib-static), kernel table numbers and subnets match.

1. The startup script /usr/local/bin/bng_router.sh creates the router netns, veth pairs and a VLAN interface. It is run from the bird.netns.service unit before BIRD and fastDPI start.

#!/bin/bash

# BIRD network namespace create and configuring process

/sbin/ip netns add router

# prepare router interfaces
/sbin/ip link add bng-w type veth peer name rib-w
/sbin/ip link set rib-w netns router
/sbin/ip link add bng-static type veth peer name rib-static
/sbin/ip link set rib-static netns router
/sbin/ip netns exec router ip address add 169.254.228.228/32 dev rib-static
/sbin/ip netns exec router ip link add link rib-w name vlan1111 type vlan id 1111
/sbin/ip netns exec router ip address add 192.168.27.101/24 dev vlan1111

/sbin/ip netns exec router ip link set dev rib-w arp on
/sbin/ip netns exec router ip link set dev rib-static arp on
/sbin/ip netns exec router ethtool -K rib-static tx off
/sbin/ip netns exec router ethtool -K rib-w tx off
/sbin/ip link set dev bng-w arp off
/sbin/ip link set dev bng-static arp off

/sbin/ip link set bng-w up
/sbin/ip link set bng-static up
/sbin/ip netns exec router ip link set lo up
/sbin/ip netns exec router ip link set rib-w up
/sbin/ip netns exec router ip link set rib-static up

/sbin/ip netns exec router ip link set vlan1111 up

exit 0
The lo loopback interface in the router netns does not need separate configuration: it automatically gets the 127.0.0.1/8 address when the netns is created; the script only brings it up with ip link set lo up.

2. SSG configuration — add the router parameters (router, router_netns, router_default_vrf, etc.) and the lag, router_device and router_vrf sections to /etc/dpi/fastdpi.conf. The router_max_ip4_route_count and router_max_ip6_route_count values in the example are for demonstration only: for a real routing table (for example, a BGP full view), set them according to the recommendations on the Parameters and values page.

# FastDPI configuration parameters
#
# Interface pairs for ethernet bridge
#
# For example this setup
#  in_dev=01-00.0:01-00.2
#  out_dev=01-00.1:01-00.3
# creates following bridges:
#  01-00.0 <--> 01-00.1
#  01-00.2 <--> 01-00.3
#
dpdk_device=10:pci:00:13.0,desc='To subscriber'
dpdk_device=11:pci:00:14.0,desc='To internet'
dpdk_device=20:pci:00:16.0,desc='To subscriber'
dpdk_device=21:pci:00:15.0,desc='To internet'
in_dev=10:20
out_dev=11:21
router_max_ip4_route_count=100
router_max_ip6_route_count=20

#Scale factor is about 1 for every 1 Gigabit of total bandwidth
scale_factor=1
num_threads=2

#FDPI/CLI Control
ctrl_port=29000
ctrl_dev=lo

federal_black_list=False

black_list_redirect=http://vasexperts.ru/test/blocked.php
nat_exclude_private=1
mem_preset=1
forward_packet_priority=6
enable_auth=1
enable_acct=1
netflow=4
netflow_timeout=60
auth_servers=127.0.0.1%lo:29002
bras_enable=1
bras_arp_ip=127.0.0.1
bras_arp_mac=be:be:be:be:be:be
bras_dhcp_mode=2
bras_dhcp_ratelimit=16
bras_dhcp_disconnect=0x000B
bras_dhcp_timeout=17
bras_terminate_l2=1
bras_arp_proxy=0x006
bras_term_by_as=0
bras_terminate_local=0
bras_vlan_terminate=0
bras_dhcp_shcv_interval=60
bras_subs_id=qinq+mac,vlan+mac,mac
router_default_vrf=vrf-grt
router=1
router_netns=router
router_kernel_table=101
router_subs_announce=6
# BEGIN LAG CONFIGURATION
lag {
  name=WAN
  short_timeout=on
  lacp=2
  device=11
  device=21
}
# END LAG CONFIGURATION
# BEGIN LLDP CONFIGURATION
lldp {
  enable=on
  device=10;desc=Te1/1;enable=on
  device=20;desc=Te2/2;enable=on
  device=11;desc=Te1/1;enable=on
  device=21;desc=Te2/2;enable=on
  system_name=bras800demo
  system_desc=172.16.2.1/32
}
# END LLDP CONFIGURATION
# BEGIN IN LAG CONFIGURATION
lag {
  name=LAN
  short_timeout=on
  lacp=2
  device=10
  device=20
}
# END IN LAG CONFIGURATION
# BEGIN ROUTER DEVICES CONFIGURATION
router_device {
  vrf=vrf-grt
  device=11
  tap=bng-w
  peer=rib-w
  subnet=224.0.0.5/32
  subnet=224.0.0.6/32
  subnet=172.16.25.169/31
  subnet=192.168.27.101/24
}
# END ROUTER DEVICES CONFIGURATION
# BEGIN ROUTER STATIC-DEVICE CONFIGURATION
router_device {
  vrf=vrf-static
  device=11
  tap=bng-static
  peer=rib-static
  subnet=169.254.228.228/32
}
# END ROUTER STATIC-DEVICE CONFIGURATION
# BEGIN VRFs CONFIGURATION
router_vrf {
  id=vrf-grt
  netns=router
  kernel_table=200
  neighbor_cache=shared
}
router_vrf {
  id=vrf-local
  netns=router
  kernel_table=203
  neighbor_cache=shared
}
router_vrf {
  id=vrf-inet
  netns=router
  kernel_table=202
  neighbor_cache=shared
}
router_vrf {
  id=vrf-static
  netns=router
  kernel_table=204
  neighbor_cache=shared
}
router_vrf {
  id=vrf-iptv
  netns=router
  kernel_table=201
  neighbor_cache=shared
}
# END VRFs CONFIGURATION
bras_vrf_isolation=1
netflow_bill_method=1
ipfix_dev=vlanens18
ipfix_nat_udp_collectors=172.16.2.1:12345
ipfix_mtu_limit=1460
ajb_udpi_path=/mnt/dump/dpi
syslog_level=4

3. BIRD configuration — /etc/bird.netns.conf: tables for each VRF, kernel protocols (table numbers match kernel_table in fastdpi.conf), static routes, a BGP session with the uplink and pipes between tables.

log syslog name "bird.netns" {  trace, info, remote, warning, error, auth, fatal, bug };
#log "/var/log/bird.log" { info, remote, warning, error, auth, fatal, bug };
router id 192.168.27.101;
ipv4 table master4;
ipv4 table GRT;
ipv4 table LOCAL;
ipv4 table INET;
ipv4 table STATIC;
ipv4 table IPTV;
ipv4 table LNS;

protocol device {
}
protocol direct {
    ipv4 {table GRT;};            # Connect to default IPv4 table
    ipv6;            # ... and to default IPv6 table
}
function is_public() {
        if net !~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
                return true;
        return false;
}
function is_private() {
        if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
                return true;
        return false;
}
filter default_gw {
        if net ~ [0.0.0.0/0] || net ~ [9.0.0.0/8+] then
                accept;
        reject;
}
filter local_pub_and_pr_subnet {
        if (source = RTS_INHERIT || source = RTS_STATIC) && (is_public() || (is_private() && (net.len != 32))) && (net !~ [0.0.0.0/0]) then
                accept;
        reject;
}
filter local_pr_subnet {
        if (source = RTS_INHERIT) && is_private() && (net.len != 32) && (net !~ [ 2.92.40.0/21+ ] ) then
                accept;
        reject;
}

filter mcpe_proto_import {
        if net ~ [10.255.102.224/28] then
                accept;
        reject;
}
filter mcpe_proto_export {
        if proto = "INETstatic" then
                accept;
        reject;
}
protocol kernel {
        ipv4 {
            table master4;
            import all;
            export all;
        };
        learn;
}

protocol kernel k_grt {
    ipv4 {
        table GRT;
        import all;
        export all;
    };
    learn;
    kernel table 200;
}
protocol kernel k_local {
    ipv4 {
        table LOCAL;
        import all;
        export all;
    };
    learn;
    kernel table 203;
}
protocol kernel k_inet {
    ipv4 {
        table INET;
        import all;
        export all;
    };
    learn;
    kernel table 202;
}
protocol kernel k_static {
    ipv4 {
        table STATIC;
        import all;
        export all;
    };
    learn;
    kernel table 204;
}
protocol kernel k_iptv {
    ipv4 {
        table IPTV;
        import all;
        export all;
    };
    learn;
    kernel table 201;
}

protocol static masterstatic {
    ipv4 {table master4;};
    # route <c.i.d.r/xx> via <i.p.n.h>
    route 0.0.0.0/0 via 172.16.25.168 ;
    route 192.168.10.5/32 via 169.254.228.1;
}

protocol static GRTstatic {
    ipv4 {table GRT;};            # Again, IPv4 channel with default options
    route 0.0.0.0/0 via 172.16.25.168 ;

}
protocol static LOCALstatic {
    ipv4 {table LOCAL;};            # Again, IPv4 channel with default options
                        route 172.16.12.0/24 via "rib-w";
            route 172.16.13.0/24 via "rib-w";
            }
protocol static IPTVstatic {
    ipv4 {table IPTV;};            # Again, IPv4 channel with default options
                    route 172.16.11.0/24 via "rib-w";
                }
protocol static INETstatic {
    ipv4 {table INET;};            # Again, IPv4 channel with default options
                route 172.16.10.0/24 via "rib-w";
                    }

protocol bgp uplink1 {
    debug { states };
    description "to uplink1";
    local 192.168.27.101 as 65000;
    neighbor 172.16.25.168 as 65000 internal;
    multihop;
    ipv4 {
        next hop self;
        table GRT;
        import all;
        export filter local_pub_and_pr_subnet;
    };
}

protocol pipe grt_iptv {
    table GRT;
    peer table IPTV;
    import filter local_pub_and_pr_subnet;
    export filter default_gw;
}
protocol pipe grt_inet {
    table GRT;
    peer table INET;
    import filter local_pub_and_pr_subnet;
    export filter default_gw;
}
protocol pipe grt_static {
    table GRT;
    peer table STATIC;
    import filter local_pub_and_pr_subnet;
    export filter default_gw;
}
protocol pipe grt_local {
    table GRT;
    peer table LOCAL;
    import filter local_pub_and_pr_subnet;
    export filter default_gw;
}

SSG configuration example without VRF

The router can be configured both without VRF and with VRF. If no router_vrf sections are set, SSG works with one default VRF: its netns and routing table are set by the router_netns and router_kernel_table parameters.

File: /etc/dpi/fastdpi.conf. Minimal router configuration for the bng_router.sh script example above (address 192.168.27.8/28 on the VLAN interface over rib-w) — add to fastdpi.conf:

in_dev=41-00.0
out_dev=41-00.1

router=1
router_netns=router
router_kernel_table=1

bras_arp_mac=00:E0:ED:43:84:42
bras_arp_ip=188.227.73.40

router_device {
    device=41-00.1
    tap=bng-w
    peer=rib-w
    subnet=192.168.27.0/28
}

In subnet, specify only the rib-w address or the smallest subnet that contains the rib-w address and the BGP neighbor address. In the example, this is 192.168.27.0/28: it contains the rib-w address (192.168.27.8) and the BGP neighbor (192.168.27.1) from Simple example: BGP and static routes.

The routing daemon must build the kernel routing table with the same number: in BIRD — kernel table 1 in the kernel protocol.

VRF configuration example in SSG

File: /etc/dpi/fastdpi.conf. Example of a full configuration with the router enabled and two VRFs (add it as a whole or use it as a basis for your own configuration):

in_dev=0b-00.0
out_dev=13-00.0

scale_factor=1

ctrl_port=29000
ctrl_dev=lo

federal_black_list=0
black_list_sm=1
black_list_redirect=http://vasexperts.ru/test/blocked.php

num_threads=1

router=1
router_netns=router
router_kernel_table=100
router_default_vrf=ROUTER

router_vrf {
      id=ROUTER
      netns=router
      kernel_table=100
      neighbor_cache=shared
}

router_vrf {
      id=ROUTER2
      netns=router
      kernel_table=101
      neighbor_cache=shared
}
router_device {
      device=13-00.0
      vrf=ROUTER
      tap=dpi_ospf
      peer=rib_ospf
      subnet=224.0.0.5/32
      subnet=224.0.0.6/32
      subnet=192.168.123.69/32
}
router_device {
      device=13-00.0
      vrf=ROUTER2
      tap=dpi_bgp
      peer=rib_bgp
      subnet=192.168.123.70/32
}
router_subs_announce=6

enable_auth=1
auth_servers=127.0.0.1%lo:29002
bras_enable=1
bras_arp_ip=10.10.102.189
bras_arp_mac=00:0c:29:f5:85:47
bras_dhcp_mode=1
bras_dhcp_server=10.10.99.3%ens256;reply_port=67
bras_pppoe_enable=1
bras_pppoe_session=100
bras_ppp_auth_list=2,3,1

enable_acct=1
netflow=4
netflow_timeout=300
bras_pppoe_service_name=demoDPI

Simple example: BGP and static routes

Simple BGP example:

filter public_subnets {
        if (net ~ [172.16.0.0/12+] || net ~ [192.168.0.0/16+] || net ~ [10.0.0.0/8+] || net ~ [127.0.0.0/8+] || net ~ [169.254.0.0/16+]) then reject;
        accept;
}

protocol bgp bgp_ipv4 {
        description "To border";
        local 192.168.27.8 as 65000;
        neighbor 192.168.27.1 as 65000;
        direct;

        ipv4 {
                import all;
                export filter public_subnets;
        };
}

Example of a static route for announcing a wide subscriber subnet as a whole:

protocol static {
        ipv4;
        route 100.69.0.0/16 blackhole;
}

BIRD configuration example (OSPF + VRF)

The example shows a particular case; for more information, refer to the documentation of the specific routing daemon. In the context of VRF Lite on the Linux architecture that SSG runs on, BIRD is a better fit.
# Define helper functions for checks:

# Any public address
function is_public() {
      if net !~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
            return true;
      return false;
}

# Any private address
function is_private() {
      if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
            return true;
      return false;
}

# Default gateway
filter default_gw {
      if net ~ [0.0.0.0/0] then
            accept;
      reject;
}

# Define filters:
# Routes not received from other routing protocols (and prefix is not /32)
filter exclude_external_routes {
      if (source = RTS_INHERIT) && (net.len != 32) then
            accept;
      reject;
}

# Exclude routes from other routing protocols; public subnets, private ones — not /32
filter exclude_ext_1_ip {
      if (source = RTS_INHERIT) && (is_public() || (is_private() && (net.len != 32))) then
            accept;
      reject;
}

log "/var/log/bird.log" all;
router id 192.168.123.65;

debug protocols all;

# Define tables
ipv4 table grt;
ipv4 table bird00;
ipv4 table bird01;

protocol device {
}

protocol direct {
      disabled;         # Disabled by default
      ipv4;             # Connect to the default IPv4 table
      ipv6;             # ... and to the default IPv6 table
}

# Define kernel "protocols"
protocol kernel kernel_grt {
      ipv4 {                  # Connect the protocol to the IPv4 table via a channel
            table grt;
            import all; # Import to the table; default — import all
            export all; # Export to the protocol; default — no export
      };
      scan time 5;
      learn;                  # Learn routes coming from the kernel table
      kernel table 99;  # Kernel table to sync with (default: main)
}
protocol kernel kernel_bird00 {
      ipv4 {                  # Connect the protocol to the IPv4 table via a channel
            table bird00;
            import all; # Import to the table; default — import all
            export all; # Export to the protocol; default — no export
      };
      scan time 5;
      learn;                  # Learn routes coming from the kernel table
      kernel table 100; # Kernel table to sync with (default: main)
}

protocol kernel kernel_bird01 {
      ipv4 {                  # Connect the protocol to the IPv4 table via a channel
            table bird01;
            import all; # Import to the table; default — import all
            export all; # Export to the protocol; default — no export
      };
      scan time 20;
      learn;                  # Learn routes coming from the kernel table
      kernel table 101; # Kernel table to sync with (default: main)
}

# Another instance for IPv6, skipping default options
protocol kernel {
      ipv6 { export all; };
}

protocol static {
      ipv4;             # Again, IPv4 channel with default options

}

# OSPF protocols (each instance with its own table)
protocol ospf v2 ospf_grt {
        tick 1;
        rfc1583compat no;
      stub router no;
      ecmp yes limit 16;
        ipv4 {
            table grt;
                import all;
            export all;
        };
        area 0.0.0.0 {
                networks {
                        192.168.123.64/30;
                };
                interface "rib.102" {
                        cost 1;
                        rx buffer large;
                  type broadcast;
                  authentication none;
               };
         };
};
protocol ospf v2 ospf_bird01 {
        tick 1;
        rfc1583compat no;
      ecmp yes limit 16;
        ipv4 {
            table bird01;
                import all;
                export all;
            #export filter exclude_ext_1_ip;
        };
        area 0.0.0.0 {
                networks {
                        192.168.123.68/30;
                };
                interface "rib.202" {
                        cost 1;
                        rx buffer large;
                  type broadcast;
                  authentication none;
               };
         };
}

# Define routing "protocols" for leaking routes between tables (using filters)
protocol pipe grt_bird00 {
      table grt;
      peer table bird00;
      import all;
      export filter default_gw;
}
protocol pipe grt_bird01 {
      table grt;
      peer table bird01;
      import all; # filter exclude_ext_1_ip;
      export all; #filter default_gw;
}

Was this information helpful?