route.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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. type Destination interface {
  11. Family() int
  12. Decode([]byte) error
  13. Encode() ([]byte, error)
  14. String() string
  15. Equal(Destination) bool
  16. }
  17. type Encap interface {
  18. Type() int
  19. Decode([]byte) error
  20. Encode() ([]byte, error)
  21. String() string
  22. Equal(Encap) bool
  23. }
  24. //Protocol describe what was the originator of the route
  25. type RouteProtocol int
  26. // Route represents a netlink route.
  27. type Route struct {
  28. LinkIndex int
  29. ILinkIndex int
  30. Scope Scope
  31. Dst *net.IPNet
  32. Src net.IP
  33. Gw net.IP
  34. MultiPath []*NexthopInfo
  35. Protocol RouteProtocol
  36. Priority int
  37. Table int
  38. Type int
  39. Tos int
  40. Flags int
  41. MPLSDst *int
  42. NewDst Destination
  43. Encap Encap
  44. Via Destination
  45. MTU int
  46. Window int
  47. Rtt int
  48. RttVar int
  49. Ssthresh int
  50. Cwnd int
  51. AdvMSS int
  52. Reordering int
  53. Hoplimit int
  54. InitCwnd int
  55. Features int
  56. RtoMin int
  57. InitRwnd int
  58. QuickACK int
  59. Congctl string
  60. FastOpenNoCookie int
  61. }
  62. func (r Route) String() string {
  63. elems := []string{}
  64. if len(r.MultiPath) == 0 {
  65. elems = append(elems, fmt.Sprintf("Ifindex: %d", r.LinkIndex))
  66. }
  67. if r.MPLSDst != nil {
  68. elems = append(elems, fmt.Sprintf("Dst: %d", r.MPLSDst))
  69. } else {
  70. elems = append(elems, fmt.Sprintf("Dst: %s", r.Dst))
  71. }
  72. if r.NewDst != nil {
  73. elems = append(elems, fmt.Sprintf("NewDst: %s", r.NewDst))
  74. }
  75. if r.Encap != nil {
  76. elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
  77. }
  78. if r.Via != nil {
  79. elems = append(elems, fmt.Sprintf("Via: %s", r.Via))
  80. }
  81. elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
  82. if len(r.MultiPath) > 0 {
  83. elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
  84. } else {
  85. elems = append(elems, fmt.Sprintf("Gw: %s", r.Gw))
  86. }
  87. elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
  88. elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
  89. return fmt.Sprintf("{%s}", strings.Join(elems, " "))
  90. }
  91. func (r Route) Equal(x Route) bool {
  92. return r.LinkIndex == x.LinkIndex &&
  93. r.ILinkIndex == x.ILinkIndex &&
  94. r.Scope == x.Scope &&
  95. ipNetEqual(r.Dst, x.Dst) &&
  96. r.Src.Equal(x.Src) &&
  97. r.Gw.Equal(x.Gw) &&
  98. nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
  99. r.Protocol == x.Protocol &&
  100. r.Priority == x.Priority &&
  101. r.Table == x.Table &&
  102. r.Type == x.Type &&
  103. r.Tos == x.Tos &&
  104. r.Hoplimit == x.Hoplimit &&
  105. r.Flags == x.Flags &&
  106. (r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
  107. (r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
  108. (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) &&
  109. (r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
  110. }
  111. func (r *Route) SetFlag(flag NextHopFlag) {
  112. r.Flags |= int(flag)
  113. }
  114. func (r *Route) ClearFlag(flag NextHopFlag) {
  115. r.Flags &^= int(flag)
  116. }
  117. type flagString struct {
  118. f NextHopFlag
  119. s string
  120. }
  121. // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE
  122. type RouteUpdate struct {
  123. Type uint16
  124. Route
  125. }
  126. type NexthopInfo struct {
  127. LinkIndex int
  128. Hops int
  129. Gw net.IP
  130. Flags int
  131. NewDst Destination
  132. Encap Encap
  133. Via Destination
  134. }
  135. func (n *NexthopInfo) String() string {
  136. elems := []string{}
  137. elems = append(elems, fmt.Sprintf("Ifindex: %d", n.LinkIndex))
  138. if n.NewDst != nil {
  139. elems = append(elems, fmt.Sprintf("NewDst: %s", n.NewDst))
  140. }
  141. if n.Encap != nil {
  142. elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
  143. }
  144. if n.Via != nil {
  145. elems = append(elems, fmt.Sprintf("Via: %s", n.Via))
  146. }
  147. elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
  148. elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
  149. elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
  150. return fmt.Sprintf("{%s}", strings.Join(elems, " "))
  151. }
  152. func (n NexthopInfo) Equal(x NexthopInfo) bool {
  153. return n.LinkIndex == x.LinkIndex &&
  154. n.Hops == x.Hops &&
  155. n.Gw.Equal(x.Gw) &&
  156. n.Flags == x.Flags &&
  157. (n.NewDst == x.NewDst || (n.NewDst != nil && n.NewDst.Equal(x.NewDst))) &&
  158. (n.Encap == x.Encap || (n.Encap != nil && n.Encap.Equal(x.Encap)))
  159. }
  160. type nexthopInfoSlice []*NexthopInfo
  161. func (n nexthopInfoSlice) Equal(x []*NexthopInfo) bool {
  162. if len(n) != len(x) {
  163. return false
  164. }
  165. for i := range n {
  166. if n[i] == nil || x[i] == nil {
  167. return false
  168. }
  169. if !n[i].Equal(*x[i]) {
  170. return false
  171. }
  172. }
  173. return true
  174. }
  175. // ipNetEqual returns true iff both IPNet are equal
  176. func ipNetEqual(ipn1 *net.IPNet, ipn2 *net.IPNet) bool {
  177. if ipn1 == ipn2 {
  178. return true
  179. }
  180. if ipn1 == nil || ipn2 == nil {
  181. return false
  182. }
  183. m1, _ := ipn1.Mask.Size()
  184. m2, _ := ipn2.Mask.Size()
  185. return m1 == m2 && ipn1.IP.Equal(ipn2.IP)
  186. }