Skip to content

junos: add then-action-conflicts lab characterizing commit-time collapse#187

Merged
dhalperi merged 1 commit into
mainfrom
spr/main/142fcedb
May 20, 2026
Merged

junos: add then-action-conflicts lab characterizing commit-time collapse#187
dhalperi merged 1 commit into
mainfrom
spr/main/142fcedb

Conversation

@dhalperi
Copy link
Copy Markdown
Member

@dhalperi dhalperi commented May 20, 2026

108-term lab empirically testing what Junos retains when a then block
contains two or more actions targeting the same attribute. Key findings:

  • For most scalar/numeric attribute families (origin, preference, tag,
    color, priority, next-hop IP, source-class, external, lp/metric/metric2
    in any combination of set/add/subtract/expression/igp, same-family
    as-path-prepend or as-path-expand pairs), last-wins universally:
    Junos drops the first action at commit time when both target the same
    attribute. Identical duplicates collapse to one.
  • The retained config is canonical, not source-order: display set
    emits actions in a deterministic order (side-effects, then named
    terminators, then bare accept/reject), regardless of authoring order.
  • Community statements all survive commit and execute sequentially with
    their plain meanings (set assigns, add unions, delete removes).
  • Cross-family at the same attribute keeps both: as-path-prepend +
    as-path-expand both retained (canonical order: prepend before
    expand); two distinct tunnel-attributes both retained.
  • Flow-control terminators interact: bare accept/reject collide as a
    same-family pair (last-wins); named terminators (next term, next
    policy, default-action) keep both lines but next term runs over
    bare accept; default-action adjacent to a bare terminator is
    effectively dead config.

Also fixes two BGP route parser issues:

  • nhh (discard/reject next-hop) JSON key handled instead of crashing
    on assert NH in entry.
  • MED is read from metric key for display json detail form (brief
    form puts it in med).

Prompt:

Execute working/junos-then-action-conflict-lab-plan.md

Stack:


⚠️ Part of a stack created by spr. Do not merge manually using the UI - doing so may have unexpected results.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.63%. Comparing base (7b78e32) to head (511a44a).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #187      +/-   ##
==========================================
+ Coverage   83.59%   83.63%   +0.03%     
==========================================
  Files          87       87              
  Lines        4194     4204      +10     
==========================================
+ Hits         3506     3516      +10     
  Misses        688      688              
Flag Coverage Δ
unittests 83.63% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member Author

@dhalperi dhalperi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read it.I think the source configs are wrong for the new lab.

@dhalperi dhalperi force-pushed the spr/main/142fcedb branch 2 times, most recently from cddb1c7 to 9558902 Compare May 20, 2026 16:14
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
| 18 | 10.50.18.0 | NEXT-HOP-IP-DIFF | next-hop 192.0.2.1; next-hop 192.0.2.2 | next-hop 192.0.2.2 | last-wins |
| 19 | 10.50.19.0 | NEXT-HOP-SELF-VS-IP | next-hop self; next-hop 192.0.2.1 | next-hop 192.0.2.1 | last-wins |
| 20 | 10.50.20.0 | NEXT-HOP-SELF-VS-PEER | next-hop self; next-hop peer-address | next-hop peer-address | last-wins |
| 21 | 10.50.21.0 | NEXT-HOP-REJECT-VS-DISCARD | next-hop reject; next-hop discard | next-hop discard | last-wins |
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we try both orders to distinguish last one wins vs one type always beats the other?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Batfish AI) Honestly we did not try both orders for next-hop reject-vs-discard. Kept the single test row but added a caveat in the Interpretation column: "last-wins (probably — only one order tested; could also be discard always wins)". Adding a counterpart row with the reverse order would be a small follow-up.

Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
@dhalperi dhalperi force-pushed the spr/main/142fcedb branch from 9558902 to 947b0a8 Compare May 20, 2026 17:55
Copy link
Copy Markdown
Member Author

