ZTE TR-181 PPPoE provisioning - WAN interface accepts parameters but PPPoE never connects

Hello everyone,

I am currently trying to understand the correct PPPoE provisioning flow on a ZTE ONT using TR-181.

After reviewing the device, I found that the ONT already has 5 WAN/PPP related interfaces created by default. None of them appear to be an active Internet PPPoE WAN.

The TR069 management WAN already works correctly, so I am trying to keep that interface untouched.

My main issue is that the ONT accepts all provisioning parameters without errors, but the PPPoE WAN never becomes operational.

At the moment:

  • Remote access provisioning works

  • WiFi provisioning works

  • VLAN parameters are written correctly

  • PPP username/password are written correctly

  • ServiceList is applied

  • LowerLayers is assigned

  • The values appear visually correct in the ONT interface

  • However, PPPoE never connects and WAN does not become active

I am not sure if on ZTE devices:

  • existing WAN interfaces must be reused,

  • default WANs should be deleted,

  • or if additional bindings are required internally.

This is the relevant PPPoE provisioning section I am testing:

// Reuse PPP interface 2
var newPpp = "Device.PPP.Interface.2";

// Enable
declare(newPpp + ".Enable", { value: now }, { value: true });

// Service type
declare(newPpp + ".X_ZTE-COM_ServiceList", { value: now }, {
  value: "INTERNET"
});

// VLAN binding
declare(newPpp + ".LowerLayers", { value: now }, {
  value: newVlan
});

// PPP username
declare(newPpp + ".Username", { value: now }, {
  value: username
});

// PPP password
declare(newPpp + ".Password", { value: now }, {
  value: password
});

// Connection trigger
declare(newPpp + ".ConnectionTrigger", { value: now }, {
  value: "AlwaysOn"
});

// NAT
declare(newPpp + ".NATEnabled", { value: now }, {
  value: true
});

This is the VLAN creation section:

var newVlan = declare(
  "Device.Ethernet.VLANTermination.+",
  { path: now },
  {}
);

declare(newVlan + ".Enable", { value: now }, {
  value: true
});

declare(newVlan + ".VLANID", { value: now }, {
  value: vlan
});

I also tried removing old PPP and VLAN interfaces while preserving TR069:

declare(path, null, { path: 0 });

The strange part is that:

  • no provisioning error is returned,

  • parameters are applied,

  • interface values look correct,

  • but PPPoE still never establishes the WAN connection.

If anyone has experience with ZTE TR-181 provisioning:

  • Is reusing Device.PPP.Interface.2 the correct approach?

  • Does ZTE require a different LowerLayers hierarchy?

  • Should VLANs and PPP interfaces be linked differently?

  • Are there mandatory parameters missing for Internet WAN activation?

Any guidance or working examples would help me a lot.

Thank you.

Look in syslog on the CPE, or the console log. To get the console log, you may have to connect a USB TTL serial adapter to the 4 pin header on the CPE.

Have you tried rebooting the CPE after everything is configured? I’ve had some CPEs where thats necessary to get them to switch out of DHCP to PPP correctly.

Thank you for the previous suggestions.

I already tried:

  • rebooting the ONT after provisioning,

  • removing old PPP/VLAN interfaces,

  • reusing existing WAN interfaces,

  • and creating new interfaces dynamically.

Unfortunately, the PPPoE WAN still never becomes operational.

I understand the recommendation about checking syslog or console logs through a USB TTL adapter, and I may try that next, but before going that far I wanted to share the complete provisioning flow in case I am missing something obvious in the TR-181 hierarchy or WAN binding sequence.

Current behavior:

  • Remote access works

  • WiFi provisioning works

  • VLAN objects are created

  • PPP interface accepts parameters

  • No provisioning faults are returned

  • Reboot does not change behavior

  • PPPoE WAN never comes up

I also visually checked the ONT web interface and the values appear correct after provisioning.

This is the complete provisioning fragment I am currently testing:

