523 lines
24 KiB
Markdown
523 lines
24 KiB
Markdown
# tet-fiber-sfp
|
|
|
|
Replace an ISP-supplied **Nokia GPON ONT** with a **D-Link DPN-100** GPON SFP ONT stick
|
|
(Realtek RTL9601CI) seated directly in a **MikroTik hAP ac** (`sfp1`), by cloning the
|
|
ONT's identity onto the stick. No extra box, no extra PSU, no extra Ethernet hop.
|
|
|
|
Done against **TET** (Latvia) on a Nokia OLT with a **G-2426G-A** ONT. It registered
|
|
**O5 / OPERATION on the first fibre connect** — no fake-O5 loop — and pulled a public
|
|
DHCP lease on the WAN VLAN. The method is generic to Nokia-OLT GPON ISPs; the exact
|
|
identity values and the WAN VLAN are yours to discover.
|
|
|
|
> **Scope of this README:** the full procedure, with every line-specific value replaced
|
|
> by a placeholder. Put your real values in `.env` (gitignored) — see
|
|
> [`example.env`](example.env).
|
|
|
|
---
|
|
|
|
## Contents
|
|
|
|
1. [Before you start](#1-before-you-start)
|
|
2. [Read your ONT's identity](#2-read-your-onts-identity-do-this-first)
|
|
3. [Bench setup — talk to the stick](#3-bench-setup--talk-to-the-stick)
|
|
4. [Configure `.env`](#4-configure-env)
|
|
5. [Write the clone values](#5-write-the-clone-values)
|
|
6. [Reboot, verify, connect the fibre](#6-reboot-verify-connect-the-fibre)
|
|
7. [Router side — WAN VLAN, DHCP, firewall](#7-router-side--wan-vlan-dhcp-firewall)
|
|
8. [Lock down the stick's management](#8-lock-down-the-sticks-management)
|
|
9. [Revert to factory](#9-revert-to-factory)
|
|
10. [Troubleshooting](#10-troubleshooting)
|
|
11. [Tools reference](#11-tools-reference)
|
|
12. [Known unknowns](#12-known-unknowns)
|
|
|
|
---
|
|
|
|
## 1. Before you start
|
|
|
|
**Hardware**
|
|
|
|
| Thing | Notes |
|
|
|---|---|
|
|
| D-Link DPN-100 GPON SFP ONT | Rev C1 here, stock firmware `R4.2.104.033e` ("Wind"), 16 MB SPI-NOR, Realtek RTL9601CI |
|
|
| MikroTik with an SFP cage | hAP ac (RB962UiGS), RouterOS 7.x. Any RouterOS box with `sfp1` works |
|
|
| Your ISP's ONT | still connected, so you can read its identity **before** you swap |
|
|
| USB-UART / serial adapter | *strongly recommended* — the only recovery path if you brick the stick |
|
|
|
|
**Know what you're doing here**
|
|
|
|
- You are presenting a different device to your ISP's OLT under your own ONT's identity.
|
|
Whether that's acceptable is between you and your contract — check it. Only ever clone
|
|
**your own** ONT, on **your own** line.
|
|
- Two ONTs with the same serial must never be on the fibre at once. Unplug the original.
|
|
- The ISP keeps OMCI control of whatever ONT is on the line. That's inherent to GPON.
|
|
- The `mtd1` "Config" partition holds this stick's unique serial, PLOAM password and **RF
|
|
calibration** — there is no download for it. Nothing in this guide writes to it directly,
|
|
but if you want a recovery copy before you start, `tools/gpon_backup.py` dumps a partition
|
|
over telnet and md5-verifies it (`python3 tools/gpon_backup.py 1 mtd1_config.bin`).
|
|
- Class 1 laser. Don't look into the fibre or the SFP's port.
|
|
|
|
---
|
|
|
|
## 2. Read your ONT's identity (do this first)
|
|
|
|
While the ISP's ONT is still up, log in to its **web UI** (its LAN address is on the
|
|
label) and go to **Maintenance → Log**. Everything you need is in the **first few lines**,
|
|
in one place — that's the ONT reporting its TR-069 `DeviceInfo` parameters to the ISP's ACS
|
|
at boot, so the whole identity set appears together. The individual values are also
|
|
scattered across the status pages, but the log saves you the hunt.
|
|
|
|
| `.env` key | Field in **Maintenance → Log** | What it is (OMCI) |
|
|
|---|---|---|
|
|
| `ONT_VENDOR` | `Manufacturer` | GPON **vendor ID**. Nokia/Alcatel-Lucent reports `ALCL` — the same 4 chars the serial starts with, so the two cross-check each other |
|
|
| `ONT_SERIAL` | `SerialNumber` | GPON **serial number** — the OLT's primary ONT identifier. 12 chars = 4 ASCII vendor bytes + 4 bytes rendered as 8 hex chars |
|
|
| `ONT_EQID` | `ProductClass` | **Equipment ID** (ME257 ONT2-G) = the model string |
|
|
| `ONT_HWVER` | `HWVer` | **Hardware version** (ME256 ONT-G) |
|
|
| `ONT_SWVER` | `SWVer` | **Software version** (ME7). If it carries a bracketed build suffix like `XXXXXXXXXXXXXX(1.2345.678)`, the OMCI value is the **14-char prefix** without it |
|
|
| `ONT_MAC` | *not in the log* | The ONT's own MAC — **printed on the box label** |
|
|
|
|
Cross-check what you can against the physical labels: the serial and model are printed on
|
|
the ONT itself, and the hardware version is usually the string the box label calls
|
|
**"ONT P/N"**. Two independent sources per value is worth the thirty seconds.
|
|
|
|
Also worth screenshotting before you lose access: the ONT's WAN service list (which
|
|
VLAN ID carries internet vs VoIP vs TR-069) and its optical levels (Rx/Tx dBm), so you
|
|
have a reference for what "healthy" looks like on your line.
|
|
|
|
**Two things you probably do not need:**
|
|
|
|
- **PLOAM password** — not exposed in the Nokia UI. On the line this was done against,
|
|
the OLT authenticates by **serial only** and registration worked without it. Leave the
|
|
stick's factory value; only revisit if the OLT rejects you with a password error.
|
|
- **The MAC, in bridge mode.** `mac1` is the *stick's own* identity (its management
|
|
interface). The stick bridges transparently, so the L2 source your ISP's DHCP/BNG
|
|
actually sees is your **router's** `sfp1.<vlan>` MAC — which you never change, and it
|
|
still works. Cloning `mac1` is faithful and harmless, but it is not in the data path.
|
|
It would only matter if you ran the stick in **router** mode.
|
|
|
|
---
|
|
|
|
## 3. Bench setup — talk to the stick
|
|
|
|
Seat the stick in `sfp1` **with no fibre attached**. The host-side link will not come up
|
|
until you tell RouterOS to ignore loss-of-signal:
|
|
|
|
```
|
|
/interface ethernet set sfp1 sfp-ignore-rx-los=yes
|
|
```
|
|
|
|
`sfp1` should now show `link-ok` at 1 Gbps. The stick's management lives **untagged** on
|
|
`sfp1` at its factory address `192.168.100.1` (telnet, `root`/`admin` — the documented
|
|
D-Link/Realtek defaults for this build). Give the router an address in that subnet:
|
|
|
|
```
|
|
/ip address add address=192.168.100.2/24 interface=sfp1 comment=gpon-bench-test
|
|
```
|
|
|
|
**Reaching it from a workstation.** Do **not** try to `dst-nat` to `192.168.100.1` —
|
|
RouterOS marks that rule INVALID. Source-NAT out of `sfp1` instead, so the stick replies
|
|
to an address it can route to:
|
|
|
|
```
|
|
/ip firewall nat add chain=srcnat out-interface=sfp1 action=masquerade \
|
|
src-address=<ADMIN_HOST> comment=gpon-bench-test
|
|
```
|
|
|
|
Your workstation then reaches `192.168.100.1` via its default gateway. Check it:
|
|
|
|
```bash
|
|
cp example.env .env # then edit .env — see step 4
|
|
python3 tools/gpon_cli.py 'system' 'ontver'
|
|
```
|
|
|
|
**The CLI is not a shell.** Login drops you into the restricted Realtek OMCI CLI,
|
|
prompt `#ONT>`. Two contexts matter:
|
|
|
|
```
|
|
#ONT> system -> #ONT/system>
|
|
#ONT/system> misc -> #ONT/system/misc> EEPROM identity fields (<field> get|set)
|
|
#ONT/system> shell -> #ONT/system/shell> real busybox root shell (uid=0)
|
|
```
|
|
|
|
Other menus: `#ONT/traffic>` → `{pon,eth,voip,omci,router,hpna}`;
|
|
`#ONT/system>` → `{mib,log,env,misc,manu,fs,ippath,net,shell,debug,ontver,custom}`.
|
|
|
|
The stick has **no default route** — it can only reach its own `/24`.
|
|
|
|
---
|
|
|
|
## 4. Configure `.env`
|
|
|
|
```bash
|
|
cp example.env .env
|
|
$EDITOR .env
|
|
```
|
|
|
|
`GPON_HOST` / `GPON_PORT` / `GPON_USER` / `GPON_PASS` are the stick's factory defaults and
|
|
are read by everything in `tools/`. Fill in the `ONT_*` values from step 2, and the
|
|
`STICK_*` values from the read-back below, which are your revert path.
|
|
|
|
`.env` is gitignored. `example.env` is the shareable template. Resolution order is
|
|
process environment → `.env` → `example.env`, so you can also do a one-off with
|
|
`GPON_HOST=… python3 tools/…`.
|
|
|
|
Record the stick's own factory identity into `.env` now, before you overwrite it:
|
|
|
|
```bash
|
|
python3 tools/gpon_cli.py 'system' 'misc' \
|
|
'vendor get' 'eqsn get' 'eqid get' 'eqvid get' 'mac1 get' 'pon_passwd get'
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Write the clone values
|
|
|
|
Five fields are direct EEPROM writes in `#ONT/system/misc`. The sixth (software version)
|
|
is not an EEPROM field at all.
|
|
|
|
### 5a. EEPROM identity
|
|
|
|
```bash
|
|
set -a; . ./.env; set +a
|
|
python3 tools/gpon_cli.py 'system' 'misc' \
|
|
"vendor set \"$ONT_VENDOR\"" \
|
|
"eqsn set \"$ONT_SERIAL\"" \
|
|
"eqid set \"$ONT_EQID\"" \
|
|
"eqvid set \"$ONT_HWVER\"" \
|
|
"mac1 set $ONT_MAC"
|
|
```
|
|
|
|
Each `set` returns `---ATECMDRESULT--- OK`. Read them back with `<field> get`.
|
|
|
|
> A read-back of `eqsn` may show the trailing 8 characters **lowercased**. That is
|
|
> cosmetic: the serial's second half is stored as 4 binary bytes and re-rendered as
|
|
> lowercase hex. The 8 bytes the OLT checks are the 4 ASCII vendor bytes followed by
|
|
> those 4 binary bytes, which are unchanged.
|
|
|
|
### 5b. Software version (ME7)
|
|
|
|
The SW version is read at boot from a config file, not from EEPROM. The Realtek config
|
|
loader (`libvos.so`) reads `/etc/sys.cfg`, `/tmp/sys.cfg`, **`/mnt/rwdir/sys.cfg`**,
|
|
`/mnt/backupdir/etc/sys.cfg` in order and **merges** them per key — so a one-line overlay
|
|
overrides only `SWVER` and leaves the read-only cramfs base untouched:
|
|
|
|
```bash
|
|
set -a; . ./.env; set +a
|
|
python3 tools/gpon_cmd.py "echo SWVER=$ONT_SWVER > /mnt/rwdir/sys.cfg" 'sync' 'cat /mnt/rwdir/sys.cfg'
|
|
```
|
|
|
|
### 5c. Leave these alone (with fallbacks if it doesn't register)
|
|
|
|
| Field | Leave at | Why |
|
|
|---|---|---|
|
|
| `misc olt_vendor` | `0` (auto) | Stock `/etc/sys.cfg` ships `MUL_VENDOR_EN=2` + an `EXPECT_VENDOR_ID` list covering ALU/Nokia auto-adapt, and the DPN-100 C1 guides also leave it. **Fallback on fake-O5:** try `21`, then `1`, then `3` |
|
|
| `misc pon_passwd` (PLOAM) | factory | Serial-based auth. **Fallback:** set it only if the OLT rejects with a password error |
|
|
| `misc mac2`, `hwver`, `mpcode`, `mpsn`, `mhwv` | unchanged | Manufacturing/secondary fields, not checked by the OLT |
|
|
|
|
---
|
|
|
|
## 6. Reboot, verify, connect the fibre
|
|
|
|
EEPROM writes are immediate and persistent; `sys.cfg` is only read at boot. So a clean
|
|
**reboot** applies everything:
|
|
|
|
```bash
|
|
python3 tools/gpon_cmd.py 'reboot'
|
|
python3 tools/gpon_verify.py 'system' 'ontver' 'misc' \
|
|
'vendor get' 'eqsn get' 'eqid get' 'eqvid get' 'mac1 get'
|
|
```
|
|
|
|
> ⚠ Do **not** use `#ONT/system/mib` → `reset` as a "commit". It resets the runtime MIB to
|
|
> defaults; it is not a save.
|
|
|
|
`gpon_verify.py` waits for telnet to drop (confirming the reboot actually began), waits
|
|
for it to come back, then reads the values. The one that proves the overlay worked is
|
|
`ontver` — it can only have changed from the stock firmware string if `/mnt/rwdir/sys.cfg`
|
|
was read at boot.
|
|
|
|
Now **unplug the fibre from the ISP's ONT and plug it into the stick.** Then:
|
|
|
|
```bash
|
|
python3 tools/gpon_cli.py 'traffic' 'pon' 'show link'
|
|
```
|
|
|
|
Want:
|
|
|
|
```
|
|
Link State: ACTIVE
|
|
Operation State Machine: OPERATION (O5)
|
|
```
|
|
|
|
`show alarm` in the same menu lists PON MAC alarms. If you're stuck below O5, see
|
|
[Troubleshooting](#10-troubleshooting).
|
|
|
|
---
|
|
|
|
## 7. Router side — WAN VLAN, DHCP, firewall
|
|
|
|
### ⚠ Do the firewall first. Read this before you add the DHCP client.
|
|
|
|
A stock RouterOS `input` chain typically protects the WAN with **one rule**:
|
|
`drop chain=input in-interface=ether1`. That is not a catch-all — the chain otherwise
|
|
**default-accepts**, and `api` (8728), `api-ssl` (8729) and `ssh` (22) commonly listen with
|
|
no address restriction. They were safe only because `ether1` was the single public interface.
|
|
|
|
On the line this was built against, the new VLAN interface got its public IP **before** it
|
|
was added to that drop — and the router's API was reachable from the internet and being
|
|
brute-forced within minutes. (Failed logins only, no breach: verified no rogue users, no
|
|
scheduler entries, no socks, and the only successful logins were from the LAN.)
|
|
|
|
**The rule: never let a public IP land on a MikroTik interface that is not already in the
|
|
WAN drop set.** Two ordering facts make this concrete:
|
|
|
|
- An **`input`** rule matching an interface **list** is valid immediately, so you can lock
|
|
it down before any address exists.
|
|
- A **`forward`** rule with `in-interface=X` is flagged `I`/INVALID while `X` has no IP, so
|
|
it cannot be pre-created — it goes valid the moment DHCP binds.
|
|
|
|
So: add the interface to the WAN list and fix the input drop **first**, then add the DHCP
|
|
client, then add the forward drop.
|
|
|
|
### Config
|
|
|
|
```
|
|
# 1) VLAN sub-interface on the stick port. Verify the VLAN ID for YOUR ISP (below).
|
|
/interface vlan add name=sfp1.<WAN_VLAN> interface=sfp1 vlan-id=<WAN_VLAN> comment=gpon-wan
|
|
|
|
# 2) FIRST: treat it as WAN. Add to the interface-list your input drop keys on...
|
|
/interface list member add list=WAN interface=sfp1.<WAN_VLAN> comment=gpon-wan
|
|
|
|
# ...and convert the single-interface input drop to match the list
|
|
/ip firewall filter ... chain=input action=drop in-interface-list=WAN \
|
|
comment="WAN mgmt lockout (all WAN interfaces)"
|
|
|
|
# 3) THEN the DHCP client. add-default-route=no keeps your existing WAN primary
|
|
# while you test; use-peer-dns=no avoids clobbering your resolvers.
|
|
/ip dhcp-client add interface=sfp1.<WAN_VLAN> add-default-route=no use-peer-dns=no \
|
|
comment=gpon-wan-v4 disabled=no
|
|
|
|
# 4) Once the lease binds: the "drop from WAN not dstnat" forward rule for it
|
|
/ip firewall filter add chain=forward action=drop connection-state=new \
|
|
connection-nat-state=!dstnat ipsec-policy=in,none in-interface=sfp1.<WAN_VLAN> \
|
|
comment="drop from WAN not dstnat (fibre)"
|
|
```
|
|
|
|
Then confirm the fibre actually passes traffic without disturbing your primary WAN:
|
|
|
|
```
|
|
/ping 8.8.8.8 src-address=<LEASED_IP> interface=sfp1.<WAN_VLAN>
|
|
```
|
|
|
|
### Finding your WAN VLAN
|
|
|
|
The VLAN IDs listed in the ONT's own WAN service table are **ONT-internal C-VLANs**. What
|
|
your router sees through the stick is the tag on the Ethernet side, which OMCI translation
|
|
may set differently — community reports of four-digit S-VLANs are about the OLT side of
|
|
the fibre, which you never see here. On this line the Ethernet-side internet VLAN turned
|
|
out to be the same low ID the ONT listed for INTERNET, and **untagged got no DHCP reply
|
|
at all**.
|
|
|
|
Determine it empirically: with the stick registered at O5, either try a DHCP client on the
|
|
ONT's listed internet VID first, or sniff for tagged frames —
|
|
`/tool sniffer quick interface=sfp1` and read the VLAN column.
|
|
|
|
Note that WAN (tagged) and the stick's management (untagged) coexist on `sfp1` with no
|
|
conflict, so you keep telnet access while the WAN is live.
|
|
|
|
### Cutting over for real
|
|
|
|
Deliberately *not* done in the reference setup — the fibre was left present-but-not-default.
|
|
To actually use it:
|
|
|
|
1. **Masquerade:** add the VLAN interface to whatever your `srcnat` rules key on, or add
|
|
`chain=srcnat out-interface=sfp1.<WAN_VLAN> action=masquerade`.
|
|
2. **Default route:** `/ip dhcp-client set [find comment=gpon-wan-v4] add-default-route=yes`
|
|
— either as primary, or with a higher `default-route-distance` for failover behind your
|
|
existing WAN.
|
|
3. **Re-add, deliberately, any service accepts and `dst-nat` port-forwards** you want
|
|
reachable on the fibre IP. Until you do, nothing is forwarded in and management is
|
|
dropped. Think before you duplicate port-forwards: doing so publishes those internal
|
|
hosts on a second public IP.
|
|
|
|
Or route **one host** out of the fibre and leave everyone else alone. RouterOS 7.22 rejects
|
|
the older mangle `action=mark-routing` form (comes up INVALID) — use `/routing rule`:
|
|
|
|
```
|
|
/routing table add name=via-fibre fib
|
|
/ip route add dst-address=0.0.0.0/0 gateway=<FIBRE_GATEWAY> routing-table=via-fibre comment="pbr: fibre default"
|
|
/ip firewall nat add chain=srcnat out-interface=sfp1.<WAN_VLAN> action=masquerade comment="pbr: masq to fibre"
|
|
# keep RFC1918 on the main table, send everything else out the fibre
|
|
/routing rule add src-address=<HOST> dst-address=10.0.0.0/8 action=lookup table=main comment=pbr
|
|
/routing rule add src-address=<HOST> dst-address=172.16.0.0/12 action=lookup table=main comment=pbr
|
|
/routing rule add src-address=<HOST> dst-address=192.168.0.0/16 action=lookup table=main comment=pbr
|
|
/routing rule add src-address=<HOST> action=lookup table=via-fibre comment="pbr SWITCH: disable to revert"
|
|
```
|
|
|
|
Disabling that last rule is the whole revert. Existing connections stay on the old WAN
|
|
until they reconnect — only new flows move. If new flows don't switch, exclude the host
|
|
from FastTrack.
|
|
|
|
### RouterOS gotchas
|
|
|
|
- **`in-interface=""` does not clear an interface matcher** — it errors with "ambiguous
|
|
value". To convert a rule: capture its `.id`, `add` the replacement with
|
|
`place-before=$id`, then `remove $id`.
|
|
- Over SSH, keep a `:local` and its use **on one line** — each line is its own scope.
|
|
- Label everything with `comment=` (see the cleanup list at the end of this section) so
|
|
you can find and remove your test objects later.
|
|
|
|
**Objects this procedure creates:** `/interface vlan sfp1.<WAN_VLAN>`; that interface in
|
|
the `WAN` interface list; `/ip dhcp-client` on it; `/ip address 192.168.100.2/24` on
|
|
`sfp1`; the `srcnat` masquerade to the stick; the input and forward firewall rules.
|
|
|
|
---
|
|
|
|
## 8. Lock down the stick's management
|
|
|
|
On stock firmware the telnet password **cannot be changed**, so control access at the
|
|
router. The stick is not internet-reachable to begin with — private address, no `dst-nat`
|
|
to it, the WAN forward-drop covers it, and it does not bridge management onto the WAN VLAN
|
|
— but by default any LAN host can reach it via the connected route.
|
|
|
|
Restrict it to one admin host, and scope the return-path masquerade to match:
|
|
|
|
```
|
|
/ip firewall filter add chain=forward action=accept src-address=<ADMIN_HOST> \
|
|
dst-address=192.168.100.0/24 comment="gpon-stick: allow admin host" \
|
|
place-before=[:pick [/ip firewall filter find chain=forward] 0]
|
|
/ip firewall filter add chain=forward action=drop dst-address=192.168.100.0/24 \
|
|
comment="gpon-stick: block LAN from stick mgmt" \
|
|
place-before=[:pick [/ip firewall filter find chain=forward] 0]
|
|
/ip firewall nat set [find comment=gpon-bench-test] src-address=<ADMIN_HOST>
|
|
```
|
|
|
|
The router's own traffic isn't forward-filtered, so it can still reach the stick. Reopen by
|
|
disabling the two `gpon-stick` rules. For a genuinely changeable password plus SSH you need
|
|
community firmware — do that with the UART adapter as your recovery net.
|
|
|
|
---
|
|
|
|
## 9. Revert to factory
|
|
|
|
From the `STICK_*` values you recorded in step 4:
|
|
|
|
```bash
|
|
set -a; . ./.env; set +a
|
|
python3 tools/gpon_cli.py 'system' 'misc' \
|
|
"vendor set \"$STICK_VENDOR\"" \
|
|
"eqsn set \"$STICK_SERIAL\"" \
|
|
"eqid set \"$STICK_EQID\"" \
|
|
"eqvid set \"$STICK_HWVER\"" \
|
|
"mac1 set $STICK_MAC"
|
|
python3 tools/gpon_cmd.py 'rm /mnt/rwdir/sys.cfg' 'sync' 'reboot'
|
|
```
|
|
|
|
Removing the overlay restores the base `SWVER` from the read-only cramfs `/etc/sys.cfg`.
|
|
|
|
To undo the router side: remove the objects listed at the end of step 7, and
|
|
`/interface ethernet set sfp1 sfp-ignore-rx-los=no`.
|
|
|
|
If the stick is bricked rather than merely misconfigured, you need the UART adapter and a
|
|
dump of its `mtd1` Config partition — which is why it's worth taking one first.
|
|
|
|
---
|
|
|
|
## 10. Troubleshooting
|
|
|
|
**Stuck at O1, or fake-O5 (registers then drops in a loop).** Fake-O5 usually means the OLT
|
|
is trying a firmware-download handshake it doesn't like the answer to. In order: re-check
|
|
`eqsn` for a typo (it is *the* identifier); confirm `ontver` reflects `ONT_SWVER`; then try
|
|
`misc olt_vendor set 21`, then `1`, then `3`, rebooting between each. If the OLT complains
|
|
about a password specifically, set `pon_passwd`. If it still refuses, the remaining lever is
|
|
community firmware (below).
|
|
|
|
**No DHCP on the WAN VLAN.** Confirm O5 first — nothing works below it. Then confirm you
|
|
have the right VLAN ID (untagged will not answer), that the VLAN interface is on `sfp1`, and
|
|
that the DHCP client is enabled and not stuck at "searching".
|
|
|
|
**`sfp1` link never comes up.** `sfp-ignore-rx-los=yes` is required without fibre. Check
|
|
`/interface ethernet monitor sfp1` and re-seat the module.
|
|
|
|
**Stick doesn't come back after reboot.** `gpon_verify.py` gives up after ~140 s; raise
|
|
`--wait`. If it truly doesn't return, re-seat it and check `sfp1`.
|
|
|
|
**`flash get` / `flash set` fail.** Broken on this stock build — `libmib.so.0` is missing.
|
|
Use the OMCI CLI (`misc <field> set`) for identity instead. The `flash` tool only becomes
|
|
usable after a community reflash, so ignore guides that lead with it.
|
|
|
|
**Temperature reads 0 / the router reports a bad SFP EEPROM checksum.** Both are expected
|
|
and neither is fixable in software: the temperature sensor isn't populated
|
|
(`misc showtemp` → `temp = 0`), and the transceiver's DDM block has a bad checksum, so
|
|
RouterOS shows `eeprom-checksum: bad` and no DDM. These sticks run genuinely hot; manage it
|
|
physically (airflow, a small heatsink on the exposed end). **Your real health signal is the
|
|
registration state, not temperature** — a thermal or link fault shows up as PON dropping
|
|
`O5 → O1` or `sfp1` flapping. Also note `misc alarmstat` reports `ALARM1`/`ALARM2`/`DOOROPEN`
|
|
as "yes" — spurious on an SFP form factor, ignore it.
|
|
|
|
**Read-only diagnostics** (need the stick's management address reachable):
|
|
|
|
| Command | Shows |
|
|
|---|---|
|
|
| `traffic/pon > show link` | PON registration state — want `ACTIVE` / `OPERATION (O5)` |
|
|
| `traffic/pon > show alarm` | PON MAC alarms |
|
|
| `system > ontver` | OMCI software version (should equal `ONT_SWVER`) |
|
|
| `system/misc > eth_status`, `CPU_inform` | Ethernet status, CPU (reports RTL8672) |
|
|
| `system/misc > showtemp`, `alarmstat` | unusable on this stick, see above |
|
|
|
|
**Reflashing (last resort, functional reasons only).** Newer community builds have working
|
|
`flash get/set` and better Nokia OMCI / fake-O5 handling. **Match the flash size** —
|
|
this stick is 16 MB, so a 16 MB build is the right target and an 8 MB one is not. Do it
|
|
with the UART adapter connected as your recovery path, never blind over telnet.
|
|
|
|
---
|
|
|
|
## 11. Tools reference
|
|
|
|
Python 3, standard library only, no dependencies. Connection settings come from `.env`
|
|
(see step 4); run them from the repo root.
|
|
|
|
| Script | Purpose |
|
|
|---|---|
|
|
| `tools/gpon_cli.py` | Drive the `#ONT` OMCI CLI — navigates menus, one argument per CLI line |
|
|
| `tools/gpon_cmd.py` | Drive the busybox root shell (enters `system` → `shell` for you) |
|
|
| `tools/gpon_verify.py` | Wait out a reboot (down, then up), then run CLI reads |
|
|
| `tools/gpon_backup.py` | Dump one MTD partition over telnet, md5-verified |
|
|
| `tools/gpon_telnet.py` | Minimal raw telnet driver, for poking at anything else |
|
|
| `tools/gpon_env.py` | Shared `.env` loader (not run directly) |
|
|
|
|
```bash
|
|
python3 tools/gpon_cli.py 'traffic' 'pon' 'show link'
|
|
python3 tools/gpon_cmd.py 'cat /proc/mtd' 'ls -la /mnt/rwdir'
|
|
python3 tools/gpon_backup.py 1 mtd1_config.bin
|
|
python3 tools/gpon_telnet.py --host 192.168.100.1 --port 23 --wait 3 '?'
|
|
```
|
|
|
|
All of them speak enough of the telnet protocol to refuse option negotiation and strip
|
|
IAC sequences, and read until the prompt returns or an idle timeout expires (`--idle`,
|
|
`--cap`) — the stick is slow and chatty, so raise those rather than assuming a hang.
|
|
|
|
**Repo layout**
|
|
|
|
```
|
|
README.md this guide
|
|
example.env template -> copy to .env (gitignored)
|
|
tools/ Python telnet drivers for the stick
|
|
```
|
|
|
|
---
|
|
|
|
## 12. Known unknowns
|
|
|
|
- **`OMCI_SW_VER2` — the standby image version.** A Nokia ONT reports **two different**
|
|
software versions (active and standby). `SWVER` sets the active ME7 value, and on this
|
|
stick both slots then report it. It registered fine — but if an OLT ever runs a
|
|
fake-O5 firmware-download sequence that requires the two to differ, this is what to
|
|
revisit, and the standby string is not obtainable from the ONT's UI.
|
|
- **ISP fleet firmware updates.** If your ISP pushes a software update to its ONT fleet,
|
|
the cloned `ONT_SWVER` may need updating to match — reported by others on Nokia OLTs.
|
|
|
|
## Credits
|
|
|
|
The hack-gpon project's DPN-100 / Realtek documentation, and the Latvian GPON-SFP
|
|
community discussion (notably `@KristapsStudy`'s thread on cloning to a Nokia OLT) for the
|
|
`OMCI_SW_VER1`/`VER2` + `OMCI_OLT_MODE` leads.
|