@dhalperi dhalperi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more changes needed.

Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
| 4005 | 10.50.164.0 | FC-ACCEPT-THEN-NEXT-POLICY | community add MARK-A; accept; community add MARK-B; next policy | community add MARK-A; community add MARK-B; next policy; accept | both retained (different families) |
| 4006 | 10.50.165.0 | FC-DEFAULT-ACTION-ACCEPT-THEN-ACCEPT | community add MARK-A; default-action accept; community add MARK-B; accept | community add MARK-A; community add MARK-B; default-action accept; accept | both retained (different families) |
| 4007 | 10.50.166.0 | FC-ACCEPT-THEN-DEFAULT-ACTION-REJECT | community add MARK-A; accept; community add MARK-B; default-action reject | community add MARK-A; community add MARK-B; default-action reject; accept | both retained (different families) |
| 4008 | 10.50.167.0 | FC-REJECT-THEN-DEFAULT-ACTION-ACCEPT | community add MARK-A; reject; community add MARK-B; default-action accept | community add MARK-A; community add MARK-B; default-action accept; reject | both retained (different families) |
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we log a risky warning here? default-action followed by terminal makes no sense, as there's no fallthrough. It's basically a no-op and a sign of unintended config.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Batfish AI) Good observation. Added a note to the README flagging both cases (default-action adjacent to a bare terminator, and any side-effect/action after reject) as reasonable candidates for a Batfish risky warning since they almost always indicate unintended config. Did not file a Batfish issue for this — happy to do so if you confirm that is the right repo.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we don't need to file it, I'll point at this discussion instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Batfish AI) Acknowledged — wont file.

Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
@dhalperi dhalperi force-pushed the spr/main/142fcedb branch from 947b0a8 to d4d3cfa Compare May 20, 2026 19:42
Copy link
Copy Markdown
Member Author

@dhalperi dhalperi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor text notes

Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
Comment thread snapshots/junos_then_action_conflicts/README.md Outdated
@dhalperi dhalperi force-pushed the spr/main/142fcedb branch from d4d3cfa to ce3d054 Compare May 20, 2026 20:23
Copy link
Copy Markdown
Member Author

@dhalperi dhalperi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good.

@dhalperi dhalperi enabled auto-merge (squash) May 20, 2026 20:26
108-term lab empirically testing what Junos retains when a `then` block
contains two or more actions targeting the same attribute. Key findings:

- For most scalar/numeric attribute families (origin, preference, tag,
  color, priority, next-hop IP, source-class, external, lp/metric/metric2
  in any combination of set/add/subtract/expression/igp, same-family
  as-path-prepend or as-path-expand pairs), last-wins universally:
  Junos drops the first action at commit time when both target the same
  attribute. Identical duplicates collapse to one.
- The retained config is canonical, not source-order: `display set`
  emits actions in a deterministic order (side-effects, then named
  terminators, then bare accept/reject), regardless of authoring order.
- Community statements all survive commit and execute sequentially with
  their plain meanings (set assigns, add unions, delete removes).
- Cross-family at the same attribute keeps both: as-path-prepend +
  as-path-expand both retained (canonical order: prepend before
  expand); two distinct tunnel-attributes both retained.
- Flow-control terminators interact: bare accept/reject collide as a
  same-family pair (last-wins); named terminators (next term, next
  policy, default-action) keep both lines but `next term` runs over
  bare `accept`; `default-action` adjacent to a bare terminator is
  effectively dead config.

Also fixes two BGP route parser issues:
- `nhh` (discard/reject next-hop) JSON key handled instead of crashing
  on `assert NH in entry`.
- MED is read from `metric` key for `display json` detail form (brief
  form puts it in `med`).

Prompt:
```
Execute working/junos-then-action-conflict-lab-plan.md
```

commit-id:142fcedb
@dhalperi dhalperi force-pushed the spr/main/142fcedb branch from ce3d054 to 511a44a Compare May 20, 2026 20:28
@dhalperi dhalperi disabled auto-merge May 20, 2026 20:30
@dhalperi dhalperi enabled auto-merge (squash) May 20, 2026 20:30
@dhalperi dhalperi merged commit 4f9712c into main May 20, 2026
115 checks passed
@dhalperi dhalperi deleted the spr/main/142fcedb branch May 20, 2026 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants