This diff is a result of a longer discussion with Sriram from NIST about ASPA validation behaviour on route-servers and especially non-transparent RS.
Handling transparent route-servers (which is the default) requires no special handling in the validation logic. The route-server AS will never show up in the AS_PATH and so this can be handled like any other lateral peering. Now non-transparent route-servers work in most cases but there is one special case where a valid path is mislabeled as unknown -- at least in the opinion of the ASPA draft authors. The authors want that paths validated via non-transparent route-servers behave like paths via transparentroute-servers. So the problematic scenario is: AS3 (RS transp/non-transp) / \ AS2 - - - - - AS4 (RS-client / validating AS) / AS2 and AS4 are AS1 lateral peers With this record: customer-as 1 provider-as { 2 } Especially AS2 has no ASPA record. On a transparent RS the path to validate on AS4 is AS1 AS2 and since AS1 has a ASPA record including AS2 it is valid. On a non-tranparent RS the path to validate is AS1 AS2 AS3. Using the same upstream algorithm we get (AS1 -> AS2 = valid) (AS2 -> AS3 = unknown) final result unknown. The result should be valid but is not because of the extra AS3. There are a few ways to solve this. The draft suggests to chop of AS3 on the path and do the validation on this modified path. Now this is more complex than it sounds and there is an alternative which is easier (for us). Instead of using the upstream algorithm, switch to the down-up algorithm. Now since AS3 is a "transit" for AS4 the path becomes valid since AS2 - AS3 is now considered a lateral peering. So this is what this diff does (which is much shorter than the explantion). -- :wq Claudio PS: the problem with all of this is that while this works in the above case (and therefor follows the draft to the letter) it fails for AS4's customer AS5. For AS5 the result of the validation alters between transparent/non-transparent RS no matter what (validating path AS4 AS2 AS1 vs AS4 AS3 AS2 AS1, first is valid 2nd is unknown). So maybe this special case for non-transparent RS is is just putting lipstick on a pig. Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.591 diff -u -p -r1.591 rde.c --- rde.c 24 Jan 2023 14:13:12 -0000 1.591 +++ rde.c 25 Jan 2023 09:43:19 -0000 @@ -2509,15 +2509,19 @@ rde_aspa_validity(struct rde_peer *peer, switch (aid) { case AID_INET: - if (peer->role != ROLE_CUSTOMER) - return asp->aspa_state.onlyup_v4; - else + if (peer->role == ROLE_CUSTOMER || + (peer->role == ROLE_RS_CLIENT && + peer->conf.enforce_as == ENFORCE_AS_ON)) return asp->aspa_state.downup_v4; - case AID_INET6: - if (peer->role != ROLE_CUSTOMER) - return asp->aspa_state.onlyup_v6; else + return asp->aspa_state.onlyup_v4; + case AID_INET6: + if (peer->role == ROLE_CUSTOMER || + (peer->role == ROLE_RS_CLIENT && + peer->conf.enforce_as == ENFORCE_AS_ON)) return asp->aspa_state.downup_v6; + else + return asp->aspa_state.onlyup_v6; default: return ASPA_NEVER_KNOWN; /* not reachable */ }