Merge "bgpwtf/cccampix/peeringdb: allow multiple routers per peer"
diff --git a/bgpwtf/cccampix/peeringdb/main.go b/bgpwtf/cccampix/peeringdb/main.go
index fa11651..a7f0199 100644
--- a/bgpwtf/cccampix/peeringdb/main.go
+++ b/bgpwtf/cccampix/peeringdb/main.go
@@ -60,19 +60,36 @@
 		netidsNet[net.ID] = &net
 	}
 
+	// Make unique ASNs.
+	asns := make(map[int64]*pb.PeeringDBMember)
+
+	for _, netixlan := range js.Data {
+		member, ok := asns[netixlan.ASN]
+		if !ok {
+			asns[netixlan.ASN] = &pb.PeeringDBMember{
+				Asn:     netixlan.ASN,
+				Name:    netidsNet[netixlan.NetID].Name,
+				Routers: []*pb.PeeringDBMember_Router{},
+			}
+			member = asns[netixlan.ASN]
+		}
+
+		member.Routers = append(member.Routers, &pb.PeeringDBMember_Router{
+			Ipv4: netixlan.IPv4,
+			Ipv6: netixlan.IPv6,
+		})
+	}
+
 	// Build joined response.
 
 	res := &pb.GetIXMembersResponse{
-		Members: make([]*pb.GetIXMembersResponse_Member, len(js.Data)),
+		Members: make([]*pb.PeeringDBMember, len(asns)),
 	}
 
-	for i, netixlan := range js.Data {
-		res.Members[i] = &pb.GetIXMembersResponse_Member{
-			Asn:  netixlan.ASN,
-			Ipv4: netixlan.IPv4,
-			Ipv6: netixlan.IPv6,
-			Name: netidsNet[netixlan.NetID].Name,
-		}
+	i = 0
+	for _, member := range asns {
+		res.Members[i] = member
+		i += 1
 	}
 
 	return res, nil
diff --git a/bgpwtf/cccampix/proto/ix.proto b/bgpwtf/cccampix/proto/ix.proto
index 73bc4d1..c938386 100644
--- a/bgpwtf/cccampix/proto/ix.proto
+++ b/bgpwtf/cccampix/proto/ix.proto
@@ -6,6 +6,21 @@
     int64 id = 1;
 }
 
+message PeeringDBMember {
+    int64 asn = 1;
+    // AS/network name.
+    string name = 2;
+
+    message Router {
+        // Per PeeringDB, at least one of the following two address families
+        // will be set.
+        string ipv4 = 1;
+        string ipv6 = 2;
+    }
+    repeated Router routers = 3;
+}
+
+
 message GetIXMembersResponse {
     message Member {
         int64 asn = 1;