aboutsummaryrefslogtreecommitdiff
path: root/six/participant_builder.go
diff options
context:
space:
mode:
Diffstat (limited to 'six/participant_builder.go')
-rw-r--r--six/participant_builder.go113
1 files changed, 113 insertions, 0 deletions
diff --git a/six/participant_builder.go b/six/participant_builder.go
new file mode 100644
index 0000000..f18a6d1
--- /dev/null
+++ b/six/participant_builder.go
@@ -0,0 +1,113 @@
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (C) 2020 Michael Crute <mike@crute.us>. All rights reserved.
3//
4// Use of this source code is governed by a license that can be found in the
5// LICENSE file.
6
7package six
8
9import (
10 "fmt"
11 "strings"
12)
13
14// Create a new SIXParticipant struct from a map of data that was parsed from
15// the participant CSV file. This assumes the column headers from that CSV file
16// so it will not work with the other data formats avaiable.
17//
18// This uses the CSV file because it's both the most rich source of data and
19// the easiest to parse.
20func NewSIXParticipantFromData(d map[string]string) *SIXParticipant {
21 r := &SIXParticipant{
22 Organization: d["Organization"],
23 URL: d["URL"],
24 ASN: mustParseInt(d["ASN"]),
25 Speed: mustParseInt(d["Speed"]),
26 Switch: d["Switch"],
27 Contact: d["Contact"],
28 Comment: d["Comment"],
29 IsConnected: parseYesNo(d["Conn?"]),
30 IsVoter: parseYesNo(d["Voter?"]),
31 Update: mustParseTime(d["Update"]),
32 Options: strings.Split(d["Options"], " "),
33 PeeringPolicy: d["Policy"],
34 ROACount: mustParseInt(d["rpki:roa"]),
35 PeeringDBPrefixCountv4: mustParseInt(d["pdb:v4"]),
36 PeeringDBPrefixCountv6: mustParseInt(d["pdb:v6"]),
37 Addresses: Addresses{
38 IPv4: parseIPNetFromCIDR(d["IPv4"]),
39 IPv6: parseIPNetFromCIDR(d["IPv6"]),
40 },
41 IRRv4: IRRData{
42 PrefixCount: mustParseInt(d["irr:p4"]),
43 ASNCount: mustParseInt(d["irr:a4"]),
44 ASSetCount: mustParseInt(d["irr:ap4"]),
45 },
46 IRRv6: IRRData{
47 PrefixCount: mustParseInt(d["irr:p6"]),
48 ASNCount: mustParseInt(d["irr:a6"]),
49 ASSetCount: mustParseInt(d["irr:ap6"]),
50 },
51 RouteServer2: getRSData(2, d),
52 RouteServer3: getRSData(3, d),
53 }
54
55 // Not all participants use the MTU9k VLAN
56 ja4 := parseIPNetFromCIDR(d["Jumbo IPv4"])
57 ja6 := parseIPNetFromCIDR(d["Jumbo IPv6"])
58 if ja4 != nil && ja6 != nil {
59 r.JumboAddresses = &Addresses{IPv4: ja4, IPv6: ja6}
60 }
61
62 return r
63}
64
65func getRSData(server int, d map[string]string) *RouteServer {
66 // Extract all the data and determine if it's all empty strings, if so then
67 // the participant isn't using the route server. If any data is not empty
68 // then they are. Do integer conversion afterward to avoid ambiguity about
69 // zero vs empty string.
70 pd := []string{
71 d[fmt.Sprintf("rs%d:v4", server)],
72 d[fmt.Sprintf("err%d:v4", server)],
73 d[fmt.Sprintf("xerr%d:v4", server)],
74 d[fmt.Sprintf("rs%d:v6", server)],
75 d[fmt.Sprintf("err%d:v6", server)],
76 d[fmt.Sprintf("xerr%d:v6", server)],
77 d[fmt.Sprintf("rs%d:v4j", server)],
78 d[fmt.Sprintf("err%d:v4j", server)],
79 d[fmt.Sprintf("xerr%d:v4j", server)],
80 d[fmt.Sprintf("rs%d:v6j", server)],
81 d[fmt.Sprintf("err%d:v6j", server)],
82 d[fmt.Sprintf("xerr%d:v6j", server)],
83 }
84
85 if allEmpty(pd) {
86 return nil
87 }
88
89 return &RouteServer{
90 Number: server,
91 asn: mustParseInt(d["ASN"]),
92 IPv4: RouteServerStats{
93 Prefixes: mustParseInt(pd[0]),
94 Errors: mustParseInt(pd[1]),
95 TransitErrors: mustParseInt(pd[2]),
96 },
97 IPv6: RouteServerStats{
98 Prefixes: mustParseInt(pd[3]),
99 Errors: mustParseInt(pd[4]),
100 TransitErrors: mustParseInt(pd[5]),
101 },
102 IPv4Jumbo: RouteServerStats{
103 Prefixes: mustParseInt(pd[6]),
104 Errors: mustParseInt(pd[7]),
105 TransitErrors: mustParseInt(pd[8]),
106 },
107 IPv6Jumbo: RouteServerStats{
108 Prefixes: mustParseInt(pd[9]),
109 Errors: mustParseInt(pd[10]),
110 TransitErrors: mustParseInt(pd[11]),
111 },
112 }
113}