neigh_linux.go 2.9 KB

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