Page MenuHomeVyOS Platform

Unbinding VPP interface used by pppoe-server drops all PPPoE session on server
Open, Requires assessmentPublicBUG

Description

delete vpp settings interface <ethN> while pppoe-server has sessions on it commits cleanly —
there is no guard against it. But changing under vpp settings restarts vpp.service, and
accel-pppd is restarted as a side effect of that PPPoE
session on the server is down, including sessions on other interfaces that were never touched.

Steps to reproduce

# r2 (server)
set vpp settings interface eth3
set service pppoe-server interface eth1
set service pppoe-server interface eth3
set service pppoe-server gateway-address '10.255.0.1'
set service pppoe-server client-ip-pool POOL1 range '10.255.0.10-10.255.0.20'
set service pppoe-server default-pool 'POOL1'
set service pppoe-server authentication mode 'local'
set service pppoe-server authentication local-users username rvtest password 'rvtest'
set service pppoe-server authentication local-users username rvtest2 password 'rvtest2'
commit
save
# r1 (client)
configure
set interfaces pppoe pppoe0 source-interface 'eth1'
set interfaces pppoe pppoe0 authentication username 'rvtest'
set interfaces pppoe pppoe0 authentication password 'rvtest'
commit
save

vyos@vpp1-r1:~$ show interfaces pppoe
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
pppoe0           10.255.0.10/32                    u/u
# r3 (client, VPP-bound eth3)
configure
set interfaces pppoe pppoe0 source-interface 'eth1'
set interfaces pppoe pppoe0 authentication username 'rvtest2'
set interfaces pppoe pppoe0 authentication password 'rvtest2'
commit
save

vyos@vpp1-r3:~$ show interfaces pppoe
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
pppoe0           10.255.0.11/32                    u/u  
vyos@vpp1-r3:~$
vyos@vpp1-r2:~$ pgrep -o accel-pppd
38786

vyos@vpp1-r2:~$ show pppoe-server sessions 
 ifname     | username |     ip      | ip6 | ip6-dp |    calling-sid    | rate-limit | state  |  uptime  | rx-bytes | tx-bytes 
----------------+----------+-------------+-----+--------+-------------------+------------+--------+----------+----------+----------
 ppp0           | rvtest   | 10.255.0.10 |     |        | 52:54:00:01:01:00 |            | active | 00:49:38 | 390 B    | 384 B    
 pppoe_session0 | rvtest2  | 10.255.0.11 |     |        | 52:54:00:03:01:00 |            | active | 00:48:21 | 0 B      | 0 B

vyos@vpp1-r2# delete vpp settings interface eth3
[edit]
vyos@vpp1-r2# commit

vyos@vpp1-r2# run show pppoe-server sessions 
 ifname | username | ip | ip6 | ip6-dp | calling-sid | rate-limit | state | uptime | rx-bytes | tx-bytes 
--------+----------+----+-----+--------+-------------+------------+-------+--------+----------+----------
[edit]

vyos@vpp1-r2# pgrep -o accel-pppd
41447
[edit]
vyos@vpp1-r2# run show pppoe-server sessions 
 ifname | username |     ip      | ip6 | ip6-dp |    calling-sid    | rate-limit | state  |  uptime  | rx-bytes | tx-bytes 
--------+----------+-------------+-----+--------+-------------------+------------+--------+----------+----------+----------
 ppp0   | rvtest   | 10.255.0.10 |     |        | 52:54:00:01:01:00 |            | active | 00:02:27 | 222 B    | 216 B    
 ppp1   | rvtest2  | 10.255.0.11 |     |        | 52:54:00:03:01:00 |            | active | 00:01:24 | 222 B    | 216 B

Expected (?)

Either the commit is refused while pppoe-server still depends on the interface, or only the
session actually running on the unbound interface is down.

Actual

accel-pppd restarted immediately (new PID). Both subscriber sessions renegotiated

Details

Version
1.5-rolling-202610191432
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Unspecified (please specify)

Event Timeline

I could reproduce this on a 2026.10.16 rolling image (r2 only: VPP, pppoe-server with local users, two clients behind eth0 and eth2). Two findings, one of them different from the description.

1. The commit is only accepted if VPP keeps another interface. With vpp settings interface eth0 as the only interface, delete vpp settings interface eth0 is refused: "settings interface" is required but not set!. With eth0 and eth2 both in vpp settings, delete vpp settings interface eth0 is accepted without any check (11 s). vpp.py has a guard for removing VPP as a whole ('remove' in config), it looks at the pppoe-server interfaces whose name starts with vpp. I did not test it. There is no check for removing a single interface.

