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