# =============================================================================
# verona — IPv6 apply script (v4-transport iBGP, no OSPFv3)
# =============================================================================
#
# Design choices vs ipv6.md plan:
#   * Drops OSPFv3 entirely. iBGP TCP session runs over the existing v4
#     loopback (10.254.254.101 ↔ 10.254.254.254) — v4 OSPF already provides
#     reachability between v4 loopbacks, so no v6 IGP is needed for the
#     session itself. The session carries IPv6 NLRI (MP-BGP, RFC 4760).
#   * v6 forwarding uses a static default route via climax's v6 P2P side
#     (2606:1c80:0:20::2). That gateway becomes reachable when climax's
#     v6 apply runs; until then v6 customer traffic will fail past verona
#     — known and accepted while the rollout proceeds tower-by-tower.
#   * iBGP next-hop is forced to self (verona's v6 loopback). Edge will
#     need a route to 2606:1c80:0:10::101/128 once edge is configured;
#     handled in the edge apply step.
#
# Apply order: review → paste into a winbox/SSH session on verona →
# verify with the checks at the bottom.
# =============================================================================

# -----------------------------------------------------------------------------
# WIPE — remove all existing internal v6 + OSPFv3 state. Leaves v4 alone.
# -----------------------------------------------------------------------------
/ppp profile set [find] remote-ipv6-prefix-pool="" dhcpv6-pd-pool=""
/ipv6 dhcp-server remove [find]
/ipv6 dhcp-server option remove [find]
/ipv6 dhcp-client remove [find]
/ipv6 nd prefix remove [find]
/ipv6 nd remove [find default=no]
/ipv6 pool remove [find]
/ipv6 route remove [find dynamic=no]
/ipv6 firewall filter remove [find]
/ipv6 firewall mangle remove [find]
/ipv6 firewall raw remove [find]
/ipv6 address remove [find dynamic=no]

# OSPFv3 — remove the v3 instance, area, interface-template entry, leave v2 alone.
/routing ospf interface-template remove [find area=backbone-v3]
/routing ospf area remove [find name=backbone-v3]
/routing ospf instance remove [find name=default-v3]

# Any leftover v6 BGP — wipe internal-only, never touch upstream peers.
/routing bgp connection remove [find name~"ibgp" and (afi~"ipv6" or address-families~"ipv6")]

# -----------------------------------------------------------------------------
# APPLY — addresses
# -----------------------------------------------------------------------------
/ipv6 settings set forward=yes accept-router-advertisements=no

/ipv6 address
add address=2606:1c80:0:10::101/128 interface=lo                  advertise=no comment="loopback"
add address=2606:1c80:0:20::1/64   interface=ether3-climax-11ghz advertise=no comment="P2P verona<->climax"
add address=2606:1c80:0:30::1/64   interface=vlan9_sfpplus1      advertise=no comment="P2P verona<->graham home"
add address=2606:1c80:1000::1/64    interface=verona              advertise=yes comment="verona mgmt LAN"
add address=2606:1c80:1500::1/64    interface=ether6-switch       advertise=yes comment="altoga mgmt LAN"

# -----------------------------------------------------------------------------
# APPLY — static routes (replaces what OSPFv3 would have done)
# -----------------------------------------------------------------------------
/ipv6 route
add dst-address=::/0                  gateway=2606:1c80:0:20::2 distance=1 comment="default via climax P2P"
add dst-address=2606:1c80:0:10::254/128 gateway=2606:1c80:0:20::2 distance=1 comment="edge loopback (iBGP target reachability fallback)"

# Blackhole the /44 aggregates so iBGP has something to advertise.
# (ROS7 syntax: `blackhole` is a flag, not a `type=` value.)
add dst-address=2606:1c80:1000::/44 blackhole distance=200 comment="verona /44 aggregate (iBGP origin)"
add dst-address=2606:1c80:1500::/44 blackhole distance=200 comment="altoga /44 aggregate (iBGP origin)"

# -----------------------------------------------------------------------------
# APPLY — neighbour discovery / RA on mgmt LANs (SLAAC + RDNSS)
# -----------------------------------------------------------------------------
/ipv6 nd
add interface=verona        ra-interval=3m20s-10m managed-address-configuration=no other-configuration=yes advertise-dns=yes
add interface=ether6-switch ra-interval=3m20s-10m managed-address-configuration=no other-configuration=yes advertise-dns=yes

/ipv6 nd prefix
add interface=verona        prefix=2606:1c80:1000::/64 autonomous=yes on-link=yes
add interface=ether6-switch prefix=2606:1c80:1500::/64 autonomous=yes on-link=yes

# Stateless DHCPv6 on each mgmt LAN — only carries DNS + search-domain options.
/ipv6 dhcp-server
add interface=verona        name=verona-mgmt-stateless address-pool=static-only
add interface=ether6-switch name=altoga-mgmt-stateless address-pool=static-only

# DHCPv6 PD server on vlan9_sfpplus1 — graham's home router connects there
# and is treated like a regular customer: it requests prefix delegation,
# receives a /56 from verona-cust-pd-1, and the dynamic route to that /56
# is created automatically with gateway=client-link-local.
add interface=vlan9_sfpplus1 name=verona-wired-pd address-pool=static-only prefix-pool=verona-cust-pd-1

