Skip to main content

DHCP/IPoE Configuration

Configure DHCP subscriber termination for IPoE sessions.

Overview

The dhcp section configures the DHCP/IPoE server (abng-dhcpd), which:

  • Terminates DHCP sessions from IPoE subscribers
  • Authenticates via RADIUS using MAC address
  • Assigns IP addresses from RADIUS or pools
  • Injects Option 82 Circuit ID for subscriber identification

Configuration Options

enabled

Enable or disable DHCP/IPoE (optional).

dhcp:
enabled: true

Type: Boolean
Required: No
Default: false
Valid values: true, false

CLI:

abng# set dhcp enabled true

Note: Requires radius.servers to be configured.

lease_time

DHCP lease time in seconds (optional).

dhcp:
lease_time: 3600

Type: Integer
Required: No
Default: 3600
Constraints: Positive integer (seconds)

Purpose: How long the subscriber can use the assigned IP.

CLI:

abng# set dhcp lease_time 3600

allocation_mode

IP address allocation mode (optional).

dhcp:
allocation_mode: "radius"

Type: String
Required: No
Default: "radius"
Valid values: "radius", "pool"

ModeDescription
radiusIP assigned by RADIUS (Framed-IP-Address)
poolIP assigned from configured pools

In radius mode, abng-dhcpd authenticates the subscriber MAC against RADIUS and the Access-Accept supplies the Framed-IP-Address plus optional rate attributes (Athena-Rate-Down / Athena-Rate-Up). The MAC is sent to RADIUS in lowercase (e.g. aa:bb:cc:dd:ee:ff), which matters for case-sensitive RADIUS user matching.

CLI:

abng# set dhcp allocation_mode "radius"

unnumbered

Use unnumbered IPoE (optional).

dhcp:
unnumbered: true

Type: Boolean
Required: No
Default: true
Valid values: true, false

Purpose: Assign /32 addresses instead of /24 subnets.

CLI:

abng# set dhcp unnumbered true

pools

IP address pools for allocation (optional, required if allocation_mode is "pool").

dhcp:
pools:
- network: "10.100.0.0/23"
gateway: "10.100.0.1"
dns_servers:
- "1.1.1.1"
- "8.8.8.8"

Pool Options

network

Network CIDR for the pool (required).

pools:
- network: "10.100.0.0/23"

Type: CIDR notation
Required: Yes
Constraints: Valid IPv4 CIDR (e.g., "10.100.0.0/23")

gateway

Gateway IP for the pool (required).

pools:
- gateway: "10.100.0.1"

Type: IPv4 address
Required: Yes
Constraints: Valid IPv4 address within the network

dns_servers

DNS servers for the pool (optional).

pools:
- dns_servers:
- "1.1.1.1"
- "8.8.8.8"

Type: List of IPv4 addresses
Required: No
Default: Empty

Example Configurations

RADIUS-Based Allocation

dhcp:
enabled: true
lease_time: 3600
allocation_mode: "radius"
unnumbered: true

IP addresses come from RADIUS Framed-IP-Address attribute.

Pool-Based Allocation

dhcp:
enabled: true
lease_time: 3600
allocation_mode: "pool"
unnumbered: true
pools:
- network: "10.100.0.0/23"
gateway: "10.100.0.1"
dns_servers:
- "1.1.1.1"
- "8.8.8.8"

IP addresses allocated from configured pools.

Multiple Pools

dhcp:
enabled: true
lease_time: 3600
allocation_mode: "pool"
pools:
- network: "10.100.0.0/23"
gateway: "10.100.0.1"
dns_servers: ["1.1.1.1", "8.8.8.8"]

- network: "10.101.0.0/23"
gateway: "10.101.0.1"
dns_servers: ["8.8.8.8", "1.1.1.1"]

Configuration via CLI

Enable DHCP

abng> configure
abng# set dhcp enabled true
abng# commit

Set Lease Time

abng# set dhcp lease_time 7200
abng# commit

Set Allocation Mode

abng# set dhcp allocation_mode "radius"
abng# commit

Add IP Pool

abng# set dhcp pools[0] network "10.100.0.0/23"
abng# set dhcp pools[0] gateway "10.100.0.1"
abng# set dhcp pools[0] dns_servers ["1.1.1.1", "8.8.8.8"]
abng# commit

