├── README.md ├── examples ├── create_peers_ecix.py ├── export-schema-example.php ├── export-schema-example.py ├── memlist_get_mem.pl └── validate.py ├── ixp-member-list.schema.json ├── ixp-member-list.txt └── versions ├── ixp-member-list-0.3.schema.json ├── ixp-member-list-0.4.schema.json ├── ixp-member-list-0.5.schema.json ├── ixp-member-list-0.6.schema.json ├── ixp-member-list-0.7.schema.json └── ixp-member-list-1.0.schema.json /README.md: -------------------------------------------------------------------------------- 1 | IX-F Member Export JSON Schema 2 | ================================ 3 | 4 | The IX-F Member Export is an agreed and standardized JSON schema which allows IXPs to make their member lists available for consumption by tools such as PeeringDB, networks with automated peering managers, prospective members and the many other tools appearing in the peering eco-system. 5 | 6 | The key element of the IX-F Member Export is that it makes the individual IXP the canonical trusted source for data about their own IXP. Data that is guaranteed to be correct and up to date. 7 | 8 | 9 | ## Location 10 | 11 | It is suggested to locate the REST call under a well defined URI on the IXP's website, or use standard HTTP redirects (3xx). We recommend the location: https://www.example.com/participants.json 12 | 13 | ## Documentation 14 | 15 | More detailed documentation is available on the [github wiki page](https://github.com/euro-ix/json-schemas/wiki). 16 | 17 | ## Directory / Implementations 18 | 19 | In April 2017, we launched a directory for all implemented IX-F member exports and in April 2018 this was moved to the IXPDB website and you can find the list of IXPs exporting their member lists by selecting the API option in the search: https://ixpdb.euro-ix.net/en/ixpdb/ixps/?reverse=&sort=name&q=&api=on 20 | 21 | ### Stale / Potentially Broken Implementations 22 | 23 | **POTENTIALLY STALE/BROKEN - THE ABOVE REFERENCED DIRECTORY WILL BE USED FROM HERE ON IN** 24 | 25 | ## Contact 26 | 27 | Please send feedback to: 28 | 29 | * Barry O'Donovan 30 | * Elisa Jasinska 31 | * Nick Hilliard 32 | * Bijal Sanghani 33 | * Leo Vegoda 34 | -------------------------------------------------------------------------------- /examples/create_peers_ecix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json 4 | import urllib 5 | 6 | url = "https://www.ecix.net/memberlist_BER.json" 7 | response = urllib.urlopen(url) 8 | ixp_data = json.loads(response.read()) 9 | 10 | for member in ixp_data['member_list']: 11 | for connection in member['connection_list']: 12 | for vlan in connection['vlan_list']: 13 | if 'ipv4' in vlan: 14 | print '-----' 15 | print 'neighbor '+vlan['ipv4']['address']+' remote-as '+ str(member['asnum']) 16 | print 'neighbor '+vlan['ipv4']['address'].encode('utf-8')+' description PEER::'+member['name'].encode('utf-8') 17 | 18 | -------------------------------------------------------------------------------- /examples/export-schema-example.php: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | // We use PDO so we can support many databases rather than just MySQL. 21 | // See http://php.net/manual/en/pdo.connections.php 22 | $db = new PDO('mysql:host=localhost;dbname=ixp;charset=utf8mb4', 'root', 'password'); 23 | 24 | // The schema is made up of different sections so we build those up as an 25 | // array piece by piece. Edit the functions we call here for your own 26 | // data / schemas 27 | 28 | // normalise times to UTC for exports 29 | date_default_timezone_set('UTC'); 30 | 31 | echo json_encode( array( 32 | 33 | 'version' => '0.6', 34 | 'timestamp' => date( 'Y-m-d', time() ) . 'T' . date( 'H:i:s', time() ) . 'Z', 35 | 36 | 'ixp_list' => array( array( 37 | 38 | 'shortname' => 'EIX', 39 | 'name' => 'Example Internet Exchange', 40 | 'country' => 'CC', 41 | 'url' => 'https://www.example.com/', 42 | 43 | // IX-F ID is the numeric index of the IXP in the IX Federation database. 44 | // This is defined as the id of the IXP in the online IX-F database which 45 | // can be found at the following endpoint: http://db.ix-f.net/api/ixp. 46 | // Note that this is a persistent index keyed on an external database source. 47 | 'ixf_id' => 0, 48 | 49 | // ixp_id - a numeric IXP identifier. Where possible, this index number 50 | // should be consistent across exports. However as the index is primarily 51 | // intended to be used as an internal index within the schema, it is not 52 | // required to be consistent across exports. 53 | 'ixp_id' => 1, 54 | 55 | 'vlan' => getVLANs($db), 56 | 'switch' => getSwitches($db), 57 | 'member_list' => getMembers($db), 58 | ) ) 59 | ), 60 | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE 61 | ) . "\n"; 62 | 63 | 64 | 65 | // Function to get VLAN information. 66 | // This shows a database query but you could just as easily hardcode an array here 67 | // if you're a small IXP. 68 | function getVLANs($db) { 69 | $vlanquery = $db->query( 70 | "SELECT v.id AS id, v.name AS name 71 | FROM vlan AS v 72 | WHERE v.private=0" 73 | ); 74 | 75 | // prepared query for VLAN information 76 | $vlaninfo = $db->prepare( 77 | "SELECT ni.network AS prefix, ni.masklen AS masklen 78 | FROM networkinfo AS ni 79 | WHERE ni.vlanid = ? AND ni.protocol = ?" 80 | ); 81 | 82 | $vlans = array(); 83 | 84 | foreach( $vlanquery->fetchAll(PDO::FETCH_ASSOC) as $v ) { 85 | $vlan['id'] = $v['id']; 86 | $vlan['name'] = $v['name']; 87 | 88 | foreach( [4,6] as $p ) { 89 | $vlaninfo->bindValue(1,$v['id']); 90 | $vlaninfo->bindValue(2,$p); 91 | $vlaninfo->execute(); 92 | if( $query = $vlaninfo->fetchAll(PDO::FETCH_ASSOC) ) { 93 | $vlan['ipv'.$p] = array( 94 | 'prefix' => $query[0]['prefix'], 95 | 'masklen' => $query[0]['masklen'] 96 | ); 97 | } 98 | } 99 | 100 | $vlans[] = $vlan; 101 | } 102 | 103 | return $vlans; 104 | } 105 | 106 | // Function to get switch information. 107 | // This shows a database query but you could just as easily hardcode an array here 108 | // if you're a small IXP. 109 | function getSwitches($db) { 110 | $switchquery = $db->query( 111 | "SELECT s.id AS id, s.name AS name 112 | FROM switch AS s 113 | WHERE s.switchtype = 1 AND s.active = 1" 114 | ); 115 | 116 | $switches = array(); 117 | 118 | foreach( $switchquery->fetchAll(PDO::FETCH_ASSOC) as $s ) { 119 | $switches[] = array( 120 | 'id' => $s['id'], 121 | 'name' => $s['name'], 122 | 'colo' => "Datacentre Name", 123 | 'city' => "City", 124 | 'country' => "CC", 125 | 126 | // PeeringDB facility ID 127 | // https://www.peeringdb.com/api/fac 128 | 'pdb_facility_id' => 0 129 | ); 130 | } 131 | 132 | return $switches; 133 | } 134 | 135 | // Function to get member information. 136 | function getMembers($db) { 137 | // Database query to find all appropriate customers for export. 138 | // Our query looks for connected customers who have not left. 139 | $members = $db->query( 140 | "SELECT c.id AS id, 141 | c.autsys AS asnum, 142 | c.name AS name, 143 | c.corpwww AS url, 144 | c.peeringemail AS contact_email, 145 | c.nocphone AS contact_phone, 146 | c.nochours AS contact_hours, 147 | c.peeringpolicy AS peering_policy, 148 | c.nocwww AS peering_policy_url, 149 | c.datejoin AS member_since, 150 | c.type AS type 151 | 152 | FROM 153 | cust AS c 154 | WHERE 155 | c.datejoin <= CURRENT_DATE() 156 | AND ( c.dateleave IS NULL OR c.dateleave = '0000-00-00' OR c.dateleave >= CURRENT_DATE() ) 157 | AND c.status = 1 158 | AND c.type != 2 159 | " 160 | ); 161 | 162 | // Prepared query for finding all virtual interfaces for a customer. 163 | // A virtual interface in IXP Manager represents one or more physical 164 | // interfaces (where >1 means a LAG port) and one or more VLAN interfaces. 165 | $virtualInterfaceQuery = $db->prepare( 166 | "SELECT vi.id AS vid 167 | FROM 168 | cust AS c 169 | LEFT JOIN virtualinterface AS vi ON c.id = vi.custid 170 | WHERE 171 | c.id = ?" 172 | ); 173 | 174 | // Prepared query to find the physical interface(s) in a virtual interface. 175 | $physicalInterfaceQuery = $db->prepare( 176 | "SELECT s.id AS switch_id, 177 | pi.speed AS if_speed 178 | FROM 179 | virtualinterface AS vi 180 | LEFT JOIN physicalinterface AS pi ON vi.id = pi.virtualinterfaceid 181 | LEFT JOIN switchport AS sp ON pi.switchportid = sp.id 182 | LEFT JOIN switch AS s ON s.id = sp.switchid 183 | WHERE 184 | vi.id = ? 185 | AND pi.status = 1" 186 | ); 187 | 188 | // Prepared query to find the VLAN interface(s) details - i.e. the IP address, etc. 189 | $vlanInterfaceQuery = $db->prepare( 190 | "SELECT v.id AS vlan_id, 191 | ip4.address AS ipv4address, 192 | ip6.address AS ipv6address, 193 | vli.ipv4enabled AS v4enabled, 194 | vli.ipv6enabled AS v6enabled, 195 | vli.maxbgpprefix AS maxprefix, 196 | c.peeringmacro AS v4macro, 197 | c.peeringmacrov6 AS v6macro, 198 | vli.rsclient AS rsclient 199 | FROM 200 | virtualinterface AS vi 201 | LEFT JOIN cust AS c ON vi.custid = c.id 202 | LEFT JOIN vlaninterface AS vli ON vli.virtualinterfaceid = vi.id 203 | LEFT JOIN vlan AS v ON vli.vlanid = v.id 204 | LEFT JOIN ipv4address AS ip4 ON vli.ipv4addressid = ip4.id 205 | LEFT JOIN ipv6address AS ip6 ON vli.ipv6addressid = ip6.id 206 | WHERE 207 | vi.id = ?" 208 | ); 209 | 210 | // Prepared query to find a MAC associated with a port 211 | $macAddressQuery = $db->prepare( 212 | "SELECT ma.mac AS mac 213 | FROM 214 | macaddress AS ma 215 | LEFT JOIN virtualinterface AS vi ON vi.id = ma.virtualinterfaceid 216 | WHERE vi.id = ?" 217 | ); 218 | 219 | // we'll build up all the member data and store it here: 220 | $memberdata = array(); 221 | 222 | // Now, iterate over all the members and build up the data for export: 223 | foreach( $members->fetchAll(PDO::FETCH_ASSOC) as $m ) { 224 | $data = array( 225 | 'id' => $m['id'], 226 | 'asnum' => $m['asnum'], 227 | 'name' => $m['name'], 228 | 'url' => $m['url'], 229 | 'contact_email' => array( $m['contact_email'] ), 230 | 'contact_phone' => array( $m['contact_phone'] ), 231 | 'contact_hours' => $m['contact_hours'], 232 | 'peering_policy' => $m['peering_policy'], 233 | 'peering_policy_url' => $m['peering_policy_url'], 234 | 'member_since' => date( 'Y-m-d\T00:00:00\Z', strtotime( $m['member_since'] ) ), 235 | 'type' => $m['type'] == 1 ? 'full' : ( $m['type'] == 4 ? 'probono' : 'other' ), 236 | 'connection_list' => array() 237 | ); 238 | 239 | // get the customers ports 240 | $virtualInterfaceQuery->bindValue(1,$data['id']); 241 | $virtualInterfaceQuery->execute(); 242 | foreach($virtualInterfaceQuery->fetchAll(PDO::FETCH_ASSOC) as $vi) { 243 | 244 | $connection = array( 245 | "ixp_id" => 1, 246 | "state" => 'active', // our query below selects only active ports 247 | ); 248 | 249 | // get physical port details 250 | $physicalInterfaceQuery->bindValue(1,$vi['vid']); 251 | $physicalInterfaceQuery->execute(); 252 | 253 | foreach($physicalInterfaceQuery->fetchAll(PDO::FETCH_ASSOC) as $pi) { 254 | $connection['if_list'][] = array( 255 | 'switch_id' => $pi['switch_id'], 256 | 'if_speed' => $pi['if_speed'], 257 | ); 258 | } 259 | 260 | // do we have a mac? 261 | $macAddressQuery->bindValue(1,$vi['vid']); 262 | $macAddressQuery->execute(); 263 | $mac = array(); 264 | foreach( $macAddressQuery->fetchAll(PDO::FETCH_ASSOC) as $ma ) { 265 | $amac = strtolower($ma['mac']); 266 | $mac[] = substr($amac,0,2).':'.substr($amac,2,2).':'.substr($amac,4,2).':'.substr($amac,6,2).':'.substr($amac,8,2).':'.substr($amac,10,2); 267 | } 268 | 269 | // get vlan interface details 270 | $vlanInterfaceQuery->bindValue(1,$vi['vid']); 271 | $vlanInterfaceQuery->execute(); 272 | foreach($vlanInterfaceQuery->fetchAll(PDO::FETCH_ASSOC) as $vli) { 273 | $vlan_list = array( 274 | 'vlan_id' => $vli['vlan_id'], 275 | ); 276 | 277 | 278 | if( $vli['v4enabled'] ) { 279 | $vlan_list['ipv4'] = array( 280 | 'address' => $vli['ipv4address'], 281 | 'routeserver' => $vli['rsclient'] ? true : false 282 | ); 283 | if($vli['maxprefix']) { $vlan_list['ipv4']['max_prefix'] = $vli['maxprefix']; } 284 | if($vli['v4macro']) { $vlan_list['ipv4']['as_macro'] = $vli['v4macro']; } 285 | if(count($mac)) { $vlan_list['ipv4']['mac_addresses'] = $mac; } 286 | } 287 | 288 | if( $vli['v6enabled'] ) { 289 | $vlan_list['ipv6'] = array( 290 | 'address' => $vli['ipv6address'], 291 | 'routeserver' => $vli['rsclient'] ? true : false 292 | ); 293 | if($vli['maxprefix']) { $vlan_list['ipv6']['max_prefix'] = $vli['maxprefix']; } 294 | if($vli['v6macro']) { 295 | $vlan_list['ipv6']['as_macro'] = $vli['v6macro']; 296 | } else if($vli['v4macro']) { 297 | $vlan_list['ipv6']['as_macro'] = $vli['v4macro']; 298 | } 299 | if(count($mac)) { $vlan_list['ipv4']['mac_addresses'] = $mac; } 300 | } 301 | 302 | $connection['vlan_list'][] = $vlan_list; 303 | } 304 | $data['connection_list'][] = $connection; 305 | } 306 | 307 | //we don't need to export the member id - this was just used for queries above: 308 | unset($data['id']); 309 | 310 | $memberdata[] = $data; 311 | } 312 | 313 | return $memberdata; 314 | } 315 | -------------------------------------------------------------------------------- /examples/export-schema-example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | Example script to implement the JSON Export Schema as defined by: 5 | https://github.com/euro-ix/json-schemas 6 | 7 | Everyone's database schema will be different so this is just an example 8 | which: 9 | 10 | - Uses IXP Manager's schema as an example 11 | - Is written as a single PHP script with minimum requirements 12 | - Is hopefully easy to follow and adapt 13 | 14 | The output is compatible with v0.6 of the schema 15 | 16 | ''' 17 | 18 | import pymysql.cursors 19 | import json 20 | import datetime 21 | 22 | 23 | def connect_db(): 24 | return pymysql.connect(host='localhost', 25 | user='username', 26 | password='password', 27 | db='ixp', 28 | charset='utf8mb4', 29 | cursorclass=pymysql.cursors.DictCursor) 30 | 31 | def select_db(sql, args): 32 | connection = connect_db() 33 | with connection.cursor() as cursor: 34 | cursor.execute(sql, args) 35 | return cursor.fetchall() 36 | 37 | def vlan_info(): 38 | ''' 39 | Function to get VLAN information. 40 | This shows a database query but you could just as easily hardcode an array here 41 | if you're a small IXP 42 | ''' 43 | list_vlans = [] 44 | 45 | for vlan in select_db("SELECT v.id AS id, v.name AS name FROM vlan AS v WHERE v.private=0", ((), )): 46 | for proto in [4, 6]: 47 | vlan["ipv" + str(proto)] = select_db("SELECT ni.network AS prefix, ni.masklen AS masklen FROM networkinfo AS ni WHERE ni.vlanid = %s AND ni.protocol = %s", (vlan["id"], proto))[0] 48 | 49 | list_vlans.append(vlan) 50 | return list_vlans 51 | 52 | def switch_info(): 53 | list_switch = select_db("SELECT s.id AS id, s.name AS name FROM switch AS s WHERE s.switchtype = 1 AND s.active = 1", ((), )) 54 | for switch in list_switch: 55 | switch["colo"] = "Datacentre Name" 56 | switch["city"] = "City" 57 | switch["country"] = "CC" 58 | switch["pdb_facility_id"] = 0 59 | return list_switch 60 | 61 | def member_info(): 62 | list_member = select_db("""SELECT c.id AS id, 63 | c.autsys AS asnum, 64 | c.name AS name, 65 | c.corpwww AS url, 66 | c.peeringemail AS contact_email, 67 | c.nocphone AS contact_phone, 68 | c.nochours AS contact_hours, 69 | c.peeringpolicy AS peering_policy, 70 | c.nocwww AS peering_policy_url, 71 | c.datejoin AS member_since 72 | 73 | FROM 74 | cust AS c 75 | WHERE 76 | c.datejoin <= CURRENT_DATE() 77 | AND ( c.dateleave IS NULL OR c.dateleave = '0000-00-00' OR c.dateleave >= CURRENT_DATE() ) 78 | AND c.status = 1 79 | AND c.type != 2""", ((), )) 80 | for member in list_member: 81 | member["contact_email"] = [member["contact_email"]] 82 | member["contact_phone"] = [member["contact_phone"]] 83 | member["connection_list"] = [] 84 | 85 | # get the customers ports 86 | for vi in select_db("SELECT vi.id AS vid FROM cust AS c LEFT JOIN virtualinterface AS vi ON c.id = vi.custid WHERE c.id = %s", (member[id], )): 87 | connection = {} 88 | connection["ixp_id"] = 1 89 | connection["state"] = "active" 90 | connection['if_list'] = [] 91 | 92 | # get physical port details 93 | for pi in select_db("""SELECT s.id AS switch_id, pi.speed AS if_speed 94 | FROM virtualinterface AS vi 95 | LEFT JOIN physicalinterface AS pi ON vi.id = pi.virtualinterfaceid 96 | LEFT JOIN switchport AS sp ON pi.switchportid = sp.id 97 | LEFT JOIN switch AS s ON s.id = sp.switchid 98 | WHERE vi.id = %s AND pi.status = 1""", (vi['vid'], )): 99 | connection['if_list'].append({"switch_id": pi['switch_id'], "if_speed": pi["if_speed"]}) 100 | 101 | # do we have a mac? 102 | list_mac = [] 103 | for ma in select_db("SELECT ma.mac AS mac FROM macaddress AS ma LEFT JOIN virtualinterface AS vi ON vi.id = ma.virtualinterfaceid WHERE vi.id = %s", (vi['vid'], )): 104 | list_mac.append(ma["ma"][0-1] + ":" + ma["ma"][2-3] + ":" + ma["ma"][4-5] + ":" + ma["ma"][6-7]) 105 | 106 | # get vlan interface details 107 | for vli in select_db("""SELECT v.id AS vlan_id, 108 | ip4.address AS ipv4address, 109 | ip6.address AS ipv6address, 110 | vli.ipv4enabled AS v4enabled, 111 | vli.ipv6enabled AS v6enabled, 112 | vli.maxbgpprefix AS maxprefix, 113 | c.peeringmacro AS v4macro, 114 | c.peeringmacrov6 AS v6macro, 115 | vli.rsclient AS rsclient 116 | FROM virtualinterface AS vi 117 | LEFT JOIN cust AS c ON vi.custid = c.id 118 | LEFT JOIN vlaninterface AS vli ON vli.virtualinterfaceid = vi.id 119 | LEFT JOIN vlan AS v ON vli.vlanid = v.id 120 | LEFT JOIN ipv4address AS ip4 ON vli.ipv4addressid = ip4.id 121 | LEFT JOIN ipv6address AS ip6 ON vli.ipv6addressid = ip6.id 122 | WHERE vi.id = %s """, (vi['vid'], )): 123 | 124 | vlan_list = {} 125 | vlan_list["vlan_id"] = vli['vlan_id'] 126 | if vli['v4enabled']: 127 | vlan_list['ipv4'] = {"address": vli['ipv4address'], "routeserver": vli['rsclient']} 128 | vlan_list['ipv4']['max_prefix'] = vli['maxprefix'] 129 | vlan_list['ipv4']['as_macro'] = vli['v4macro'] 130 | if len(list_mac) > 0: 131 | vlan_list['ipv4']['mac_addresses'] = list_mac 132 | 133 | if vli['v6enabled']: 134 | vlan_list['ipv6'] = {"address": vli['ipv6address'], "routeserver": vli['rsclient']} 135 | vlan_list['ipv6']['max_prefix'] = vli['maxprefix'] 136 | if vli['v6macro']: 137 | vlan_list['ipv6']['as_macro'] = vli['v6macro'] 138 | else: 139 | vlan_list['ipv6']['as_macro'] = vli['v4macro'] 140 | if len(list_mac) > 0: 141 | vlan_list['ipv6']['mac_addresses'] = list_mac 142 | 143 | connection["vlan_list"] = vlan_list 144 | 145 | 146 | member["connection_list"].append(connection) 147 | return list_member 148 | 149 | 150 | def make_dict_ixp_info(): 151 | ''' 152 | The schema is made up of different sections so we build those up as an 153 | array piece by piece. Edit the functions we call here for your own 154 | data / schemas 155 | ''' 156 | my_ixp = {} 157 | my_ixp["version"] = "0.6" 158 | nowdate = datetime.datetime.now() 159 | my_ixp["timestamp"] = nowdate.isoformat('T') 160 | my_ixp["ixp_list"] = [] 161 | my_ixp["ixp_list"].append({ 162 | "shortname": "EIX", 163 | "name": "Example Internet Exchange", 164 | "country": "CC", 165 | "url": "http://www.example.com", 166 | 167 | # IX-F ID is the numeric index of the IXP in the IX Federation database. 168 | # This is defined as the id of the IXP in the online IX-F database which 169 | # can be found at the following endpoint: http://db.ix-f.net/api/ixp. 170 | # Note that this is a persistent index keyed on an external database source. 171 | "ixf_id": 0, 172 | 173 | # ixp_id - a numeric IXP identifier. Where possible, this index number 174 | # should be consistent across exports. However as the index is primarily 175 | # intended to be used as an internal index within the schema, it is not 176 | # required to be consistent across exports. 177 | "ixp_id": 1, 178 | 179 | "vlan": vlan_info(), 180 | "switch": switch_info(), 181 | "member_list": member_info() 182 | }) 183 | 184 | 185 | 186 | def main(): 187 | print json.dumps(make_dict_ixp_info) 188 | 189 | if __name__ == '__main__': 190 | main() 191 | -------------------------------------------------------------------------------- /examples/memlist_get_mem.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use feature qw(:5.10); 6 | 7 | use JSON; 8 | use FindBin; 9 | 10 | if (@ARGV < 2) { 11 | die "Usage: $FindBin::Script json-file mem-index ...\n"; 12 | } 13 | 14 | my $json_fname = shift @ARGV; 15 | 16 | open my $fh, '<', $json_fname 17 | or die "$FindBin::Script: cannot read $json_fname: $!\n"; 18 | 19 | my $json_text = do { 20 | local($/) = undef; 21 | <$fh>; 22 | }; 23 | 24 | $fh->close; 25 | my $json = JSON->new->allow_nonref; 26 | my $ixp_data = $json->decode($json_text); 27 | 28 | my $members = $ixp_data->{'member_list'}; 29 | 30 | for my $index (@ARGV) { 31 | my $mem = $members->[$index]; 32 | 33 | if (!$mem) { 34 | say "// $index - out of bounds\n"; 35 | } 36 | 37 | my $json_out = $json->pretty->encode($mem); 38 | say "// $index\n$json_out"; 39 | } 40 | 41 | __END__ 42 | 43 | =head1 NAME 44 | 45 | memlist_get_mem.pl - extract information about a member from an IX-F JSON export 46 | 47 | =head1 SYNOPSIS 48 | 49 | curl JSON-URL > members.json 50 | 51 | memlist_get_mem.pl members.json index1 index2 ... 52 | 53 | =head1 DESCRIPTION 54 | 55 | When using the L, the 56 | validator may sometimes spit out errors regarding a member in the list, 57 | indicated only by its index in the list. To help identify the entry, 58 | this tool can be used. 59 | 60 | =head1 EXAMPLE 61 | 62 | =over 63 | 64 | =item 1. 65 | 66 | The L reports an error: 67 | 68 | member_list[761].url: Invalid URL format 69 | 70 | =item 2. 71 | 72 | Download a copy of the member list to F 73 | 74 | =item 3. 75 | 76 | Use this script to extract information about the member: 77 | 78 | memlist_get_mem.pl members.json 761 | grep url 79 | 80 | Output will be something like: 81 | 82 | "url" : "http:// www.foobar.com", 83 | # ^ 84 | # | 85 | # misplaced space 86 | 87 | =back 88 | 89 | =head1 SEE ALSO 90 | 91 | =over 92 | 93 | =item * 94 | 95 | L 96 | 97 | =item * 98 | 99 | L 100 | 101 | =item * 102 | 103 | L 104 | 105 | =back 106 | 107 | =head1 AUTHOR 108 | 109 | Steven Bakker, AMS-IX - 2017. 110 | -------------------------------------------------------------------------------- /examples/validate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import argparse 5 | import requests 6 | import jsonschema 7 | import re 8 | import json 9 | 10 | 11 | def parse_args(args): 12 | schema_url = ('https://raw.githubusercontent.com' 13 | '/euro-ix/json-schemas/master/' 14 | 'ixp-member-list.schema.json') 15 | 16 | parser = argparse.ArgumentParser( 17 | description='Validate json output against schema.' 18 | ) 19 | parser.add_argument( 20 | '-u', 21 | '--username', 22 | default=None, 23 | help='HTTP Basic Auth User' 24 | ) 25 | parser.add_argument( 26 | '-p', 27 | '--password', 28 | default=None, 29 | help='HTTP Basic Auth Password' 30 | ) 31 | parser.add_argument( 32 | '-s', 33 | '--schema', 34 | default=schema_url, 35 | help='URL of json schema to validate against' 36 | ) 37 | parser.add_argument('url', help='URL of json to validate') 38 | return parser.parse_args(args) 39 | 40 | 41 | def main(argv=sys.argv[1:]): 42 | args = parse_args(argv) 43 | 44 | schema_url = args.schema 45 | response = requests.get(schema_url) 46 | schema = response.json() 47 | 48 | # Special case for "file://" URL (not handled by "requests") 49 | match = re.search('^file://(.*)$', args.url) 50 | if match: 51 | ixp_data = json.loads(open(match.group(1), 'r').read()) 52 | else: 53 | if args.username and args.password: 54 | response = requests.get( 55 | args.url, 56 | auth=( 57 | args.username, 58 | args.password 59 | ) 60 | ) 61 | else: 62 | response = requests.get(args.url) 63 | 64 | ixp_data = response.json() 65 | 66 | jsonschema.validate(ixp_data, schema) 67 | 68 | 69 | if __name__ == '__main__': 70 | main() 71 | -------------------------------------------------------------------------------- /ixp-member-list.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_list", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema; this is not the version of the file within an IXP; but the schema version", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of when the data was exported", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_list": { 23 | "title": "IXP Info List", 24 | "description": "A list of schemas representing IXP information", 25 | "type": "array", 26 | "items": 27 | { 28 | "description": "A single IXP entry", 29 | "type": "object", 30 | "required": ["ixf_id","ixp_id","shortname"], 31 | "properties": { 32 | 33 | "ixp_id": { 34 | "description": "IXP numeric identifier, persistent value free to set by the IXP", 35 | "type": "integer" 36 | }, 37 | "shortname": { 38 | "description": "Short name of the IXP", 39 | "type": "string" 40 | }, 41 | "name": { 42 | "description": "Name of the IXP", 43 | "type": "string" 44 | }, 45 | "url": { 46 | "description": "Website of the IXP", 47 | "type": "string", 48 | "format": "uri" 49 | }, 50 | "stats_api": { 51 | "description": "URL to statistics API", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "country": { 56 | "description": "ISO country code where the IXP is located", 57 | "type": "string" 58 | }, 59 | "ixf_id": { 60 | "description": "IXP ID from the IX-F database", 61 | "type": "integer" 62 | }, 63 | "peeringdb_id": { 64 | "description": "PeeringDB ID of the IX - the y in: https://www.peeringdb.com/ix/y", 65 | "type": "integer" 66 | }, 67 | "support_email": { 68 | "description": "Support email address", 69 | "type": "string", 70 | "format" : "email" 71 | }, 72 | "support_phone": { 73 | "description": "Support phone number", 74 | "type": "string" 75 | }, 76 | "support_contact_hours": { 77 | "description": "Support contact hours, eg. 24/7, 8/5, etc", 78 | "type": "string" 79 | }, 80 | "emergency_email": { 81 | "description": "Emergency support email address", 82 | "type": "string", 83 | "format" : "email" 84 | }, 85 | "emergency_phone": { 86 | "description": "Emergency support phone number", 87 | "type": "string" 88 | }, 89 | "emergency_contact_hours": { 90 | "description": "Emergency support contact hours, eg. 24/7, 8/5, etc", 91 | "type": "string" 92 | }, 93 | "billing_email": { 94 | "description": "Billing email address", 95 | "type": "string", 96 | "format" : "email" 97 | }, 98 | "billing_phone": { 99 | "description": "Billing phone number", 100 | "type": "string" 101 | }, 102 | "billing_contact_hours": { 103 | "description": "Billing contact hours, eg. 24/7, 8/5, etc", 104 | "type": "string" 105 | }, 106 | "peering_policy_list": { 107 | "description": "Peering policy choices available in the member list", 108 | "type": "array", 109 | "items": 110 | { 111 | "type": "string" 112 | } 113 | }, 114 | 115 | "switch": { 116 | "description": "Switches available at the IXP", 117 | "type": "array", 118 | "items": 119 | { 120 | "type": "object", 121 | "properties": { 122 | 123 | "id": { 124 | "description": "Unique ID of the switch", 125 | "type": "integer" 126 | }, 127 | "name": { 128 | "description": "Switch name", 129 | "type": "string" 130 | }, 131 | "colo": { 132 | "description": "Colo the switch is located in", 133 | "type": "string" 134 | }, 135 | "pdb_facility_id": { 136 | "description": "Peering DB ID of the data centre", 137 | "type": "integer" 138 | }, 139 | "city": { 140 | "description": "City the switch is located in", 141 | "type": "string" 142 | }, 143 | "country": { 144 | "description": "Country the switch is located in", 145 | "type": "string" 146 | }, 147 | "manufacturer": { 148 | "description": "Free text field to indicate the manufacturer of the switch for informational purposes.", 149 | "type": "string" 150 | }, 151 | "model": { 152 | "description": "Free text field to indicate the model of the switch for informational purposes. Should not be present without manufacturer.", 153 | "type": "string" 154 | }, 155 | "software": { 156 | "description": "Free text field to indicate the software of the switch for informational purposes.", 157 | "type": "string" 158 | } 159 | } 160 | } 161 | }, 162 | 163 | "vlan": { 164 | "description": "VLANs available at the IXP", 165 | "type": "array", 166 | "items": 167 | { 168 | "description": "A single VLAN entry", 169 | "type": "object", 170 | "properties": { 171 | 172 | "id": { 173 | "description": "Unique ID of the VLAN", 174 | "type": "integer" 175 | }, 176 | "name": { 177 | "description": "VLAN name", 178 | "type": "string" 179 | }, 180 | "ipv4": { 181 | "description": "IPv4 details in this VLAN", 182 | "type": "object", 183 | "properties": { 184 | 185 | "prefix": { 186 | "description": "Prefix of the IPv4 address", 187 | "type": "string", 188 | "format": "ipv4" 189 | }, 190 | "mask_length": { 191 | "description": "Mask length of the IPv4 address", 192 | "type": "integer" 193 | }, 194 | "looking_glass_urls": { 195 | "description": "URLs of looking glass(es) available for this VLAN and protocol.", 196 | "type": "array", 197 | "items": { 198 | "type": "string", 199 | "format": "uri" 200 | } 201 | } 202 | } 203 | }, 204 | "ipv6": { 205 | "description": "IPv6 details in this VLAN", 206 | "type": "object", 207 | "properties": { 208 | 209 | "prefix": { 210 | "description": "Prefix of the IPv6 address", 211 | "type": "string", 212 | "format": "ipv6" 213 | }, 214 | "mask_length": { 215 | "description": "Mask length of the IPv6 address", 216 | "type": "integer" 217 | }, 218 | "looking_glass_urls": { 219 | "description": "URLs of looking glass(es) available for this VLAN and protocol.", 220 | "type": "array", 221 | "items": { 222 | "type": "string", 223 | "format": "uri" 224 | } 225 | } 226 | } 227 | } 228 | } 229 | } 230 | } 231 | } 232 | } 233 | }, 234 | 235 | "member_list": { 236 | "title": "IXP Member List", 237 | "description": "A list of schemas representing IXP members", 238 | "type": "array", 239 | "items": 240 | { 241 | "description": "A single member entry", 242 | "type": "object", 243 | "required": ["asnum","connection_list"], 244 | "properties": { 245 | 246 | "asnum": { 247 | "description": "AS number of the network", 248 | "type": "integer" 249 | }, 250 | "member_type": { 251 | "description": "Participant type: peering, ixp or other", 252 | "type": "string", 253 | "enum": ["peering","ixp","other"] 254 | }, 255 | "name": { 256 | "description": "Name of the network", 257 | "type": "string" 258 | }, 259 | "url": { 260 | "description": "URL to website of the network", 261 | "type": "string", 262 | "format": "uri" 263 | }, 264 | "peering_policy": { 265 | "description": "Peering policy of the network", 266 | "type": "string" 267 | }, 268 | "peering_policy_url": { 269 | "description": "URL to the network's peering policy", 270 | "type": "string", 271 | "format": "uri" 272 | }, 273 | "member_since": { 274 | "description": "Date when the network joined the IXP", 275 | "type": "string", 276 | "format": "date-time" 277 | }, 278 | "contact_email": { 279 | "description": "List of contact email addresses of the network", 280 | "type": "array", 281 | "items": 282 | { 283 | "type": "string", 284 | "format" : "email" 285 | } 286 | }, 287 | "contact_phone": { 288 | "description": "List of contact phone numbers of the network", 289 | "type": "array", 290 | "items": 291 | { 292 | "type": "string" 293 | } 294 | }, 295 | "contact_hours": { 296 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 297 | "type": "string" 298 | }, 299 | 300 | "connection_list": { 301 | "description": "List of connections of the network at the IXP", 302 | "type": "array", 303 | "items": 304 | { 305 | "description": "A single connection entry", 306 | "type": "object", 307 | "required": ["ixp_id"], 308 | "properties": { 309 | 310 | "ixp_id": { 311 | "description": "IXP numeric identifier, persistent value free to set by the IXP, referencing the same ID as used in the ixp_list element", 312 | "type": "integer" 313 | }, 314 | "state": { 315 | "description": "State of the connection", 316 | "type": "string" 317 | }, 318 | "connected_since": { 319 | "description": "Date when the connection was activated", 320 | "type": "string", 321 | "format": "date-time" 322 | }, 323 | "if_list": { 324 | "description": "List of interfaces making up the connection", 325 | "type": "array", 326 | "items": 327 | { 328 | "description": "A single interface entry", 329 | "type": "object", 330 | "properties": { 331 | 332 | "switch_id": { 333 | "description": "Switch ID where the interface or LAG is connected, persistent value free to set by the IXP", 334 | "type": "integer" 335 | }, 336 | "if_speed": { 337 | "description": "Speed of the interface or LAG in Mb, i.e. 10G = 10000", 338 | "type": "integer" 339 | }, 340 | "if_type": { 341 | "description": "Type of the interface or LAG", 342 | "type": "string" 343 | } 344 | } 345 | } 346 | 347 | 348 | }, 349 | "vlan_list": { 350 | "type": "array", 351 | "items": 352 | { 353 | "description": "A single VLAN entry", 354 | "type": "object", 355 | "properties": { 356 | 357 | "vlan_id": { 358 | "description": "The VLAN ID this connection is placed in, persistent value free to set by the IXP", 359 | "type": "integer" 360 | }, 361 | "ipv4": { 362 | "description": "The network's IPv4 address details in this VLAN", 363 | "type": "object", 364 | "properties": { 365 | 366 | "address": { 367 | "description": "The IPv4 address", 368 | "type": "string", 369 | "format": "ipv4" 370 | }, 371 | "as_macro": { 372 | "description": "The IPv4 AS-MACRO, if applicable", 373 | "type": "string" 374 | }, 375 | "max_prefix": { 376 | "description": "The max number of prefixes on this connection for IPv4", 377 | "type": "integer" 378 | }, 379 | "routeserver": { 380 | "description": "Does this IPv4 address connect to the IXP routeserver", 381 | "type": "boolean" 382 | }, 383 | "mac_addresses": { 384 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 385 | "type": "array", 386 | "items": { 387 | "type": "string" 388 | } 389 | }, 390 | "services": { 391 | "description": "Array of IX operated service(s) available from this connection.", 392 | "type": "array", 393 | "items": { 394 | "type": "object", 395 | "properties": { 396 | "type": { 397 | "description": "The IX operated service available from this connection.", 398 | "type": "string", 399 | "enum": ["ixroutecollector", "ixrouteserver"] 400 | }, 401 | "os": { 402 | "description": "Free text field to indicate the operating system of the route server for informational purposes.", 403 | "type": "string" 404 | }, 405 | "os_version": { 406 | "description": "Free text field to indicate the operating system version of the route server for informational purposes. Should not be present without os.", 407 | "type": "string" 408 | }, 409 | "daemon": { 410 | "description": "Free text field to indicate the BGP software daemon that provides the route server for informational purposes.", 411 | "type": "string" 412 | }, 413 | "daemon_version": { 414 | "description": "Free text field to indicate the BGP software daemon version that provides the route server for informational purposes. Should not be present without daemon.", 415 | "type": "string" 416 | } 417 | } 418 | } 419 | } 420 | } 421 | }, 422 | "ipv6": { 423 | "description": "The network's IPv6 address details in this VLAN", 424 | "type": "object", 425 | "properties": { 426 | 427 | "address": { 428 | "description": "The IPv6 address", 429 | "type": "string", 430 | "format": "ipv6" 431 | }, 432 | "as_macro": { 433 | "description": "The IPv6 AS-MACRO, if applicable", 434 | "type": "string" 435 | }, 436 | "max_prefix": { 437 | "description": "The max number of prefixes on this connection for IPv6", 438 | "type": "integer" 439 | }, 440 | "routeserver": { 441 | "description": "Does this IPv6 address connect to the IXP routeserver", 442 | "type": "boolean" 443 | }, 444 | "mac_addresses": { 445 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 446 | "type": "array", 447 | "items": { 448 | "type": "string" 449 | } 450 | }, 451 | "services": { 452 | "description": "Array of IX operated service(s) available from this connection.", 453 | "type": "array", 454 | "items": { 455 | "type": "object", 456 | "properties": { 457 | "type": { 458 | "description": "The IX operated service available from this connection.", 459 | "type": "string", 460 | "enum": ["ixroutecollector", "ixrouteserver"] 461 | }, 462 | "os": { 463 | "description": "Free text field to indicate the operating system of the route server for informational purposes.", 464 | "type": "string" 465 | }, 466 | "os_version": { 467 | "description": "Free text field to indicate the operating system version of the route server for informational purposes. Should not be present without os.", 468 | "type": "string" 469 | }, 470 | "daemon": { 471 | "description": "Free text field to indicate the BGP software daemon that provides the route server for informational purposes.", 472 | "type": "string" 473 | }, 474 | "daemon_version": { 475 | "description": "Free text field to indicate the BGP software daemon version that provides the route server for informational purposes. Should not be present without daemon.", 476 | "type": "string" 477 | } 478 | } 479 | } 480 | } 481 | } 482 | } 483 | } 484 | } 485 | 486 | 487 | } 488 | } 489 | } 490 | 491 | } 492 | } 493 | } 494 | 495 | } 496 | } 497 | } 498 | -------------------------------------------------------------------------------- /ixp-member-list.txt: -------------------------------------------------------------------------------- 1 | 2 | ####################################################################### 3 | # IX Member List Schema 4 | # 5 | # Elisa Jasinska 6 | # Nick Hilliard 7 | # Bijal Sanghani 8 | # Barry O'Donovan 9 | # Arnold Nipper 10 | # 11 | # version 1.0 - 2019-07-18 12 | # 13 | # 14 | # revision history: 15 | # 16 | # v 0.1 * initial release 17 | # v 0.2 * included feedback from Steven Bakker (AMS-IX) 18 | # v 0.3 * included feedback from Nick Hilliard (INEX) 19 | # v 0.4 * included feedback from Kay Rechthien (ECIX), Martin Levy 20 | # (CloudFlare) and added Grizz's p: 21 | # + ixp_info -> ixp_list, added ixp_id referenced in 22 | # member_list.connection_list entries 23 | # + re-named former ixp_id to ixf_id and refined its type 24 | # + added emgergency contact fields: emgergency_email, 25 | # emgergency_phone, emgergency_contact_hours 26 | # + added billing contact hours field: billing_contact_hours 27 | # + added member_type field in member_list entries 28 | # + fixed typo in peering_policy_url 29 | # + added mac_address field in vlan_list entries 30 | # + added stats_api field in ixp_list entries 31 | # + changed version to dotted format 32 | # + spelin fixxups and apostrophe's 33 | # v 0.5 * included feedback from Arnold Nipper (DE-CIX): 34 | # + pdb_facility_id added to switch 35 | # v 0.6 * included feedback from Arnold Nipper (DE-CIX): 36 | # + allow multiple MACs per address family and list macs 37 | # by address family as some IXPs allow different L3 interfaces 38 | # for v4/v6 39 | # v 0.7 * added new fields following ix-f/euro-ix meeting in London, UK 40 | # on Jan 10th. Fields include: 41 | # + add: ixf_id: (integer, required) (closes #21) 42 | # + add: peeringdb_id: (integer, not required) 43 | # + add: switch manufacturer and model (strings, not required) 44 | # + add: looking_glass_urls (array of strings, not required) to vlan ipv4/6 45 | # + add: service_type (array of strings, not required) to member connection 46 | # - remove: types probono and routeserver from member_list.member_type 47 | # v 1.0 * added new fields following euro-ix requirements 48 | # + add: software to switches: (string, not required) 49 | # + refactor service_type to an array of objects called 'services' 50 | # and add: os: (string, not required), os_version: (string, not required), 51 | # daemon: (string, not required), and daemon_version: (string, not required) 52 | 53 | 54 | 55 | ####################################################################### 56 | # basic example 57 | 58 | { 59 | "version": "1.0", 60 | "timestamp": "2019-07-18T00:00:00Z", 61 | "ixp_list": [ 62 | { 63 | "ixp_id": 42, 64 | "shortname": "AMS-IX", 65 | "ixf_id": 2 66 | } 67 | ], 68 | "member_list": [ 69 | { 70 | "asnum": 8560, 71 | "connection_list": [ 72 | { 73 | "ixp_id": 42 74 | } 75 | ] 76 | }, 77 | { 78 | "asnum": 197219, 79 | "connection_list": [ 80 | { 81 | "ixp_id": 42 82 | } 83 | ] 84 | }, 85 | { 86 | "asnum": 51088, 87 | "connection_list": [ 88 | { 89 | "ixp_id": 42 90 | } 91 | ] 92 | }, 93 | { 94 | "asnum": 47836, 95 | "connection_list": [ 96 | { 97 | "ixp_id": 42 98 | } 99 | ] 100 | } 101 | # ... more members 102 | ] 103 | } 104 | 105 | 106 | ####################################################################### 107 | # more complex example 108 | 109 | { 110 | "version": "1.0", 111 | "timestamp": "2019-07-18T00:00:00Z", 112 | "ixp_list": [ 113 | { 114 | "shortname": "AMS-IX", 115 | "name": "Amsterdam Internet Exchange", 116 | "ixp_id": 42, 117 | "ixf_id": 2, 118 | "peeringdb_id": 26, 119 | "country": "NL", 120 | "url": "http://www.ams-ix.net/", 121 | "stats_api": "https://my.ams-ix.net/api/v1/stats.json", 122 | "support_email": "noc@ams-ix.net", 123 | "support_phone": "+31 20 514 1717", 124 | "support_contact_hours": "8/5", 125 | "emergency_email": "noc@ams-ix.net", 126 | "emergency_phone": "+31 20 514 1717", 127 | "emergency_contact_hours": "24/7", 128 | "billing_email": "info@ams-ix.net", 129 | "billing_phone": "+31 20 305 89 99", 130 | "billing_contact_hours": "8/5", 131 | "peering_policy_list": [ 132 | "open", 133 | "selective", 134 | "closed", 135 | "case-by-case", 136 | "custom" 137 | ], 138 | "switch": [ 139 | { 140 | "id": 0, 141 | "name": "PXC-TC5-144", 142 | "colo": "Telecity 5", 143 | "pdb_facility_id": 1236, 144 | "city": "Amsterdam", 145 | "country": "NL", 146 | "manufacturer": "Acme Switch Co.", 147 | "model": "Big Switch", 148 | "software": "SwitchOS" 149 | }, 150 | { 151 | "id": 1, 152 | "name": "PXC-GLO-146", 153 | "colo": "Global Switch", 154 | "pdb_facility_id": 63, 155 | "city": "Amsterdam", 156 | "country": "NL" 157 | } 158 | ], 159 | "vlan": [ 160 | { 161 | "id": 0, 162 | "name": "ISP", 163 | "ipv4": { 164 | "prefix": "80.249.208.0", 165 | "mask_length": 21 166 | }, 167 | "ipv6": { 168 | "prefix": "2001:7f8:1::", 169 | "mask_length": 64 170 | } 171 | }, 172 | { 173 | "id": 1, 174 | "name": "GRX", 175 | "ipv4": { 176 | "prefix": "193.105.101.0", 177 | "mask_length": 23 178 | } 179 | } 180 | ] 181 | } 182 | ], 183 | "member_list": [ 184 | { 185 | "asnum": 65505, 186 | "member_type": "peering", 187 | "name": "Netflix", 188 | "url": "http://netflix.com/", 189 | "contact_email": [ 190 | "peering@example.com", 191 | "mrpeering@example.com" 192 | ], 193 | "contact_phone": [ 194 | "+1 1234 5678" 195 | ], 196 | "contact_hours": "8/5", 197 | "peering_policy": "open", 198 | "peering_policy_url": "https://www.netflix.com/openconnect/", 199 | "member_since": "2009-02-04T00:00:00Z", 200 | "connection_list": [ 201 | { 202 | "ixp_id": 42, 203 | "connected_since": "2009-02-04T00:00:00Z", 204 | "state": "active", 205 | "if_list": [ 206 | { 207 | "switch_id": 0, 208 | "if_speed": 10000, 209 | "if_type": "LR4" 210 | } 211 | ], 212 | "vlan_list": [ 213 | { 214 | "vlan_id": 0, 215 | "ipv4": { 216 | "address": "192.0.2.250", 217 | "routeserver": true, 218 | "max_prefix": 42, 219 | "as_macro": "AS-NFLX-V4", 220 | "mac_addresses" : [ 221 | "00:11:22:33:44:16" 222 | ] 223 | }, 224 | "ipv6": { 225 | "address": "2001:db8::250", 226 | "routeserver": true, 227 | "max_prefix": 42, 228 | "as_macro": "AS-NFLX-V6", 229 | "mac_addresses" : [ 230 | "00:11:22:33:44:16" 231 | ] 232 | } 233 | } 234 | ] 235 | }, 236 | { 237 | "ixp_id": 42, 238 | "connected_since": "2009-02-04T00:00:00Z", 239 | "state": "active", 240 | "if_list": [ 241 | { 242 | "switch_id": 1, 243 | "if_speed": 10000, 244 | "if_type": "LR4" 245 | } 246 | ], 247 | "vlan_list": [ 248 | { 249 | "vlan_id": 0, 250 | "ipv4": { 251 | "address": "192.0.2.100", 252 | "routeserver": true, 253 | "max_prefix": 42, 254 | "as_macro": "AS-NFLX-V4", 255 | "mac_addresses" : [ 256 | "00:11:22:33:44:17" 257 | ] 258 | }, 259 | "ipv6": { 260 | "address": "2001:db8::100", 261 | "routeserver": true, 262 | "max_prefix": 42, 263 | "as_macro": "AS-NFLX-V6", 264 | "mac_addresses" : [ 265 | "00:11:22:33:44:17" 266 | ] 267 | } 268 | } 269 | ] 270 | } 271 | ] 272 | }, 273 | { 274 | "asnum": 65500, 275 | "member_type": "ixp", 276 | "name": "Example IXP", 277 | "url": "http://ixp.example.com/", 278 | "peering_policy": "mandatory", 279 | "member_since": "2000-02-04T00:00:00Z", 280 | "connection_list": [ 281 | { 282 | "ixp_id": 42, 283 | "state": "active", 284 | "if_list": [ 285 | { 286 | "switch_id": 0, 287 | "if_speed": 10000, 288 | } 289 | ], 290 | "vlan_list": [ 291 | { 292 | "vlan_id": 2, 293 | "ipv4": { 294 | "address": "192.0.2.254", 295 | "routeserver": false, 296 | "max_prefix": 100000, 297 | "as_macro": "AS-EXAMPLE-IX-RS", 298 | "services": [ 299 | { 300 | "type": "ixrouteserver", 301 | "os": "Ubuntu Linux", 302 | "os_version": "18.04", 303 | "daemon": "bird", 304 | "daemon_version": "1.6.2", 305 | } 306 | ] 307 | }, 308 | "ipv6": { 309 | "address": "2001:db8::254", 310 | "routeserver": false, 311 | "max_prefix": 10000, 312 | "as_macro": "AS-EXAMPLE-IX-RS-V6", 313 | "services": [ 314 | { 315 | "type": "ixrouteserver", 316 | "os": "Ubuntu Linux", 317 | "os_version": "18.04", 318 | "daemon": "bird", 319 | "daemon_version": "1.6.2", 320 | } 321 | ] 322 | } 323 | } 324 | ] 325 | } 326 | ] 327 | } 328 | ] 329 | } 330 | -------------------------------------------------------------------------------- /versions/ixp-member-list-0.3.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_info", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of the export", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_info": { 23 | "title": "IXP Info", 24 | "description": "A schema representing IXP information", 25 | "type": "object", 26 | "properties": { 27 | 28 | "shortname": { 29 | "description": "Short name of the IXP", 30 | "type": "string" 31 | }, 32 | "name": { 33 | "description": "Name of the IXP", 34 | "type": "string" 35 | }, 36 | "url": { 37 | "description": "Website of the IXP", 38 | "type": "string", 39 | "format": "uri" 40 | }, 41 | "country": { 42 | "description": "Country code of where the IXP is located", 43 | "type": "string" 44 | }, 45 | "ixp_id": { 46 | "description": "IXP ID as represented in IXP and PeeringDB", 47 | "type": "string" 48 | }, 49 | "support_email": { 50 | "description": "Technical support email address", 51 | "type": "string", 52 | "format" : "email" 53 | }, 54 | "support_phone": { 55 | "description": "Technical support phone number", 56 | "type": "string" 57 | }, 58 | "support_contact_hours": { 59 | "description": "Technical support contact hours, eg. 24/7, 8/5, etc", 60 | "type": "string" 61 | }, 62 | "billing_email": { 63 | "description": "Billing email address", 64 | "type": "string", 65 | "format" : "email" 66 | }, 67 | "billing_phone": { 68 | "description": "Billing phone number", 69 | "type": "string" 70 | }, 71 | "peering_policy_list": { 72 | "description": "Peering policy choices available in the member list", 73 | "type": "array", 74 | "items": 75 | { 76 | "type": "string" 77 | } 78 | }, 79 | 80 | "switch": { 81 | "description": "Switches available at the IXP", 82 | "type": "array", 83 | "items": 84 | { 85 | "type": "object", 86 | "properties": { 87 | 88 | "id": { 89 | "description": "Unique ID of the switch", 90 | "type": "integer" 91 | }, 92 | "name": { 93 | "description": "Switch name", 94 | "type": "string" 95 | }, 96 | "colo": { 97 | "description": "Colo the switch is located in", 98 | "type": "string" 99 | }, 100 | "city": { 101 | "description": "City the switch is located in", 102 | "type": "string" 103 | }, 104 | "country": { 105 | "description": "Country the switch is located in", 106 | "type": "string" 107 | } 108 | } 109 | } 110 | }, 111 | 112 | "vlan": { 113 | "description": "VLANs available at the IXP", 114 | "type": "array", 115 | "items": 116 | { 117 | "description": "A single VLAN entry", 118 | "type": "object", 119 | "properties": { 120 | 121 | "id": { 122 | "description": "Unique ID of the VLAN", 123 | "type": "integer" 124 | }, 125 | "name": { 126 | "description": "VLAN name", 127 | "type": "string" 128 | }, 129 | "ipv4": { 130 | "description": "IPv4 details in this VLAN", 131 | "type": "object", 132 | "properties": { 133 | 134 | "prefix": { 135 | "description": "Prefix of the IPv4 address", 136 | "type": "string", 137 | "format": "ipv4" 138 | }, 139 | "mask_length": { 140 | "description": "Mask length of the IPv4 address", 141 | "type": "integer" 142 | } 143 | } 144 | }, 145 | "ipv6": { 146 | "description": "IPv6 details in this VLAN", 147 | "type": "object", 148 | "properties": { 149 | 150 | "prefix": { 151 | "description": "Prefix of the IPv6 address", 152 | "type": "string", 153 | "format": "ipv6" 154 | }, 155 | "mask_length": { 156 | "description": "Mask length of the IPv6 address", 157 | "type": "integer" 158 | } 159 | } 160 | } 161 | } 162 | } 163 | } 164 | } 165 | }, 166 | 167 | "member_list": { 168 | "title": "IXP Member List", 169 | "description": "A schema representing the IXP's Member List", 170 | "type": "array", 171 | "items": 172 | { 173 | "description": "A single member entry", 174 | "type": "object", 175 | "required": ["asnum"], 176 | "properties": { 177 | 178 | "asnum": { 179 | "description": "AS number of the network", 180 | "type": "integer" 181 | }, 182 | "name": { 183 | "description": "Name of the network", 184 | "type": "string" 185 | }, 186 | "url": { 187 | "description": "URL to website of the network", 188 | "type": "string", 189 | "format": "uri" 190 | }, 191 | "peering_policy": { 192 | "description": "Peering policy of the network", 193 | "type": "string" 194 | }, 195 | "peering_policy_url": { 196 | "description": "URL to the networks peering policy", 197 | "type": "string", 198 | "format": "uri" 199 | }, 200 | "member_since": { 201 | "description": "Date when the network joined the IX", 202 | "type": "string", 203 | "format": "date-time" 204 | }, 205 | "contact_email": { 206 | "description": "List of contact email addresses of the network", 207 | "type": "array", 208 | "items": 209 | { 210 | "type": "string", 211 | "format" : "email" 212 | } 213 | }, 214 | "contact_phone": { 215 | "description": "List of contact phone numbers of the network", 216 | "type": "array", 217 | "items": 218 | { 219 | "type": "string" 220 | } 221 | }, 222 | "contact_hours": { 223 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 224 | "type": "string" 225 | }, 226 | 227 | "connection_list": { 228 | "description": "List of connection of the network at the IXP", 229 | "type": "array", 230 | "items": 231 | { 232 | "description": "A single connection entry", 233 | "type": "object", 234 | "properties": { 235 | 236 | "state": { 237 | "description": "State of the connection", 238 | "type": "string" 239 | }, 240 | "connected_since": { 241 | "description": "Date when the connection has been activated", 242 | "type": "string", 243 | "format": "date-time" 244 | }, 245 | "if_list": { 246 | "description": "List of interfaces making up the connection", 247 | "type": "array", 248 | "items": 249 | { 250 | "description": "A single interface entry", 251 | "type": "object", 252 | "properties": { 253 | 254 | "switch_id": { 255 | "description": "Switch od of where the interface or LAG is connected", 256 | "type": "integer" 257 | }, 258 | "if_speed": { 259 | "description": "Speed of the interface or LAG", 260 | "type": "integer" 261 | }, 262 | "if_type": { 263 | "description": "Type of the interface or LAG", 264 | "type": "string" 265 | } 266 | } 267 | } 268 | 269 | 270 | }, 271 | "vlan_list": { 272 | "type": "array", 273 | "items": 274 | { 275 | "description": "A single VLAN entry", 276 | "type": "object", 277 | "properties": { 278 | 279 | "vlan_id": { 280 | "description": "The VLAN ID this connection is placed in", 281 | "type": "integer" 282 | }, 283 | "ipv4": { 284 | "description": "The networks IPv4 address details in this VLAN", 285 | "type": "object", 286 | "properties": { 287 | 288 | "address": { 289 | "description": "The IPv4 address", 290 | "type": "string", 291 | "format": "ipv4" 292 | }, 293 | "as_macro": { 294 | "description": "The IPv4 AS-MACRO, if applicable", 295 | "type": "string" 296 | }, 297 | "max_prefix": { 298 | "description": "The max prefix on this connection for IPv4", 299 | "type": "integer" 300 | }, 301 | "routeserver": { 302 | "description": "Does this IPv4 connection participate in the routeserver", 303 | "type": "boolean" 304 | } 305 | } 306 | }, 307 | "ipv6": { 308 | "description": "The networks IPv6 address details in this VLAN", 309 | "type": "object", 310 | "properties": { 311 | 312 | "address": { 313 | "description": "The IPv6 address", 314 | "type": "string", 315 | "format": "ipv6" 316 | }, 317 | "as_macro": { 318 | "description": "The IPv6 AS-MACRO, if applicable", 319 | "type": "string" 320 | }, 321 | "max_prefix": { 322 | "description": "The max prefix on this connection for IPv6", 323 | "type": "integer" 324 | }, 325 | "routeserver": { 326 | "description": "Does this IPv6 connection participate in the routeserver", 327 | "type": "boolean" 328 | } 329 | } 330 | } 331 | } 332 | } 333 | 334 | 335 | } 336 | } 337 | } 338 | 339 | } 340 | } 341 | } 342 | 343 | } 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /versions/ixp-member-list-0.4.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_list", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of when the data was exported", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_list": { 23 | "title": "IXP Info List", 24 | "description": "A list of schemas representing IXP information", 25 | "type": "array", 26 | "items": 27 | { 28 | "description": "A single IXP entry", 29 | "type": "object", 30 | "required": ["ixp_id","shortname"], 31 | "properties": { 32 | 33 | "ixp_id": { 34 | "description": "IXP numeric identifier", 35 | "type": "integer" 36 | }, 37 | "shortname": { 38 | "description": "Short name of the IXP", 39 | "type": "string" 40 | }, 41 | "name": { 42 | "description": "Name of the IXP", 43 | "type": "string" 44 | }, 45 | "url": { 46 | "description": "Website of the IXP", 47 | "type": "string", 48 | "format": "uri" 49 | }, 50 | "stats_api": { 51 | "description": "URL to statistics API", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "country": { 56 | "description": "ISO country code where the IXP is located", 57 | "type": "string" 58 | }, 59 | "ixf_id": { 60 | "description": "IXP ID from the IX-F database", 61 | "type": "integer" 62 | }, 63 | "support_email": { 64 | "description": "Support email address", 65 | "type": "string", 66 | "format" : "email" 67 | }, 68 | "support_phone": { 69 | "description": "Support phone number", 70 | "type": "string" 71 | }, 72 | "support_contact_hours": { 73 | "description": "Support contact hours, eg. 24/7, 8/5, etc", 74 | "type": "string" 75 | }, 76 | "emergency_email": { 77 | "description": "Emergency support email address", 78 | "type": "string", 79 | "format" : "email" 80 | }, 81 | "emergency_phone": { 82 | "description": "Emergency support phone number", 83 | "type": "string" 84 | }, 85 | "emergency_contact_hours": { 86 | "description": "Emergency support contact hours, eg. 24/7, 8/5, etc", 87 | "type": "string" 88 | }, 89 | "billing_email": { 90 | "description": "Billing email address", 91 | "type": "string", 92 | "format" : "email" 93 | }, 94 | "billing_phone": { 95 | "description": "Billing phone number", 96 | "type": "string" 97 | }, 98 | "billing_contact_hours": { 99 | "description": "Billing contact hours, eg. 24/7, 8/5, etc", 100 | "type": "string" 101 | }, 102 | "peering_policy_list": { 103 | "description": "Peering policy choices available in the member list", 104 | "type": "array", 105 | "items": 106 | { 107 | "type": "string" 108 | } 109 | }, 110 | 111 | "switch": { 112 | "description": "Switches available at the IXP", 113 | "type": "array", 114 | "items": 115 | { 116 | "type": "object", 117 | "properties": { 118 | 119 | "id": { 120 | "description": "Unique ID of the switch", 121 | "type": "integer" 122 | }, 123 | "name": { 124 | "description": "Switch name", 125 | "type": "string" 126 | }, 127 | "colo": { 128 | "description": "Colo the switch is located in", 129 | "type": "string" 130 | }, 131 | "city": { 132 | "description": "City the switch is located in", 133 | "type": "string" 134 | }, 135 | "country": { 136 | "description": "Country the switch is located in", 137 | "type": "string" 138 | } 139 | } 140 | } 141 | }, 142 | 143 | "vlan": { 144 | "description": "VLANs available at the IXP", 145 | "type": "array", 146 | "items": 147 | { 148 | "description": "A single VLAN entry", 149 | "type": "object", 150 | "properties": { 151 | 152 | "id": { 153 | "description": "Unique ID of the VLAN", 154 | "type": "integer" 155 | }, 156 | "name": { 157 | "description": "VLAN name", 158 | "type": "string" 159 | }, 160 | "ipv4": { 161 | "description": "IPv4 details in this VLAN", 162 | "type": "object", 163 | "properties": { 164 | 165 | "prefix": { 166 | "description": "Prefix of the IPv4 address", 167 | "type": "string", 168 | "format": "ipv4" 169 | }, 170 | "mask_length": { 171 | "description": "Mask length of the IPv4 address", 172 | "type": "integer" 173 | } 174 | } 175 | }, 176 | "ipv6": { 177 | "description": "IPv6 details in this VLAN", 178 | "type": "object", 179 | "properties": { 180 | 181 | "prefix": { 182 | "description": "Prefix of the IPv6 address", 183 | "type": "string", 184 | "format": "ipv6" 185 | }, 186 | "mask_length": { 187 | "description": "Mask length of the IPv6 address", 188 | "type": "integer" 189 | } 190 | } 191 | } 192 | } 193 | } 194 | } 195 | } 196 | } 197 | }, 198 | 199 | "member_list": { 200 | "title": "IXP Member List", 201 | "description": "A list of schemas representing IXP members", 202 | "type": "array", 203 | "items": 204 | { 205 | "description": "A single member entry", 206 | "type": "object", 207 | "required": ["asnum","connection_list"], 208 | "properties": { 209 | 210 | "asnum": { 211 | "description": "AS number of the network", 212 | "type": "integer" 213 | }, 214 | "member_type": { 215 | "description": "Participant type: peering, ixp, pro bono, routeserver or other", 216 | "type": "string", 217 | "enum": ["peering","ixp","routeserver","probono","other"] 218 | }, 219 | "name": { 220 | "description": "Name of the network", 221 | "type": "string" 222 | }, 223 | "url": { 224 | "description": "URL to website of the network", 225 | "type": "string", 226 | "format": "uri" 227 | }, 228 | "peering_policy": { 229 | "description": "Peering policy of the network", 230 | "type": "string" 231 | }, 232 | "peering_policy_url": { 233 | "description": "URL to the network's peering policy", 234 | "type": "string", 235 | "format": "uri" 236 | }, 237 | "member_since": { 238 | "description": "Date when the network joined the IXP", 239 | "type": "string", 240 | "format": "date-time" 241 | }, 242 | "contact_email": { 243 | "description": "List of contact email addresses of the network", 244 | "type": "array", 245 | "items": 246 | { 247 | "type": "string", 248 | "format" : "email" 249 | } 250 | }, 251 | "contact_phone": { 252 | "description": "List of contact phone numbers of the network", 253 | "type": "array", 254 | "items": 255 | { 256 | "type": "string" 257 | } 258 | }, 259 | "contact_hours": { 260 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 261 | "type": "string" 262 | }, 263 | 264 | "connection_list": { 265 | "description": "List of connections of the network at the IXP", 266 | "type": "array", 267 | "items": 268 | { 269 | "description": "A single connection entry", 270 | "type": "object", 271 | "required": ["ixp_id"], 272 | "properties": { 273 | 274 | "ixp_id": { 275 | "description": "IXP numeric identifier", 276 | "type": "integer" 277 | }, 278 | "state": { 279 | "description": "State of the connection", 280 | "type": "string" 281 | }, 282 | "connected_since": { 283 | "description": "Date when the connection was activated", 284 | "type": "string", 285 | "format": "date-time" 286 | }, 287 | "if_list": { 288 | "description": "List of interfaces making up the connection", 289 | "type": "array", 290 | "items": 291 | { 292 | "description": "A single interface entry", 293 | "type": "object", 294 | "properties": { 295 | 296 | "switch_id": { 297 | "description": "Switch id where the interface or LAG is connected", 298 | "type": "integer" 299 | }, 300 | "if_speed": { 301 | "description": "Speed of the interface or LAG", 302 | "type": "integer" 303 | }, 304 | "if_type": { 305 | "description": "Type of the interface or LAG", 306 | "type": "string" 307 | } 308 | } 309 | } 310 | 311 | 312 | }, 313 | "vlan_list": { 314 | "type": "array", 315 | "items": 316 | { 317 | "description": "A single VLAN entry", 318 | "type": "object", 319 | "properties": { 320 | 321 | "vlan_id": { 322 | "description": "The VLAN ID this connection is placed in", 323 | "type": "integer" 324 | }, 325 | "mac_address": { 326 | "description": "MAC address of the member interface", 327 | "type": "string" 328 | }, 329 | "ipv4": { 330 | "description": "The network's IPv4 address details in this VLAN", 331 | "type": "object", 332 | "properties": { 333 | 334 | "address": { 335 | "description": "The IPv4 address", 336 | "type": "string", 337 | "format": "ipv4" 338 | }, 339 | "as_macro": { 340 | "description": "The IPv4 AS-MACRO, if applicable", 341 | "type": "string" 342 | }, 343 | "max_prefix": { 344 | "description": "The max number of prefixes on this connection for IPv4", 345 | "type": "integer" 346 | }, 347 | "routeserver": { 348 | "description": "Does this IPv4 address connect to the IXP routeserver", 349 | "type": "boolean" 350 | } 351 | } 352 | }, 353 | "ipv6": { 354 | "description": "The network's IPv6 address details in this VLAN", 355 | "type": "object", 356 | "properties": { 357 | 358 | "address": { 359 | "description": "The IPv6 address", 360 | "type": "string", 361 | "format": "ipv6" 362 | }, 363 | "as_macro": { 364 | "description": "The IPv6 AS-MACRO, if applicable", 365 | "type": "string" 366 | }, 367 | "max_prefix": { 368 | "description": "The max number of prefixes on this connection for IPv6", 369 | "type": "integer" 370 | }, 371 | "routeserver": { 372 | "description": "Does this IPv6 address connect to the IXP routeserver", 373 | "type": "boolean" 374 | } 375 | } 376 | } 377 | } 378 | } 379 | 380 | 381 | } 382 | } 383 | } 384 | 385 | } 386 | } 387 | } 388 | 389 | } 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /versions/ixp-member-list-0.5.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_list", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema; this is not the version of the file within an IXP; but the schema version", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of when the data was exported", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_list": { 23 | "title": "IXP Info List", 24 | "description": "A list of schemas representing IXP information", 25 | "type": "array", 26 | "items": 27 | { 28 | "description": "A single IXP entry", 29 | "type": "object", 30 | "required": ["ixp_id","shortname"], 31 | "properties": { 32 | 33 | "ixp_id": { 34 | "description": "IXP numeric identifier", 35 | "type": "integer" 36 | }, 37 | "shortname": { 38 | "description": "Short name of the IXP", 39 | "type": "string" 40 | }, 41 | "name": { 42 | "description": "Name of the IXP", 43 | "type": "string" 44 | }, 45 | "url": { 46 | "description": "Website of the IXP", 47 | "type": "string", 48 | "format": "uri" 49 | }, 50 | "stats_api": { 51 | "description": "URL to statistics API", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "country": { 56 | "description": "ISO country code where the IXP is located", 57 | "type": "string" 58 | }, 59 | "ixf_id": { 60 | "description": "IXP ID from the IX-F database", 61 | "type": "integer" 62 | }, 63 | "support_email": { 64 | "description": "Support email address", 65 | "type": "string", 66 | "format" : "email" 67 | }, 68 | "support_phone": { 69 | "description": "Support phone number", 70 | "type": "string" 71 | }, 72 | "support_contact_hours": { 73 | "description": "Support contact hours, eg. 24/7, 8/5, etc", 74 | "type": "string" 75 | }, 76 | "emergency_email": { 77 | "description": "Emergency support email address", 78 | "type": "string", 79 | "format" : "email" 80 | }, 81 | "emergency_phone": { 82 | "description": "Emergency support phone number", 83 | "type": "string" 84 | }, 85 | "emergency_contact_hours": { 86 | "description": "Emergency support contact hours, eg. 24/7, 8/5, etc", 87 | "type": "string" 88 | }, 89 | "billing_email": { 90 | "description": "Billing email address", 91 | "type": "string", 92 | "format" : "email" 93 | }, 94 | "billing_phone": { 95 | "description": "Billing phone number", 96 | "type": "string" 97 | }, 98 | "billing_contact_hours": { 99 | "description": "Billing contact hours, eg. 24/7, 8/5, etc", 100 | "type": "string" 101 | }, 102 | "peering_policy_list": { 103 | "description": "Peering policy choices available in the member list", 104 | "type": "array", 105 | "items": 106 | { 107 | "type": "string" 108 | } 109 | }, 110 | 111 | "switch": { 112 | "description": "Switches available at the IXP", 113 | "type": "array", 114 | "items": 115 | { 116 | "type": "object", 117 | "properties": { 118 | 119 | "id": { 120 | "description": "Unique ID of the switch", 121 | "type": "integer" 122 | }, 123 | "name": { 124 | "description": "Switch name", 125 | "type": "string" 126 | }, 127 | "colo": { 128 | "description": "Colo the switch is located in", 129 | "type": "string" 130 | }, 131 | "pdb_facility_id": { 132 | "description": "Peering DB ID of the data centre", 133 | "type": "integer" 134 | }, 135 | "city": { 136 | "description": "City the switch is located in", 137 | "type": "string" 138 | }, 139 | "country": { 140 | "description": "Country the switch is located in", 141 | "type": "string" 142 | } 143 | } 144 | } 145 | }, 146 | 147 | "vlan": { 148 | "description": "VLANs available at the IXP", 149 | "type": "array", 150 | "items": 151 | { 152 | "description": "A single VLAN entry", 153 | "type": "object", 154 | "properties": { 155 | 156 | "id": { 157 | "description": "Unique ID of the VLAN", 158 | "type": "integer" 159 | }, 160 | "name": { 161 | "description": "VLAN name", 162 | "type": "string" 163 | }, 164 | "ipv4": { 165 | "description": "IPv4 details in this VLAN", 166 | "type": "object", 167 | "properties": { 168 | 169 | "prefix": { 170 | "description": "Prefix of the IPv4 address", 171 | "type": "string", 172 | "format": "ipv4" 173 | }, 174 | "mask_length": { 175 | "description": "Mask length of the IPv4 address", 176 | "type": "integer" 177 | } 178 | } 179 | }, 180 | "ipv6": { 181 | "description": "IPv6 details in this VLAN", 182 | "type": "object", 183 | "properties": { 184 | 185 | "prefix": { 186 | "description": "Prefix of the IPv6 address", 187 | "type": "string", 188 | "format": "ipv6" 189 | }, 190 | "mask_length": { 191 | "description": "Mask length of the IPv6 address", 192 | "type": "integer" 193 | } 194 | } 195 | } 196 | } 197 | } 198 | } 199 | } 200 | } 201 | }, 202 | 203 | "member_list": { 204 | "title": "IXP Member List", 205 | "description": "A list of schemas representing IXP members", 206 | "type": "array", 207 | "items": 208 | { 209 | "description": "A single member entry", 210 | "type": "object", 211 | "required": ["asnum","connection_list"], 212 | "properties": { 213 | 214 | "asnum": { 215 | "description": "AS number of the network", 216 | "type": "integer" 217 | }, 218 | "member_type": { 219 | "description": "Participant type: peering, ixp, pro bono, routeserver or other", 220 | "type": "string", 221 | "enum": ["peering","ixp","routeserver","probono","other"] 222 | }, 223 | "name": { 224 | "description": "Name of the network", 225 | "type": "string" 226 | }, 227 | "url": { 228 | "description": "URL to website of the network", 229 | "type": "string", 230 | "format": "uri" 231 | }, 232 | "peering_policy": { 233 | "description": "Peering policy of the network", 234 | "type": "string" 235 | }, 236 | "peering_policy_url": { 237 | "description": "URL to the network's peering policy", 238 | "type": "string", 239 | "format": "uri" 240 | }, 241 | "member_since": { 242 | "description": "Date when the network joined the IXP", 243 | "type": "string", 244 | "format": "date-time" 245 | }, 246 | "contact_email": { 247 | "description": "List of contact email addresses of the network", 248 | "type": "array", 249 | "items": 250 | { 251 | "type": "string", 252 | "format" : "email" 253 | } 254 | }, 255 | "contact_phone": { 256 | "description": "List of contact phone numbers of the network", 257 | "type": "array", 258 | "items": 259 | { 260 | "type": "string" 261 | } 262 | }, 263 | "contact_hours": { 264 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 265 | "type": "string" 266 | }, 267 | 268 | "connection_list": { 269 | "description": "List of connections of the network at the IXP", 270 | "type": "array", 271 | "items": 272 | { 273 | "description": "A single connection entry", 274 | "type": "object", 275 | "required": ["ixp_id"], 276 | "properties": { 277 | 278 | "ixp_id": { 279 | "description": "IXP numeric identifier", 280 | "type": "integer" 281 | }, 282 | "state": { 283 | "description": "State of the connection", 284 | "type": "string" 285 | }, 286 | "connected_since": { 287 | "description": "Date when the connection was activated", 288 | "type": "string", 289 | "format": "date-time" 290 | }, 291 | "if_list": { 292 | "description": "List of interfaces making up the connection", 293 | "type": "array", 294 | "items": 295 | { 296 | "description": "A single interface entry", 297 | "type": "object", 298 | "properties": { 299 | 300 | "switch_id": { 301 | "description": "Switch id where the interface or LAG is connected", 302 | "type": "integer" 303 | }, 304 | "if_speed": { 305 | "description": "Speed of the interface or LAG", 306 | "type": "integer" 307 | }, 308 | "if_type": { 309 | "description": "Type of the interface or LAG", 310 | "type": "string" 311 | } 312 | } 313 | } 314 | 315 | 316 | }, 317 | "vlan_list": { 318 | "type": "array", 319 | "items": 320 | { 321 | "description": "A single VLAN entry", 322 | "type": "object", 323 | "properties": { 324 | 325 | "vlan_id": { 326 | "description": "The VLAN ID this connection is placed in", 327 | "type": "integer" 328 | }, 329 | "mac_address": { 330 | "description": "MAC address of the member interface", 331 | "type": "string" 332 | }, 333 | "ipv4": { 334 | "description": "The network's IPv4 address details in this VLAN", 335 | "type": "object", 336 | "properties": { 337 | 338 | "address": { 339 | "description": "The IPv4 address", 340 | "type": "string", 341 | "format": "ipv4" 342 | }, 343 | "as_macro": { 344 | "description": "The IPv4 AS-MACRO, if applicable", 345 | "type": "string" 346 | }, 347 | "max_prefix": { 348 | "description": "The max number of prefixes on this connection for IPv4", 349 | "type": "integer" 350 | }, 351 | "routeserver": { 352 | "description": "Does this IPv4 address connect to the IXP routeserver", 353 | "type": "boolean" 354 | } 355 | } 356 | }, 357 | "ipv6": { 358 | "description": "The network's IPv6 address details in this VLAN", 359 | "type": "object", 360 | "properties": { 361 | 362 | "address": { 363 | "description": "The IPv6 address", 364 | "type": "string", 365 | "format": "ipv6" 366 | }, 367 | "as_macro": { 368 | "description": "The IPv6 AS-MACRO, if applicable", 369 | "type": "string" 370 | }, 371 | "max_prefix": { 372 | "description": "The max number of prefixes on this connection for IPv6", 373 | "type": "integer" 374 | }, 375 | "routeserver": { 376 | "description": "Does this IPv6 address connect to the IXP routeserver", 377 | "type": "boolean" 378 | } 379 | } 380 | } 381 | } 382 | } 383 | 384 | 385 | } 386 | } 387 | } 388 | 389 | } 390 | } 391 | } 392 | 393 | } 394 | } 395 | } 396 | -------------------------------------------------------------------------------- /versions/ixp-member-list-0.6.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_list", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema; this is not the version of the file within an IXP; but the schema version", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of when the data was exported", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_list": { 23 | "title": "IXP Info List", 24 | "description": "A list of schemas representing IXP information", 25 | "type": "array", 26 | "items": 27 | { 28 | "description": "A single IXP entry", 29 | "type": "object", 30 | "required": ["ixp_id","shortname"], 31 | "properties": { 32 | 33 | "ixp_id": { 34 | "description": "IXP numeric identifier, persistent value free to set by the IXP", 35 | "type": "integer" 36 | }, 37 | "shortname": { 38 | "description": "Short name of the IXP", 39 | "type": "string" 40 | }, 41 | "name": { 42 | "description": "Name of the IXP", 43 | "type": "string" 44 | }, 45 | "url": { 46 | "description": "Website of the IXP", 47 | "type": "string", 48 | "format": "uri" 49 | }, 50 | "stats_api": { 51 | "description": "URL to statistics API", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "country": { 56 | "description": "ISO country code where the IXP is located", 57 | "type": "string" 58 | }, 59 | "ixf_id": { 60 | "description": "IXP ID from the IX-F database", 61 | "type": "integer" 62 | }, 63 | "support_email": { 64 | "description": "Support email address", 65 | "type": "string", 66 | "format" : "email" 67 | }, 68 | "support_phone": { 69 | "description": "Support phone number", 70 | "type": "string" 71 | }, 72 | "support_contact_hours": { 73 | "description": "Support contact hours, eg. 24/7, 8/5, etc", 74 | "type": "string" 75 | }, 76 | "emergency_email": { 77 | "description": "Emergency support email address", 78 | "type": "string", 79 | "format" : "email" 80 | }, 81 | "emergency_phone": { 82 | "description": "Emergency support phone number", 83 | "type": "string" 84 | }, 85 | "emergency_contact_hours": { 86 | "description": "Emergency support contact hours, eg. 24/7, 8/5, etc", 87 | "type": "string" 88 | }, 89 | "billing_email": { 90 | "description": "Billing email address", 91 | "type": "string", 92 | "format" : "email" 93 | }, 94 | "billing_phone": { 95 | "description": "Billing phone number", 96 | "type": "string" 97 | }, 98 | "billing_contact_hours": { 99 | "description": "Billing contact hours, eg. 24/7, 8/5, etc", 100 | "type": "string" 101 | }, 102 | "peering_policy_list": { 103 | "description": "Peering policy choices available in the member list", 104 | "type": "array", 105 | "items": 106 | { 107 | "type": "string" 108 | } 109 | }, 110 | 111 | "switch": { 112 | "description": "Switches available at the IXP", 113 | "type": "array", 114 | "items": 115 | { 116 | "type": "object", 117 | "properties": { 118 | 119 | "id": { 120 | "description": "Unique ID of the switch", 121 | "type": "integer" 122 | }, 123 | "name": { 124 | "description": "Switch name", 125 | "type": "string" 126 | }, 127 | "colo": { 128 | "description": "Colo the switch is located in", 129 | "type": "string" 130 | }, 131 | "pdb_facility_id": { 132 | "description": "Peering DB ID of the data centre", 133 | "type": "integer" 134 | }, 135 | "city": { 136 | "description": "City the switch is located in", 137 | "type": "string" 138 | }, 139 | "country": { 140 | "description": "Country the switch is located in", 141 | "type": "string" 142 | } 143 | } 144 | } 145 | }, 146 | 147 | "vlan": { 148 | "description": "VLANs available at the IXP", 149 | "type": "array", 150 | "items": 151 | { 152 | "description": "A single VLAN entry", 153 | "type": "object", 154 | "properties": { 155 | 156 | "id": { 157 | "description": "Unique ID of the VLAN", 158 | "type": "integer" 159 | }, 160 | "name": { 161 | "description": "VLAN name", 162 | "type": "string" 163 | }, 164 | "ipv4": { 165 | "description": "IPv4 details in this VLAN", 166 | "type": "object", 167 | "properties": { 168 | 169 | "prefix": { 170 | "description": "Prefix of the IPv4 address", 171 | "type": "string", 172 | "format": "ipv4" 173 | }, 174 | "mask_length": { 175 | "description": "Mask length of the IPv4 address", 176 | "type": "integer" 177 | } 178 | } 179 | }, 180 | "ipv6": { 181 | "description": "IPv6 details in this VLAN", 182 | "type": "object", 183 | "properties": { 184 | 185 | "prefix": { 186 | "description": "Prefix of the IPv6 address", 187 | "type": "string", 188 | "format": "ipv6" 189 | }, 190 | "mask_length": { 191 | "description": "Mask length of the IPv6 address", 192 | "type": "integer" 193 | } 194 | } 195 | } 196 | } 197 | } 198 | } 199 | } 200 | } 201 | }, 202 | 203 | "member_list": { 204 | "title": "IXP Member List", 205 | "description": "A list of schemas representing IXP members", 206 | "type": "array", 207 | "items": 208 | { 209 | "description": "A single member entry", 210 | "type": "object", 211 | "required": ["asnum","connection_list"], 212 | "properties": { 213 | 214 | "asnum": { 215 | "description": "AS number of the network", 216 | "type": "integer" 217 | }, 218 | "member_type": { 219 | "description": "Participant type: peering, ixp, pro bono, routeserver or other", 220 | "type": "string", 221 | "enum": ["peering","ixp","routeserver","probono","other"] 222 | }, 223 | "name": { 224 | "description": "Name of the network", 225 | "type": "string" 226 | }, 227 | "url": { 228 | "description": "URL to website of the network", 229 | "type": "string", 230 | "format": "uri" 231 | }, 232 | "peering_policy": { 233 | "description": "Peering policy of the network", 234 | "type": "string" 235 | }, 236 | "peering_policy_url": { 237 | "description": "URL to the network's peering policy", 238 | "type": "string", 239 | "format": "uri" 240 | }, 241 | "member_since": { 242 | "description": "Date when the network joined the IXP", 243 | "type": "string", 244 | "format": "date-time" 245 | }, 246 | "contact_email": { 247 | "description": "List of contact email addresses of the network", 248 | "type": "array", 249 | "items": 250 | { 251 | "type": "string", 252 | "format" : "email" 253 | } 254 | }, 255 | "contact_phone": { 256 | "description": "List of contact phone numbers of the network", 257 | "type": "array", 258 | "items": 259 | { 260 | "type": "string" 261 | } 262 | }, 263 | "contact_hours": { 264 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 265 | "type": "string" 266 | }, 267 | 268 | "connection_list": { 269 | "description": "List of connections of the network at the IXP", 270 | "type": "array", 271 | "items": 272 | { 273 | "description": "A single connection entry", 274 | "type": "object", 275 | "required": ["ixp_id"], 276 | "properties": { 277 | 278 | "ixp_id": { 279 | "description": "IXP numeric identifier, persistent value free to set by the IXP, referencing the same ID as used in the ixp_list element", 280 | "type": "integer" 281 | }, 282 | "state": { 283 | "description": "State of the connection", 284 | "type": "string" 285 | }, 286 | "connected_since": { 287 | "description": "Date when the connection was activated", 288 | "type": "string", 289 | "format": "date-time" 290 | }, 291 | "if_list": { 292 | "description": "List of interfaces making up the connection", 293 | "type": "array", 294 | "items": 295 | { 296 | "description": "A single interface entry", 297 | "type": "object", 298 | "properties": { 299 | 300 | "switch_id": { 301 | "description": "Switch ID where the interface or LAG is connected, persistent value free to set by the IXP", 302 | "type": "integer" 303 | }, 304 | "if_speed": { 305 | "description": "Speed of the interface or LAG in Mb, i.e. 10G = 10000", 306 | "type": "integer" 307 | }, 308 | "if_type": { 309 | "description": "Type of the interface or LAG", 310 | "type": "string" 311 | } 312 | } 313 | } 314 | 315 | 316 | }, 317 | "vlan_list": { 318 | "type": "array", 319 | "items": 320 | { 321 | "description": "A single VLAN entry", 322 | "type": "object", 323 | "properties": { 324 | 325 | "vlan_id": { 326 | "description": "The VLAN ID this connection is placed in, persistent value free to set by the IXP", 327 | "type": "integer" 328 | }, 329 | "ipv4": { 330 | "description": "The network's IPv4 address details in this VLAN", 331 | "type": "object", 332 | "properties": { 333 | 334 | "address": { 335 | "description": "The IPv4 address", 336 | "type": "string", 337 | "format": "ipv4" 338 | }, 339 | "as_macro": { 340 | "description": "The IPv4 AS-MACRO, if applicable", 341 | "type": "string" 342 | }, 343 | "max_prefix": { 344 | "description": "The max number of prefixes on this connection for IPv4", 345 | "type": "integer" 346 | }, 347 | "routeserver": { 348 | "description": "Does this IPv4 address connect to the IXP routeserver", 349 | "type": "boolean" 350 | }, 351 | "mac_addresses": { 352 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 353 | "type": "array", 354 | "items": { 355 | "type": "string" 356 | } 357 | } 358 | } 359 | }, 360 | "ipv6": { 361 | "description": "The network's IPv6 address details in this VLAN", 362 | "type": "object", 363 | "properties": { 364 | 365 | "address": { 366 | "description": "The IPv6 address", 367 | "type": "string", 368 | "format": "ipv6" 369 | }, 370 | "as_macro": { 371 | "description": "The IPv6 AS-MACRO, if applicable", 372 | "type": "string" 373 | }, 374 | "max_prefix": { 375 | "description": "The max number of prefixes on this connection for IPv6", 376 | "type": "integer" 377 | }, 378 | "routeserver": { 379 | "description": "Does this IPv6 address connect to the IXP routeserver", 380 | "type": "boolean" 381 | }, 382 | "mac_addresses": { 383 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 384 | "type": "array", 385 | "items": { 386 | "type": "string" 387 | } 388 | } 389 | } 390 | } 391 | } 392 | } 393 | 394 | 395 | } 396 | } 397 | } 398 | 399 | } 400 | } 401 | } 402 | 403 | } 404 | } 405 | } 406 | -------------------------------------------------------------------------------- /versions/ixp-member-list-0.7.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_list", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema; this is not the version of the file within an IXP; but the schema version", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of when the data was exported", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_list": { 23 | "title": "IXP Info List", 24 | "description": "A list of schemas representing IXP information", 25 | "type": "array", 26 | "items": 27 | { 28 | "description": "A single IXP entry", 29 | "type": "object", 30 | "required": ["ixf_id","ixp_id","shortname"], 31 | "properties": { 32 | 33 | "ixp_id": { 34 | "description": "IXP numeric identifier, persistent value free to set by the IXP", 35 | "type": "integer" 36 | }, 37 | "shortname": { 38 | "description": "Short name of the IXP", 39 | "type": "string" 40 | }, 41 | "name": { 42 | "description": "Name of the IXP", 43 | "type": "string" 44 | }, 45 | "url": { 46 | "description": "Website of the IXP", 47 | "type": "string", 48 | "format": "uri" 49 | }, 50 | "stats_api": { 51 | "description": "URL to statistics API", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "country": { 56 | "description": "ISO country code where the IXP is located", 57 | "type": "string" 58 | }, 59 | "ixf_id": { 60 | "description": "IXP ID from the IX-F database", 61 | "type": "integer" 62 | }, 63 | "peeringdb_id": { 64 | "description": "PeeringDB ID of the IX - the y in: https://www.peeringdb.com/ix/y", 65 | "type": "integer" 66 | }, 67 | "support_email": { 68 | "description": "Support email address", 69 | "type": "string", 70 | "format" : "email" 71 | }, 72 | "support_phone": { 73 | "description": "Support phone number", 74 | "type": "string" 75 | }, 76 | "support_contact_hours": { 77 | "description": "Support contact hours, eg. 24/7, 8/5, etc", 78 | "type": "string" 79 | }, 80 | "emergency_email": { 81 | "description": "Emergency support email address", 82 | "type": "string", 83 | "format" : "email" 84 | }, 85 | "emergency_phone": { 86 | "description": "Emergency support phone number", 87 | "type": "string" 88 | }, 89 | "emergency_contact_hours": { 90 | "description": "Emergency support contact hours, eg. 24/7, 8/5, etc", 91 | "type": "string" 92 | }, 93 | "billing_email": { 94 | "description": "Billing email address", 95 | "type": "string", 96 | "format" : "email" 97 | }, 98 | "billing_phone": { 99 | "description": "Billing phone number", 100 | "type": "string" 101 | }, 102 | "billing_contact_hours": { 103 | "description": "Billing contact hours, eg. 24/7, 8/5, etc", 104 | "type": "string" 105 | }, 106 | "peering_policy_list": { 107 | "description": "Peering policy choices available in the member list", 108 | "type": "array", 109 | "items": 110 | { 111 | "type": "string" 112 | } 113 | }, 114 | 115 | "switch": { 116 | "description": "Switches available at the IXP", 117 | "type": "array", 118 | "items": 119 | { 120 | "type": "object", 121 | "properties": { 122 | 123 | "id": { 124 | "description": "Unique ID of the switch", 125 | "type": "integer" 126 | }, 127 | "name": { 128 | "description": "Switch name", 129 | "type": "string" 130 | }, 131 | "colo": { 132 | "description": "Colo the switch is located in", 133 | "type": "string" 134 | }, 135 | "pdb_facility_id": { 136 | "description": "Peering DB ID of the data centre", 137 | "type": "integer" 138 | }, 139 | "city": { 140 | "description": "City the switch is located in", 141 | "type": "string" 142 | }, 143 | "country": { 144 | "description": "Country the switch is located in", 145 | "type": "string" 146 | }, 147 | "manufacturer": { 148 | "description": "Free text field to indicate the manufacturer of the switch for informational purposes.", 149 | "type": "string" 150 | }, 151 | "model": { 152 | "description": "Free text field to indicate the model of the switch for informational purposes. Should not be present without manufacturer.", 153 | "type": "string" 154 | } 155 | } 156 | } 157 | }, 158 | 159 | "vlan": { 160 | "description": "VLANs available at the IXP", 161 | "type": "array", 162 | "items": 163 | { 164 | "description": "A single VLAN entry", 165 | "type": "object", 166 | "properties": { 167 | 168 | "id": { 169 | "description": "Unique ID of the VLAN", 170 | "type": "integer" 171 | }, 172 | "name": { 173 | "description": "VLAN name", 174 | "type": "string" 175 | }, 176 | "ipv4": { 177 | "description": "IPv4 details in this VLAN", 178 | "type": "object", 179 | "properties": { 180 | 181 | "prefix": { 182 | "description": "Prefix of the IPv4 address", 183 | "type": "string", 184 | "format": "ipv4" 185 | }, 186 | "mask_length": { 187 | "description": "Mask length of the IPv4 address", 188 | "type": "integer" 189 | }, 190 | "looking_glass_urls": { 191 | "description": "URLs of looking glass(es) available for this VLAN and protocol.", 192 | "type": "array", 193 | "items": { 194 | "type": "string", 195 | "format": "uri" 196 | } 197 | } 198 | } 199 | }, 200 | "ipv6": { 201 | "description": "IPv6 details in this VLAN", 202 | "type": "object", 203 | "properties": { 204 | 205 | "prefix": { 206 | "description": "Prefix of the IPv6 address", 207 | "type": "string", 208 | "format": "ipv6" 209 | }, 210 | "mask_length": { 211 | "description": "Mask length of the IPv6 address", 212 | "type": "integer" 213 | }, 214 | "looking_glass_urls": { 215 | "description": "URLs of looking glass(es) available for this VLAN and protocol.", 216 | "type": "array", 217 | "items": { 218 | "type": "string", 219 | "format": "uri" 220 | } 221 | } 222 | } 223 | } 224 | } 225 | } 226 | } 227 | } 228 | } 229 | }, 230 | 231 | "member_list": { 232 | "title": "IXP Member List", 233 | "description": "A list of schemas representing IXP members", 234 | "type": "array", 235 | "items": 236 | { 237 | "description": "A single member entry", 238 | "type": "object", 239 | "required": ["asnum","connection_list"], 240 | "properties": { 241 | 242 | "asnum": { 243 | "description": "AS number of the network", 244 | "type": "integer" 245 | }, 246 | "member_type": { 247 | "description": "Participant type: peering, ixp, pro bono, routeserver or other", 248 | "type": "string", 249 | "enum": ["peering","ixp","other"] 250 | }, 251 | "name": { 252 | "description": "Name of the network", 253 | "type": "string" 254 | }, 255 | "url": { 256 | "description": "URL to website of the network", 257 | "type": "string", 258 | "format": "uri" 259 | }, 260 | "peering_policy": { 261 | "description": "Peering policy of the network", 262 | "type": "string" 263 | }, 264 | "peering_policy_url": { 265 | "description": "URL to the network's peering policy", 266 | "type": "string", 267 | "format": "uri" 268 | }, 269 | "member_since": { 270 | "description": "Date when the network joined the IXP", 271 | "type": "string", 272 | "format": "date-time" 273 | }, 274 | "contact_email": { 275 | "description": "List of contact email addresses of the network", 276 | "type": "array", 277 | "items": 278 | { 279 | "type": "string", 280 | "format" : "email" 281 | } 282 | }, 283 | "contact_phone": { 284 | "description": "List of contact phone numbers of the network", 285 | "type": "array", 286 | "items": 287 | { 288 | "type": "string" 289 | } 290 | }, 291 | "contact_hours": { 292 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 293 | "type": "string" 294 | }, 295 | 296 | "connection_list": { 297 | "description": "List of connections of the network at the IXP", 298 | "type": "array", 299 | "items": 300 | { 301 | "description": "A single connection entry", 302 | "type": "object", 303 | "required": ["ixp_id"], 304 | "properties": { 305 | 306 | "ixp_id": { 307 | "description": "IXP numeric identifier, persistent value free to set by the IXP, referencing the same ID as used in the ixp_list element", 308 | "type": "integer" 309 | }, 310 | "state": { 311 | "description": "State of the connection", 312 | "type": "string" 313 | }, 314 | "connected_since": { 315 | "description": "Date when the connection was activated", 316 | "type": "string", 317 | "format": "date-time" 318 | }, 319 | "if_list": { 320 | "description": "List of interfaces making up the connection", 321 | "type": "array", 322 | "items": 323 | { 324 | "description": "A single interface entry", 325 | "type": "object", 326 | "properties": { 327 | 328 | "switch_id": { 329 | "description": "Switch ID where the interface or LAG is connected, persistent value free to set by the IXP", 330 | "type": "integer" 331 | }, 332 | "if_speed": { 333 | "description": "Speed of the interface or LAG in Mb, i.e. 10G = 10000", 334 | "type": "integer" 335 | }, 336 | "if_type": { 337 | "description": "Type of the interface or LAG", 338 | "type": "string" 339 | } 340 | } 341 | } 342 | 343 | 344 | }, 345 | "vlan_list": { 346 | "type": "array", 347 | "items": 348 | { 349 | "description": "A single VLAN entry", 350 | "type": "object", 351 | "properties": { 352 | 353 | "vlan_id": { 354 | "description": "The VLAN ID this connection is placed in, persistent value free to set by the IXP", 355 | "type": "integer" 356 | }, 357 | "ipv4": { 358 | "description": "The network's IPv4 address details in this VLAN", 359 | "type": "object", 360 | "properties": { 361 | 362 | "address": { 363 | "description": "The IPv4 address", 364 | "type": "string", 365 | "format": "ipv4" 366 | }, 367 | "as_macro": { 368 | "description": "The IPv4 AS-MACRO, if applicable", 369 | "type": "string" 370 | }, 371 | "max_prefix": { 372 | "description": "The max number of prefixes on this connection for IPv4", 373 | "type": "integer" 374 | }, 375 | "routeserver": { 376 | "description": "Does this IPv4 address connect to the IXP routeserver", 377 | "type": "boolean" 378 | }, 379 | "mac_addresses": { 380 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 381 | "type": "array", 382 | "items": { 383 | "type": "string" 384 | } 385 | }, 386 | "service_type": { 387 | "description": "ENUM field to indicate the service type(s) available from this connection. Defined types: 'ixrouteserver' (IX operated route server), 'ixroutecollector' (IX operated route collector)", 388 | "type": "array", 389 | "items": { 390 | "type": "string" 391 | } 392 | } 393 | } 394 | }, 395 | "ipv6": { 396 | "description": "The network's IPv6 address details in this VLAN", 397 | "type": "object", 398 | "properties": { 399 | 400 | "address": { 401 | "description": "The IPv6 address", 402 | "type": "string", 403 | "format": "ipv6" 404 | }, 405 | "as_macro": { 406 | "description": "The IPv6 AS-MACRO, if applicable", 407 | "type": "string" 408 | }, 409 | "max_prefix": { 410 | "description": "The max number of prefixes on this connection for IPv6", 411 | "type": "integer" 412 | }, 413 | "routeserver": { 414 | "description": "Does this IPv6 address connect to the IXP routeserver", 415 | "type": "boolean" 416 | }, 417 | "mac_addresses": { 418 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 419 | "type": "array", 420 | "items": { 421 | "type": "string" 422 | } 423 | }, 424 | "service_type": { 425 | "description": "ENUM field to indicate the service type(s) available from this connection. Defined types: 'ixrouteserver' (IX operated route server), 'ixroutecollector' (IX operated route collector)", 426 | "type": "array", 427 | "items": { 428 | "type": "string" 429 | } 430 | } 431 | } 432 | } 433 | } 434 | } 435 | 436 | 437 | } 438 | } 439 | } 440 | 441 | } 442 | } 443 | } 444 | 445 | } 446 | } 447 | } 448 | -------------------------------------------------------------------------------- /versions/ixp-member-list-1.0.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "IXP Member List Schema", 4 | "description": "A JSON schema representing an IXP Member List", 5 | "type": "object", 6 | "required": ["version", "timestamp", "ixp_list", "member_list"], 7 | "properties": { 8 | 9 | "version": { 10 | "title": "IXP Member List Schema Version", 11 | "description": "Version number of the schema; this is not the version of the file within an IXP; but the schema version", 12 | "type": "string" 13 | }, 14 | 15 | "timestamp": { 16 | "title": "IXP Member List Schema export timestamp", 17 | "description": "Timestamp of when the data was exported", 18 | "type": "string", 19 | "format": "date-time" 20 | }, 21 | 22 | "ixp_list": { 23 | "title": "IXP Info List", 24 | "description": "A list of schemas representing IXP information", 25 | "type": "array", 26 | "items": 27 | { 28 | "description": "A single IXP entry", 29 | "type": "object", 30 | "required": ["ixf_id","ixp_id","shortname"], 31 | "properties": { 32 | 33 | "ixp_id": { 34 | "description": "IXP numeric identifier, persistent value free to set by the IXP", 35 | "type": "integer" 36 | }, 37 | "shortname": { 38 | "description": "Short name of the IXP", 39 | "type": "string" 40 | }, 41 | "name": { 42 | "description": "Name of the IXP", 43 | "type": "string" 44 | }, 45 | "url": { 46 | "description": "Website of the IXP", 47 | "type": "string", 48 | "format": "uri" 49 | }, 50 | "stats_api": { 51 | "description": "URL to statistics API", 52 | "type": "string", 53 | "format": "uri" 54 | }, 55 | "country": { 56 | "description": "ISO country code where the IXP is located", 57 | "type": "string" 58 | }, 59 | "ixf_id": { 60 | "description": "IXP ID from the IX-F database", 61 | "type": "integer" 62 | }, 63 | "peeringdb_id": { 64 | "description": "PeeringDB ID of the IX - the y in: https://www.peeringdb.com/ix/y", 65 | "type": "integer" 66 | }, 67 | "support_email": { 68 | "description": "Support email address", 69 | "type": "string", 70 | "format" : "email" 71 | }, 72 | "support_phone": { 73 | "description": "Support phone number", 74 | "type": "string" 75 | }, 76 | "support_contact_hours": { 77 | "description": "Support contact hours, eg. 24/7, 8/5, etc", 78 | "type": "string" 79 | }, 80 | "emergency_email": { 81 | "description": "Emergency support email address", 82 | "type": "string", 83 | "format" : "email" 84 | }, 85 | "emergency_phone": { 86 | "description": "Emergency support phone number", 87 | "type": "string" 88 | }, 89 | "emergency_contact_hours": { 90 | "description": "Emergency support contact hours, eg. 24/7, 8/5, etc", 91 | "type": "string" 92 | }, 93 | "billing_email": { 94 | "description": "Billing email address", 95 | "type": "string", 96 | "format" : "email" 97 | }, 98 | "billing_phone": { 99 | "description": "Billing phone number", 100 | "type": "string" 101 | }, 102 | "billing_contact_hours": { 103 | "description": "Billing contact hours, eg. 24/7, 8/5, etc", 104 | "type": "string" 105 | }, 106 | "peering_policy_list": { 107 | "description": "Peering policy choices available in the member list", 108 | "type": "array", 109 | "items": 110 | { 111 | "type": "string" 112 | } 113 | }, 114 | 115 | "switch": { 116 | "description": "Switches available at the IXP", 117 | "type": "array", 118 | "items": 119 | { 120 | "type": "object", 121 | "properties": { 122 | 123 | "id": { 124 | "description": "Unique ID of the switch", 125 | "type": "integer" 126 | }, 127 | "name": { 128 | "description": "Switch name", 129 | "type": "string" 130 | }, 131 | "colo": { 132 | "description": "Colo the switch is located in", 133 | "type": "string" 134 | }, 135 | "pdb_facility_id": { 136 | "description": "Peering DB ID of the data centre", 137 | "type": "integer" 138 | }, 139 | "city": { 140 | "description": "City the switch is located in", 141 | "type": "string" 142 | }, 143 | "country": { 144 | "description": "Country the switch is located in", 145 | "type": "string" 146 | }, 147 | "manufacturer": { 148 | "description": "Free text field to indicate the manufacturer of the switch for informational purposes.", 149 | "type": "string" 150 | }, 151 | "model": { 152 | "description": "Free text field to indicate the model of the switch for informational purposes. Should not be present without manufacturer.", 153 | "type": "string" 154 | }, 155 | "software": { 156 | "description": "Free text field to indicate the software of the switch for informational purposes.", 157 | "type": "string" 158 | } 159 | } 160 | } 161 | }, 162 | 163 | "vlan": { 164 | "description": "VLANs available at the IXP", 165 | "type": "array", 166 | "items": 167 | { 168 | "description": "A single VLAN entry", 169 | "type": "object", 170 | "properties": { 171 | 172 | "id": { 173 | "description": "Unique ID of the VLAN", 174 | "type": "integer" 175 | }, 176 | "name": { 177 | "description": "VLAN name", 178 | "type": "string" 179 | }, 180 | "ipv4": { 181 | "description": "IPv4 details in this VLAN", 182 | "type": "object", 183 | "properties": { 184 | 185 | "prefix": { 186 | "description": "Prefix of the IPv4 address", 187 | "type": "string", 188 | "format": "ipv4" 189 | }, 190 | "mask_length": { 191 | "description": "Mask length of the IPv4 address", 192 | "type": "integer" 193 | }, 194 | "looking_glass_urls": { 195 | "description": "URLs of looking glass(es) available for this VLAN and protocol.", 196 | "type": "array", 197 | "items": { 198 | "type": "string", 199 | "format": "uri" 200 | } 201 | } 202 | } 203 | }, 204 | "ipv6": { 205 | "description": "IPv6 details in this VLAN", 206 | "type": "object", 207 | "properties": { 208 | 209 | "prefix": { 210 | "description": "Prefix of the IPv6 address", 211 | "type": "string", 212 | "format": "ipv6" 213 | }, 214 | "mask_length": { 215 | "description": "Mask length of the IPv6 address", 216 | "type": "integer" 217 | }, 218 | "looking_glass_urls": { 219 | "description": "URLs of looking glass(es) available for this VLAN and protocol.", 220 | "type": "array", 221 | "items": { 222 | "type": "string", 223 | "format": "uri" 224 | } 225 | } 226 | } 227 | } 228 | } 229 | } 230 | } 231 | } 232 | } 233 | }, 234 | 235 | "member_list": { 236 | "title": "IXP Member List", 237 | "description": "A list of schemas representing IXP members", 238 | "type": "array", 239 | "items": 240 | { 241 | "description": "A single member entry", 242 | "type": "object", 243 | "required": ["asnum","connection_list"], 244 | "properties": { 245 | 246 | "asnum": { 247 | "description": "AS number of the network", 248 | "type": "integer" 249 | }, 250 | "member_type": { 251 | "description": "Participant type: peering, ixp or other", 252 | "type": "string", 253 | "enum": ["peering","ixp","other"] 254 | }, 255 | "name": { 256 | "description": "Name of the network", 257 | "type": "string" 258 | }, 259 | "url": { 260 | "description": "URL to website of the network", 261 | "type": "string", 262 | "format": "uri" 263 | }, 264 | "peering_policy": { 265 | "description": "Peering policy of the network", 266 | "type": "string" 267 | }, 268 | "peering_policy_url": { 269 | "description": "URL to the network's peering policy", 270 | "type": "string", 271 | "format": "uri" 272 | }, 273 | "member_since": { 274 | "description": "Date when the network joined the IXP", 275 | "type": "string", 276 | "format": "date-time" 277 | }, 278 | "contact_email": { 279 | "description": "List of contact email addresses of the network", 280 | "type": "array", 281 | "items": 282 | { 283 | "type": "string", 284 | "format" : "email" 285 | } 286 | }, 287 | "contact_phone": { 288 | "description": "List of contact phone numbers of the network", 289 | "type": "array", 290 | "items": 291 | { 292 | "type": "string" 293 | } 294 | }, 295 | "contact_hours": { 296 | "description": "Network contact hours, eg. 24/7, 8/5, etc", 297 | "type": "string" 298 | }, 299 | 300 | "connection_list": { 301 | "description": "List of connections of the network at the IXP", 302 | "type": "array", 303 | "items": 304 | { 305 | "description": "A single connection entry", 306 | "type": "object", 307 | "required": ["ixp_id"], 308 | "properties": { 309 | 310 | "ixp_id": { 311 | "description": "IXP numeric identifier, persistent value free to set by the IXP, referencing the same ID as used in the ixp_list element", 312 | "type": "integer" 313 | }, 314 | "state": { 315 | "description": "State of the connection", 316 | "type": "string" 317 | }, 318 | "connected_since": { 319 | "description": "Date when the connection was activated", 320 | "type": "string", 321 | "format": "date-time" 322 | }, 323 | "if_list": { 324 | "description": "List of interfaces making up the connection", 325 | "type": "array", 326 | "items": 327 | { 328 | "description": "A single interface entry", 329 | "type": "object", 330 | "properties": { 331 | 332 | "switch_id": { 333 | "description": "Switch ID where the interface or LAG is connected, persistent value free to set by the IXP", 334 | "type": "integer" 335 | }, 336 | "if_speed": { 337 | "description": "Speed of the interface or LAG in Mb, i.e. 10G = 10000", 338 | "type": "integer" 339 | }, 340 | "if_type": { 341 | "description": "Type of the interface or LAG", 342 | "type": "string" 343 | } 344 | } 345 | } 346 | 347 | 348 | }, 349 | "vlan_list": { 350 | "type": "array", 351 | "items": 352 | { 353 | "description": "A single VLAN entry", 354 | "type": "object", 355 | "properties": { 356 | 357 | "vlan_id": { 358 | "description": "The VLAN ID this connection is placed in, persistent value free to set by the IXP", 359 | "type": "integer" 360 | }, 361 | "ipv4": { 362 | "description": "The network's IPv4 address details in this VLAN", 363 | "type": "object", 364 | "properties": { 365 | 366 | "address": { 367 | "description": "The IPv4 address", 368 | "type": "string", 369 | "format": "ipv4" 370 | }, 371 | "as_macro": { 372 | "description": "The IPv4 AS-MACRO, if applicable", 373 | "type": "string" 374 | }, 375 | "max_prefix": { 376 | "description": "The max number of prefixes on this connection for IPv4", 377 | "type": "integer" 378 | }, 379 | "routeserver": { 380 | "description": "Does this IPv4 address connect to the IXP routeserver", 381 | "type": "boolean" 382 | }, 383 | "mac_addresses": { 384 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 385 | "type": "array", 386 | "items": { 387 | "type": "string" 388 | } 389 | }, 390 | "services": { 391 | "description": "Array of IX operated service(s) available from this connection.", 392 | "type": "array", 393 | "items": { 394 | "type": "object", 395 | "properties": { 396 | "type": { 397 | "description": "The IX operated service available from this connection.", 398 | "type": "string", 399 | "enum": ["ixroutecollector", "ixrouteserver"] 400 | }, 401 | "os": { 402 | "description": "Free text field to indicate the operating system of the route server for informational purposes.", 403 | "type": "string" 404 | }, 405 | "os_version": { 406 | "description": "Free text field to indicate the operating system version of the route server for informational purposes. Should not be present without os.", 407 | "type": "string" 408 | }, 409 | "daemon": { 410 | "description": "Free text field to indicate the BGP software daemon that provides the route server for informational purposes.", 411 | "type": "string" 412 | }, 413 | "daemon_version": { 414 | "description": "Free text field to indicate the BGP software daemon version that provides the route server for informational purposes. Should not be present without daemon.", 415 | "type": "string" 416 | } 417 | } 418 | } 419 | } 420 | } 421 | }, 422 | "ipv6": { 423 | "description": "The network's IPv6 address details in this VLAN", 424 | "type": "object", 425 | "properties": { 426 | 427 | "address": { 428 | "description": "The IPv6 address", 429 | "type": "string", 430 | "format": "ipv6" 431 | }, 432 | "as_macro": { 433 | "description": "The IPv6 AS-MACRO, if applicable", 434 | "type": "string" 435 | }, 436 | "max_prefix": { 437 | "description": "The max number of prefixes on this connection for IPv6", 438 | "type": "integer" 439 | }, 440 | "routeserver": { 441 | "description": "Does this IPv6 address connect to the IXP routeserver", 442 | "type": "boolean" 443 | }, 444 | "mac_addresses": { 445 | "description": "MAC address of the member interface (format: lowercase string xx:xx:xx:xx:xx:xx)", 446 | "type": "array", 447 | "items": { 448 | "type": "string" 449 | } 450 | }, 451 | "services": { 452 | "description": "Array of IX operated service(s) available from this connection.", 453 | "type": "array", 454 | "items": { 455 | "type": "object", 456 | "properties": { 457 | "type": { 458 | "description": "The IX operated service available from this connection.", 459 | "type": "string", 460 | "enum": ["ixroutecollector", "ixrouteserver"] 461 | }, 462 | "os": { 463 | "description": "Free text field to indicate the operating system of the route server for informational purposes.", 464 | "type": "string" 465 | }, 466 | "os_version": { 467 | "description": "Free text field to indicate the operating system version of the route server for informational purposes. Should not be present without os.", 468 | "type": "string" 469 | }, 470 | "daemon": { 471 | "description": "Free text field to indicate the BGP software daemon that provides the route server for informational purposes.", 472 | "type": "string" 473 | }, 474 | "daemon_version": { 475 | "description": "Free text field to indicate the BGP software daemon version that provides the route server for informational purposes. Should not be present without daemon.", 476 | "type": "string" 477 | } 478 | } 479 | } 480 | } 481 | } 482 | } 483 | } 484 | } 485 | 486 | 487 | } 488 | } 489 | } 490 | 491 | } 492 | } 493 | } 494 | 495 | } 496 | } 497 | } 498 | --------------------------------------------------------------------------------