Skip to content

Commit 4b67b33

Browse files
authored
Adds public IP of LB to localIPs slice (#55)
* Adds public IP of LB to localIPs slice Virtual machines will be part of managed instance groups, which sit behind a pass-through TCP load balancer. In such cases, packets arriving to the machine from the load balancer will have a destination address of the load balancer's public IP, which is not a local address on the machine. Without these changes uuid-annotator will refuse to annoate a connection, since it doesn't recognize either the Src of Dest IP address as being its own (annotate.FindDirection() fails). These changes cause siteannotator.New() to append the public IP address from siteinfo to localIPs if it is a virtual machine. * Fixes a typo in a comment
1 parent 889e676 commit 4b67b33

File tree

4 files changed

+82
-22
lines changed

4 files changed

+82
-22
lines changed

main.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ func main() {
102102
localAddrs, err := net.InterfaceAddrs()
103103
rtx.Must(err, "Could not read local addresses")
104104
localIPs := findLocalIPs(localAddrs)
105+
106+
// Load the siteinfo annotations for "site" specific metadata. Additionally,
107+
// if this is a virtual site, New() will append the public IP of the
108+
// managed instance group's load balancer to localIPs. If uuid-annotator
109+
// does not know about the public IP of the load balancer, then it will fail
110+
// to annotate anything because it doesn't recognize its own public address
111+
// in either the Src or Dest of incoming tcp-info events.
112+
js, err := content.FromURL(mainCtx, siteinfo.URL)
113+
rtx.Must(err, "Could not load siteinfo URL")
114+
site, localIPs := siteannotator.New(mainCtx, mlabHostname, js, localIPs)
115+
105116
p, err := content.FromURL(mainCtx, maxmindurl.URL)
106117
rtx.Must(err, "Could not get maxmind data from url")
107118
geo := geoannotator.New(mainCtx, p, localIPs)
@@ -132,10 +143,6 @@ func main() {
132143
}()
133144

134145
if *eventsocket.Filename != "" {
135-
// Load the siteinfo annotations for "site" specific metadata.
136-
js, err := content.FromURL(mainCtx, siteinfo.URL)
137-
rtx.Must(err, "Could not load siteinfo URL")
138-
site := siteannotator.New(mainCtx, mlabHostname, js, localIPs)
139146

140147
// Generate .json files for every UUID discovered.
141148
h := handler.New(*datadir, *eventbuffersize, []annotator.Annotator{geo, asn, site})

siteannotator/server.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ type siteAnnotator struct {
3030
var ErrHostnameNotFound = errors.New("hostname not found")
3131

3232
// New makes a new server Annotator using metadata from siteinfo JSON.
33-
func New(ctx context.Context, hostname string, js content.Provider, localIPs []net.IP) annotator.Annotator {
33+
func New(ctx context.Context, hostname string, js content.Provider, localIPs []net.IP) (annotator.Annotator, []net.IP) {
3434
g := &siteAnnotator{
3535
siteinfoSource: js,
3636
hostname: hostname,
37-
localIPs: localIPs,
3837
}
3938
var err error
40-
g.server, err = g.load(ctx)
39+
g.server, localIPs, err = g.load(ctx, localIPs)
40+
g.localIPs = localIPs
4141
rtx.Must(err, "Could not load annotation db")
42-
return g
42+
return g, localIPs
4343
}
4444

4545
// Annotate assigns the server geolocation and ASN metadata.
@@ -109,22 +109,34 @@ func parseCIDR(v4, v6 string) (net.IPNet, net.IPNet, error) {
109109
}
110110

111111
// load unconditionally loads siteinfo dataset and returns them.
112-
func (g *siteAnnotator) load(ctx context.Context) (*annotator.ServerAnnotations, error) {
112+
func (g *siteAnnotator) load(ctx context.Context, localIPs []net.IP) (*annotator.ServerAnnotations, []net.IP, error) {
113113
js, err := g.siteinfoSource.Get(ctx)
114114
if err != nil {
115-
return nil, err
115+
return nil, nil, err
116116
}
117117
var s map[string]siteinfoAnnotation
118118
err = json.Unmarshal(js, &s)
119119
if err != nil {
120-
return nil, err
120+
return nil, nil, err
121121
}
122122
if v, ok := s[g.hostname]; ok {
123123
g.v4, g.v6, err = parseCIDR(v.Network.IPv4, v.Network.IPv6)
124124
if err != nil {
125-
return nil, err
125+
return nil, nil, err
126126
}
127-
return &v.Annotation, nil
127+
// If this is a virtual site, append the site's public IP address to
128+
// localIPs. The public address of the load balancer is not known on any
129+
// interface on the machine. Without adding it to localIPs,
130+
// uuid-annotator will fail to recognize its own public address in
131+
// either the Src or Dest fields of incoming tcp-info events, and will
132+
// fail to annotate anything.
133+
if v.Type == "virtual" {
134+
// Ignore IPNet and error, since parseCIDR() above has already
135+
// validated the IP addresses.
136+
ip, _, _ := net.ParseCIDR(v.Network.IPv4)
137+
localIPs = append(localIPs, ip)
138+
}
139+
return &v.Annotation, localIPs, nil
128140
}
129-
return nil, ErrHostnameNotFound
141+
return nil, nil, ErrHostnameNotFound
130142
}

siteannotator/server_test.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"net"
77
"net/url"
8+
"reflect"
89
"strings"
910
"testing"
1011

@@ -188,7 +189,7 @@ func TestNew(t *testing.T) {
188189
t.Run(tt.name, func(t *testing.T) {
189190
setUp()
190191
ctx := context.Background()
191-
g := New(ctx, tt.hostname, *tt.provider, tt.localIPs)
192+
g, _ := New(ctx, tt.hostname, *tt.provider, tt.localIPs)
192193
ann := annotator.Annotations{}
193194
if err := g.Annotate(tt.ID, &ann); (err != nil) != tt.wantErr {
194195
t.Errorf("srvannotator.Annotate() error = %v, wantErr %v", err, tt.wantErr)
@@ -201,13 +202,14 @@ func TestNew(t *testing.T) {
201202
}
202203
func Test_srvannotator_load(t *testing.T) {
203204
var bad content.Provider
205+
var testLocalIPs []net.IP = []net.IP{net.ParseIP("10.0.0.1")}
204206
tests := []struct {
205-
name string
206-
provider *content.Provider
207-
hostname string
208-
ID *inetdiag.SockID
209-
want *annotator.ServerAnnotations
210-
wantErr bool
207+
name string
208+
provider *content.Provider
209+
hostname string
210+
want *annotator.ServerAnnotations
211+
wantLocalIPs []net.IP
212+
wantErr bool
211213
}{
212214
{
213215
name: "success",
@@ -231,6 +233,7 @@ func Test_srvannotator_load(t *testing.T) {
231233
},
232234
},
233235
},
236+
wantLocalIPs: testLocalIPs,
234237
},
235238
{
236239
name: "success-project-flat-name",
@@ -254,6 +257,7 @@ func Test_srvannotator_load(t *testing.T) {
254257
},
255258
},
256259
},
260+
wantLocalIPs: testLocalIPs,
257261
},
258262
{
259263
name: "success-no-six",
@@ -269,6 +273,23 @@ func Test_srvannotator_load(t *testing.T) {
269273
ASName: "TATA COMMUNICATIONS (AMERICA) INC",
270274
},
271275
},
276+
wantLocalIPs: testLocalIPs,
277+
},
278+
{
279+
name: "success-append-localips",
280+
provider: &localRawfile,
281+
hostname: "mlab1-six06.mlab-sandbox.measurement-lab.org",
282+
want: &annotator.ServerAnnotations{
283+
Site: "six06",
284+
Machine: "mlab1",
285+
Geo: &annotator.Geolocation{
286+
City: "New York",
287+
},
288+
Network: &annotator.Network{
289+
ASName: "TATA COMMUNICATIONS (AMERICA) INC",
290+
},
291+
},
292+
wantLocalIPs: append(testLocalIPs, net.ParseIP("64.86.148.129")),
272293
},
273294
{
274295
name: "error-bad-ipv4",
@@ -322,7 +343,10 @@ func Test_srvannotator_load(t *testing.T) {
322343
hostname: tt.hostname,
323344
}
324345
ctx := context.Background()
325-
an, err := g.load(ctx)
346+
an, localIPs, err := g.load(ctx, testLocalIPs)
347+
if !reflect.DeepEqual(localIPs, tt.wantLocalIPs) {
348+
t.Errorf("srvannotator.load() want localIPs %v, got %v", tt.wantLocalIPs, localIPs)
349+
}
326350
if (err != nil) != tt.wantErr {
327351
t.Errorf("srvannotator.Annotate() error = %v, wantErr %v", err, tt.wantErr)
328352
}

testdata/annotations.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,23 @@
4646
},
4747
"Type": "virtual"
4848
},
49+
"mlab1-six06.mlab-sandbox.measurement-lab.org": {
50+
"Annotation": {
51+
"Geo": {
52+
"City": "New York"
53+
},
54+
"Machine": "mlab1",
55+
"Network": {
56+
"ASName": "TATA COMMUNICATIONS (AMERICA) INC"
57+
},
58+
"Site": "six06"
59+
},
60+
"Network": {
61+
"IPv4": "64.86.148.129/32",
62+
"IPv6": "2001:5a0:4300::/64"
63+
},
64+
"Type": "virtual"
65+
},
4966
"mlab1-six01.mlab-sandbox.measurement-lab.org": {
5067
"Annotation": {
5168
"Geo": {

0 commit comments

Comments
 (0)