Skip to content

Commit

Permalink
Add proxy support to the neighbor functions (vishvananda#149)
Browse files Browse the repository at this point in the history
- Don't require a MAC address for a neighbor proxy
- Include proxies in the list of neighbors

Signed-off-by: Zvi "CtrlZvi" Effron <[email protected]>
  • Loading branch information
CtrlZvi authored and vishvananda committed Aug 23, 2016
1 parent d631d40 commit d710fba
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 2 deletions.
25 changes: 23 additions & 2 deletions neigh_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
dstData := nl.NewRtAttr(NDA_DST, ipData)
req.AddData(dstData)

hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData)
if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData)
}

_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
return err
Expand All @@ -165,14 +167,33 @@ func NeighList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighList(linkIndex, family)
}

// NeighProxyList gets a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link and ip family.
func NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return pkgHandle.NeighProxyList(linkIndex, family)
}

// NeighList gets a list of IP-MAC mappings in the system (ARP table).
// Equivalent to: `ip neighbor show`.
// The list can be filtered by link and ip family.
func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
return h.neighList(linkIndex, family, 0)
}

// NeighProxyList gets a list of neighbor proxies in the system.
// Equivalent to: `ip neighbor show proxy`.
// The list can be filtered by link, ip family.
func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
return h.neighList(linkIndex, family, NTF_PROXY)
}

func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) {
req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
msg := Ndmsg{
Family: uint8(family),
Index: uint32(linkIndex),
Flags: uint8(flags),
}
req.AddData(&msg)

Expand Down
88 changes: 88 additions & 0 deletions neigh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ type arpEntry struct {
mac net.HardwareAddr
}

type proxyEntry struct {
ip net.IP
dev int
}

func parseMAC(s string) net.HardwareAddr {
m, err := net.ParseMAC(s)
if err != nil {
Expand All @@ -27,6 +32,15 @@ func dumpContains(dump []Neigh, e arpEntry) bool {
return false
}

func dumpContainsProxy(dump []Neigh, p proxyEntry) bool {
for _, n := range dump {
if n.IP.Equal(p.ip) && (n.LinkIndex == p.dev) && (n.Flags&NTF_PROXY) == NTF_PROXY {
return true
}
}
return false
}

func TestNeighAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
Expand Down Expand Up @@ -102,3 +116,77 @@ func TestNeighAddDel(t *testing.T) {
t.Fatal(err)
}
}

func TestNeighAddDelProxy(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()

dummy := Dummy{LinkAttrs{Name: "neigh0"}}
if err := LinkAdd(&dummy); err != nil {
t.Fatal(err)
}

ensureIndex(dummy.Attrs())

proxyTable := []proxyEntry{
{net.ParseIP("10.99.0.1"), dummy.Index},
{net.ParseIP("10.99.0.2"), dummy.Index},
{net.ParseIP("10.99.0.3"), dummy.Index},
{net.ParseIP("10.99.0.4"), dummy.Index},
{net.ParseIP("10.99.0.5"), dummy.Index},
}

// Add the proxyTable
for _, entry := range proxyTable {
err := NeighAdd(&Neigh{
LinkIndex: dummy.Index,
Flags: NTF_PROXY,
IP: entry.ip,
})

if err != nil {
t.Errorf("Failed to NeighAdd: %v", err)
}
}

// Dump and see that all added entries are there
dump, err := NeighProxyList(dummy.Index, 0)
if err != nil {
t.Errorf("Failed to NeighList: %v", err)
}

for _, entry := range proxyTable {
if !dumpContainsProxy(dump, entry) {
t.Errorf("Dump does not contain: %v", entry)
}
}

// Delete the proxyTable
for _, entry := range proxyTable {
err := NeighDel(&Neigh{
LinkIndex: dummy.Index,
Flags: NTF_PROXY,
IP: entry.ip,
})

if err != nil {
t.Errorf("Failed to NeighDel: %v", err)
}
}

// Dump and see that none of deleted entries are there
dump, err = NeighProxyList(dummy.Index, 0)
if err != nil {
t.Errorf("Failed to NeighList: %v", err)
}

for _, entry := range proxyTable {
if dumpContainsProxy(dump, entry) {
t.Errorf("Dump contains: %v", entry)
}
}

if err := LinkDel(&dummy); err != nil {
t.Fatal(err)
}
}

0 comments on commit d710fba

Please sign in to comment.