github.com/vishvananda/netlink@v1.3.0/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 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 // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE 157 158 // NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set: 159 // - unix.NLM_F_REPLACE - Replace existing matching config object with this request 160 // - unix.NLM_F_EXCL - Don't replace the config object if it already exists 161 // - unix.NLM_F_CREATE - Create config object if it doesn't already exist 162 // - unix.NLM_F_APPEND - Add to the end of the object list 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 // ipNetEqual returns true iff both IPNet are equal 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 }