-
Notifications
You must be signed in to change notification settings - Fork 162
/
path.go
153 lines (133 loc) · 4.45 KB
/
path.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2019 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package snet
import (
"crypto/sha256"
"encoding/binary"
"fmt"
"net"
"time"
"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/spath"
)
// MaxSegTTL is the maximum expiry for a path segment. It's one day in seconds.
const MaxSegTTL = 24 * 60 * 60
// Path is an abstract representation of a path. Most applications do not need
// access to the raw internals.
//
// An empty path is a special kind of path that can be used for intra-AS
// traffic. Empty paths are valid return values for certain route calls (e.g.,
// if the source and destination ASes match, or if a router was configured
// without a source of paths). An empty path only contains a Destination value,
// all other values are zero values.
type Path interface {
// UnderlayNextHop returns the address:port pair of a local-AS underlay
// speaker. Usually, this is a border router that will forward the traffic.
UnderlayNextHop() *net.UDPAddr
// Path returns a raw (data-plane compatible) representation of the path.
Path() spath.Path
// Interfaces returns a list of interfaces on the path. If the list is not
// available the result is nil.
// XXX(matzf): move this to PathMetadata
Interfaces() []PathInterface
// Destination is the AS the path points to. Empty paths return the local
// AS of the router that created them.
Destination() addr.IA
// Metadata returns supplementary information about this path.
// Returns nil if the metadata is not available.
Metadata() PathMetadata
// Copy create a copy of the path.
Copy() Path
}
// PathInterface is an interface of the path.
type PathInterface struct {
// ID is the ID of the interface.
ID common.IFIDType
// IA is the ISD AS identifier of the interface.
IA addr.IA
}
func (iface PathInterface) String() string {
return fmt.Sprintf("%s#%d", iface.IA, iface.ID)
}
// PathMetadata contains supplementary information about a path.
// XXX(matzf): change this to a struct type
type PathMetadata interface {
// MTU returns the MTU of the path.
MTU() uint16
// Expiry returns the expiration time of the path.
Expiry() time.Time
}
type PathFingerprint string
func (pf PathFingerprint) String() string {
return common.RawBytes(pf).String()
}
type Fingerprinter interface {
Interfaces() []PathInterface
}
// Fingerprint uniquely identifies the path based on the sequence of
// ASes and BRs, i.e. by its PathInterfaces.
// Other metadata, such as MTU or NextHop have no effect on the fingerprint.
// Returns empty string for paths where the interfaces list is not available.
func Fingerprint(path Fingerprinter) PathFingerprint {
interfaces := path.Interfaces()
if len(interfaces) == 0 {
return ""
}
h := sha256.New()
for _, intf := range interfaces {
binary.Write(h, binary.BigEndian, intf.IA.IAInt())
binary.Write(h, binary.BigEndian, intf.ID)
}
return PathFingerprint(h.Sum(nil))
}
// partialPath is a path object with incomplete metadata. It is used as a
// temporary solution where a full path cannot be reconstituted from other
// objects, notably snet.UDPAddr and snet.SVCAddr.
type partialPath struct {
spath spath.Path
underlay *net.UDPAddr
destination addr.IA
}
func (p *partialPath) UnderlayNextHop() *net.UDPAddr {
return p.underlay
}
func (p *partialPath) Path() spath.Path {
return spath.Path{
Raw: append(p.spath.Raw[:0:0], p.spath.Raw...),
Type: p.spath.Type,
}
}
func (p *partialPath) Interfaces() []PathInterface {
return nil
}
func (p *partialPath) Destination() addr.IA {
return p.destination
}
func (p *partialPath) Metadata() PathMetadata {
return nil
}
func (p *partialPath) Copy() Path {
if p == nil {
return nil
}
return &partialPath{
spath: p.Path(),
underlay: CopyUDPAddr(p.underlay),
destination: p.destination,
}
}
func (p *partialPath) String() string {
return fmt.Sprintf("{spath: %s, underlay: %s, dest: %s}", p.spath, p.underlay, p.destination)
}