else if (manufacturer.includes("ZTE")) {

  // ================================
  // ADMIN
  // ================================
  try {
    declare("Device.Users.User.1.Username", { value: now }, { value: "admin" });
    declare("Device.Users.User.1.Password", { value: now }, { value: "4223441" });
  } catch (e) {
    log("ERROR admin: " + e);
  }

  // ================================
  // WIFI
  // ================================
  try {
    declare("Device.WiFi.SSID.1.SSID", { value: now }, { value: ssid });

    declare(
      "Device.WiFi.AccessPoint.1.Security.KeyPassphrase",
      { value: now },
      { value: wifiPass }
    );

    declare("Device.WiFi.SSID.1.Enable", { value: now }, { value: true });

    declare("Device.WiFi.AccessPoint.1.Enable", { value: now }, { value: true });

  } catch (e) {
    log("ERROR WIFI: " + e);
  }

  // ================================
  // REMOVE PPP EXCEPT TR069
  // ================================
  try {

    var pppCount =
      declare("Device.PPP.InterfaceNumberOfEntries", { value: now });

    var maxPpp =
      (pppCount && pppCount.value)
        ? Number(pppCount.value[0])
        : 0;

    for (var i = 1; i <= maxPpp; i++) {

      var path = "Device.PPP.Interface." + i;

      try {

        var svc =
          declare(path + ".X_ZTE-COM_ServiceList", { value: now });

        var val =
          svc && svc.value ? svc.value[0] : "";

        if (val && val.includes("TR069")) {
          continue;
        }

        declare(path, null, { path: 0 });

      } catch (e) {}
    }

  } catch (e) {
    log("ERROR PPP: " + e);
  }

  // ================================
  // REMOVE VLAN EXCEPT TR069
  // ================================
  try {

    var vlanCount =
      declare("Device.Ethernet.VLANTerminationNumberOfEntries", { value: now });

    var maxVlan =
      (vlanCount && vlanCount.value)
        ? Number(vlanCount.value[0])
        : 0;

    for (var j = 1; j <= maxVlan; j++) {

      var path =
        "Device.Ethernet.VLANTermination." + j;

      try {

        var lower =
          declare(path + ".LowerLayers", { value: now });

        var val =
          lower && lower.value ? lower.value[0] : "";

        if (val && val.includes("TR069")) {
          continue;
        }

        declare(path, null, { path: 0 });

      } catch (e) {}
    }

  } catch (e) {
    log("ERROR VLAN: " + e);
  }

  // ================================
  // CREATE VLAN
  // ================================
  try {

    var newVlan =
      declare(
        "Device.Ethernet.VLANTermination.+",
        { path: now },
        {}
      );

    declare(
      newVlan + ".Enable",
      { value: now },
      { value: true }
    );

    declare(
      newVlan + ".VLANID",
      { value: now },
      { value: vlan }
    );

  } catch (e) {
    log("ERROR VLAN create: " + e);
  }

  // ================================
  // CREATE / REUSE PPP
  // ================================
  try {

    var newPpp;

    try {

      newPpp = "Device.PPP.Interface.2";

      declare(
        newPpp + ".Enable",
        { value: now },
        { value: true }
      );

    } catch (e) {

      newPpp =
        declare(
          "Device.PPP.Interface.+",
          { path: now },
          {}
        );
    }

    declare(
      newPpp + ".Enable",
      { value: now },
      { value: true }
    );

    declare(
      newPpp + ".X_ZTE-COM_ServiceList",
      { value: now },
      { value: "INTERNET" }
    );

    declare(
      newPpp + ".LowerLayers",
      { value: now },
      { value: newVlan }
    );

    declare(
      newPpp + ".Username",
      { value: now },
      { value: username }
    );

    declare(
      newPpp + ".Password",
      { value: now },
      { value: password }
    );

    declare(
      newPpp + ".ConnectionTrigger",
      { value: now },
      { value: "AlwaysOn" }
    );

    declare(
      newPpp + ".NATEnabled",
      { value: now },
      { value: true }
    );

    log("WAN creada en: " + newPpp);

  } catch (e) {
    log("ERROR PPP create: " + e);
  }
}

