routers update
This commit is contained in:
parent
6f65f1035a
commit
34c88a2380
12 changed files with 177 additions and 31 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = K4QG-8NQV
|
||||
#
|
||||
# model = RB5009UG+S+
|
||||
|
|
@ -468,7 +468,7 @@ add chain=ospf-in disabled=no rule="accept;\r\
|
|||
add chain=ospf-out disabled=no rule="accept;"
|
||||
/routing ospf interface-template
|
||||
add area=ospf-area-1 auth=sha512 auth-id=1 disabled=no interfaces=\
|
||||
ether2-climax type=ptp use-bfd=yes
|
||||
ether2-climax type=ptp use-bfd=no
|
||||
add area=ospf-area-1 disabled=no passive
|
||||
/routing ospf static-neighbor
|
||||
add address=10.250.1.70%ether2-climax area=ospf-area-1 disabled=no \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = FUVS-HCM5
|
||||
#
|
||||
# model = CCR1009-7G-1C-1S+
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = UETF-WF31
|
||||
#
|
||||
# model = CCR2004-16G-2S+
|
||||
|
|
@ -399,8 +399,6 @@ set api address=204.110.188.0/22,10.0.0.0/8,100.64.0.0/10
|
|||
set api-ssl certificate=MyCA
|
||||
/ip ssh
|
||||
set host-key-type=ed25519 strong-crypto=yes
|
||||
/ipv6 address
|
||||
add address=2606:1c80:0:1010::1 interface=ether6-verona-11ghz
|
||||
/ipv6 dhcp-relay option
|
||||
set client_mac value="0x0001\$(CLIENT_MAC)"
|
||||
/ipv6 nd
|
||||
|
|
@ -436,7 +434,7 @@ add area=backbone-v3 cost=10 disabled=no use-bfd=no
|
|||
add area=backbone-v2 auth=sha512 auth-id=1 cost=10 disabled=no interfaces=\
|
||||
ether6-verona-11ghz priority=1 type=ptp use-bfd=no
|
||||
add area=backbone-v2 auth=sha512 auth-id=1 cost=10 disabled=no interfaces=\
|
||||
ether5-494 priority=1 type=ptp use-bfd=yes
|
||||
ether5-494 priority=1 type=ptp use-bfd=no
|
||||
add area=backbone-v3 auth=sha512 auth-id=1 cost=10 disabled=no interfaces=\
|
||||
ether3-culleoka-11ghz priority=1 type=ptp use-bfd=no
|
||||
add area=backbone-v2 auth=sha512 auth-id=1 cost=10 disabled=no interfaces=\
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = XS5B-41QR
|
||||
#
|
||||
# model = CCR1009-7G-1C-1S+
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = HVP9-3G0K
|
||||
#
|
||||
# model = CCR1009-7G-1C-1S+
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# may/09/2026 08:51:41 by RouterOS 6.49.18
|
||||
# may/09/2026 09:00:22 by RouterOS 6.49.18
|
||||
# software id = 8XZE-R7EJ
|
||||
#
|
||||
# model = CCR2004-1G-12S+2XS
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = 2I9X-PQZP
|
||||
#
|
||||
# model = CCR1009-7G-1C-1S+
|
||||
|
|
|
|||
|
|
@ -285,17 +285,21 @@ func runExport(cfg *Config) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
// findRouter looks up a router by name in the config; returns nil if missing.
|
||||
func findRouter(cfg *Config, name string) *Router {
|
||||
for i := range cfg.Routers {
|
||||
if cfg.Routers[i].Name == name {
|
||||
r := cfg.Routers[i]
|
||||
return &r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// runAPI logs into one router by name and runs an arbitrary API command,
|
||||
// printing the rows returned. Useful for ad-hoc lookups (`arp culleoka`).
|
||||
func runAPI(cfg *Config, routerName string, apiArgs []string) {
|
||||
var target *Router
|
||||
for i := range cfg.Routers {
|
||||
if cfg.Routers[i].Name == routerName {
|
||||
r := cfg.Routers[i]
|
||||
target = &r
|
||||
break
|
||||
}
|
||||
}
|
||||
target := findRouter(cfg, routerName)
|
||||
if target == nil {
|
||||
log.Fatalf("no router named %q in config", routerName)
|
||||
}
|
||||
|
|
@ -324,6 +328,130 @@ func runAPI(cfg *Config, routerName string, apiArgs []string) {
|
|||
}
|
||||
}
|
||||
|
||||
// runSchema introspects a MikroTik API path on a single router and shows
|
||||
// what parameter names exist in the wild. ROS7 keeps shuffling property
|
||||
// names between point releases (address-families → afi, type=blackhole
|
||||
// → blackhole flag, etc.), and the live router + the .rsc exports are
|
||||
// the only authoritative reference. Two sources, in order:
|
||||
//
|
||||
// 1. Live API: union of property keys observed across all rows under
|
||||
// <path>/print, with one example value per key. Falls back to /get
|
||||
// for singletons (/system/identity, /ip/dns, etc.).
|
||||
//
|
||||
// 2. Local .rsc exports: any block whose first line is the matching
|
||||
// ROS-script path (e.g. `/routing bgp connection` for input
|
||||
// `/routing/bgp/connection`), with the next several non-blank lines
|
||||
// so the user can see actual `add ...` invocations.
|
||||
//
|
||||
// Trailing /add /set /remove /print /get on the input path are stripped
|
||||
// — typing `mikrotik-tool schema verona /routing/bgp/connection/add` is
|
||||
// the natural reflex when you've just hit "unknown parameter" on an add.
|
||||
func runSchema(cfg *Config, routerName, path string) {
|
||||
target := findRouter(cfg, routerName)
|
||||
if target == nil {
|
||||
log.Fatalf("no router named %q in config", routerName)
|
||||
}
|
||||
r := cfg.resolve(*target)
|
||||
|
||||
norm := strings.TrimPrefix(path, "/")
|
||||
norm = strings.Trim(norm, "/")
|
||||
for _, suffix := range []string{"/add", "/set", "/remove", "/print", "/get", "/getall"} {
|
||||
norm = strings.TrimSuffix(norm, suffix)
|
||||
}
|
||||
apiPath := "/" + norm
|
||||
|
||||
fmt.Printf("=== schema: %s on %s ===\n", apiPath, r.Name)
|
||||
|
||||
c, err := dialAPI(r)
|
||||
if err != nil {
|
||||
log.Fatalf("[%s] %v", r.Name, err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
keys := map[string]string{}
|
||||
source := ""
|
||||
|
||||
if rep, err := c.RunArgs([]string{apiPath + "/print"}); err == nil && len(rep.Re) > 0 {
|
||||
source = fmt.Sprintf("union of keys across %d existing item(s)", len(rep.Re))
|
||||
for _, row := range rep.Re {
|
||||
for k, v := range row.Map {
|
||||
if _, exists := keys[k]; !exists {
|
||||
keys[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if rep, err := c.RunArgs([]string{apiPath + "/get"}); err == nil && len(rep.Re) > 0 {
|
||||
source = "singleton (/get)"
|
||||
for _, row := range rep.Re {
|
||||
for k, v := range row.Map {
|
||||
keys[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
fmt.Printf("\n# live api: no rows visible at %s\n", apiPath)
|
||||
} else {
|
||||
fmt.Printf("\n# live api: %s\n", source)
|
||||
var names []string
|
||||
for k := range keys {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
example := keys[k]
|
||||
if len(example) > 60 {
|
||||
example = example[:60] + "…"
|
||||
}
|
||||
fmt.Printf(" %-32s e.g. %s\n", k, example)
|
||||
}
|
||||
}
|
||||
|
||||
rscPath := "/" + strings.ReplaceAll(norm, "/", " ")
|
||||
fmt.Printf("\n# .rsc examples (matching `%s`):\n", rscPath)
|
||||
rscFiles, _ := filepath.Glob("*.rsc")
|
||||
sort.Strings(rscFiles)
|
||||
found := 0
|
||||
const maxExamples = 6
|
||||
const maxLinesPerExample = 12
|
||||
for _, f := range rscFiles {
|
||||
if found >= maxExamples {
|
||||
break
|
||||
}
|
||||
data, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lines := strings.Split(string(data), "\n")
|
||||
for i, line := range lines {
|
||||
if found >= maxExamples {
|
||||
break
|
||||
}
|
||||
if strings.TrimSpace(line) != rscPath {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("\n [%s:%d]\n", f, i+1)
|
||||
for j := 1; j < maxLinesPerExample && i+j < len(lines); j++ {
|
||||
next := lines[i+j]
|
||||
trimmed := strings.TrimSpace(next)
|
||||
if strings.HasPrefix(trimmed, "/") {
|
||||
break
|
||||
}
|
||||
if trimmed == "" {
|
||||
break
|
||||
}
|
||||
fmt.Printf(" %s\n", strings.TrimRight(next, "\r"))
|
||||
}
|
||||
found++
|
||||
}
|
||||
}
|
||||
if found == 0 {
|
||||
fmt.Println(" (no matches in local .rsc files)")
|
||||
} else if found >= maxExamples {
|
||||
fmt.Printf("\n (truncated at %d examples)\n", maxExamples)
|
||||
}
|
||||
}
|
||||
|
||||
func runList(cfg *Config) {
|
||||
for _, r := range cfg.Routers {
|
||||
r2 := cfg.resolve(r)
|
||||
|
|
@ -339,7 +467,12 @@ commands:
|
|||
export ssh to each router, run "/export", save stdout to <name>.rsc locally
|
||||
inventory discover access points, backhaul radios, and tower switches across
|
||||
every router (skipping customer equipment) and re-render
|
||||
inventory.yaml in place`)
|
||||
inventory.yaml in place
|
||||
api run an arbitrary API command on one router
|
||||
(e.g. mikrotik-tool api verona /ip/route/print)
|
||||
schema show parameter names accepted under an API path on one router,
|
||||
plus matching examples from local .rsc exports
|
||||
(e.g. mikrotik-tool schema verona /routing/bgp/connection)`)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
|
|
@ -388,6 +521,12 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
runAPI(cfg, args[1], args[2:])
|
||||
case "schema":
|
||||
if len(args) < 3 {
|
||||
fmt.Fprintln(os.Stderr, "usage: mikrotik-tool schema <router> <api-path>")
|
||||
os.Exit(2)
|
||||
}
|
||||
runSchema(cfg, args[1], args[2])
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
|
||||
usage()
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = 5HTF-YFWV
|
||||
#
|
||||
# model = CCR1009-7G-1C-1S+
|
||||
|
|
|
|||
|
|
@ -118,20 +118,22 @@ add chain=forward action=drop
|
|||
# -----------------------------------------------------------------------------
|
||||
# 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: only advertise verona+altoga /44 aggregates over this session.
|
||||
/routing filter rule
|
||||
add chain=v6-ibgp-out disabled=no rule="if (dst==2606:1c80:1000::/44 || dst==2606:1c80:1500::/44) { accept; } else { reject; }"
|
||||
|
||||
/routing bgp instance
|
||||
add name=bgp-instance-1 as=393837 router-id=10.254.254.101
|
||||
|
||||
/routing bgp connection
|
||||
add name=ibgp-edge-v6 \
|
||||
remote.address=10.254.254.254 \
|
||||
remote.as=393837 \
|
||||
local.address=10.254.254.101 \
|
||||
local.role=ibgp \
|
||||
address-families=ipv6 \
|
||||
multihop=yes \
|
||||
output.filter-chain=v6-ibgp-out \
|
||||
nexthop-choice=force-self \
|
||||
add name=ibgp-edge-v6 instance=bgp-instance-1 templates=default \
|
||||
afi=ip,ipv6 local.role=ibgp local.address=10.254.254.101 \
|
||||
remote.address=10.254.254.254 remote.as=393837 multihop=yes \
|
||||
nexthop-choice=force-self output.filter-chain=v6-ibgp-out \
|
||||
comment="iBGP to edge, v4 transport / v6 NLRI"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# 2026-05-09 08:51:42 by RouterOS 7.21.4
|
||||
# 2026-05-09 09:00:22 by RouterOS 7.21.4
|
||||
# software id = Y1CT-1WB1
|
||||
#
|
||||
# model = CCR2004-16G-2S+
|
||||
|
|
@ -425,6 +425,8 @@ set ether15_wave_n queue=FQ_Codel
|
|||
set ether16 queue=FQ_Codel
|
||||
set sfp-sfpplus1-verona-tower-switch queue=FQ_Codel
|
||||
set sfp-sfpplus2-switch queue=FQ_Codel
|
||||
/routing bgp instance
|
||||
add as=393837 name=bgp-instance-1 router-id=10.254.254.101
|
||||
/routing bgp template
|
||||
set default disabled=no output.network=bgp-networks
|
||||
/routing id
|
||||
|
|
@ -974,6 +976,11 @@ add address=204.110.191.2 disabled=yes require-message-auth=no service=\
|
|||
set accept=yes
|
||||
/routing bfd configuration
|
||||
add disabled=no interfaces=all min-rx=200ms min-tx=200ms multiplier=5
|
||||
/routing bgp connection
|
||||
add afi=ip,ipv6 comment="iBGP to edge, v4 transport / v6 NLRI" instance=\
|
||||
bgp-instance-1 local.address=10.254.254.101 .role=ibgp multihop=yes name=\
|
||||
ibgp-edge-v6 nexthop-choice=force-self output.filter-chain=v6-ibgp-out \
|
||||
remote.address=10.254.254.254 .as=393837 templates=default
|
||||
/routing filter rule
|
||||
add chain=ospf-in disabled=no rule="accept;"
|
||||
add chain=ospf-out disabled=no rule="accept;"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue