Skip to content

Commit 8bd13c3

Browse files
committed
Add MPLS label, NOPEER community, and route oscillation tests
- Add MPLS label tests (LABEL-001 to LABEL-010) for RFC 3107 - Label encoding in MP_REACH_NLRI with SAFI=4 - 3-byte label encoding with BOS bit - Label stack depth, reserved ranges, withdrawal values - Add NOPEER community tests (NOPEER-001 to NOPEER-005) for RFC 3765 - NOPEER well-known community value 0xFFFFFF04 - Route scope control for bilateral peers - NOPEER vs NO_EXPORT comparison - Add route oscillation tests (OSCIL-001 to OSCIL-005) for RFC 3345 - Type I/II oscillation conditions - MED non-deterministic ordering - Route reflection and confederation considerations - Add constants for MPLS labels, NOPEER community, and oscillation types - Update test category count to 32 - Update README with new test categories and RFC references
1 parent 259fffd commit 8bd13c3

4 files changed

Lines changed: 207 additions & 1 deletion

File tree

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,35 @@ Tests for Route Refresh Capability per RFC 2918:
646646
- RFR-009: Route Refresh AFI/SAFI Not Advertised
647647
- RFR-010: Route Refresh End-of-RIB
648648

649+
### mpls_labels
650+
Tests for MPLS Label Distribution in BGP per RFC 3107:
651+
- LABEL-001: MPLS Label in MP_REACH_NLRI SAFI-4
652+
- LABEL-002: MPLS Label 3-Byte Encoding
653+
- LABEL-003: MPLS Label Stack Depth
654+
- LABEL-004: MPLS Label Reserved Range 0-15
655+
- LABEL-005: MPLS Label Implicit NULL
656+
- LABEL-006: MPLS Label Withdrawal Value
657+
- LABEL-007: MPLS Label Next Hop Self
658+
- LABEL-008: MPLS Label Preservation on Redistribute
659+
- LABEL-009: MPLS Label NLRI Length Field
660+
- LABEL-010: MPLS Label Capability Advertisement
661+
662+
### nopeer
663+
Tests for NOPEER Community per RFC 3765:
664+
- NOPEER-001: NOPEER Community Value (0xFFFFFF04)
665+
- NOPEER-002: NOPEER Route Scope Control
666+
- NOPEER-003: NOPEER vs NO_EXPORT Comparison
667+
- NOPEER-004: NOPEER Well-Known Transitive
668+
- NOPEER-005: NOPEER Filtering Implementation
669+
670+
### route_oscillation
671+
Tests for BGP Route Oscillation Conditions per RFC 3345:
672+
- OSCIL-001: Type I Oscillation with Route Reflection
673+
- OSCIL-002: Type I Oscillation with Confederation
674+
- OSCIL-003: MED Non-Deterministic Ordering
675+
- OSCIL-004: Type II Oscillation Conditions
676+
- OSCIL-005: MED Comparison Same AS Only
677+
649678
## References
650679