Verification

View DHCP Configuration

abng> show configuration | match "^dhcp:"
dhcp:
enabled: true
lease_time: 3600
allocation_mode: radius
unnumbered: true
pools:
- network: 10.100.0.0/23
gateway: 10.100.0.1
dns_servers: [1.1.1.1, 8.8.8.8]

View DHCP Sessions

abng> show subscribers dhcp
┌────┬───────┬──────────┬───────────────┬────────────┬──────────┐
│ ID │ Type │ Username │ IP Address │ Interface │ Speed D/U│
├────┼───────┼──────────┼───────────────┼────────────┼──────────┤
5 │ DHCP │ - │ 203.0.113.20 │ eth1.111.5 │ 50M/20M │
6 │ DHCP │ - │ 203.0.113.21 │ eth1.111.6 │ 100M/40M │
└────┴───────┴──────────┴───────────────┴────────────┴──────────┘

Check abng-dhcpd Logs

sudo journalctl -u abng-dhcpd -f

Integration with RADIUS

DHCP requires RADIUS for authentication:

dhcp:
enabled: true
allocation_mode: "radius"

radius:
servers:
- host: "10.255.0.10"
secret: "your-secret"
nas_identifier: "AthenaBNG"
nas_ip_address: "10.255.0.1"

RADIUS attributes used:

  • User-Name — MAC address, lowercase (e.g., "aa:bb:cc:dd:ee:ff")
  • Calling-Station-Id — MAC address
  • NAS-Port-Id — Circuit ID (interface name)
  • Framed-IP-Address — Assigned IP address
  • Framed-IP-Netmask — Subnet mask (/32 for unnumbered)
  • Session-Timeout — Session timeout in seconds
  • Athena-Rate-Down / Athena-Rate-Up — Optional per-subscriber download/upload rates

Integration with QoS

DHCP sessions can have per-subscriber QoS rules:

qos:
enabled: true
default_down: "50mbit"
default_up: "20mbit"
default_overhead_profile: "ipoe_ethernet"

QoS is applied when:

  1. DHCP session is established
  2. RADIUS returns rate attributes (Athena-Rate-Down / Athena-Rate-Up)
  3. CAKE shaping is applied per subscriber — downstream on the subscriber VLAN interface and upstream via a per-session IFB device

Unmetered subscribers: if RADIUS returns no rate attribute, the subscriber is left unmetered (no shaping). There is no implicit default rate — a subscriber with no plan runs unshaped.

Rate changes on renewal: rates re-apply on lease renewal. If the rate returned by RADIUS differs from the active session's, abng-dhcpd / abngd update it and re-apply QoS in place (the per-session IFB is keyed by session id, which is unchanged across a renewal). RADIUS CoA can also change rates mid-session.

IPv6 / DHCPv6-PD

IPoE dual-stack is available. Enable the DHCPv6-PD listener with dhcp.ipv6_enabled, and optionally set the DNS servers advertised to clients with dhcp.ipv6_dns:

dhcp:
ipv6_enabled: true
ipv6_dns:
- "2606:4700:4700::1111"

It follows the same RADIUS-authoritative, no-pool, fail-closed model as PPPoE:

  • IA_PD is delegated from the RADIUS Delegated-IPv6-Prefix; with no delegated prefix from RADIUS the client is answered NoPrefixAvail — never a locally invented prefix.
  • IA_NA is answered NoAddrsAvail — the IPoE WAN address comes via SLAAC (Framed-IPv6-Prefix), not stateful DHCPv6.

Dual-stack session correlation

A DHCPv6 exchange carries no Option-82 circuit-id, so a circuit-only subscriber (authenticated by its access circuit rather than a MAC) could not be matched on its own. AthenaBNG reuses the delegated prefix returned in the subscriber's IPv4 Access-Accept for the DHCPv6-PD request arriving on the same access interface — so one RADIUS authentication provisions the whole dual-stack session. Genuine v6-only subscribers still fall back to their own DHCPv6 (DUID→MAC) authentication.

See IPv6 / Dual-Stack for the full model.

Option 82 (Relay Agent Information)

By default AthenaBNG injects Option 82 with a Circuit ID derived from the subscriber VLAN interface and a Remote ID of the BNG hostname, so upstream RADIUS can identify the access line. The behaviour is configurable under dhcp.option82:

