neigh_linux.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package osl
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net"
  6. "github.com/Sirupsen/logrus"
  7. "github.com/vishvananda/netlink"
  8. )
  9. // NeighOption is a function option type to set interface options
  10. type NeighOption func(nh *neigh)
  11. type neigh struct {
  12. dstIP net.IP
  13. dstMac net.HardwareAddr
  14. linkName string
  15. linkDst string
  16. family int
  17. }
  18. func (n *networkNamespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) *neigh {
  19. n.Lock()
  20. defer n.Unlock()
  21. for _, nh := range n.neighbors {
  22. if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
  23. return nh
  24. }
  25. }
  26. return nil
  27. }
  28. func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error {
  29. var (
  30. iface netlink.Link
  31. err error
  32. )
  33. nh := n.findNeighbor(dstIP, dstMac)
  34. if nh == nil {
  35. return fmt.Errorf("could not find the neighbor entry to delete")
  36. }
  37. if osDelete {
  38. n.Lock()
  39. nlh := n.nlHandle
  40. n.Unlock()
  41. if nh.linkDst != "" {
  42. iface, err = nlh.LinkByName(nh.linkDst)
  43. if err != nil {
  44. return fmt.Errorf("could not find interface with destination name %s: %v",
  45. nh.linkDst, err)
  46. }
  47. }
  48. nlnh := &netlink.Neigh{
  49. IP: dstIP,
  50. State: netlink.NUD_PERMANENT,
  51. Family: nh.family,
  52. }
  53. if nlnh.Family > 0 {
  54. nlnh.HardwareAddr = dstMac
  55. nlnh.Flags = netlink.NTF_SELF
  56. }
  57. if nh.linkDst != "" {
  58. nlnh.LinkIndex = iface.Attrs().Index
  59. }
  60. if err := nlh.NeighDel(nlnh); err != nil {
  61. return fmt.Errorf("could not delete neighbor entry: %v", err)
  62. }
  63. }
  64. n.Lock()
  65. for i, nh := range n.neighbors {
  66. if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
  67. n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
  68. break
  69. }
  70. }
  71. n.Unlock()
  72. return nil
  73. }
  74. func (n *networkNamespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, options ...NeighOption) error {
  75. var (
  76. iface netlink.Link
  77. err error
  78. )
  79. nh := n.findNeighbor(dstIP, dstMac)
  80. if nh != nil {
  81. logrus.Debugf("Neighbor entry already present for IP %v, mac %v", dstIP, dstMac)
  82. // If it exists silently return
  83. return nil
  84. }
  85. nh = &neigh{
  86. dstIP: dstIP,
  87. dstMac: dstMac,
  88. }
  89. nh.processNeighOptions(options...)
  90. if nh.linkName != "" {
  91. nh.linkDst = n.findDst(nh.linkName, false)
  92. if nh.linkDst == "" {
  93. return fmt.Errorf("could not find the interface with name %s", nh.linkName)
  94. }
  95. }
  96. n.Lock()
  97. nlh := n.nlHandle
  98. n.Unlock()
  99. if nh.linkDst != "" {
  100. iface, err = nlh.LinkByName(nh.linkDst)
  101. if err != nil {
  102. return fmt.Errorf("could not find interface with destination name %s: %v",
  103. nh.linkDst, err)
  104. }
  105. }
  106. nlnh := &netlink.Neigh{
  107. IP: dstIP,
  108. HardwareAddr: dstMac,
  109. State: netlink.NUD_PERMANENT,
  110. Family: nh.family,
  111. }
  112. if nlnh.Family > 0 {
  113. nlnh.Flags = netlink.NTF_SELF
  114. }
  115. if nh.linkDst != "" {
  116. nlnh.LinkIndex = iface.Attrs().Index
  117. }
  118. if err := nlh.NeighSet(nlnh); err != nil {
  119. return fmt.Errorf("could not add neighbor entry: %v", err)
  120. }
  121. n.Lock()
  122. n.neighbors = append(n.neighbors, nh)
  123. n.Unlock()
  124. return nil
  125. }