Use topology/links and anynetlinks filters with eq/in operators so store WAN follow-ups return real peer tunnels instead of unscoped dumps. Co-authored-by: Cursor <cursoragent@cursor.com>
64 lines
3.2 KiB
Markdown
64 lines
3.2 KiB
Markdown
# Prisma Phase 2 — Voice Path Attribution Discovery
|
|
|
|
Time-boxed discovery notes for "voice is on this tunnel" / per-handset
|
|
attribution. Phase 1 (runtime waninterface status, overlay tunnels,
|
|
app DPI by `path_type`) ships without these.
|
|
|
|
## Confirmed Phase 1 surfaces (pan.dev + code)
|
|
|
|
| Need | Endpoint | Notes |
|
|
|------|----------|-------|
|
|
| Circuit runtime status | `GET /sdwan/v2.1/api/sites/{siteId}/waninterfaces/{wiId}/status` | Wired in `getWanInterfaceStatus` |
|
|
| Overlay tunnels | `POST /sdwan/v2.0/api/topology/links/query` with `query_params.{source\|target}_site_id.{in\|eq}` | Preferred — includes status, peer names, vpnlinks[] |
|
|
| Anynet fallback | `POST /sdwan/v4.0/api/anynetlinks/query` with `query_params.ep{1\|2}_site_id.{eq\|in}` | Config rows; no runtime status |
|
|
| Voice DPI by path_type | `getAppMetric` with `filter.path_type=[VPN]` etc. | AppPerf* only; AppAudioMos omits path_type |
|
|
| Alarm → tunnel id | `info.vpn_reasons[].vpn_link_id` | `extractVpnLinkIdsFromAlarmInfo` |
|
|
|
|
## Live-tenant corrections (2026-07-28 / store 1005)
|
|
|
|
| Issue | Fix |
|
|
|-------|-----|
|
|
| `limit: { count: N }` → 400 "expected int" | Topology/anynet `limit` is a bare int |
|
|
| `query: { site_id: [...] }` silently ignored | Use `query_params: { field: { eq\|in: … } }` (array under query_params → 400) |
|
|
| 100 tunnels all `peer — unknown` | Site-scoped topology query; resolve peer opposite local site; renderer collapses all-unknown |
|
|
| `vpnlinks` have no site fields | Prefer topology links; anynet via ep1/ep2; never unscoped vpnlinks dump |
|
|
| Pairing down volume | Prefer public-anynet; rank down/unknown first; cap ≤12; renderer shows ≤6 |
|
|
| Cascading 429s | Path-type breakout gated by `PRISMA_VOICE_PATH_TYPE_BREAKOUT`; status GETs capped |
|
|
|
|
Probe recipes:
|
|
|
|
```bash
|
|
node scripts/prismaProbe.js wi-status <siteId> <wanInterfaceId>
|
|
node scripts/prismaProbe.js tunnels <siteId>
|
|
node scripts/prismaProbe.js app-by-path-type <siteId> <appId> --metric loss
|
|
node scripts/prismaProbe.js try-shapes app-by-path <siteId> <appId> <wiId>
|
|
```
|
|
|
|
## Phase 2a candidates (probe before implementing further)
|
|
|
|
1. **App metrics + `filter.path`** (waninterface id) — already supported in
|
|
`getAppMetric({ pathIds })` behind `PRISMA_VOICE_PATH_ATTRIBUTION=1`.
|
|
Confirm live tenant accepts the filter (SCHEMA_CHECK_FAIL risk).
|
|
|
|
2. **Flow / session / app-path details** — SCM UI "Application Path Details"
|
|
HAR may reveal monitor endpoints that bind RTP to a specific path.
|
|
Candidates: topology query v3.6, object_stats, app/wan contexts.
|
|
|
|
3. **Join keys to Webex** — need client IP, subnet, or device id in Prisma
|
|
flow records to map to Meraki/Webex handset inventory. **Not confirmed.**
|
|
|
|
## Phase 2c status
|
|
|
|
`attributeVoicePathToEndpoint()` in
|
|
`services/callReport/voicePathAttribution.js` returns `null` until a
|
|
join key is confirmed. Path-level / path_type-level annotation is live
|
|
via `annotateWanWithPath()`.
|
|
|
|
## Confidence language
|
|
|
|
| Level | Meaning |
|
|
|-------|---------|
|
|
| `site` | Site-wide DPI only (`siteLevelApprox: true`) |
|
|
| `path_type` | One path_type uniquely worse in window |
|
|
| `path` | One waninterface uniquely worse (`byPath`) |
|
|
| `endpoint` | Per-handset — **not available** without flow join keys |
|