dhcp:
option82:
enabled: true
existing_policy: keep # keep | replace | append
circuit_id_format: "{interface}"
remote_id: "" # empty = BNG hostname; "" omits it
trust_circuit_id: false
OptionPurpose
existing_policyWhat to do when Option 82 is already present (e.g. inserted by an access node): keep, replace, or append.
circuit_id_formatCircuit-ID template; {interface} expands to the subscriber VLAN interface.
remote_idRemote-ID value; empty means the hostname, "" omits it.
trust_circuit_idSee below.

trust_circuit_id

By default an Option 82 circuit-id is only trusted when the packet was relayed (giaddr ≠ 0), so a directly-connected subscriber cannot forge one. Set trust_circuit_id: true on a subscriber trunk fed by a trusted L2 access node — for example an NBN access node that stamps the AVC circuit-id without setting giaddr — so the injected circuit-id (the AVC) is used as the RADIUS NAS-Port-Id. This lets you authenticate subscribers by their access circuit regardless of the CPE behind it.

CLI:

abng# set dhcp option82 trust_circuit_id true

Re-authentication on renewal

Subscribers are re-authenticated against RADIUS on every DHCP renewal, not only at first bind. If RADIUS now rejects a previously-authorised subscriber, its lease is NAK'd and the session is torn down (route withdrawn, Accounting-Stop sent) instead of renewing indefinitely. If RADIUS is unreachable the renewal fails open — the lease is kept — so an AAA outage cannot mass-disconnect established subscribers; only an explicit reject terminates a session.

Lease Persistence

abng-dhcpd persists its active lease table to /opt/athena-bng/run/dhcp-leases.json so a restart of the daemon does not disrupt subscribers. The file is written atomically (temp file + rename) every 30 seconds and again on shutdown.

On startup abng-dhcpd restores the leases from this file:

  • Leases that expired while the daemon was down are dropped.
  • Surviving leases are re-inserted with their IPs reserved in the address pool and marked already-notified (abngd keeps the session across the dhcpd restart).

The effect is that an abng-dhcpd restart no longer NAKs renewing clients or desyncs the address pool — clients keep their lease. Lease and accounting timers are preserved using absolute timestamps, so the remaining lease time survives the restart. RADIUS Accounting-On is still sent at startup and Accounting-Stop/Off at shutdown.

This is automatic and requires no configuration.

Validation Rules

FieldValidation
enabledBoolean
lease_timePositive integer (seconds)
allocation_modeOne of: radius, pool
unnumberedBoolean
pools[].networkValid CIDR notation
pools[].gatewayValid IPv4 address
pools[].dns_serversList of valid IPv4 addresses
option82.existing_policyOne of: keep, replace, append
option82.trust_circuit_idBoolean
ipv6_enabledBoolean
ipv6_dnsList of valid IPv6 addresses

Best Practices

  1. Allocation Mode — Use "radius" for subscriber-specific IPs
  2. Lease Time — Use 3600s (1 hour) for standard DHCP
  3. Unnumbered — Use /32 addresses for IPoE (no subnet)
  4. Pools — Define separate pools for different subscriber classes
  5. RADIUS — Always configure RADIUS for authentication
  6. QoS — Enable QoS for per-subscriber rate limiting
  7. DNS — Configure DNS servers in pools or via RADIUS

Troubleshooting

No DHCP Sessions Appearing

  1. Check DHCP is enabled: show configuration | match dhcp
  2. Check VLAN demux is enabled: show configuration | match demux
  3. Check VLAN interfaces are created: show vlans
  4. Check RADIUS is reachable: radtest testuser testpass <radius-ip> 1812 <secret>
  5. Check abng-dhcpd logs: journalctl -u abng-dhcpd -f

Sessions Not Getting IP

  1. Check allocation mode: show configuration | match allocation_mode
  2. Check pools are configured (if pool mode): show configuration | match pools
  3. Check RADIUS returns Framed-IP-Address (if radius mode)
  4. Check abng-dhcpd logs: journalctl -u abng-dhcpd -f

IP Pool Exhaustion

  1. Check pool size: show configuration | match pools
  2. Check active sessions: show subscribers dhcp | count
  3. Expand pool or reduce lease time
  4. Check for stale leases: journalctl -u abng-dhcpd | grep "lease expired"

Next Steps