2. accel-pppd is not restarted by the commit, it crashes. The commit runs only the vpp script (commit_scripts: ['vpp']). vpp.service is stopped and started, and accel-pppd gets the link events of the VPP interfaces:

vpp.service Stopping
accel-pppoe: pppoe: delete link event received, stopping the service on: eth0 / eth2
vpp.service Started
accel-pppoe: pppoe: new link event received, starting the service on: eth2 ... (four times within one second)
systemd: accel-ppp@pppoe.service: Main process exited, code=killed, status=6/ABRT

Restart=always of the unit then starts a new accel-pppd (new PID, 5792 -> 6393). All sessions are gone, including pppoe_session1 on eth2, which was not touched, and they came back after 105 s (the clients redial). The same happens when an unrelated VPP setting is deleted (poll-sleep-usec): vpp 3827 -> 4371, accel-pppd 3942 -> 4600, 0 sessions, first session back after about 95 s, and also there the journal shows ABRT. In that run eth2 was a kernel interface and its session dropped as well.

So the restart of VPP alone is enough to drop every session. I did not get a core file (/var/core stayed empty), so I do not know where the abort happens.

I could reproduce this on a 2026.10.16 rolling image (r2 only: VPP, pppoe-server with local users, two clients behind eth0 and eth2). Two findings, one of them different from the description.

1. The commit is only accepted if VPP keeps another interface. With vpp settings interface eth0 as the only interface, delete vpp settings interface eth0 is refused: "settings interface" is required but not set!. With eth0 and eth2 both in vpp settings, delete vpp settings interface eth0 is accepted without any check (11 s). vpp.py has a guard for removing VPP as a whole ('remove' in config), it looks at the pppoe-server interfaces whose name starts with vpp. I did not test it. There is no check for removing a single interface.

2. accel-pppd is not restarted by the commit, it crashes. The commit runs only the vpp script (commit_scripts: ['vpp']). vpp.service is stopped and started, and accel-pppd gets the link events of the VPP interfaces:

vpp.service Stopping
accel-pppoe: pppoe: delete link event received, stopping the service on: eth0 / eth2
vpp.service Started
accel-pppoe: pppoe: new link event received, starting the service on: eth2 ... (four times within one second)
systemd: accel-ppp@pppoe.service: Main process exited, code=killed, status=6/ABRT

Restart=always of the unit then starts a new accel-pppd (new PID, 5792 -> 6393). All sessions are gone, including pppoe_session1 on eth2, which was not touched, and they came back after 105 s (the clients redial). The same happens when an unrelated VPP setting is deleted (poll-sleep-usec): vpp 3827 -> 4371, accel-pppd 3942 -> 4600, 0 sessions, first session back after about 95 s, and also there the journal shows ABRT. In that run eth2 was a kernel interface and its session dropped as well.

So the restart of VPP alone is enough to drop every session.

3. Where it aborts, and the fix. The packaged accel-pppd is stripped, so I built accel-ppp-ng (1.13.0) with debug symbols from the state of 2026-10-07 (dd07b23, the last upstream commit before the image date, not necessarily the exact package) and attached gdb. The same VPP change gives this (function and line only, no session data):

abort ()
triton_md_disable_handler     triton/md.c:235     (epoll_ctl(EPOLL_CTL_DEL) failed, the code aborts)
triton_md_unregister_handler  triton/md.c:139
destroy_ppp_channel           ppp/ppp.c:269       (is_non_dev = 1)
destablish_ppp                ppp/ppp.c:376
ppp_layer_finished            ppp/ppp.c:717
lcp_layer_finished            ppp/ppp_lcp.c:195
ppp_fsm_timeout1              ppp/ppp_fsm.c:193   (LCP restart timer expired)
restart_timer_func            ppp/ppp_fsm.c:526

So the abort is in the teardown of a session that is handled without a ppp device (the VPP sessions), after the LCP timer expired because VPP was stopped. accel-ppp-ng#44 (T9499, "do not close the shared fd of a non-dev ppp session early", merged 2026-10-29) is about this fd. With the build of the merge of #44 (1516b7d) and with current current (9c2c18e), the same VPP change does not abort: accel-pppd keeps its PID, gdb catches no signal, the session on the kernel interface stays up, only the session on the VPP interface ends and the client is back after about 110 s. The image used here is older than that merge, so this needs a retest once an image with a newer accel-ppp-ng exists. The question for the commit itself (refuse the removal of a VPP interface that pppoe-server uses, or accept that its sessions end) stays open, but the crash that took every session with it is no longer part of it.