1// +build linux 2 3package netlink 4 5import ( 6 "net" 7 "testing" 8) 9 10type arpEntry struct { 11 ip net.IP 12 mac net.HardwareAddr 13} 14 15type proxyEntry struct { 16 ip net.IP 17 dev int 18} 19 20func parseMAC(s string) net.HardwareAddr { 21 m, err := net.ParseMAC(s) 22 if err != nil { 23 panic(err) 24 } 25 return m 26} 27 28func dumpContains(dump []Neigh, e arpEntry) bool { 29 for _, n := range dump { 30 if n.IP.Equal(e.ip) && (n.State&NUD_INCOMPLETE) == 0 { 31 return true 32 } 33 } 34 return false 35} 36 37func dumpContainsNeigh(dump []Neigh, ne Neigh) bool { 38 for _, n := range dump { 39 if n.IP.Equal(ne.IP) && n.LLIPAddr.Equal(ne.LLIPAddr) { 40 return true 41 } 42 } 43 return false 44} 45 46func dumpContainsProxy(dump []Neigh, p proxyEntry) bool { 47 for _, n := range dump { 48 if n.IP.Equal(p.ip) && (n.LinkIndex == p.dev) && (n.Flags&NTF_PROXY) == NTF_PROXY { 49 return true 50 } 51 } 52 return false 53} 54 55func TestNeighAddDelLLIPAddr(t *testing.T) { 56 setUpNetlinkTestWithKModule(t, "ipip") 57 58 tearDown := setUpNetlinkTest(t) 59 defer tearDown() 60 61 dummy := Iptun{ 62 LinkAttrs: LinkAttrs{Name: "neigh0"}, 63 PMtuDisc: 1, 64 Local: net.IPv4(127, 0, 0, 1), 65 Remote: net.IPv4(127, 0, 0, 1)} 66 if err := LinkAdd(&dummy); err != nil { 67 t.Errorf("Failed to create link: %v", err) 68 } 69 ensureIndex(dummy.Attrs()) 70 71 entry := Neigh{ 72 LinkIndex: dummy.Index, 73 State: NUD_PERMANENT, 74 IP: net.IPv4(198, 51, 100, 2), 75 LLIPAddr: net.IPv4(198, 51, 100, 1), 76 } 77 78 err := NeighAdd(&entry) 79 if err != nil { 80 t.Errorf("Failed to NeighAdd: %v", err) 81 } 82 83 // Dump and see that all added entries are there 84 dump, err := NeighList(dummy.Index, 0) 85 if err != nil { 86 t.Errorf("Failed to NeighList: %v", err) 87 } 88 89 if !dumpContainsNeigh(dump, entry) { 90 t.Errorf("Dump does not contain: %v: %v", entry, dump) 91 92 } 93 94 // Delete the entry 95 err = NeighDel(&entry) 96 if err != nil { 97 t.Errorf("Failed to NeighDel: %v", err) 98 } 99 100 if err := LinkDel(&dummy); err != nil { 101 t.Fatal(err) 102 } 103} 104 105func TestNeighAddDel(t *testing.T) { 106 tearDown := setUpNetlinkTest(t) 107 defer tearDown() 108 109 dummy := Dummy{LinkAttrs{Name: "neigh0"}} 110 if err := LinkAdd(&dummy); err != nil { 111 t.Fatal(err) 112 } 113 114 ensureIndex(dummy.Attrs()) 115 116 arpTable := []arpEntry{ 117 {net.ParseIP("10.99.0.1"), parseMAC("aa:bb:cc:dd:00:01")}, 118 {net.ParseIP("10.99.0.2"), parseMAC("aa:bb:cc:dd:00:02")}, 119 {net.ParseIP("10.99.0.3"), parseMAC("aa:bb:cc:dd:00:03")}, 120 {net.ParseIP("10.99.0.4"), parseMAC("aa:bb:cc:dd:00:04")}, 121 {net.ParseIP("10.99.0.5"), parseMAC("aa:bb:cc:dd:00:05")}, 122 } 123 124 // Add the arpTable 125 for _, entry := range arpTable { 126 err := NeighAdd(&Neigh{ 127 LinkIndex: dummy.Index, 128 State: NUD_REACHABLE, 129 IP: entry.ip, 130 HardwareAddr: entry.mac, 131 }) 132 133 if err != nil { 134 t.Errorf("Failed to NeighAdd: %v", err) 135 } 136 } 137 138 // Dump and see that all added entries are there 139 dump, err := NeighList(dummy.Index, 0) 140 if err != nil { 141 t.Errorf("Failed to NeighList: %v", err) 142 } 143 144 for _, entry := range arpTable { 145 if !dumpContains(dump, entry) { 146 t.Errorf("Dump does not contain: %v", entry) 147 } 148 } 149 150 // Delete the arpTable 151 for _, entry := range arpTable { 152 err := NeighDel(&Neigh{ 153 LinkIndex: dummy.Index, 154 IP: entry.ip, 155 HardwareAddr: entry.mac, 156 }) 157 158 if err != nil { 159 t.Errorf("Failed to NeighDel: %v", err) 160 } 161 } 162 163 // TODO: seems not working because of cache 164 //// Dump and see that none of deleted entries are there 165 //dump, err = NeighList(dummy.Index, 0) 166 //if err != nil { 167 //t.Errorf("Failed to NeighList: %v", err) 168 //} 169 170 //for _, entry := range arpTable { 171 //if dumpContains(dump, entry) { 172 //t.Errorf("Dump contains: %v", entry) 173 //} 174 //} 175 176 if err := LinkDel(&dummy); err != nil { 177 t.Fatal(err) 178 } 179} 180 181func TestNeighAddDelProxy(t *testing.T) { 182 tearDown := setUpNetlinkTest(t) 183 defer tearDown() 184 185 dummy := Dummy{LinkAttrs{Name: "neigh0"}} 186 if err := LinkAdd(&dummy); err != nil { 187 t.Fatal(err) 188 } 189 190 ensureIndex(dummy.Attrs()) 191 192 proxyTable := []proxyEntry{ 193 {net.ParseIP("10.99.0.1"), dummy.Index}, 194 {net.ParseIP("10.99.0.2"), dummy.Index}, 195 {net.ParseIP("10.99.0.3"), dummy.Index}, 196 {net.ParseIP("10.99.0.4"), dummy.Index}, 197 {net.ParseIP("10.99.0.5"), dummy.Index}, 198 } 199 200 // Add the proxyTable 201 for _, entry := range proxyTable { 202 err := NeighAdd(&Neigh{ 203 LinkIndex: dummy.Index, 204 Flags: NTF_PROXY, 205 IP: entry.ip, 206 }) 207 208 if err != nil { 209 t.Errorf("Failed to NeighAdd: %v", err) 210 } 211 } 212 213 // Dump and see that all added entries are there 214 dump, err := NeighProxyList(dummy.Index, 0) 215 if err != nil { 216 t.Errorf("Failed to NeighList: %v", err) 217 } 218 219 for _, entry := range proxyTable { 220 if !dumpContainsProxy(dump, entry) { 221 t.Errorf("Dump does not contain: %v", entry) 222 } 223 } 224 225 // Delete the proxyTable 226 for _, entry := range proxyTable { 227 err := NeighDel(&Neigh{ 228 LinkIndex: dummy.Index, 229 Flags: NTF_PROXY, 230 IP: entry.ip, 231 }) 232 233 if err != nil { 234 t.Errorf("Failed to NeighDel: %v", err) 235 } 236 } 237 238 // Dump and see that none of deleted entries are there 239 dump, err = NeighProxyList(dummy.Index, 0) 240 if err != nil { 241 t.Errorf("Failed to NeighList: %v", err) 242 } 243 244 for _, entry := range proxyTable { 245 if dumpContainsProxy(dump, entry) { 246 t.Errorf("Dump contains: %v", entry) 247 } 248 } 249 250 if err := LinkDel(&dummy); err != nil { 251 t.Fatal(err) 252 } 253} 254