|
| 1 | +# Plan: Convert NLRI Classes to Packed-Bytes-First Pattern |
| 2 | + |
| 3 | +**Status:** 🔄 Ready to start |
| 4 | +**Priority:** 🟡 Medium |
| 5 | +**Command:** `/convert-nlri <nlri-name>` |
| 6 | +**Reference:** `.claude/exabgp/PACKED_BYTES_FIRST_PATTERN.md` |
| 7 | +**Prerequisite:** `plan/nlri-immutability-refactoring.md` (Phase 5 complete for VPLS) |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## Overview |
| 12 | + |
| 13 | +Convert all NLRI classes to the packed-bytes-first pattern to: |
| 14 | +- Reduce memory allocation (store wire bytes directly) |
| 15 | +- Enable lazy unpacking (parse fields only when accessed) |
| 16 | +- Support zero-copy routing (return stored bytes without re-packing) |
| 17 | + |
| 18 | +## Key Principles |
| 19 | + |
| 20 | +1. **`_packed` is ALWAYS required** - no `None`, no conditionals in properties |
| 21 | +2. **Two entry points only:** |
| 22 | + - `unpack_nlri()` - from existing wire Buffer (don't modify, just store) |
| 23 | + - `make_xxx()` - build new packed bytes from components |
| 24 | +3. **`@property` for all fields** - simple return, no conditionals |
| 25 | +4. **No `make_empty()`** - breaks immutability |
| 26 | + |
| 27 | +## Prerequisite: NLRI Immutability Refactoring |
| 28 | + |
| 29 | +**See:** `plan/nlri-immutability-refactoring.md` |
| 30 | + |
| 31 | +Configuration parser refactoring status: |
| 32 | +- Phase 1: ✅ COMPLETE - Add factory methods to NLRI classes |
| 33 | +- Phase 2: ✅ COMPLETE - RouteBuilderValidator deferred construction |
| 34 | +- Phase 3: ✅ COMPLETE - Static route deferred construction |
| 35 | +- Phase 4: ✅ COMPLETE - TypeSelectorValidator deferred construction |
| 36 | +- Phase 5: ✅ COMPLETE for VPLS - Remove mutation support |
| 37 | + |
| 38 | +**VPLS is fully immutable and can be used as reference implementation.** |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## Conversion Status |
| 43 | + |
| 44 | +### Core NLRI Classes |
| 45 | + |
| 46 | +| Class | File | Has Tests | Converted | Notes | |
| 47 | +|-------|------|-----------|-----------|-------| |
| 48 | +| VPLS | `nlri/vpls.py` | ✅ | ✅ | Reference implementation | |
| 49 | +| RTC | `nlri/rtc.py` | ✅ | ❌ | Partial - rt needs negotiated | |
| 50 | +| Flow | `nlri/flow.py` | ❌ | ❌ | Builder pattern - not applicable | |
| 51 | +| INET | `nlri/inet.py` | ❌ | ❌ | Base for Label/IPVPN | |
| 52 | +| Label | `nlri/label.py` | ❌ | ❌ | Extends INET | |
| 53 | +| IPVPN | `nlri/ipvpn.py` | ❌ | ❌ | Extends Label | |
| 54 | + |
| 55 | +### EVPN Classes |
| 56 | + |
| 57 | +| Class | File | Has Tests | Converted | Notes | |
| 58 | +|-------|------|-----------|-----------|-------| |
| 59 | +| EVPN (base) | `evpn/nlri.py` | ❌ | ❌ | Base class | |
| 60 | +| GenericEVPN | `evpn/nlri.py` | ❌ | ❌ | Fallback handler | |
| 61 | +| MAC | `evpn/mac.py` | ❌ | ❌ | Type 2 | |
| 62 | +| EthernetAD | `evpn/ethernetad.py` | ❌ | ❌ | Type 1 | |
| 63 | +| Multicast | `evpn/multicast.py` | ❌ | ❌ | Type 3 | |
| 64 | +| EthernetSegment | `evpn/segment.py` | ❌ | ❌ | Type 4 | |
| 65 | +| Prefix | `evpn/prefix.py` | ❌ | ❌ | Type 5 | |
| 66 | + |
| 67 | +### MVPN Classes |
| 68 | + |
| 69 | +| Class | File | Has Tests | Converted | Notes | |
| 70 | +|-------|------|-----------|-----------|-------| |
| 71 | +| MVPN (base) | `mvpn/nlri.py` | ❌ | ❌ | Base class | |
| 72 | +| GenericMVPN | `mvpn/nlri.py` | ❌ | ❌ | Fallback handler | |
| 73 | +| SourceAD | `mvpn/sourcead.py` | ❌ | ❌ | Type 1 | |
| 74 | +| SharedJoin | `mvpn/sharedjoin.py` | ❌ | ❌ | Type 6 | |
| 75 | +| SourceJoin | `mvpn/sourcejoin.py` | ❌ | ❌ | Type 7 | |
| 76 | + |
| 77 | +### MUP Classes |
| 78 | + |
| 79 | +| Class | File | Has Tests | Converted | Notes | |
| 80 | +|-------|------|-----------|-----------|-------| |
| 81 | +| MUP (base) | `mup/nlri.py` | ❌ | ❌ | Base class | |
| 82 | +| GenericMUP | `mup/nlri.py` | ❌ | ❌ | Fallback handler | |
| 83 | +| InterworkSegmentDiscoveryRoute | `mup/isd.py` | ❌ | ❌ | ISD | |
| 84 | +| DirectSegmentDiscoveryRoute | `mup/dsd.py` | ❌ | ❌ | DSD | |
| 85 | +| Type1SessionTransformedRoute | `mup/t1st.py` | ❌ | ❌ | T1ST | |
| 86 | +| Type2SessionTransformedRoute | `mup/t2st.py` | ❌ | ❌ | T2ST | |
| 87 | + |
| 88 | +### BGP-LS Classes |
| 89 | + |
| 90 | +| Class | File | Has Tests | Converted | Notes | |
| 91 | +|-------|------|-----------|-----------|-------| |
| 92 | +| BGPLS (base) | `bgpls/nlri.py` | ❌ | ❌ | Base class | |
| 93 | +| GenericBGPLS | `bgpls/nlri.py` | ❌ | ❌ | Fallback handler | |
| 94 | +| NODE | `bgpls/node.py` | ❌ | ❌ | Node descriptor | |
| 95 | +| LINK | `bgpls/link.py` | ❌ | ❌ | Link descriptor | |
| 96 | +| PREFIXv4 | `bgpls/prefixv4.py` | ❌ | ❌ | IPv4 prefix | |
| 97 | +| PREFIXv6 | `bgpls/prefixv6.py` | ❌ | ❌ | IPv6 prefix | |
| 98 | +| SRv6SID | `bgpls/srv6sid.py` | ❌ | ❌ | SRv6 SID | |
| 99 | + |
| 100 | +--- |
| 101 | + |
| 102 | +## Conversion Order (Recommended) |
| 103 | + |
| 104 | +1. **Simple fixed-length first:** |
| 105 | + - RTC (already partial) |
| 106 | + - MVPN types (fixed format) |
| 107 | + - MUP types |
| 108 | + |
| 109 | +2. **EVPN types:** |
| 110 | + - Variable length but well-defined structure |
| 111 | + |
| 112 | +3. **BGP-LS types:** |
| 113 | + - Complex TLV structure |
| 114 | + |
| 115 | +4. **Skip or document as not applicable:** |
| 116 | + - Flow (builder pattern with rules) |
| 117 | + - INET/Label/IPVPN (inheritance hierarchy - needs careful analysis) |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +## How to Convert |
| 122 | + |
| 123 | +Use the slash command: |
| 124 | +``` |
| 125 | +/convert-nlri <nlri-name> |
| 126 | +``` |
| 127 | + |
| 128 | +Examples: |
| 129 | +- `/convert-nlri rtc` |
| 130 | +- `/convert-nlri evpn/mac` |
| 131 | +- `/convert-nlri mvpn/sourcead` |
| 132 | +- `/convert-nlri mup/isd` |
| 133 | + |
| 134 | +The command will: |
| 135 | +1. Read and analyze the NLRI structure |
| 136 | +2. Check for / create unit tests |
| 137 | +3. Convert to packed-bytes-first pattern |
| 138 | +4. Run tests to verify |
| 139 | + |
| 140 | +--- |
| 141 | + |
| 142 | +## Progress Log |
| 143 | + |
| 144 | +### 2025-12-07 |
| 145 | +- Created conversion plan |
| 146 | +- Created `/convert-nlri` slash command |
| 147 | +- VPLS already converted (reference implementation) |
| 148 | + |
| 149 | +### 2025-12-07 - Phase 5 Verified |
| 150 | +- Verified Phase 4 of prerequisite plan (TypeSelectorValidator) |
| 151 | +- Completed Phase 5: VPLS immutability |
| 152 | + - Updated announce/path.py, label.py, vpn.py to use Settings mode |
| 153 | + - Removed deprecated make_empty() and assign() from VPLS |
| 154 | + - Removed builder mode slots and simplified properties |
| 155 | + - All 11 tests pass |
| 156 | +- VPLS is now fully immutable and ready as reference implementation |
| 157 | + |
| 158 | +--- |
| 159 | + |
| 160 | +**Updated:** 2025-12-07 |
0 commit comments