github.com/vishvananda/netlink@v1.3.1/route.go (about) 1 package netlink 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 ) 8 9 // Scope is an enum representing a route scope. 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 // Protocol describe what was the originator of the route 49 type RouteProtocol int 50 51 // Route represents a netlink route. 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 MTULock bool 74 Window int 75 Rtt int 76 RttVar int 77 Ssthresh int 78 Cwnd int 79 AdvMSS int 80 Reordering int 81 Hoplimit int 82 InitCwnd int 83 Features int 84 RtoMin int 85 RtoMinLock bool 86 InitRwnd int 87 QuickACK int 88 Congctl string 89 FastOpenNoCookie int 90 } 91 92 func (r Route) String() string { 93 elems := []string{} 94 if len(r.MultiPath) == 0 { 95 elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex)) 96 } 97 if r.MPLSDst != nil { 98 elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst)) 99 } else { 100 elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst)) 101 } 102 if r.NewDst != nil { 103 elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst)) 104 } 105 if r.Encap != nil { 106 elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap)) 107 } 108 if r.Via != nil { 109 elems = append(elems, fmt.Sprintf("Via: %s", r.Via)) 110 } 111 elems = append(elems, fmt.Sprintf("Src: %s", r.Src)) 112 if len(r.MultiPath) > 0 { 113 elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath)) 114 } else { 115 elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw)) 116 } 117 elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) 118 elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) 119 elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm)) 120 return fmt.Sprintf("{%s}", strings.Join(elems, " ")) 121 } 122 123 func (r Route) Equal(x Route) bool { 124 return r.LinkIndex == x.LinkIndex && 125 r.ILinkIndex == x.ILinkIndex && 126 r.Scope == x.Scope && 127 ipNetEqual(r.Dst, x.Dst) && 128 r.Src.Equal(x.Src) && 129 r.Gw.Equal(x.Gw) && 130 nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) && 131 r.Protocol == x.Protocol && 132 r.Priority == x.Priority && 133 r.Realm == x.Realm && 134 r.Table == x.Table && 135 r.Type == x.Type && 136 r.Tos == x.Tos && 137 r.Hoplimit == x.Hoplimit && 138 r.Flags == x.Flags && 139 (r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) && 140 (r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) && 141 (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) && 142 (r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap))) 143 } 144 145 func (r *Route) SetFlag(flag NextHopFlag) { 146 r.Flags |= int(flag) 147 } 148 149 func (r *Route) ClearFlag(flag NextHopFlag) { 150 r.Flags &^= int(flag) 151 } 152 153 type flagString struct { 154 f NextHopFlag 155 s string 156 } 157 158 // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE 159 160 // NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set: 161 // - unix.NLM_F_REPLACE - Replace existing matching config object with this request 162 // - unix.NLM_F_EXCL - Don't replace the config object if it already exists 163 // - unix.NLM_F_CREATE - Create config object if it doesn't already exist 164 // - unix.NLM_F_APPEND - Add to the end of the object list 165 type RouteUpdate struct { 166 Type uint16 167 NlFlags uint16 168 Route 169 } 170 171 type NexthopInfo struct { 172 LinkIndex int 173 Hops int 174 Gw net.IP 175 Flags int 176 NewDst Destination 177 Encap Encap 178 Via Destination 179 } 180 181 func (n *NexthopInfo) String() string { 182 elems := []string{} 183 elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex)) 184 if n.NewDst != nil { 185 elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst)) 186 } 187 if n.Encap != nil { 188 elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap)) 189 } 190 if n.Via != nil { 191 elems = append(elems, fmt.Sprintf("Via: %s", n.Via)) 192 } 193 elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1)) 194 elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw)) 195 elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags())) 196 return fmt.Sprintf("{%s}", strings.Join(elems, " ")) 197 } 198 199 func (n NexthopInfo) Equal(x NexthopInfo) bool { 200 return n.LinkIndex == x.LinkIndex && 201 n.Hops == x.Hops && 202 n.Gw.Equal(x.Gw) && 203 n.Flags == x.Flags && 204 (n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) && 205 (n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap))) 206 } 207 208 type nexthopInfoSlice []*NexthopInfo 209 210 func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool { 211 if len(n) != len(x) { 212 return false 213 } 214 for i := range n { 215 if n[i] == nil || x[i] == nil { 216 return false 217 } 218 if !n[i].Equal(*x[i]) { 219 return false 220 } 221 } 222 return true 223 } 224 225 // ipNetEqual returns true iff both IPNet are equal 226 func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool { 227 if ipn1 == ipn2 { 228 return true 229 } 230 if ipn1 == nil || ipn2 == nil { 231 return false 232 } 233 m1, _ := ipn1.Mask.Size() 234 m2, _ := ipn2.Mask.Size() 235 return m1 == m2 && ipn1.IP.Equal(ipn2.IP) 236 }