diff --git a/data/templates/accel-ppp/l2tp.config.j2 b/data/templates/accel-ppp/l2tp.config.j2
index 89cc0eae7..49755254a 100644
--- a/data/templates/accel-ppp/l2tp.config.j2
+++ b/data/templates/accel-ppp/l2tp.config.j2
@@ -1,161 +1,98 @@
 ### generated by accel_l2tp.py ###
 [modules]
 log_syslog
 l2tp
-chap-secrets
-{% for proto in auth_proto %}
-{{ proto }}
-{% endfor %}
-{% if auth_mode == 'radius' %}
-radius
-{% endif %}
-ippool
 shaper
-ipv6pool
-ipv6_nd
-ipv6_dhcp
+{# Common authentication backend definitions #}
+{% include 'accel-ppp/config_modules_auth_mode.j2' %}
+ippool
+{# Common IPv6 definitions #}
+{% include 'accel-ppp/config_modules_ipv6.j2' %}
+{# Common authentication protocols (pap, chap ...) #}
+{% include 'accel-ppp/config_modules_auth_protocols.j2' %}
 
 [core]
-thread-count={{ thread_cnt }}
+thread-count={{ thread_count }}
 
 [common]
 {% if max_concurrent_sessions is vyos_defined %}
 max-starting={{ max_concurrent_sessions }}
 {% endif %}
 
 [log]
 syslog=accel-l2tp,daemon
 copy=1
 level=5
 
-{% if dnsv4 %}
-[dns]
-{%     for dns in dnsv4 %}
-dns{{ loop.index }}={{ dns }}
-{%     endfor %}
-{% endif %}
+{# Common DNS name-server definition #}
+{% include 'accel-ppp/config_name_server.j2' %}
 
-{% if dnsv6 %}
-[ipv6-dns]
-{%     for dns in dnsv6 %}
-{{ dns }}
-{%     endfor %}
-{% endif %}
-
-{% if wins %}
+{% if wins_server is vyos_defined %}
 [wins]
-{%     for server in wins %}
+{%     for server in wins_server %}
 wins{{ loop.index }}={{ server }}
 {%     endfor %}
 {% endif %}
 
 [l2tp]
 verbose=1
 ifname=l2tp%d
 ppp-max-mtu={{ mtu }}
-mppe={{ ppp_mppe }}
-{% if outside_addr %}
-bind={{ outside_addr }}
+mppe={{ ppp_options.mppe }}
+{% if outside_address is vyos_defined %}
+bind={{ outside_address }}
 {% endif %}
-{% if lns_shared_secret %}
-secret={{ lns_shared_secret }}
+{% if lns.shared_secret is vyos_defined %}
+secret={{ lns.shared_secret }}
 {% endif %}
-{% if lns_host_name %}
-host-name={{ lns_host_name }}
+{% if lns.host_name is vyos_defined %}
+host-name={{ lns.host_name }}
 {% endif %}
 {% if default_pool is vyos_defined %}
 ip-pool={{ default_pool }}
 {% endif %}
 
 [client-ip-range]
 0.0.0.0/0
 
 {# Common IP pool definitions #}
 {% include 'accel-ppp/config_ip_pool.j2' %}
 
-{% if auth_mode == 'local' %}
-[chap-secrets]
-chap-secrets={{ chap_secrets_file }}
-{% elif auth_mode == 'radius' %}
-[radius]
-verbose=1
-{%     for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
-{%     endfor %}
-{%     if radius_dynamic_author.server is vyos_defined %}
-dae-server={{ radius_dynamic_author.server }}:{{ radius_dynamic_author.port }},{{ radius_dynamic_author.key }}
-{%     endif %}
-{%     if radius_acct_interim_interval is vyos_defined %}
-acct-interim-interval={{ radius_acct_interim_interval }}
-{%     endif %}
-{%     if radius_acct_inter_jitter %}
-acct-interim-jitter={{ radius_acct_inter_jitter }}
-{%     endif %}
-acct-timeout={{ radius_acct_tmo }}
-timeout={{ radius_timeout }}
-max-try={{ radius_max_try }}
-{%     if radius_nas_id %}
-nas-identifier={{ radius_nas_id }}
-{%     endif %}
-{%     if radius_nas_ip %}
-nas-ip-address={{ radius_nas_ip }}
-{%     endif %}
-{%     if radius_source_address %}
-bind={{ radius_source_address }}
-{%     endif %}
-{% endif %}
-{% if gateway_address is vyos_defined %}
-gw-ip-address={{ gateway_address }}
-{% endif %}
+{# Common chap-secrets and RADIUS server/option definitions #}
+{% include 'accel-ppp/config_chap_secrets_radius.j2' %}
 
 [ppp]
 verbose=1
 check-ip=1
 single-session=replace
-lcp-echo-timeout={{ ppp_echo_timeout }}
-lcp-echo-interval={{ ppp_echo_interval }}
-lcp-echo-failure={{ ppp_echo_failure }}
-{% if ccp_disable %}
+lcp-echo-interval={{ ppp_options.lcp_echo_interval }}
+lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }}
+lcp-echo-failure={{ ppp_options.lcp_echo_failure }}
+{# MTU #}
+mtu={{ mtu }}
+ipv6={{ 'allow' if ppp_options.ipv6 is vyos_defined("deny") and client_ipv6_pool is vyos_defined else ppp_options.ipv6 }}
+ipv4={{ ppp_options.ipv4 }}
+mppe={{ ppp_options.mppe }}
+{% if ccp_disable is vyos_defined %}
 ccp=0
 {% endif %}
-{% if ppp_ipv6 is vyos_defined %}
-ipv6={{ ppp_ipv6 }}
-{% else %}
-{{ 'ipv6=allow' if client_ipv6_pool_configured else '' }}
-{% endif %}
-{% if ppp_ipv6_intf_id is vyos_defined %}
-ipv6-intf-id={{ ppp_ipv6_intf_id }}
-{% endif %}
-{% if ppp_ipv6_peer_intf_id is vyos_defined %}
-ipv6-peer-intf-id={{ ppp_ipv6_peer_intf_id }}
-{% endif %}
-ipv6-accept-peer-intf-id={{ "1" if ppp_ipv6_accept_peer_intf_id else "0" }}
+unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }}
 
-{% if client_ipv6_pool %}
-[ipv6-pool]
-{%     for p in client_ipv6_pool %}
-{{ p.prefix }},{{ p.mask }}
-{%     endfor %}
-{%     for p in client_ipv6_delegate_prefix %}
-delegate={{ p.prefix }},{{ p.mask }}
-{%     endfor %}
+{% if ppp_options.ipv6_intf_id is vyos_defined %}
+ipv6-intf-id={{ ppp_options.ipv6_intf_id }}
 {% endif %}
-
-{% if client_ipv6_delegate_prefix %}
-[ipv6-dhcp]
-verbose=1
+{% if ppp_options.ipv6_peer_intf_id is vyos_defined %}
+ipv6-peer-intf-id={{ ppp_options.ipv6_peer_intf_id }}
 {% endif %}
+ipv6-accept-peer-intf-id={{ "1" if ppp_options.ipv6_accept_peer_intf_id is vyos_defined else "0" }}
 
-{% if radius_shaper_attr %}
-[shaper]
-verbose=1
-attr={{ radius_shaper_attr }}
-{%     if radius_shaper_vendor %}
-vendor={{ radius_shaper_vendor }}
-{%     endif %}
-{% endif %}
+{# Common IPv6 pool definitions #}
+{% include 'accel-ppp/config_ipv6_pool.j2' %}
+
+{# Common RADIUS shaper configuration #}
+{% include 'accel-ppp/config_shaper_radius.j2' %}
 
 [cli]
 tcp=127.0.0.1:2004
 sessions-columns=ifname,username,calling-sid,ip,{{ ip6_column | join(',') }}{{ ',' if ip6_column }}rate-limit,type,comp,state,rx-bytes,tx-bytes,uptime
 
diff --git a/data/templates/accel-ppp/sstp.config.j2 b/data/templates/accel-ppp/sstp.config.j2
index 6117cea1b..014ae1235 100644
--- a/data/templates/accel-ppp/sstp.config.j2
+++ b/data/templates/accel-ppp/sstp.config.j2
@@ -1,71 +1,72 @@
 ### generated by vpn_sstp.py ###
 [modules]
 log_syslog
 sstp
 shaper
 {# Common authentication backend definitions #}
 {% include 'accel-ppp/config_modules_auth_mode.j2' %}
 ippool
 {# Common IPv6 definitions #}
 {% include 'accel-ppp/config_modules_ipv6.j2' %}
 {# Common authentication protocols (pap, chap ...) #}
 {% include 'accel-ppp/config_modules_auth_protocols.j2' %}
 
 [core]
 thread-count={{ thread_count }}
 
 [common]
 single-session=replace
 {% if max_concurrent_sessions is vyos_defined %}
 max-starting={{ max_concurrent_sessions }}
 {% endif %}
 
 [log]
 syslog=accel-sstp,daemon
 copy=1
 level=5
 
 [client-ip-range]
 disable
 
 [sstp]
 verbose=1
 ifname=sstp%d
 port={{ port }}
 accept=ssl
 ssl-ca-file=/run/accel-pppd/sstp-ca.pem
 ssl-pemfile=/run/accel-pppd/sstp-cert.pem
 ssl-keyfile=/run/accel-pppd/sstp-cert.key
 {% if default_pool is vyos_defined %}
 ip-pool={{ default_pool }}
 {% endif %}
 
 {# Common IP pool definitions #}
 {% include 'accel-ppp/config_ip_pool.j2' %}
 
 {# Common IPv6 pool definitions #}
 {% include 'accel-ppp/config_ipv6_pool.j2' %}
 
 {# Common DNS name-server definition #}
 {% include 'accel-ppp/config_name_server.j2' %}
 
 {# Common chap-secrets and RADIUS server/option definitions #}
 {% include 'accel-ppp/config_chap_secrets_radius.j2' %}
 
 [ppp]
 verbose=1
 check-ip=1
 {# MTU #}
 mtu={{ mtu }}
+unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }}
 ipv6={{ 'allow' if ppp_options.ipv6 is vyos_defined("deny") and client_ipv6_pool is vyos_defined else ppp_options.ipv6 }}
 ipv4={{ ppp_options.ipv4 }}
 mppe={{ ppp_options.mppe }}
 lcp-echo-interval={{ ppp_options.lcp_echo_interval }}
 lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }}
 lcp-echo-failure={{ ppp_options.lcp_echo_failure }}
 
 {# Common RADIUS shaper configuration #}
 {% include 'accel-ppp/config_shaper_radius.j2' %}
 
 [cli]
 tcp=127.0.0.1:2005
diff --git a/interface-definitions/include/accel-ppp/auth-protocols.xml.i b/interface-definitions/include/accel-ppp/auth-protocols.xml.i
index d43266152..4ab4753bb 100644
--- a/interface-definitions/include/accel-ppp/auth-protocols.xml.i
+++ b/interface-definitions/include/accel-ppp/auth-protocols.xml.i
@@ -1,31 +1,31 @@
 <!-- include start from accel-ppp/auth-protocols.xml.i -->
 <leafNode name="protocols">
   <properties>
-    <help>Authentication protocol for remote access peer SSTP VPN</help>
+    <help>Authentication protocol for remote access peer</help>
     <completionHelp>
       <list>pap chap mschap mschap-v2</list>
     </completionHelp>
     <valueHelp>
       <format>pap</format>
       <description>Authentication via PAP (Password Authentication Protocol)</description>
     </valueHelp>
     <valueHelp>
       <format>chap</format>
       <description>Authentication via CHAP (Challenge Handshake Authentication Protocol)</description>
     </valueHelp>
     <valueHelp>
       <format>mschap</format>
       <description>Authentication via MS-CHAP (Microsoft Challenge Handshake Authentication Protocol)</description>
     </valueHelp>
     <valueHelp>
       <format>mschap-v2</format>
       <description>Authentication via MS-CHAPv2 (Microsoft Challenge Handshake Authentication Protocol, version 2)</description>
     </valueHelp>
     <constraint>
       <regex>(pap|chap|mschap|mschap-v2)</regex>
     </constraint>
     <multi/>
   </properties>
   <defaultValue>pap chap mschap mschap-v2</defaultValue>
 </leafNode>
 <!-- include end -->
diff --git a/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i b/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i
index b4008a63b..5661bdc05 100644
--- a/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i
+++ b/interface-definitions/include/accel-ppp/mtu-128-16384.xml.i
@@ -1,11 +1,11 @@
 <!-- include start from accel-ppp/mtu-128-16384.xml.i -->
 <leafNode name="mtu">
   <properties>
-    <help>Maximum Transmission Unit (MTU) - default 1492</help>
+    <help>Maximum Transmission Unit (MTU)</help>
     <constraint>
       <validator name="numeric" argument="--range 128-16384"/>
     </constraint>
   </properties>
   <defaultValue>1492</defaultValue>
 </leafNode>
 <!-- include end -->
diff --git a/interface-definitions/include/version/l2tp-version.xml.i b/interface-definitions/include/version/l2tp-version.xml.i
index 89edb160c..f4507d93b 100644
--- a/interface-definitions/include/version/l2tp-version.xml.i
+++ b/interface-definitions/include/version/l2tp-version.xml.i
@@ -1,3 +1,3 @@
 <!-- include start from include/version/l2tp-version.xml.i -->
-<syntaxVersion component='l2tp' version='5'></syntaxVersion>
+<syntaxVersion component='l2tp' version='6'></syntaxVersion>
 <!-- include end -->
diff --git a/interface-definitions/vpn-l2tp.xml.in b/interface-definitions/vpn-l2tp.xml.in
index 7980cfdf5..3e2d00e6b 100644
--- a/interface-definitions/vpn-l2tp.xml.in
+++ b/interface-definitions/vpn-l2tp.xml.in
@@ -1,255 +1,163 @@
 <?xml version="1.0"?>
 <interfaceDefinition>
   <node name="vpn">
     <children>
       <node name="l2tp" owner="${vyos_conf_scripts_dir}/vpn_l2tp.py">
         <properties>
           <help>L2TP Virtual Private Network (VPN)</help>
           <priority>902</priority>
         </properties>
         <children>
           <node name="remote-access">
             <properties>
               <help>Remote access L2TP VPN</help>
             </properties>
             <children>
               #include <include/accel-ppp/max-concurrent-sessions.xml.i>
               #include <include/accel-ppp/mtu-128-16384.xml.i>
+              <leafNode name="mtu">
+                <defaultValue>1436</defaultValue>
+              </leafNode>
               <leafNode name="outside-address">
                 <properties>
                   <help>External IP address to which VPN clients will connect</help>
                   <constraint>
                     <validator name="ipv4-address"/>
                   </constraint>
                 </properties>
               </leafNode>
               #include <include/accel-ppp/gateway-address.xml.i>
               #include <include/name-server-ipv4-ipv6.xml.i>
               <node name="lns">
                 <properties>
                   <help>L2TP Network Server (LNS)</help>
                 </properties>
                 <children>
                   <leafNode name="shared-secret">
                     <properties>
                       <help>Tunnel password used to authenticate the client (LAC)</help>
                     </properties>
                   </leafNode>
                   <leafNode name="host-name">
                     <properties>
                       <help>Sent to the client (LAC) in the Host-Name attribute</help>
                       <constraint>
                         #include <include/constraint/host-name.xml.i>
                       </constraint>
                       <constraintErrorMessage>Host-name must be alphanumeric and can contain hyphens</constraintErrorMessage>
                     </properties>
                   </leafNode>
                 </children>
               </node>
               <leafNode name="ccp-disable">
                 <properties>
                   <help>Disable Compression Control Protocol (CCP)</help>
                   <valueless />
                 </properties>
               </leafNode>
               <node name="ipsec-settings">
                 <properties>
                   <help>Internet Protocol Security (IPsec) for remote access L2TP VPN</help>
                 </properties>
                 <children>
                   <node name="authentication">
                     <properties>
                       <help>IPsec authentication settings</help>
                     </properties>
                     <children>
                       <leafNode name="mode">
                         <properties>
                           <help>Authentication mode for IPsec</help>
                           <valueHelp>
                             <format>pre-shared-secret</format>
                             <description>Use pre-shared secret for IPsec authentication</description>
                           </valueHelp>
                           <valueHelp>
                             <format>x509</format>
                             <description>Use X.509 certificate for IPsec authentication</description>
                           </valueHelp>
                           <constraint>
                             <regex>(pre-shared-secret|x509)</regex>
                           </constraint>
                           <completionHelp>
                             <list>pre-shared-secret x509</list>
                           </completionHelp>
                         </properties>
                       </leafNode>
                       #include <include/ipsec/authentication-pre-shared-secret.xml.i>
                       #include <include/ipsec/authentication-x509.xml.i>
                     </children>
                   </node>
                   <leafNode name="ike-lifetime">
                     <properties>
                       <help>IKE lifetime</help>
                       <valueHelp>
                         <format>u32:30-86400</format>
                         <description>IKE lifetime in seconds</description>
                       </valueHelp>
                       <constraint>
                         <validator name="numeric" argument="--range 30-86400"/>
                       </constraint>
                     </properties>
                     <defaultValue>3600</defaultValue>
                   </leafNode>
                    <leafNode name="lifetime">
                     <properties>
                       <help>ESP lifetime</help>
                       <valueHelp>
                         <format>u32:30-86400</format>
                         <description>IKE lifetime in seconds</description>
                       </valueHelp>
                       <constraint>
                         <validator name="numeric" argument="--range 30-86400"/>
                       </constraint>
                     </properties>
                     <defaultValue>3600</defaultValue>
                   </leafNode>
                   #include <include/ipsec/esp-group.xml.i>
                   #include <include/ipsec/ike-group.xml.i>
                 </children>
               </node>
               #include <include/accel-ppp/wins-server.xml.i>
               #include <include/accel-ppp/client-ip-pool.xml.i>
               #include <include/accel-ppp/client-ipv6-pool.xml.i>
               #include <include/generic-description.xml.i>
               #include <include/dhcp-interface.xml.i>
-              <leafNode name="idle">
-                <properties>
-                  <help>PPP idle timeout</help>
-                  <valueHelp>
-                    <format>u32:30-86400</format>
-                    <description>PPP idle timeout in seconds</description>
-                  </valueHelp>
-                    <constraint>
-                      <validator name="numeric" argument="--range 30-86400"/>
-                    </constraint>
-                </properties>
-              </leafNode>
               <node name="authentication">
                 <properties>
                   <help>Authentication for remote access L2TP VPN</help>
                 </properties>
                 <children>
-                  <leafNode name="require">
-                    <properties>
-                      <help>Authentication protocol for remote access peer L2TP VPN</help>
-                      <valueHelp>
-                        <format>pap</format>
-                        <description>Require the peer to authenticate itself using PAP [Password Authentication Protocol].</description>
-                      </valueHelp>
-                      <valueHelp>
-                        <format>chap</format>
-                        <description>Require the peer to authenticate itself using CHAP [Challenge Handshake Authentication Protocol].</description>
-                      </valueHelp>
-                      <valueHelp>
-                        <format>mschap</format>
-                        <description>Require the peer to authenticate itself using CHAP [Challenge Handshake Authentication Protocol].</description>
-                      </valueHelp>
-                      <valueHelp>
-                        <format>mschap-v2</format>
-                        <description>Require the peer to authenticate itself using MS-CHAPv2 [Microsoft Challenge Handshake Authentication Protocol, Version 2].</description>
-                      </valueHelp>
-                      <constraint>
-                        <regex>(pap|chap|mschap|mschap-v2)</regex>
-                      </constraint>
-                      <completionHelp>
-                        <list>pap chap mschap mschap-v2</list>
-                      </completionHelp>
-                      <multi />
-                    </properties>
-                  </leafNode>
-                  #include <include/accel-ppp/ppp-mppe.xml.i>
+                  #include <include/accel-ppp/auth-protocols.xml.i>
                   #include <include/accel-ppp/auth-mode.xml.i>
                   #include <include/accel-ppp/auth-local-users.xml.i>
                   #include <include/radius-auth-server-ipv4.xml.i>
+                  #include <include/accel-ppp/radius-additions.xml.i>
                   <node name="radius">
                     <children>
-                      #include <include/accel-ppp/radius-accounting-interim-interval.xml.i>
-                      <tagNode name="server">
-                        <children>
-                          #include <include/accel-ppp/radius-additions-disable-accounting.xml.i>
-                          <leafNode name="fail-time">
-                            <properties>
-                              <help>Mark server unavailable for N seconds on failure</help>
-                              <valueHelp>
-                                <format>u32:0-600</format>
-                                <description>Fail time penalty</description>
-                              </valueHelp>
-                              <constraint>
-                                <validator name="numeric" argument="--range 0-600"/>
-                              </constraint>
-                              <constraintErrorMessage>Fail time must be between 0 and 600 seconds</constraintErrorMessage>
-                            </properties>
-                          </leafNode>
-                        </children>
-                      </tagNode>
-                      <leafNode name="timeout">
-                        <properties>
-                          <help>Timeout to wait response from server (seconds)</help>
-                        </properties>
-                      </leafNode>
-                      <leafNode name="acct-timeout">
-                        <properties>
-                          <help>Timeout to wait reply for Interim-Update packets</help>
-                        </properties>
-                      </leafNode>
-                      <leafNode name="max-try">
-                        <properties>
-                          <help>Maximum number of tries to send Access-Request/Accounting-Request queries</help>
-                        </properties>
-                      </leafNode>
-                      #include <include/radius-nas-identifier.xml.i>
-                      #include <include/radius-nas-ip-address.xml.i>
-                      <node name="dae-server">
-                        <properties>
-                          <help>IPv4 address and port to bind Dynamic Authorization Extension server (DM/CoA)</help>
-                        </properties>
-                        <children>
-                          <leafNode name="ip-address">
-                            <properties>
-                              <help>IP address for Dynamic Authorization Extension server (DM/CoA)</help>
-                            </properties>
-                          </leafNode>
-                          <leafNode name="port">
-                            <properties>
-                              <help>Port for Dynamic Authorization Extension server (DM/CoA)</help>
-                            </properties>
-                            <defaultValue>1700</defaultValue>
-                          </leafNode>
-                          <leafNode name="secret">
-                            <properties>
-                              <help>Secret for Dynamic Authorization Extension server (DM/CoA)</help>
-                            </properties>
-                          </leafNode>
-                        </children>
-                      </node>
                       #include <include/accel-ppp/radius-additions-rate-limit.xml.i>
                     </children>
                   </node>
                 </children>
               </node>
               <node name="ppp-options">
                 <properties>
                   <help>Advanced protocol options</help>
                 </properties>
                 <children>
-                  #include <include/accel-ppp/lcp-echo-interval-failure.xml.i>
+                  #include <include/accel-ppp/ppp-mppe.xml.i>
+                  #include <include/accel-ppp/ppp-options-ipv4.xml.i>
                   #include <include/accel-ppp/ppp-options-ipv6.xml.i>
                   #include <include/accel-ppp/ppp-options-ipv6-interface-id.xml.i>
+                  #include <include/accel-ppp/lcp-echo-interval-failure.xml.i>
+                  #include <include/accel-ppp/lcp-echo-timeout.xml.i>
                 </children>
               </node>
               #include <include/accel-ppp/default-pool.xml.i>
             </children>
           </node>
         </children>
       </node>
     </children>
   </node>
 </interfaceDefinition>
diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py
index 32624719f..682da44b0 100644
--- a/smoketest/scripts/cli/base_accel_ppp_test.py
+++ b/smoketest/scripts/cli/base_accel_ppp_test.py
@@ -1,419 +1,447 @@
 # Copyright (C) 2020-2023 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import re
 import unittest
 
 
 from base_vyostest_shim import VyOSUnitTestSHIM
 from configparser import ConfigParser
 
 from vyos.configsession import ConfigSession
 from vyos.configsession import ConfigSessionError
 from vyos.template import is_ipv4
 from vyos.utils.system import get_half_cpus
 from vyos.utils.process import process_named_running
 from vyos.utils.process import cmd
 
 
 class BasicAccelPPPTest:
     class TestCase(VyOSUnitTestSHIM.TestCase):
         @classmethod
         def setUpClass(cls):
             cls._process_name = "accel-pppd"
 
             super(BasicAccelPPPTest.TestCase, cls).setUpClass()
 
             # ensure we can also run this test on a live system - so lets clean
             # out the current configuration :)
             cls.cli_delete(cls, cls._base_path)
 
         def setUp(self):
             self._gateway = "192.0.2.1"
             # ensure we can also run this test on a live system - so lets clean
             # out the current configuration :)
             self.cli_delete(self._base_path)
 
         def tearDown(self):
             # Check for running process
             self.assertTrue(process_named_running(self._process_name))
 
             self.cli_delete(self._base_path)
             self.cli_commit()
 
             # Check for running process
             self.assertFalse(process_named_running(self._process_name))
 
         def set(self, path):
             self.cli_set(self._base_path + path)
 
         def delete(self, path):
             self.cli_delete(self._base_path + path)
 
         def basic_protocol_specific_config(self):
             """
             An astract method.
             Initialize protocol scpecific configureations.
             """
             self.assertFalse(True, msg="Function must be defined")
 
         def initial_auth_config(self):
             """
             Initialization of default authentication for all protocols
             """
             self.set(
                 [
                     "authentication",
                     "local-users",
                     "username",
                     "vyos",
                     "password",
                     "vyos",
                 ]
             )
             self.set(["authentication", "mode", "local"])
 
         def initial_gateway_config(self):
             """
             Initialization of default gateway
             """
             self.set(["gateway-address", self._gateway])
 
         def initial_pool_config(self):
             """
             Initialization of default client ip pool
             """
             first_pool = "SIMPLE-POOL"
             self.set(["client-ip-pool", first_pool, "range", "192.0.2.0/24"])
             self.set(["default-pool", first_pool])
 
         def basic_config(self, is_auth=True, is_gateway=True, is_client_pool=True):
             """
             Initialization of basic configuration
             :param is_auth: authentication initialization
             :type is_auth: bool
             :param is_gateway: gateway initialization
             :type is_gateway: bool
             :param is_client_pool: client ip pool initialization
             :type is_client_pool: bool
             """
             self.basic_protocol_specific_config()
             if is_auth:
                 self.initial_auth_config()
             if is_gateway:
                 self.initial_gateway_config()
             if is_client_pool:
                 self.initial_pool_config()
 
         def getConfig(self, start, end="cli"):
             """
             Return part of configuration from line
             where the first injection of start keyword to the line
             where the first injection of end keyowrd
             :param start: start keyword
             :type start: str
             :param end: end keyword
             :type end: str
             :return: part of config
             :rtype: str
             """
             command = f'cat {self._config_file} | sed -n "/^\[{start}/,/^\[{end}/p"'
             out = cmd(command)
             return out
 
         def verify(self, conf):
             self.assertEqual(conf["core"]["thread-count"], str(get_half_cpus()))
 
         def test_accel_name_servers(self):
             # Verify proper Name-Server configuration for IPv4 and IPv6
             self.basic_config()
 
             nameserver = ["192.0.2.1", "192.0.2.2", "2001:db8::1"]
             for ns in nameserver:
                 self.set(["name-server", ns])
 
             # commit changes
             self.cli_commit()
 
             # Validate configuration values
             conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
             conf.read(self._config_file)
 
             # IPv4 and IPv6 nameservers must be checked individually
             for ns in nameserver:
                 if is_ipv4(ns):
                     self.assertIn(ns, [conf["dns"]["dns1"], conf["dns"]["dns2"]])
                 else:
                     self.assertEqual(conf["ipv6-dns"][ns], None)
 
         def test_accel_local_authentication(self):
             # Test configuration of local authentication
             self.basic_config()
 
             # upload / download limit
             user = "test"
             password = "test2"
             static_ip = "100.100.100.101"
             upload = "5000"
             download = "10000"
-
             self.set(
                 [
                     "authentication",
                     "local-users",
                     "username",
                     user,
                     "password",
                     password,
                 ]
             )
             self.set(
                 [
                     "authentication",
                     "local-users",
                     "username",
                     user,
                     "static-ip",
                     static_ip,
                 ]
             )
             self.set(
                 [
                     "authentication",
                     "local-users",
                     "username",
                     user,
                     "rate-limit",
                     "upload",
                     upload,
                 ]
             )
 
             # upload rate-limit requires also download rate-limit
             with self.assertRaises(ConfigSessionError):
                 self.cli_commit()
             self.set(
                 [
                     "authentication",
                     "local-users",
                     "username",
                     user,
                     "rate-limit",
                     "download",
                     download,
                 ]
             )
 
             # commit changes
             self.cli_commit()
 
             # Validate configuration values
             conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
             conf.read(self._config_file)
 
             # check proper path to chap-secrets file
             self.assertEqual(conf["chap-secrets"]["chap-secrets"], self._chap_secrets)
 
             # basic verification
             self.verify(conf)
 
             # check local users
             tmp = cmd(f"sudo cat {self._chap_secrets}")
             regex = f"{user}\s+\*\s+{password}\s+{static_ip}\s+{download}/{upload}"
             tmp = re.findall(regex, tmp)
             self.assertTrue(tmp)
 
             # Check local-users default value(s)
             self.delete(
                 ["authentication", "local-users", "username", user, "static-ip"]
             )
             # commit changes
             self.cli_commit()
 
             # check local users
             tmp = cmd(f"sudo cat {self._chap_secrets}")
             regex = f"{user}\s+\*\s+{password}\s+\*\s+{download}/{upload}"
             tmp = re.findall(regex, tmp)
             self.assertTrue(tmp)
 
         def test_accel_radius_authentication(self):
             # Test configuration of RADIUS authentication for PPPoE server
             self.basic_config()
 
             radius_server = "192.0.2.22"
             radius_key = "secretVyOS"
             radius_port = "2000"
             radius_port_acc = "3000"
+            acct_interim_jitter = '10'
+            acct_interim_interval = '10'
+            acct_timeout = '30'
 
             self.set(["authentication", "mode", "radius"])
             self.set(
                 ["authentication", "radius", "server", radius_server, "key", radius_key]
             )
             self.set(
                 [
                     "authentication",
                     "radius",
                     "server",
                     radius_server,
                     "port",
                     radius_port,
                 ]
             )
             self.set(
                 [
                     "authentication",
                     "radius",
                     "server",
                     radius_server,
                     "acct-port",
                     radius_port_acc,
                 ]
             )
+            self.set(
+                [
+                    "authentication",
+                    "radius",
+                    "acct-interim-jitter",
+                    acct_interim_jitter,
+                ]
+            )
+            self.set(
+                [
+                    "authentication",
+                    "radius",
+                    "accounting-interim-interval",
+                    acct_interim_interval,
+                ]
+            )
+            self.set(
+                [
+                    "authentication",
+                    "radius",
+                    "acct-timeout",
+                    acct_timeout,
+                ]
+            )
 
             coa_server = "4.4.4.4"
             coa_key = "testCoA"
             self.set(
                 ["authentication", "radius", "dynamic-author", "server", coa_server]
             )
             self.set(["authentication", "radius", "dynamic-author", "key", coa_key])
 
             nas_id = "VyOS-PPPoE"
             nas_ip = "7.7.7.7"
             self.set(["authentication", "radius", "nas-identifier", nas_id])
             self.set(["authentication", "radius", "nas-ip-address", nas_ip])
 
             source_address = "1.2.3.4"
             self.set(["authentication", "radius", "source-address", source_address])
 
             # commit changes
             self.cli_commit()
 
             # Validate configuration values
             conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
             conf.read(self._config_file)
 
             # basic verification
             self.verify(conf)
 
             # check auth
             self.assertTrue(conf["radius"].getboolean("verbose"))
-            self.assertEqual(conf["radius"]["acct-timeout"], "3")
+            self.assertEqual(conf["radius"]["acct-timeout"], acct_timeout)
+            self.assertEqual(conf["radius"]["acct-interim-interval"], acct_interim_interval)
+            self.assertEqual(conf["radius"]["acct-interim-jitter"], acct_interim_jitter)
             self.assertEqual(conf["radius"]["timeout"], "3")
             self.assertEqual(conf["radius"]["max-try"], "3")
 
             self.assertEqual(
                 conf["radius"]["dae-server"], f"{coa_server}:1700,{coa_key}"
             )
             self.assertEqual(conf["radius"]["nas-identifier"], nas_id)
             self.assertEqual(conf["radius"]["nas-ip-address"], nas_ip)
             self.assertEqual(conf["radius"]["bind"], source_address)
 
             server = conf["radius"]["server"].split(",")
             self.assertEqual(radius_server, server[0])
             self.assertEqual(radius_key, server[1])
             self.assertEqual(f"auth-port={radius_port}", server[2])
             self.assertEqual(f"acct-port={radius_port_acc}", server[3])
             self.assertEqual(f"req-limit=0", server[4])
             self.assertEqual(f"fail-time=0", server[5])
 
             #
             # Disable Radius Accounting
             #
             self.delete(
                 ["authentication", "radius", "server", radius_server, "acct-port"]
             )
             self.set(
                 [
                     "authentication",
                     "radius",
                     "server",
                     radius_server,
                     "disable-accounting",
                 ]
             )
 
             # commit changes
             self.cli_commit()
 
             conf.read(self._config_file)
 
             server = conf["radius"]["server"].split(",")
             self.assertEqual(radius_server, server[0])
             self.assertEqual(radius_key, server[1])
             self.assertEqual(f"auth-port={radius_port}", server[2])
             self.assertEqual(f"acct-port=0", server[3])
             self.assertEqual(f"req-limit=0", server[4])
             self.assertEqual(f"fail-time=0", server[5])
 
         def test_accel_ipv4_pool(self):
             """
             Test accel-ppp IPv4 pool
             """
             self.basic_config(is_gateway=False, is_client_pool=False)
             gateway = "192.0.2.1"
             subnet = "172.16.0.0/24"
             first_pool = "POOL1"
             second_pool = "POOL2"
             range = "192.0.2.10-192.0.2.20"
 
             self.set(["gateway-address", gateway])
             self.set(["client-ip-pool", first_pool, "range", subnet])
             self.set(["client-ip-pool", first_pool, "next-pool", second_pool])
             self.set(["client-ip-pool", second_pool, "range", range])
             self.set(["default-pool", first_pool])
             # commit changes
 
             self.cli_commit()
 
             # Validate configuration values
             conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
             conf.read(self._config_file)
 
             self.assertEqual(
                 f"{first_pool},next={second_pool}", conf["ip-pool"][f"{subnet},name"]
             )
             self.assertEqual(second_pool, conf["ip-pool"][f"{range},name"])
             self.assertEqual(gateway, conf["ip-pool"]["gw-ip-address"])
             self.assertEqual(first_pool, conf[self._protocol_section]["ip-pool"])
 
         def test_accel_next_pool(self):
             """
             T5099 required specific order
             """
             self.basic_config(is_gateway=False, is_client_pool=False)
 
             gateway = "192.0.2.1"
             first_pool = "VyOS-pool1"
             first_subnet = "192.0.2.0/25"
             second_pool = "Vyos-pool2"
             second_subnet = "203.0.113.0/25"
             third_pool = "Vyos-pool3"
             third_subnet = "198.51.100.0/24"
 
             self.set(["gateway-address", gateway])
             self.set(["client-ip-pool", first_pool, "range", first_subnet])
             self.set(["client-ip-pool", first_pool, "next-pool", second_pool])
             self.set(["client-ip-pool", second_pool, "range", second_subnet])
             self.set(["client-ip-pool", second_pool, "next-pool", third_pool])
             self.set(["client-ip-pool", third_pool, "range", third_subnet])
 
             # commit changes
             self.cli_commit()
 
             config = self.getConfig("ip-pool")
 
             pool_config = f"""gw-ip-address={gateway}
 {third_subnet},name={third_pool}
 {second_subnet},name={second_pool},next={third_pool}
 {first_subnet},name={first_pool},next={second_pool}"""
             self.assertIn(pool_config, config)
diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py
index 3001e71bf..fa3bb87db 100755
--- a/smoketest/scripts/cli/test_service_pppoe-server.py
+++ b/smoketest/scripts/cli/test_service_pppoe-server.py
@@ -1,241 +1,235 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2022-2023 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import unittest
 
 from base_accel_ppp_test import BasicAccelPPPTest
 
 from configparser import ConfigParser
 from vyos.utils.file import read_file
 from vyos.template import range_to_regex
 
 local_if = ['interfaces', 'dummy', 'dum667']
 ac_name = 'ACN'
 interface = 'eth0'
 
 class TestServicePPPoEServer(BasicAccelPPPTest.TestCase):
     @classmethod
     def setUpClass(cls):
         cls._base_path = ['service', 'pppoe-server']
         cls._config_file = '/run/accel-pppd/pppoe.conf'
         cls._chap_secrets = '/run/accel-pppd/pppoe.chap-secrets'
         cls._protocol_section = 'pppoe'
         # call base-classes classmethod
         super(TestServicePPPoEServer, cls).setUpClass()
 
     def tearDown(self):
         self.cli_delete(local_if)
         super().tearDown()
 
     def verify(self, conf):
         mtu = '1492'
 
         # validate some common values in the configuration
         for tmp in ['log_syslog', 'pppoe', 'ippool',
                     'auth_mschap_v2', 'auth_mschap_v1', 'auth_chap_md5',
                     'auth_pap', 'shaper']:
             # Settings without values provide None
             self.assertEqual(conf['modules'][tmp], None)
 
         # check Access Concentrator setting
         self.assertTrue(conf['pppoe']['ac-name'] == ac_name)
         self.assertTrue(conf['pppoe'].getboolean('verbose'))
         self.assertTrue(conf['pppoe']['interface'], interface)
 
         # check ppp
         self.assertTrue(conf['ppp'].getboolean('verbose'))
         self.assertTrue(conf['ppp'].getboolean('check-ip'))
         self.assertEqual(conf['ppp']['mtu'], mtu)
         self.assertEqual(conf['ppp']['lcp-echo-interval'], '30')
         self.assertEqual(conf['ppp']['lcp-echo-timeout'], '0')
         self.assertEqual(conf['ppp']['lcp-echo-failure'], '3')
 
         super().verify(conf)
 
     def basic_protocol_specific_config(self):
         self.cli_set(local_if + ['address', '192.0.2.1/32'])
         self.set(['access-concentrator', ac_name])
         self.set(['interface', interface])
 
 
     def test_pppoe_server_ppp_options(self):
         # Test configuration of local authentication for PPPoE server
         self.basic_config()
 
         # other settings
         mppe = 'require'
         self.set(['ppp-options', 'ccp'])
         self.set(['ppp-options', 'mppe', mppe])
         self.set(['limits', 'connection-limit', '20/min'])
 
         # min-mtu
         min_mtu = '1400'
         self.set(['ppp-options', 'min-mtu', min_mtu])
 
         # mru
         mru = '9000'
         self.set(['ppp-options', 'mru', mru])
 
         # interface-cache
         interface_cache = '128000'
         self.set(['ppp-options', 'interface-cache', interface_cache])
 
         # commit changes
         self.cli_commit()
 
         # Validate configuration values
         conf = ConfigParser(allow_no_value=True, delimiters='=')
         conf.read(self._config_file)
 
         # basic verification
         self.verify(conf)
 
         self.assertEqual(conf['chap-secrets']['gw-ip-address'], self._gateway)
 
         # check ppp
         self.assertEqual(conf['ppp']['mppe'], mppe)
         self.assertEqual(conf['ppp']['min-mtu'], min_mtu)
         self.assertEqual(conf['ppp']['mru'], mru)
 
         self.assertTrue(conf['ppp'].getboolean('ccp'))
 
         # check other settings
         self.assertEqual(conf['connlimit']['limit'], '20/min')
 
         # check interface-cache
         self.assertEqual(conf['ppp']['unit-cache'], interface_cache)
 
     def test_pppoe_server_authentication_protocols(self):
         # Test configuration of local authentication for PPPoE server
         self.basic_config()
 
         # explicitly test mschap-v2 - no special reason
         self.set( ['authentication', 'protocols', 'mschap-v2'])
 
         # commit changes
         self.cli_commit()
 
         # Validate configuration values
         conf = ConfigParser(allow_no_value=True)
         conf.read(self._config_file)
 
         self.assertEqual(conf['modules']['auth_mschap_v2'], None)
 
     def test_pppoe_server_shaper(self):
         fwmark = '223'
         limiter = 'tbf'
         self.basic_config()
 
         self.set(['shaper', 'fwmark', fwmark])
         # commit changes
 
         self.cli_commit()
 
         # Validate configuration values
         conf = ConfigParser(allow_no_value=True, delimiters='=')
         conf.read(self._config_file)
 
         # basic verification
         self.verify(conf)
 
         self.assertEqual(conf['shaper']['fwmark'], fwmark)
         self.assertEqual(conf['shaper']['down-limiter'], limiter)
 
     def test_pppoe_server_client_ipv6_pool(self):
         # Test configuration of IPv6 client pools
         self.basic_config()
 
         # Enable IPv6
         allow_ipv6 = 'allow'
         random = 'random'
         self.set(['ppp-options', 'ipv6', allow_ipv6])
         self.set(['ppp-options', 'ipv6-intf-id', random])
         self.set(['ppp-options', 'ipv6-accept-peer-intf-id'])
         self.set(['ppp-options', 'ipv6-peer-intf-id', random])
 
         prefix = '2001:db8:ffff::/64'
         prefix_mask = '128'
         client_prefix = f'{prefix},{prefix_mask}'
         self.set(['client-ipv6-pool', 'prefix', prefix, 'mask', prefix_mask])
 
         delegate_prefix = '2001:db8::/40'
         delegate_mask = '56'
         self.set(['client-ipv6-pool', 'delegate', delegate_prefix, 'delegation-prefix', delegate_mask])
 
         # commit changes
         self.cli_commit()
 
         # Validate configuration values
         conf = ConfigParser(allow_no_value=True, delimiters='=')
         conf.read(self._config_file)
 
         for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']:
             self.assertEqual(conf['modules'][tmp], None)
 
         self.assertEqual(conf['ppp']['ipv6'], allow_ipv6)
         self.assertEqual(conf['ppp']['ipv6-intf-id'], random)
         self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random)
         self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id'))
 
         self.assertEqual(conf['ipv6-pool'][client_prefix], None)
         self.assertEqual(conf['ipv6-pool']['delegate'], f'{delegate_prefix},{delegate_mask}')
 
     def test_accel_radius_authentication(self):
         radius_called_sid = 'ifname:mac'
-        radius_acct_interim_jitter = '9'
-        radius_acct_interim_interval = '60'
 
         self.set(['authentication', 'radius', 'called-sid-format', radius_called_sid])
-        self.set(['authentication', 'radius', 'acct-interim-jitter', radius_acct_interim_jitter])
-        self.set(['authentication', 'radius', 'accounting-interim-interval', radius_acct_interim_interval])
 
         # run common tests
         super().test_accel_radius_authentication()
 
         # Validate configuration values
         conf = ConfigParser(allow_no_value=True, delimiters='=')
         conf.read(self._config_file)
 
         # Validate configuration
         self.assertEqual(conf['pppoe']['called-sid'], radius_called_sid)
-        self.assertEqual(conf['radius']['acct-interim-jitter'], radius_acct_interim_jitter)
-        self.assertEqual(conf['radius']['acct-interim-interval'], radius_acct_interim_interval)
 
     def test_pppoe_server_vlan(self):
 
         vlans = ['100', '200', '300-310']
 
         # Test configuration of local authentication for PPPoE server
         self.basic_config()
 
         for vlan in vlans:
             self.set(['interface', interface, 'vlan', vlan])
 
         # commit changes
         self.cli_commit()
 
         # Validate configuration values
         config = read_file(self._config_file)
         for vlan in vlans:
             tmp = range_to_regex(vlan)
             self.assertIn(f'interface=re:^{interface}\.{tmp}$', config)
 
         tmp = ','.join(vlans)
         self.assertIn(f'vlan-mon={interface},{tmp}', config)
 
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vpn_l2tp.py b/smoketest/scripts/cli/test_vpn_l2tp.py
index 05ffb6bb5..5b3e419bd 100755
--- a/smoketest/scripts/cli/test_vpn_l2tp.py
+++ b/smoketest/scripts/cli/test_vpn_l2tp.py
@@ -1,212 +1,135 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2023 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import re
 import unittest
 
 from base_accel_ppp_test import BasicAccelPPPTest
 from configparser import ConfigParser
 from vyos.utils.process import cmd
 
 
 class TestVPNL2TPServer(BasicAccelPPPTest.TestCase):
     @classmethod
     def setUpClass(cls):
         cls._base_path = ['vpn', 'l2tp', 'remote-access']
         cls._config_file = '/run/accel-pppd/l2tp.conf'
         cls._chap_secrets = '/run/accel-pppd/l2tp.chap-secrets'
         cls._protocol_section = 'l2tp'
         # call base-classes classmethod
         super(TestVPNL2TPServer, cls).setUpClass()
 
     @classmethod
     def tearDownClass(cls):
         super(TestVPNL2TPServer, cls).tearDownClass()
 
     def basic_protocol_specific_config(self):
         pass
 
-    def test_accel_local_authentication(self):
-        # Test configuration of local authentication
+    def test_l2tp_server_ppp_options(self):
+        # Test configuration of local authentication for PPPoE server
         self.basic_config()
-
-        # upload / download limit
-        user = "test"
-        password = "test2"
-        static_ip = "100.100.100.101"
-        upload = "5000"
-        download = "10000"
-
-        self.set(
-            [
-                "authentication",
-                "local-users",
-                "username",
-                user,
-                "password",
-                password,
-            ]
-        )
-        self.set(
-            [
-                "authentication",
-                "local-users",
-                "username",
-                user,
-                "static-ip",
-                static_ip,
-            ]
-        )
-        self.set(
-            [
-                "authentication",
-                "local-users",
-                "username",
-                user,
-                "rate-limit",
-                "upload",
-                upload,
-            ]
-        )
-        self.set(
-            [
-                "authentication",
-                "local-users",
-                "username",
-                user,
-                "rate-limit",
-                "download",
-                download,
-            ]
-        )
+        mtu = '1425'
+        lcp_echo_failure = '5'
+        lcp_echo_interval = '40'
+        lcp_echo_timeout = '3000'
+        # other settings
+        mppe = 'require'
+        self.set(['ccp-disable'])
+        self.set(['ppp-options', 'mppe', mppe])
+        self.set(['authentication', 'radius', 'preallocate-vif'])
+        self.set(['mtu', mtu])
+        self.set(['ppp-options', 'lcp-echo-failure', lcp_echo_failure])
+        self.set(['ppp-options', 'lcp-echo-interval', lcp_echo_interval])
+        self.set(['ppp-options', 'lcp-echo-timeout', lcp_echo_timeout])
 
         # commit changes
         self.cli_commit()
 
         # Validate configuration values
-        conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
+        conf = ConfigParser(allow_no_value=True, delimiters='=')
         conf.read(self._config_file)
 
-        # check proper path to chap-secrets file
-        self.assertEqual(conf["chap-secrets"]["chap-secrets"], self._chap_secrets)
-
         # basic verification
         self.verify(conf)
 
-        # check local users
-        tmp = cmd(f"sudo cat {self._chap_secrets}")
-        regex = f"{user}\s+\*\s+{password}\s+{static_ip}\s+{download}/{upload}"
-        tmp = re.findall(regex, tmp)
-        self.assertTrue(tmp)
-
-        # Check local-users default value(s)
-        self.delete(["authentication", "local-users", "username", user, "static-ip"])
-        # commit changes
-        self.cli_commit()
-
-        # check local users
-        tmp = cmd(f"sudo cat {self._chap_secrets}")
-        regex = f"{user}\s+\*\s+{password}\s+\*\s+{download}/{upload}"
-        tmp = re.findall(regex, tmp)
-        self.assertTrue(tmp)
-
-    def test_accel_radius_authentication(self):
-        # Test configuration of RADIUS authentication for PPPoE server
+        # check ppp
+        self.assertEqual(conf['ppp']['mppe'], mppe)
+        self.assertFalse(conf['ppp'].getboolean('ccp'))
+        self.assertEqual(conf['ppp']['unit-preallocate'], '1')
+        self.assertTrue(conf['ppp'].getboolean('verbose'))
+        self.assertTrue(conf['ppp'].getboolean('check-ip'))
+        self.assertEqual(conf['ppp']['mtu'], mtu)
+        self.assertEqual(conf['ppp']['lcp-echo-interval'], lcp_echo_interval)
+        self.assertEqual(conf['ppp']['lcp-echo-timeout'], lcp_echo_timeout)
+        self.assertEqual(conf['ppp']['lcp-echo-failure'], lcp_echo_failure)
+
+    def test_l2tp_server_authentication_protocols(self):
+        # Test configuration of local authentication for PPPoE server
         self.basic_config()
 
-        radius_server = "192.0.2.22"
-        radius_key = "secretVyOS"
-        radius_port = "2000"
-
-        self.set(["authentication", "mode", "radius"])
-        self.set(
-            ["authentication", "radius", "server", radius_server, "key", radius_key]
-        )
-        self.set(
-            [
-                "authentication",
-                "radius",
-                "server",
-                radius_server,
-                "port",
-                radius_port,
-            ]
-        )
-
-
-        nas_id = "VyOS-PPPoE"
-        nas_ip = "7.7.7.7"
-        self.set(["authentication", "radius", "nas-identifier", nas_id])
-        self.set(["authentication", "radius", "nas-ip-address", nas_ip])
-
-        source_address = "1.2.3.4"
-        self.set(["authentication", "radius", "source-address", source_address])
+        # explicitly test mschap-v2 - no special reason
+        self.set( ['authentication', 'protocols', 'mschap-v2'])
 
         # commit changes
         self.cli_commit()
 
         # Validate configuration values
-        conf = ConfigParser(allow_no_value=True, delimiters="=", strict=False)
+        conf = ConfigParser(allow_no_value=True)
         conf.read(self._config_file)
 
-        # basic verification
-        self.verify(conf)
+        self.assertEqual(conf['modules']['auth_mschap_v2'], None)
+
+    def test_l2tp_server_client_ipv6_pool(self):
+        # Test configuration of IPv6 client pools
+        self.basic_config()
+
+        # Enable IPv6
+        allow_ipv6 = 'allow'
+        random = 'random'
+        self.set(['ppp-options', 'ipv6', allow_ipv6])
+        self.set(['ppp-options', 'ipv6-intf-id', random])
+        self.set(['ppp-options', 'ipv6-accept-peer-intf-id'])
+        self.set(['ppp-options', 'ipv6-peer-intf-id', random])
 
-        # check auth
-        self.assertTrue(conf["radius"].getboolean("verbose"))
-        self.assertEqual(conf["radius"]["acct-timeout"], "3")
-        self.assertEqual(conf["radius"]["timeout"], "3")
-        self.assertEqual(conf["radius"]["max-try"], "3")
-
-        self.assertEqual(conf["radius"]["nas-identifier"], nas_id)
-        self.assertEqual(conf["radius"]["nas-ip-address"], nas_ip)
-        self.assertEqual(conf["radius"]["bind"], source_address)
-
-        server = conf["radius"]["server"].split(",")
-        self.assertEqual(radius_server, server[0])
-        self.assertEqual(radius_key, server[1])
-        self.assertEqual(f"auth-port={radius_port}", server[2])
-        self.assertEqual(f"req-limit=0", server[4])
-        self.assertEqual(f"fail-time=0", server[5])
-
-        #
-        # Disable Radius Accounting
-        #
-        self.set(
-            [
-                "authentication",
-                "radius",
-                "server",
-                radius_server,
-                "disable-accounting",
-            ]
-        )
+        prefix = '2001:db8:ffff::/64'
+        prefix_mask = '128'
+        client_prefix = f'{prefix},{prefix_mask}'
+        self.set(['client-ipv6-pool', 'prefix', prefix, 'mask', prefix_mask])
+
+        delegate_prefix = '2001:db8::/40'
+        delegate_mask = '56'
+        self.set(['client-ipv6-pool', 'delegate', delegate_prefix, 'delegation-prefix', delegate_mask])
 
         # commit changes
         self.cli_commit()
 
+        # Validate configuration values
+        conf = ConfigParser(allow_no_value=True, delimiters='=')
         conf.read(self._config_file)
 
-        server = conf["radius"]["server"].split(",")
-        self.assertEqual(radius_server, server[0])
-        self.assertEqual(radius_key, server[1])
-        self.assertEqual(f"auth-port={radius_port}", server[2])
-        self.assertEqual(f"acct-port=0", server[3])
-        self.assertEqual(f"req-limit=0", server[4])
-        self.assertEqual(f"fail-time=0", server[5])
+        for tmp in ['ipv6pool', 'ipv6_nd', 'ipv6_dhcp']:
+            self.assertEqual(conf['modules'][tmp], None)
+
+        self.assertEqual(conf['ppp']['ipv6'], allow_ipv6)
+        self.assertEqual(conf['ppp']['ipv6-intf-id'], random)
+        self.assertEqual(conf['ppp']['ipv6-peer-intf-id'], random)
+        self.assertTrue(conf['ppp'].getboolean('ipv6-accept-peer-intf-id'))
 
+        self.assertEqual(conf['ipv6-pool'][client_prefix], None)
+        self.assertEqual(conf['ipv6-pool']['delegate'], f'{delegate_prefix},{delegate_mask}')
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py
index 9a022d93c..03a27d3cd 100755
--- a/src/conf_mode/vpn_l2tp.py
+++ b/src/conf_mode/vpn_l2tp.py
@@ -1,429 +1,123 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2019-2023 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
-import re
 
-from copy import deepcopy
-from stat import S_IRUSR, S_IWUSR, S_IRGRP
 from sys import exit
 
 from vyos.config import Config
-from vyos.template import is_ipv4
+from vyos.configdict import get_accel_dict
 from vyos.template import render
 from vyos.utils.process import call
-from vyos.utils.system import get_half_cpus
 from vyos.utils.dict import dict_search
-from vyos.utils.network import check_port_availability
-from vyos.utils.network import is_listen_port_bind_service
+from vyos.accel_ppp_util import verify_accel_ppp_base_service
 from vyos.accel_ppp_util import verify_accel_ppp_ip_pool
 from vyos.accel_ppp_util import get_pools_in_order
+from vyos.base import Warning
 from vyos import ConfigError
 
 from vyos import airbag
 airbag.enable()
 
+
 l2tp_conf = '/run/accel-pppd/l2tp.conf'
 l2tp_chap_secrets = '/run/accel-pppd/l2tp.chap-secrets'
 
-default_config_data = {
-    'auth_mode': 'local',
-    'auth_ppp_mppe': 'prefer',
-    'auth_proto': ['auth_mschap_v2'],
-    'chap_secrets_file': l2tp_chap_secrets, # used in Jinja2 template
-    'client_ip_pool': {},
-    'client_ip_subnets': [],
-    'client_ipv6_pool': [],
-    'client_ipv6_pool_configured': False,
-    'client_ipv6_delegate_prefix': [],
-    'dnsv4': [],
-    'dnsv6': [],
-    'gateway_address': '10.255.255.0',
-    'local_users' : [],
-    'mtu': '1436',
-    'outside_addr': '',
-    'ppp_mppe': 'prefer',
-    'ppp_echo_failure' : '3',
-    'ppp_echo_interval' : '30',
-    'ppp_echo_timeout': '0',
-    'ppp_ipv6_accept_peer_intf_id': False,
-    'ppp_ipv6_intf_id': None,
-    'ppp_ipv6_peer_intf_id': None,
-    'radius_server': [],
-    'radius_acct_inter_jitter': '',
-    'radius_acct_interim_interval': None,
-    'radius_acct_tmo': '3',
-    'radius_max_try': '3',
-    'radius_timeout': '3',
-    'radius_nas_id': '',
-    'radius_nas_ip': '',
-    'radius_source_address': '',
-    'radius_shaper_attr': '',
-    'radius_shaper_vendor': '',
-    'radius_dynamic_author': {},
-    'wins': [],
-    'ip6_column': [],
-    'thread_cnt': get_half_cpus()
-}
-
 def get_config(config=None):
     if config:
         conf = config
     else:
         conf = Config()
-    base_path = ['vpn', 'l2tp', 'remote-access']
-    if not conf.exists(base_path):
+    base = ['vpn', 'l2tp', 'remote-access']
+    if not conf.exists(base):
         return None
 
-    conf.set_level(base_path)
-    l2tp = deepcopy(default_config_data)
-
-    ### general options ###
-    if conf.exists(['name-server']):
-        for name_server in conf.return_values(['name-server']):
-            if is_ipv4(name_server):
-                l2tp['dnsv4'].append(name_server)
-            else:
-                l2tp['dnsv6'].append(name_server)
-
-    if conf.exists(['wins-server']):
-        l2tp['wins'] = conf.return_values(['wins-server'])
-
-    if conf.exists('outside-address'):
-        l2tp['outside_addr'] = conf.return_value('outside-address')
-
-    if conf.exists(['authentication', 'mode']):
-        l2tp['auth_mode'] = conf.return_value(['authentication', 'mode'])
-
-    if conf.exists(['authentication', 'require']):
-        l2tp['auth_proto'] = []
-        auth_mods = {
-            'pap': 'auth_pap',
-            'chap': 'auth_chap_md5',
-            'mschap': 'auth_mschap_v1',
-            'mschap-v2': 'auth_mschap_v2'
-        }
-
-        for proto in conf.return_values(['authentication', 'require']):
-            l2tp['auth_proto'].append(auth_mods[proto])
-
-    if conf.exists(['authentication', 'mppe']):
-        l2tp['auth_ppp_mppe'] = conf.return_value(['authentication', 'mppe'])
-
-    #
-    # local auth
-    if conf.exists(['authentication', 'local-users']):
-        for username in conf.list_nodes(['authentication', 'local-users', 'username']):
-            user = {
-                'name' : username,
-                'password' : '',
-                'state' : 'enabled',
-                'ip' : '*',
-                'upload' : None,
-                'download' : None
-            }
-
-            conf.set_level(base_path + ['authentication', 'local-users', 'username', username])
-
-            if conf.exists(['password']):
-                user['password'] = conf.return_value(['password'])
-
-            if conf.exists(['disable']):
-                user['state'] = 'disable'
-
-            if conf.exists(['static-ip']):
-                user['ip'] = conf.return_value(['static-ip'])
-
-            if conf.exists(['rate-limit', 'download']):
-                user['download'] = conf.return_value(['rate-limit', 'download'])
-
-            if conf.exists(['rate-limit', 'upload']):
-                user['upload'] = conf.return_value(['rate-limit', 'upload'])
-
-            l2tp['local_users'].append(user)
-
-    #
-    # RADIUS auth and settings
-    conf.set_level(base_path + ['authentication', 'radius'])
-    if conf.exists(['server']):
-        for server in conf.list_nodes(['server']):
-            radius = {
-                'server' : server,
-                'key' : '',
-                'fail_time' : 0,
-                'port' : '1812',
-                'acct_port' : '1813'
-            }
-
-            conf.set_level(base_path + ['authentication', 'radius', 'server', server])
-
-            if conf.exists(['disable-accounting']):
-                radius['acct_port'] = '0'
-
-            if conf.exists(['fail-time']):
-                radius['fail_time'] = conf.return_value(['fail-time'])
-
-            if conf.exists(['port']):
-                radius['port'] = conf.return_value(['port'])
-
-            if conf.exists(['acct-port']):
-                radius['acct_port'] = conf.return_value(['acct-port'])
-
-            if conf.exists(['key']):
-                radius['key'] = conf.return_value(['key'])
-
-            if not conf.exists(['disable']):
-                l2tp['radius_server'].append(radius)
-
-        #
-        # advanced radius-setting
-        conf.set_level(base_path + ['authentication', 'radius'])
-
-        if conf.exists(['accounting-interim-interval']):
-            l2tp['radius_acct_interim_interval'] = conf.return_value(['accounting-interim-interval'])
-
-        if conf.exists(['acct-interim-jitter']):
-            l2tp['radius_acct_inter_jitter'] = conf.return_value(['acct-interim-jitter'])
-
-        if conf.exists(['acct-timeout']):
-            l2tp['radius_acct_tmo'] = conf.return_value(['acct-timeout'])
-
-        if conf.exists(['max-try']):
-            l2tp['radius_max_try'] = conf.return_value(['max-try'])
-
-        if conf.exists(['timeout']):
-            l2tp['radius_timeout'] = conf.return_value(['timeout'])
-
-        if conf.exists(['nas-identifier']):
-            l2tp['radius_nas_id'] = conf.return_value(['nas-identifier'])
-
-        if conf.exists(['nas-ip-address']):
-            l2tp['radius_nas_ip'] = conf.return_value(['nas-ip-address'])
-
-        if conf.exists(['source-address']):
-            l2tp['radius_source_address'] = conf.return_value(['source-address'])
-
-        # Dynamic Authorization Extensions (DOA)/Change Of Authentication (COA)
-        if conf.exists(['dae-server']):
-            dae = {
-                'port' : '',
-                'server' : '',
-                'key' : ''
-            }
-
-            if conf.exists(['dae-server', 'ip-address']):
-                dae['server'] = conf.return_value(['dae-server', 'ip-address'])
-
-            if conf.exists(['dae-server', 'port']):
-                dae['port'] = conf.return_value(['dae-server', 'port'])
-
-            if conf.exists(['dae-server', 'secret']):
-                dae['key'] = conf.return_value(['dae-server', 'secret'])
-
-            l2tp['radius_dynamic_author'] = dae
-
-        if conf.exists(['rate-limit', 'enable']):
-            l2tp['radius_shaper_attr'] = 'Filter-Id'
-            c_attr = ['rate-limit', 'enable', 'attribute']
-            if conf.exists(c_attr):
-                l2tp['radius_shaper_attr'] = conf.return_value(c_attr)
-
-            c_vendor = ['rate-limit', 'enable', 'vendor']
-            if conf.exists(c_vendor):
-                l2tp['radius_shaper_vendor'] = conf.return_value(c_vendor)
-
-    conf.set_level(base_path)
-    if conf.exists(['client-ip-pool']):
-        for pool_name in conf.list_nodes(['client-ip-pool']):
-            l2tp['client_ip_pool'][pool_name] = {}
-            l2tp['client_ip_pool'][pool_name]['range'] = conf.return_value(['client-ip-pool', pool_name, 'range'])
-            l2tp['client_ip_pool'][pool_name]['next_pool'] = conf.return_value(['client-ip-pool', pool_name, 'next-pool'])
-
+    # retrieve common dictionary keys
+    l2tp = get_accel_dict(conf, base, l2tp_chap_secrets)
     if dict_search('client_ip_pool', l2tp):
         # Multiple named pools require ordered values T5099
-        l2tp['ordered_named_pools'] = get_pools_in_order(dict_search('client_ip_pool', l2tp))
-
-    if conf.exists(['client-ipv6-pool', 'prefix']):
-        l2tp['client_ipv6_pool_configured'] = True
-        l2tp['ip6_column'].append('ip6')
-        for prefix in conf.list_nodes(['client-ipv6-pool', 'prefix']):
-            tmp = {
-                'prefix': prefix,
-                'mask': '64'
-            }
-
-            if conf.exists(['client-ipv6-pool', 'prefix', prefix, 'mask']):
-                tmp['mask'] = conf.return_value(['client-ipv6-pool', 'prefix', prefix, 'mask'])
-
-            l2tp['client_ipv6_pool'].append(tmp)
-
-    if conf.exists(['client-ipv6-pool', 'delegate']):
+        l2tp['ordered_named_pools'] = get_pools_in_order(
+            dict_search('client_ip_pool', l2tp))
+    l2tp['ip6_column'] = []
+    if dict_search('client_ipv6_pool.prefix', l2tp):
+        l2tp['ip6_column'].append('ipv6')
+    if dict_search('client_ipv6_pool.delegate', l2tp):
         l2tp['ip6_column'].append('ip6-db')
-        for prefix in conf.list_nodes(['client-ipv6-pool', 'delegate']):
-            tmp = {
-                'prefix': prefix,
-                'mask': ''
-            }
-
-            if conf.exists(['client-ipv6-pool', 'delegate', prefix, 'delegation-prefix']):
-                tmp['mask'] = conf.return_value(['client-ipv6-pool', 'delegate', prefix, 'delegation-prefix'])
-
-            l2tp['client_ipv6_delegate_prefix'].append(tmp)
-
-    if conf.exists(['default-pool']):
-        l2tp['default_pool'] = conf.return_value(['default-pool'])
-
-    if conf.exists(['mtu']):
-        l2tp['mtu'] = conf.return_value(['mtu'])
-
-    # gateway address
-    if conf.exists(['gateway-address']):
-        l2tp['gateway_address'] = conf.return_value(['gateway-address'])
-
-    # LNS secret
-    if conf.exists(['lns', 'shared-secret']):
-        l2tp['lns_shared_secret'] = conf.return_value(['lns', 'shared-secret'])
-    if conf.exists(['lns', 'host-name']):
-        l2tp['lns_host_name'] = conf.return_value(['lns', 'host-name'])
-
-    if conf.exists(['ccp-disable']):
-        l2tp['ccp_disable'] = True
-
-    # PPP options
-    if conf.exists(['idle']):
-        l2tp['ppp_echo_timeout'] = conf.return_value(['idle'])
-
-    if conf.exists(['ppp-options', 'lcp-echo-failure']):
-        l2tp['ppp_echo_failure'] = conf.return_value(['ppp-options', 'lcp-echo-failure'])
-
-    if conf.exists(['ppp-options', 'lcp-echo-interval']):
-        l2tp['ppp_echo_interval'] = conf.return_value(['ppp-options', 'lcp-echo-interval'])
-
-    if conf.exists(['ppp-options', 'ipv6']):
-        l2tp['ppp_ipv6'] = conf.return_value(['ppp-options', 'ipv6'])
-
-    if conf.exists(['ppp-options', 'ipv6-accept-peer-intf-id']):
-        l2tp['ppp_ipv6_accept_peer_intf_id'] = True
-
-    if conf.exists(['ppp-options', 'ipv6-intf-id']):
-        l2tp['ppp_ipv6_intf_id'] = conf.return_value(['ppp-options', 'ipv6-intf-id'])
-
-    if conf.exists(['ppp-options', 'ipv6-peer-intf-id']):
-        l2tp['ppp_ipv6_peer_intf_id'] = conf.return_value(['ppp-options', 'ipv6-peer-intf-id'])
-
     l2tp['server_type'] = 'l2tp'
     return l2tp
 
 
-
-
-
 def verify(l2tp):
     if not l2tp:
         return None
 
-    if l2tp['auth_mode'] == 'local':
-        if not l2tp['local_users']:
-            raise ConfigError('L2TP local auth mode requires local users to be configured!')
-
-        for user in l2tp['local_users']:
-            if not user['password']:
-                raise ConfigError(f"Password required for user {user['name']}")
-
-    elif l2tp['auth_mode'] == 'radius':
-        if len(l2tp['radius_server']) == 0:
-            raise ConfigError("RADIUS authentication requires at least one server")
-
-        for radius in l2tp['radius_server']:
-            if not radius['key']:
-                raise ConfigError(f"Missing RADIUS secret for server { radius['key'] }")
+    verify_accel_ppp_base_service(l2tp)
 
-        if l2tp['radius_dynamic_author']:
-            if not l2tp['radius_dynamic_author']['server']:
-                raise ConfigError("Missing ip-address for dae-server")
-            if not l2tp['radius_dynamic_author']['key']:
-                raise ConfigError("Missing secret for dae-server")
-            address = l2tp['radius_dynamic_author']['server']
-            port = l2tp['radius_dynamic_author']['port']
-            proto = 'tcp'
-            # check if dae listen port is not used by another service
-            if check_port_availability(address, int(port), proto) is not True and \
-                not is_listen_port_bind_service(int(port), 'accel-pppd'):
-                raise ConfigError(f'"{proto}" port "{port}" is used by another service')
+    if dict_search('authentication.radius.dynamic_author.server', l2tp):
+        if not dict_search('authentication.radius.dynamic_author.key', l2tp):
+            raise ConfigError('DA/CoE server key required!')
 
-    if l2tp['auth_mode'] == 'local' or l2tp['auth_mode'] == 'noauth':
-        if not l2tp['client_ip_pool']:
+    if dict_search('authentication.mode', l2tp) in ['local', 'noauth']:
+        if not l2tp['client_ip_pool'] and not l2tp['client_ipv6_pool']:
             raise ConfigError(
-                "L2TP local auth mode requires local client-ip-pool to be configured!")
-    verify_accel_ppp_ip_pool(l2tp)
-
-    # check ipv6
-    if l2tp['client_ipv6_delegate_prefix'] and not l2tp['client_ipv6_pool']:
-        raise ConfigError('IPv6 prefix delegation requires client-ipv6-pool prefix')
-
-    for prefix in l2tp['client_ipv6_delegate_prefix']:
-        if not prefix['mask']:
-            raise ConfigError('Delegation-prefix required for individual delegated networks')
+                "L2TP local auth mode requires local client-ip-pool or client-ipv6-pool to be configured!")
+        if dict_search('client_ip_pool', l2tp) and not dict_search('default_pool', l2tp):
+            Warning("'default-pool' is not defined")
 
-    if len(l2tp['wins']) > 2:
-        raise ConfigError('Not more then two IPv4 WINS name-servers can be configured')
-
-    if len(l2tp['dnsv4']) > 2:
-        raise ConfigError('Not more then two IPv4 DNS name-servers can be configured')
+    verify_accel_ppp_ip_pool(l2tp)
 
-    if len(l2tp['dnsv6']) > 3:
-        raise ConfigError('Not more then three IPv6 DNS name-servers can be configured')
+    if 'wins_server' in l2tp and len(l2tp['wins_server']) > 2:
+        raise ConfigError(
+            'Not more then two WINS name-servers can be configured')
 
     return None
 
 
 def generate(l2tp):
     if not l2tp:
         return None
 
     render(l2tp_conf, 'accel-ppp/l2tp.config.j2', l2tp)
 
-    if l2tp['auth_mode'] == 'local':
-        render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.j2', l2tp)
-        os.chmod(l2tp_chap_secrets, S_IRUSR | S_IWUSR | S_IRGRP)
-
-    else:
-        if os.path.exists(l2tp_chap_secrets):
-             os.unlink(l2tp_chap_secrets)
+    if dict_search('authentication.mode', l2tp) == 'local':
+        render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2',
+               l2tp, permission=0o640)
 
     return None
 
 
 def apply(l2tp):
     if not l2tp:
         call('systemctl stop accel-ppp@l2tp.service')
         for file in [l2tp_chap_secrets, l2tp_conf]:
             if os.path.exists(file):
                 os.unlink(file)
 
         return None
 
     call('systemctl restart accel-ppp@l2tp.service')
 
+
 if __name__ == '__main__':
     try:
         c = get_config()
         verify(c)
         generate(c)
         apply(c)
+
     except ConfigError as e:
         print(e)
         exit(1)
diff --git a/src/migration-scripts/l2tp/5-to-6 b/src/migration-scripts/l2tp/5-to-6
new file mode 100755
index 000000000..ca0b13dcc
--- /dev/null
+++ b/src/migration-scripts/l2tp/5-to-6
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+import os
+
+from sys import argv
+from sys import exit
+from vyos.configtree import ConfigTree
+
+
+if len(argv) < 2:
+    print("Must specify file name!")
+    exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+    config_file = f.read()
+
+config = ConfigTree(config_file)
+base = ['vpn', 'l2tp', 'remote-access']
+if not config.exists(base):
+    exit(0)
+
+#migrate idle to ppp option lcp-echo-timeout
+idle_path = base + ['idle']
+if config.exists(idle_path):
+    config.set(base + ['ppp-options', 'lcp-echo-timeout'],
+               value=config.return_value(idle_path))
+    config.delete(idle_path)
+
+#migrate mppe from authentication to ppp-otion
+mppe_path = base + ['authentication', 'mppe']
+if config.exists(mppe_path):
+    config.set(base + ['ppp-options', 'mppe'],
+               value=config.return_value(mppe_path))
+    config.delete(mppe_path)
+
+#migrate require to protocol
+require_path = base + ['authentication', 'require']
+if config.exists(require_path):
+    protocols = list(config.return_values(require_path))
+    for protocol in protocols:
+        config.set(base + ['authentication', 'protocols'], value=protocol,
+                   replace=False)
+    config.delete(require_path)
+else:
+    config.set(base + ['authentication', 'protocols'], value='mschap-v2')
+
+#migrate default gateway if not exist
+if not config.exists(base + ['gateway-address']):
+    config.set(base + ['gateway-address'], value='10.255.255.0')
+
+#migrate authentication radius timeout
+rad_timeout_path = base + ['authentication', 'radius', 'timeout']
+if config.exists(rad_timeout_path):
+    if int(config.return_value(rad_timeout_path)) > 60:
+        config.set(rad_timeout_path, value=60)
+
+#migrate authentication radius acct timeout
+rad_acct_timeout_path = base + ['authentication', 'radius', 'acct-timeout']
+if config.exists(rad_acct_timeout_path):
+    if int(config.return_value(rad_acct_timeout_path)) > 60:
+        config.set(rad_acct_timeout_path,value=60)
+
+#migrate authentication radius max-try
+rad_max_try_path = base + ['authentication', 'radius', 'max-try']
+if config.exists(rad_max_try_path):
+    if int(config.return_value(rad_max_try_path)) > 20:
+        config.set(rad_max_try_path, value=20)
+
+#migrate dae-server to dynamic-author
+dae_path_old = base + ['authentication', 'radius', 'dae-server']
+dae_path_new = base + ['authentication', 'radius', 'dynamic-author']
+
+if config.exists(dae_path_old + ['ip-address']):
+    config.set(dae_path_new + ['server'],
+               value=config.return_value(dae_path_old + ['ip-address']))
+
+if config.exists(dae_path_old + ['port']):
+    config.set(dae_path_new + ['port'],
+               value=config.return_value(dae_path_old + ['port']))
+
+if config.exists(dae_path_old + ['secret']):
+    config.set(dae_path_new + ['key'],
+               value=config.return_value(dae_path_old + ['secret']))
+
+if config.exists(dae_path_old):
+    config.delete(dae_path_old)
+
+try:
+    with open(file_name, 'w') as f:
+        f.write(config.to_string())
+except OSError as e:
+    print("Failed to save the modified config: {}".format(e))
+    exit(1)