1 package netlink
2
3 import (
4 "fmt"
5 "net"
6 "strings"
7 )
8
9
10 type Scope uint8
11
12 type NextHopFlag int
13
14 const (
15 RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
16 RT_FILTER_SCOPE
17 RT_FILTER_TYPE
18 RT_FILTER_TOS
19 RT_FILTER_IIF
20 RT_FILTER_OIF
21 RT_FILTER_DST
22 RT_FILTER_SRC
23 RT_FILTER_GW
24 RT_FILTER_TABLE
25 RT_FILTER_HOPLIMIT
26 RT_FILTER_PRIORITY
27 RT_FILTER_MARK
28 RT_FILTER_MASK
29 RT_FILTER_REALM
30 )
31
32 type Destination interface {
33 Family() int
34 Decode([]byte) error
35 Encode() ([]byte, error)
36 String() string
37 Equal(Destination) bool
38 }
39
40 type Encap interface {
41 Type() int
42 Decode([]byte) error
43 Encode() ([]byte, error)
44 String() string
45 Equal(Encap) bool
46 }
47
48
49 type RouteProtocol int
50
51
52 type Route struct {
53 LinkIndex int
54 ILinkIndex int
55 Scope Scope
56 Dst *net.IPNet
57 Src net.IP
58 Gw net.IP
59 MultiPath []*NexthopInfo
60 Protocol RouteProtocol
61 Priority int
62 Family int
63 Table int
64 Type int
65 Tos int
66 Flags int
67 MPLSDst *int
68 NewDst Destination
69 Encap Encap
70 Via Destination
71 Realm int
72 MTU int
73 Window int
74 Rtt int
75 RttVar int
76 Ssthresh int
77 Cwnd int
78 AdvMSS int
79 Reordering int
80 Hoplimit int
81 InitCwnd int
82 Features int
83 RtoMin int
84 InitRwnd int
85 QuickACK int
86 Congctl string
87 FastOpenNoCookie int
88 }
89
90 func (r Route) String() string {
91 elems := []string{}
92 if len(r.MultiPath) == 0 {
93 elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex))
94 }
95 if r.MPLSDst != nil {
96 elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst))
97 } else {
98 elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst))
99 }
100 if r.NewDst != nil {
101 elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst))
102 }
103 if r.Encap != nil {
104 elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
105 }
106 if r.Via != nil {
107 elems = append(elems, fmt.Sprintf("Via: %s", r.Via))
108 }
109 elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
110 if len(r.MultiPath) > 0 {
111 elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
112 } else {
113 elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw))
114 }
115 elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
116 elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
117 elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm))
118 return fmt.Sprintf("{%s}", strings.Join(elems, " "))
119 }
120
121 func (r Route) Equal(x Route) bool {
122 return r.LinkIndex == x.LinkIndex &&
123 r.ILinkIndex == x.ILinkIndex &&
124 r.Scope == x.Scope &&
125 ipNetEqual(r.Dst, x.Dst) &&
126 r.Src.Equal(x.Src) &&
127 r.Gw.Equal(x.Gw) &&
128 nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
129 r.Protocol == x.Protocol &&
130 r.Priority == x.Priority &&
131 r.Realm == x.Realm &&
132 r.Table == x.Table &&
133 r.Type == x.Type &&
134 r.Tos == x.Tos &&
135 r.Hoplimit == x.Hoplimit &&
136 r.Flags == x.Flags &&
137 (r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
138 (r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
139 (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) &&
140 (r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
141 }
142
143 func (r *Route) SetFlag(flag NextHopFlag) {
144 r.Flags |= int(flag)
145 }
146
147 func (r *Route) ClearFlag(flag NextHopFlag) {
148 r.Flags &^= int(flag)
149 }
150
151 type flagString struct {
152 f NextHopFlag
153 s string
154 }
155
156
157
158
159
160
161
162
163 type RouteUpdate struct {
164 Type uint16
165 NlFlags uint16
166 Route
167 }
168
169 type NexthopInfo struct {
170 LinkIndex int
171 Hops int
172 Gw net.IP
173 Flags int
174 NewDst Destination
175 Encap Encap
176 Via Destination
177 }
178
179 func (n *NexthopInfo) String() string {
180 elems := []string{}
181 elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex))
182 if n.NewDst != nil {
183 elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst))
184 }
185 if n.Encap != nil {
186 elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
187 }
188 if n.Via != nil {
189 elems = append(elems, fmt.Sprintf("Via: %s", n.Via))
190 }
191 elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
192 elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
193 elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
194 return fmt.Sprintf("{%s}", strings.Join(elems, " "))
195 }
196
197 func (n NexthopInfo) Equal(x NexthopInfo) bool {
198 return n.LinkIndex == x.LinkIndex &&
199 n.Hops == x.Hops &&
200 n.Gw.Equal(x.Gw) &&
201 n.Flags == x.Flags &&
202 (n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) &&
203 (n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap)))
204 }
205
206 type nexthopInfoSlice []*NexthopInfo
207
208 func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool {
209 if len(n) != len(x) {
210 return false
211 }
212 for i := range n {
213 if n[i] == nil || x[i] == nil {
214 return false
215 }
216 if !n[i].Equal(*x[i]) {
217 return false
218 }
219 }
220 return true
221 }
222
223
224 func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool {
225 if ipn1 == ipn2 {
226 return true
227 }
228 if ipn1 == nil || ipn2 == nil {
229 return false
230 }
231 m1, _ := ipn1.Mask.Size()
232 m2, _ := ipn2.Mask.Size()
233 return m1 == m2 && ipn1.IP.Equal(ipn2.IP)
234 }
235
View as plain text