route.go 5.7 KB

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