651680
- [RFC 4271 - A Border Gateway Protocol 4 (BGP-4)](https://www.rfc-editor.org/rfc/rfc4271)
@@ -668,6 +697,8 @@ Tests for Route Refresh Capability per RFC 2918:
668697
- [RFC 4364 - BGP/MPLS IP Virtual Private Networks (VPNs)](https://www.rfc-editor.org/rfc/rfc4364)
669698
- [RFC 2842 - Capabilities Advertisement with BGP-4](https://www.rfc-editor.org/rfc/rfc2842)
670699
- [RFC 5492 - Extensions to BGP-4 for Capabilities Advertisement](https://www.rfc-editor.org/rfc/rfc5492)
700+
- [RFC 3107 - Carrying Label Information in BGP-4](https://www.rfc-editor.org/rfc/rfc3107)
701+
- [RFC 3765 - NOPEER Community for BGP Route Scope Control](https://www.rfc-editor.org/rfc/rfc3765)
671702
- [RFC 1105 - BGP (obsolete)](https://www.rfc-editor.org/rfc/rfc1105)
672703
- [RFC 1163 - BGP-2 (obsolete)](https://www.rfc-editor.org/rfc/rfc1163)
673704
- [RFC 1267 - BGP-3 (obsolete)](https://www.rfc-editor.org/rfc/rfc1267)

src/bgp_test_framework/constants.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,34 @@
288288
CAPABILITY_ERROR_SUBCODES = {
289289
"UNSUPPORTED_CAPABILITY": 7,
290290
}
291+
292+
MPLS_LABEL_SAFI = 4
293+
MPLS_LABEL_ENCODING_LENGTH = 3
294+
MPLS_LABEL_STACK_DEPTH_MAX = 4
295+
MPLS_LABEL_WITHDRAWAL_VALUE = 0x800000
296+
297+
WELL_KNOWN_COMMUNITIES_RFC3765 = {
298+
"NO_EXPORT": 0xFFFFFF01,
299+
"NO_ADVERTISE": 0xFFFFFF02,
300+
"NO_EXPORT_SUBCONFED": 0xFFFFFF03,
301+
"NOPEER": 0xFFFFFF04,
302+
}
303+
304+
NOPEER_COMMUNITY = 0xFFFFFF04
305+
306+
OSCILLATION_TYPES = {
307+
"TYPE_I": 1,
308+
"TYPE_II": 2,
309+
}
310+
311+
MED_COMPARISON_RULES = {
312+
"SAME_NEIGHBORING_AS": 0,
313+
"NON_COMPARABLE": 255,
314+
}
315+
316+
DAMPING_CALCULATION = {
317+
"STABILITYFIGURE_INITIAL": 0,
318+
"WITHDRAWAL_PENALTY": 1000,
319+
"READVERTISEMENT_PENALTY": 500,
320+
"ATTRCHANGE_PENALTY": 500,
321+
}

src/bgp_test_framework/tests.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class TestCategory(Enum):
5151
VPN = "vpn"
5252
CAPABILITIES = "capabilities"
5353
ROUTE_REFRESH = "route_refresh"
54+
MPLS_LABELS = "mpls_labels"
55+
NOPEER = "nopeer"
56+
ROUTE_OSCILLATION = "route_oscillation"
5457

5558

5659
@dataclass
@@ -2416,3 +2419,144 @@ def get_tests() -> List[TestCase]:
24162419
description="End-of-RIB marker after Route Refresh - RFC 2918",
24172420
),
24182421
]
2422+
2423+
2424+
class MPLSLabelTests:
2425+
@staticmethod
2426+
def get_tests() -> List[TestCase]:
2427+
return [
2428+
TestCase(
2429+
test_id="LABEL-001",
2430+
name="MPLS Label in MP_REACH_NLRI SAFI-4",
2431+
category=TestCategory.MPLS_LABELS,
2432+
description="MP_REACH_NLRI with SAFI=4 for label distribution - RFC 3107",
2433+
),
2434+
TestCase(
2435+
test_id="LABEL-002",
2436+
name="MPLS Label 3-Byte Encoding",
2437+
category=TestCategory.MPLS_LABELS,
2438+
description="Label encoded as 3 octets: 20-bit value + BOS bit - RFC 3107 Section 3",
2439+
),
2440+
TestCase(
2441+
test_id="LABEL-003",
2442+
name="MPLS Label Stack Depth",
2443+
category=TestCategory.MPLS_LABELS,
2444+
description="Multiple labels for label stack encoding - RFC 3107 Section 3",
2445+
),
2446+
TestCase(
2447+
test_id="LABEL-004",
2448+
name="MPLS Label Reserved Range 0-15",
2449+
category=TestCategory.MPLS_LABELS,
2450+
description="Labels 0-15 are reserved per RFC 3032 - RFC 3107",
2451+
),
2452+
TestCase(
2453+
test_id="LABEL-005",
2454+
name="MPLS Label Implicit NULL",
2455+
category=TestCategory.MPLS_LABELS,
2456+
description="Label 3 is Implicit NULL - RFC 3107",
2457+
),
2458+
TestCase(
2459+
test_id="LABEL-006",
2460+
name="MPLS Label Withdrawal Value",
2461+
category=TestCategory.MPLS_LABELS,
2462+
description="Withdrawal NLRI label set to 0x800000 - RFC 3107 Section 3",
2463+
),
2464+
TestCase(
2465+
test_id="LABEL-007",
2466+
name="MPLS Label Next Hop Self",
2467+
category=TestCategory.MPLS_LABELS,
2468+
description="Label assigned by Next Hop router - RFC 3107 Section 3",
2469+
),
2470+
TestCase(
2471+
test_id="LABEL-008",
2472+
name="MPLS Label Preservation on Redistribute",
2473+
category=TestCategory.MPLS_LABELS,
2474+
description="Labels must not change unless Next Hop changes - RFC 3107 Section 3",
2475+
),
2476+
TestCase(
2477+
test_id="LABEL-009",
2478+
name="MPLS Label NLRI Length Field",
2479+
category=TestCategory.MPLS_LABELS,
2480+
description="Length field indicates prefix bits plus label bits - RFC 3107 Section 3",
2481+
),
2482+
TestCase(
2483+
test_id="LABEL-010",
2484+
name="MPLS Label Capability Advertisement",
2485+
category=TestCategory.MPLS_LABELS,
2486+
description="MP_EXT capability required for label SAFI - RFC 3107 Section 5",
2487+
),
2488+
]
2489+
2490+
2491+
class NOPEERCommunityTests:
2492+
@staticmethod
2493+
def get_tests() -> List[TestCase]:
2494+
return [
2495+
TestCase(
2496+
test_id="NOPEER-001",
2497+
name="NOPEER Community Value",
2498+
category=TestCategory.NOPEER,
2499+
description="NOPEER well-known community value 0xFFFFFF04 - RFC 3765 Section 4",
2500+
),
2501+
TestCase(
2502+
test_id="NOPEER-002",
2503+
name="NOPEER Route Scope Control",
2504+
category=TestCategory.NOPEER,
2505+
description="NOPEER restricts advertisement to bilateral peers - RFC 3765 Section 2",
2506+
),
2507+
TestCase(
2508+
test_id="NOPEER-003",
2509+
name="NOPEER vs NO_EXPORT Comparison",
2510+
category=TestCategory.NOPEER,
2511+
description="NOPEER allows advertisement to provider but not peer - RFC 3765",
2512+
),
2513+
TestCase(
2514+
test_id="NOPEER-004",
2515+
name="NOPEER Well-Known Transitive",
2516+
category=TestCategory.NOPEER,
2517+
description="NOPEER is well-known and transitive - RFC 3765 Section 2",
2518+
),
2519+
TestCase(
2520+
test_id="NOPEER-005",
2521+
name="NOPEER Filtering Implementation",
2522+
category=TestCategory.NOPEER,
2523+
description="Receiving AS may filter based on peering relationship - RFC 3765 Section 2",
2524+
),
2525+
]
2526+
2527+
2528+
class RouteOscillationTests:
2529+
@staticmethod
2530+
def get_tests() -> List[TestCase]:
2531+
return [
2532+
TestCase(
2533+
test_id="OSCIL-001",
2534+
name="Type I Oscillation with Route Reflection",
2535+
category=TestCategory.ROUTE_OSCILLATION,
2536+
description="Type I churn requires single-level RR + MED - RFC 3345 Section 2.1",
2537+
),
2538+
TestCase(
2539+
test_id="OSCIL-002",
2540+
name="Type I Oscillation with Confederation",
2541+
category=TestCategory.ROUTE_OSCILLATION,
2542+
description="Type I churn with AS confederations - RFC 3345 Section 2.2",
2543+
),
2544+
TestCase(
2545+
test_id="OSCIL-003",
2546+
name="MED Non-Deterministic Ordering",
2547+
category=TestCategory.ROUTE_OSCILLATION,
2548+
description="Non-deterministic path ordering can cause loops - RFC 3345 Section 2",
2549+
),
2550+
TestCase(
2551+
test_id="OSCIL-004",
2552+
name="Type II Oscillation Conditions",
2553+
category=TestCategory.ROUTE_OSCILLATION,
2554+
description="Type II oscillation conditions - RFC 3345 Section 3",
2555+
),
2556+
TestCase(
2557+
test_id="OSCIL-005",
2558+
name="MED Comparison Same AS Only",
2559+
category=TestCategory.ROUTE_OSCILLATION,
2560+
description="MED comparable only between routes from same neighboring AS - RFC 3345",
2561+
),
2562+
]

tests/unit/test_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def test_collision_tests(self):
192192

193193
class TestTestCategories:
194194
def test_all_categories_defined(self):
195-
assert len(TestCategory) == 29
195+
assert len(TestCategory) == 32
196196
assert TestCategory.MESSAGE_HEADER.value == "message_header"
197197
assert TestCategory.OPEN_MESSAGE.value == "open_message"
198198
assert TestCategory.UPDATE_MESSAGE.value == "update_message"

0 commit comments

Comments
 (0)