- let attr_set = self.routes.lock().unwrap().get_route_attrs(addr);
- let mut paths: Vec<(ASPath, u32, u32)> = Vec::new();
- for attrs in attr_set.iter() {
- let mut as4_path = None;
- let mut as_path = None;
- let mut pref = 100;
- let mut med = 0;
- for attr in attrs.iter() {
- match attr {
- PathAttribute::AS4_PATH(path) => as4_path = Some(path),
- PathAttribute::AS_PATH(path) => as_path = Some(path),
- PathAttribute::LOCAL_PREF(p) => pref = *p,
- PathAttribute::MULTI_EXIT_DISC(m) => med = *m,
- _ => {},
+ let lock = self.routes.lock().unwrap();
+ let mut path_vecs = lock.get_route_attrs(addr).1;
+ if path_vecs.is_empty() { return 0; }
+
+ path_vecs.sort_unstable_by(|path_a, path_b| {
+ path_a.pref.cmp(&path_b.pref)
+ .then(path_b.path_len.cmp(&path_a.path_len))
+ .then(path_b.med.cmp(&path_a.med))
+ });
+
+ let primary_route = path_vecs.pop().unwrap();
+ if path_vecs.len() > 3 {
+ // If we have at least 3 paths, try to find the last unique ASN which doesn't show up in other paths
+ // If we hit a T1 that is reasonably assumed to care about net neutrality, return the
+ // previous ASN.
+ let mut prev_asn = 0;
+ 'asn_candidates: for asn in primary_route.path_suffix.iter().rev() {
+ if *asn == 0 { continue 'asn_candidates; }
+ match *asn {
+ // Included: CenturyLink (L3), Cogent, Telia, NTT, GTT, Level3,
+ // GBLX (L3), Zayo, TI Sparkle Seabone, HE, Telefonica
+ // Left out from Caida top-20: TATA, PCCW, Vodafone, RETN, Orange, Telstra,
+ // Singtel, Rostelecom, DTAG
+ 209|174|1299|2914|3257|3356|3549|6461|6762|6939|12956 if prev_asn != 0 => return prev_asn,
+ _ => if path_vecs.iter().any(|route| !route.path_suffix.contains(asn)) {
+ if prev_asn != 0 { return prev_asn } else {
+ // Multi-origin prefix, just give up and take the last AS in the
+ // default path
+ break 'asn_candidates;
+ }
+ } else {
+ // We only ever possibly return an ASN if it appears in all paths
+ prev_asn = *asn;
+ },