ip neighbour: Add support for lladdr to be an IP address

The ip neighbour supports adding of peers statically using commands
where the lladdr is an IP address.

ip neighbor add 10.0.0.2 lladdr 203.0.113.6 dev tun8

This is used in the case of point-to-multipoint GRE to setup the
remote end point of the tunnel

Note that link-layer address and neighbor address are both IP addresses

Signed-off-by: Manohar Castelino <manohar.r.castelino@intel.com>
This commit is contained in:
Manohar Castelino 2017-08-28 17:59:25 -07:00 committed by Vish (Ishaya) Abrams
parent 8a610f1e24
commit 921f7441f1
3 changed files with 85 additions and 2 deletions

View File

@ -14,6 +14,7 @@ type Neigh struct {
Flags int Flags int
IP net.IP IP net.IP
HardwareAddr net.HardwareAddr HardwareAddr net.HardwareAddr
LLIPAddr net.IP //Used in the case of NHRP
} }
// String returns $ip/$hwaddr $label // String returns $ip/$hwaddr $label

View File

@ -128,6 +128,7 @@ func (h *Handle) NeighDel(neigh *Neigh) error {
func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
var family int var family int
if neigh.Family > 0 { if neigh.Family > 0 {
family = neigh.Family family = neigh.Family
} else { } else {
@ -151,7 +152,10 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
dstData := nl.NewRtAttr(NDA_DST, ipData) dstData := nl.NewRtAttr(NDA_DST, ipData)
req.AddData(dstData) req.AddData(dstData)
if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil { if neigh.LLIPAddr != nil {
llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4())
req.AddData(llIPData)
} else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData) req.AddData(hwData)
} }
@ -237,12 +241,33 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
return nil, err return nil, err
} }
// This should be cached for perfomance
// once per table dump
link, err := LinkByIndex(neigh.LinkIndex)
if err != nil {
return nil, err
}
encapType := link.Attrs().EncapType
for _, attr := range attrs { for _, attr := range attrs {
switch attr.Attr.Type { switch attr.Attr.Type {
case NDA_DST: case NDA_DST:
neigh.IP = net.IP(attr.Value) neigh.IP = net.IP(attr.Value)
case NDA_LLADDR: case NDA_LLADDR:
neigh.HardwareAddr = net.HardwareAddr(attr.Value) // BUG: Is this a bug in the netlink library?
// #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
// #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
attrLen := attr.Attr.Len - syscall.SizeofRtAttr
if attrLen == 4 && (encapType == "ipip" ||
encapType == "sit" ||
encapType == "gre") {
neigh.LLIPAddr = net.IP(attr.Value)
} else if attrLen == 16 &&
encapType == "tunnel6" {
neigh.IP = net.IP(attr.Value)
} else {
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
}
} }
} }

View File

@ -34,6 +34,15 @@ func dumpContains(dump []Neigh, e arpEntry) bool {
return false return false
} }
func dumpContainsNeigh(dump []Neigh, ne Neigh) bool {
for _, n := range dump {
if n.IP.Equal(ne.IP) && n.LLIPAddr.Equal(ne.LLIPAddr) {
return true
}
}
return false
}
func dumpContainsProxy(dump []Neigh, p proxyEntry) bool { func dumpContainsProxy(dump []Neigh, p proxyEntry) bool {
for _, n := range dump { for _, n := range dump {
if n.IP.Equal(p.ip) && (n.LinkIndex == p.dev) && (n.Flags&NTF_PROXY) == NTF_PROXY { if n.IP.Equal(p.ip) && (n.LinkIndex == p.dev) && (n.Flags&NTF_PROXY) == NTF_PROXY {
@ -43,6 +52,54 @@ func dumpContainsProxy(dump []Neigh, p proxyEntry) bool {
return false return false
} }
func TestNeighAddDelLLIPAddr(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
dummy := Iptun{
LinkAttrs: LinkAttrs{Name: "neigh0"},
PMtuDisc: 1,
Local: net.IPv4(127, 0, 0, 1),
Remote: net.IPv4(127, 0, 0, 1)}
if err := LinkAdd(&dummy); err != nil {
t.Errorf("Failed to create link: %v", err)
}
ensureIndex(dummy.Attrs())
entry := Neigh{
LinkIndex: dummy.Index,
State: NUD_PERMANENT,
IP: net.IPv4(198, 51, 100, 2),
LLIPAddr: net.IPv4(198, 51, 100, 1),
}
err := NeighAdd(&entry)
if err != nil {
t.Errorf("Failed to NeighAdd: %v", err)
}
// Dump and see that all added entries are there
dump, err := NeighList(dummy.Index, 0)
if err != nil {
t.Errorf("Failed to NeighList: %v", err)
}
if !dumpContainsNeigh(dump, entry) {
t.Errorf("Dump does not contain: %v: %v", entry, dump)
}
// Delete the entry
err = NeighDel(&entry)
if err != nil {
t.Errorf("Failed to NeighDel: %v", err)
}
if err := LinkDel(&dummy); err != nil {
t.Fatal(err)
}
}
func TestNeighAddDel(t *testing.T) { func TestNeighAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t) tearDown := setUpNetlinkTest(t)
defer tearDown() defer tearDown()