# RA on vlan9_sfpplus1 advertises the link /64 + DNS option so the home
# router learns the default route via verona's link-local automatically.
/ipv6 nd
add interface=vlan9_sfpplus1 ra-interval=3m20s-10m managed-address-configuration=no other-configuration=yes advertise-dns=yes

/ipv6 nd prefix
add interface=vlan9_sfpplus1 prefix=2606:1c80:0:30::/64 autonomous=no on-link=yes

/ipv6 dhcp-server option
add name=v6-dns code=23 value="'2606:4700:4700::1111''2606:4700:4700::1001'"

# -----------------------------------------------------------------------------
# APPLY — customer PD pools and PPP profile bindings
# -----------------------------------------------------------------------------
/ipv6 pool
add name=verona-cust-pd-1 prefix=2606:1c80:1001::/48 prefix-length=56
add name=altoga-cust-pd-1 prefix=2606:1c80:1501::/48 prefix-length=56

/ppp profile
set [find name=pppoe-verona] remote-ipv6-prefix-pool=verona-cust-pd-1 dhcpv6-pd-pool=verona-cust-pd-1
set [find name=pppoe-altoga] remote-ipv6-prefix-pool=altoga-cust-pd-1 dhcpv6-pd-pool=altoga-cust-pd-1

# -----------------------------------------------------------------------------
# APPLY — firewall (mirror v4 hygiene; deny by default)
# -----------------------------------------------------------------------------
/ipv6 firewall filter
add chain=input action=accept connection-state=established,related comment="established"
add chain=input action=drop   connection-state=invalid             comment="invalid"
add chain=input action=accept protocol=icmpv6                      comment="icmpv6"
add chain=input action=accept src-address=fe80::/10                comment="link-local"
add chain=input action=accept src-address=2606:1c80::/32           comment="internal"
add chain=input action=drop                                        comment="default deny"

add chain=forward action=accept connection-state=established,related              comment="established"
add chain=forward action=drop   connection-state=invalid                          comment="invalid"
add chain=forward action=accept protocol=icmpv6 hop-limit=equal:1                 comment="PMTUD"
add chain=forward action=accept protocol=icmpv6                                   comment="icmpv6"
add chain=forward action=accept src-address=2606:1c80::/32 dst-address=2606:1c80::/32 comment="internal-to-internal"
add chain=forward action=accept in-interface-list=customer                        comment="v6 outbound from customers"
add chain=forward action=drop                                                     comment="default deny"

# -----------------------------------------------------------------------------
# APPLY — iBGP to edge over v4 transport, carrying v6 NLRI
# -----------------------------------------------------------------------------
# ROS 7.21.4 syntax notes (verified live on verona 2026-05-09):
#   - parameter is `afi=ip,ipv6` NOT `address-families=...`
#   - need a `/routing bgp instance` to reference (carries the local AS)
#   - `templates=default` ties it to the existing /routing/bgp/template
# Output filter: advertise verona's own routes — verona+altoga /44 customer
# aggregates, verona loopback /128, and connected /64 P2Ps to climax (:20)
# and graham's home (:30). Core (the v6 RR) reflects these to every other
# client. Anything else is rejected so we don't leak customer LANs etc.
/routing filter rule
add chain=v6-ibgp-out disabled=no rule="if (dst==2606:1c80:1000::/44 || dst==2606:1c80:1500::/44 || dst==2606:1c80:0:10::101/128 || (dst-len==64 && (dst==2606:1c80:0:20::/64 || dst==2606:1c80:0:30::/64))) { accept; } else { reject; }"

/routing bgp instance
add name=bgp-instance-1 as=393837 router-id=10.254.254.101

# Single iBGP session to CORE (which is the v6 route reflector for the fleet).
# v6 transport (loopback-to-loopback) — sidesteps the v4-mapped-next-hop bug
# we saw with v4 transport carrying v6 NLRI.
# output.redistribute=connected,static picks up the loopback /128 (connected)
# and the customer /44 blackhole aggregates (static); the filter chain narrows
# to just those three prefixes.
/routing bgp connection
add name=ibgp-rr-core instance=bgp-instance-1 templates=default \
    afi=ip,ipv6 local.role=ibgp local.address=2606:1c80:0:10::101 \
    remote.address=2606:1c80:0:10::253 remote.as=393837 multihop=yes \
    nexthop-choice=force-self output.filter-chain=v6-ibgp-out \
    output.redistribute=connected,static \
    comment="iBGP to core (v6 RR), v6 transport"

# -----------------------------------------------------------------------------
# VERIFY — paste these after the apply
# -----------------------------------------------------------------------------
# /ipv6 address print
# /ipv6 route print where active
# /ipv6 nd print
# /ipv6 pool print
# /ppp profile print where name~"pppoe-"
# /routing bgp connection print
# /routing bgp session print
#
# Once climax has its v6 apply done:
#   /ping 2606:1c80:0:20::2 count=3       ;; climax P2P side
#   /ping 2606:1c80:0:10::102 count=3     ;; climax loopback
# Once edge is done end-to-end:
#   /ping 2606:1c80:0:10::254 count=3     ;; edge loopback
#   /ping 2606:4700:4700::1111 count=3    ;; cloudflare end-to-end
#   /routing bgp session print            ;; ibgp-edge-v6 should be Established
