/
area.go
211 lines (183 loc) · 6.63 KB
/
area.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package ospf
import (
"context"
"net"
"sync"
"time"
"github.com/povsister/dns-circuit/ospf/packet"
)
type AreaConfig struct {
Instance *Instance
AreaId uint32
Address *AreaAddress
Options packet.BitOption
}
func NewArea(ctx context.Context, c *AreaConfig) *Area {
a := &Area{
ctx: ctx,
ins: c.Instance,
AreaId: c.AreaId,
Addresses: []*AreaAddress{c.Address},
RouterLSAs: make(map[packet.LSAIdentity]*LSDBRouterItem),
NetworkLSAs: make(map[packet.LSAIdentity]*LSDBNetworkItem),
SummaryLSAs: make(map[packet.LSAIdentity]*LSDBSummaryItem),
Options: c.Options,
ExternalRoutingCapability: c.Options.IsBitSet(packet.CapabilityEbit),
TransitCapability: true,
}
return a
}
func (a *Area) AddInterface(c *InterfaceConfig) {
i := NewInterface(context.Background(), c)
i.Area = a
a.Interfaces = append(a.Interfaces, i)
a.updateLSDBWhenInterfaceAdd(i)
}
type Area struct {
ctx context.Context
wg sync.WaitGroup
ins *Instance
Options packet.BitOption
// A 32-bit number identifying the area. The Area ID of 0.0.0.0 is
// reserved for the backbone.
AreaId uint32
// List of area address ranges
// In order to aggregate routing information at area boundaries,
// area address ranges can be employed. Each address range is
// specified by an [address,mask] pair and a status indication of
// either Advertise or DoNotAdvertise
Addresses []*AreaAddress
// This router's interfaces connecting to the area. A router
// interface belongs to one and only one area (or the backbone).
// For the backbone area this list includes all the virtual links.
// A virtual link is identified by the Router ID of its other
// endpoint; its cost is the cost of the shortest intra-area path
// through the Transit area that exists between the two routers.
Interfaces []*Interface
// A router has a separate link state database for every area to
// which it belongs. All routers belonging to the same area have
// identical link state databases for the area.
// Link-state database is composed of router-LSAs, network-LSAs and
// summary-LSAs (all listed in the area data structure). In
// addition, external routes (AS-external-LSAs) are included in all
// non-stub area databases (see Section 3.6).
lsDbRw sync.RWMutex
// A router-LSA is generated by each router in the area. It
// describes the state of the router's interfaces to the area.
RouterLSAs map[packet.LSAIdentity]*LSDBRouterItem
// One network-LSA is generated for each transit broadcast and NBMA
// network in the area. A network-LSA describes the set of routers
// currently connected to the network.
NetworkLSAs map[packet.LSAIdentity]*LSDBNetworkItem
// Summary-LSAs originate from the area's area border routers.
// They describe routes to destinations internal to the Autonomous
// System, yet external to the area (i.e., inter-area
// destinations).
SummaryLSAs map[packet.LSAIdentity]*LSDBSummaryItem
pendingWrappingLSAsRw sync.RWMutex
// LSAs that reaches MaxSequenceNumber must be flushed out from the
// routing domain. Then install and re-flooded into domain.
pendingWrappingLSAs []packet.LSAdvertisement
// pendingWrappingLSAs are checked whether it can be re-flooded every tick.
pendingWrappingLSAsTicker *TickerFunc
// This parameter indicates whether the area can carry data traffic
// that neither originates nor terminates in the area itself. This
// parameter is calculated when the area's shortest-path tree is
// built (see Section 16.1, where TransitCapability is set to TRUE
// if and only if there are one or more fully adjacent virtual
// links using the area as Transit area), and is used as an input
// to a subsequent step of the routing table build process (see
// Section 16.3). When an area's TransitCapability is set to TRUE,
// the area is said to be a "transit area".
TransitCapability bool
// Whether AS-external-LSAs will be flooded into/throughout the
// area. This is a configurable parameter. If AS-external-LSAs
// are excluded from the area, the area is called a "stub". Within
// stub areas, routing to AS external destinations will be based
// solely on a default summary route. The backbone cannot be
// configured as a stub area. Also, virtual links cannot be
// configured through stub areas. For more information, see
// Section 3.6.
ExternalRoutingCapability bool
// If the area has been configured as a stub area, and the router
// itself is an area border router, then the StubDefaultCost
// indicates the cost of the default summary-LSA that the router
// should advertise into the area. See Section 12.4.3 for more
// information.
StubDefaultCost int
// The shortest-path tree for the area, with this router itself as
// root. Derived from the collected router-LSAs and network-LSAs
// by the Dijkstra algorithm (see Section 16.1).
SPF *SPFTree
}
type LSDBRouterItem struct {
*lsaMeta
h packet.LSAheader
l packet.V2RouterLSA
}
func (l *LSDBRouterItem) doAging() uint16 {
l.h.LSAge = l.age()
return l.h.LSAge
}
type LSDBNetworkItem struct {
*lsaMeta
h packet.LSAheader
l packet.V2NetworkLSA
}
func (l *LSDBNetworkItem) doAging() uint16 {
l.h.LSAge = l.age()
return l.h.LSAge
}
type LSDBSummaryItem struct {
*lsaMeta
h packet.LSAheader
l packet.V2SummaryLSAImpl
}
func (l *LSDBSummaryItem) doAging() uint16 {
l.h.LSAge = l.age()
return l.h.LSAge
}
type lsaMeta struct {
rw sync.RWMutex
ctime time.Time // used to calculate LSAge
recvTime time.Time // received time while flooding
doNotRefresh bool
lastFloodTime time.Time
}
func (lm *lsaMeta) age() uint16 {
lm.rw.RLock()
defer lm.rw.RUnlock()
age := time.Since(lm.ctime)
if age >= 0 && age <= time.Second*packet.MaxAge {
return uint16(age.Seconds())
}
return packet.MaxAge
}
func (a *Area) start() {
for _, ifi := range a.Interfaces {
ifi.start()
}
}
func (a *Area) shutdown() {
a.lsDbFlushAllSelfOriginatedLSA()
for _, ifi := range a.Interfaces {
if err := ifi.close(); err != nil {
logWarn("Interface %s close err: %v", ifi.c.ifi.Name, err)
}
}
a.wg.Wait()
}
type AreaAddress struct {
Address *net.IPNet
// Routing information is condensed at area boundaries.
// External to the area, at most a single route is
// advertised (via a summary-LSA) for each address
// range. The route is advertised if and only if the
// address range's Status is set to Advertise.
// Unadvertised ranges allow the existence of certain
// networks to be intentionally hidden from other
// areas. Status is set to Advertise by default.
DoNotAdvertise bool
}
type SPFTree struct {
}