At this point I am wondering if:

  • ZTE requires additional TR-181 bindings,

  • LowerLayers alone is not enough,

  • PPP.Interface.2 cannot be reused this way,

  • or Internet WANs must be created from another object hierarchy entirely.

If anyone has experience with ZTE ONTs and TR-181 PPPoE provisioning, I would really appreciate some guidance.

Thank you.

Your script is a bit clunky, but nothing jumps out at me as being incorrect. Have you asked ZTE what the minimum config is to get PPP to work?

Hello @akcoder,

Thanks again for the feedback.

One important thing I forgot to mention is that I already tested creating a new WAN interface manually from the ZTE web interface.

What I noticed is that the ONT seems to have a hard limit of 5 WAN interfaces.

If I try to create an additional WAN from the GUI, the ONT displays a message indicating that the maximum number of interfaces has already been reached.

Because of that, to create a new PPPoE WAN manually, I first have to delete one of the existing WAN interfaces.

That is why in my script I tried dynamically removing old PPP/VLAN interfaces while preserving the TR069 management WAN.

My current idea was something like:

  • iterate through existing interfaces,

  • detect which one is used for TR069,

  • keep that one untouched,

  • remove all the others,

  • then create or reuse a clean PPPoE Internet WAN dynamically.

Conceptually, does that approach make sense for ZTE ONTs?

Or would it be better to:

  • reuse one of the existing WAN interfaces instead of deleting them,

  • or overwrite an existing DHCP WAN into PPPoE?

I am still trying to understand what is considered the correct provisioning logic on these devices.

From what I observed manually in the GUI, deleting one existing WAN is mandatory before creating another one because of the 5-interface limit.

So I assume the same logic probably applies through TR-181 provisioning as well.

Also, I have not contacted ZTE directly about this yet. I am still trying to understand the provisioning model better first before reaching out to them.

Thank you.

Are you just getting started with GenieACS and TR-069? Or do you have an existing implementation with routers in the field configured with your settings?

If you are just getting started, my recommendation is to default your CPE, add the PPP interface and I presume you also have an interface for management. Use this as the base config file for your CPEs. Then all of your CPEs of that model will always be in a known state.

Hello @akcoder,

Thanks for the advice.

Just to give you a bit more context about my setup: I’m actually a developer and I’ve been building my own ISP management platform for a while now. At this point I already have most of the system covered end-to-end.

I have APIs that dynamically provide all the provisioning data per customer (VLANs, PPP credentials, WiFi settings, etc.), and I also manage the OLT directly from my system, which then triggers TR-069 provisioning on the routers automatically.

So overall, the platform is already working well in production for most devices.

The only remaining gap I’m trying to solve is TR-069 provisioning consistency across some specific ONT models. Most devices work fine, but there are about 2–3 ONUs that are giving me issues.

In this case (ZTE), I can fully manage:

  • remote access configuration

  • WiFi provisioning

  • parameter updates via ACS

  • and I can confirm values are correctly applied on the device side

However, the specific problem is PPPoE auto-provisioning. Even though the parameters are being pushed correctly, the PPPoE WAN does not come up automatically.

That’s the exact point I’m trying to solve now: making PPPoE provisioning fully automatic and reliable on this model, as part of the same dynamic flow I already use for the rest of the network.

So I’m not really at the “getting started” stage anymore, but more at the stage of refining and standardizing edge cases per vendor/model.

Thanks again for your guidance.

Did you check that the pppoe parameter doesn’t need to receive an enabled= value? For example, I also use ZTE but via DHCP iPoE, and my example is this when doing a WAN push in my provisioning script.

        ConnectionType: "IP_Routed",
        Enable: true,
        Name: "INTERNET-IPV4-V1004",
        "X_ZTE-COM_ServiceList": "INTERNET",
        "X_ZTE-COM_VLANEnable": true,
        "X_ZTE-COM_VLANID": 1004