Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
Merge pull request #784 from amshinde/add-arp-neighbors
Browse files Browse the repository at this point in the history
network: Add grpc method to add static arp neighbors
  • Loading branch information
amshinde authored May 14, 2020
2 parents c3a183d + 42438f9 commit 906f7e2
Show file tree
Hide file tree
Showing 12 changed files with 2,146 additions and 1,156 deletions.
4 changes: 4 additions & 0 deletions grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1571,6 +1571,10 @@ func (a *agentGRPC) ListRoutes(ctx context.Context, req *pb.ListRoutesRequest) (
return a.sandbox.listRoutes(nil)
}

func (a *agentGRPC) AddARPNeighbors(ctx context.Context, req *pb.AddARPNeighborsRequest) (*gpb.Empty, error) {
return emptyResp, a.sandbox.addARPNeighbors(nil, req.Neighbors)
}

func (a *agentGRPC) OnlineCPUMem(ctx context.Context, req *pb.OnlineCPUMemRequest) (*gpb.Empty, error) {
if !req.Wait {
go a.onlineCPUMem(req)
Expand Down
56 changes: 56 additions & 0 deletions network.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
errNoLink = grpcStatus.Errorf(codes.InvalidArgument, "Need network link")
errNoMAC = grpcStatus.Errorf(codes.InvalidArgument, "Need hardware address")
errNoRoutes = grpcStatus.Errorf(codes.InvalidArgument, "Need network routes")
errNoNeighbors = grpcStatus.Errorf(codes.InvalidArgument, "Need ARP neighbors")
guestDNSFile = "/etc/resolv.conf"
kataGuestSandboxDNSFile = "/run/kata-containers/sandbox/resolv.conf"
)
Expand Down Expand Up @@ -625,6 +626,61 @@ func (s *sandbox) updateRoute(netHandle *netlink.Handle, route *types.Route, add
return nil
}

// addARPNeighbors will take neighbors and add them to ARP entries.
// This is used to mirror any static arp entries created by the network
// plugin in the network namespace on the host side.
func (s *sandbox) addARPNeighbors(netHandle *netlink.Handle, requestedNeighbors *pb.ARPNeighbors) error {
if requestedNeighbors == nil {
return errNoNeighbors
}

var err error
if netHandle == nil {
netHandle, err = netlink.NewHandle(unix.NETLINK_ROUTE)
if err != nil {
return err
}
defer netHandle.Delete()
}

for _, neighbor := range requestedNeighbors.ARPNeighbors {
// Find link index from route's device name.
link, err := netHandle.LinkByName(neighbor.Device)
if err != nil {
return grpcStatus.Errorf(codes.Internal, "Could not find link from device %s: %v", neighbor.Device, err)
}

toIP := net.ParseIP(neighbor.ToIPAddress.Address)
if toIP == nil {
return grpcStatus.Errorf(codes.Internal, "Invalid To IP address %s for device %s", neighbor.ToIPAddress.Address, neighbor.Device)
}

var mac net.HardwareAddr
if neighbor.Lladdr != "" {
mac, err = net.ParseMAC(neighbor.Lladdr)
if err != nil {
return grpcStatus.Errorf(codes.Internal, "Invalid hardware address %s for device %s: %v", neighbor.Lladdr, neighbor.Device, err)
}
}

neigh := netlink.Neigh{
LinkIndex: link.Attrs().Index,
HardwareAddr: mac,
State: int(neighbor.State),
IP: toIP,
Flags: int(neighbor.Flags),
}

err = netHandle.NeighAdd(&neigh)
if err != nil {
return grpcStatus.Errorf(codes.Internal, "Could not add ARP neighbor %+v: %v", neighbor, err)
}

}

return nil
}

/////////
// DNS //
/////////
Expand Down
68 changes: 68 additions & 0 deletions network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,3 +557,71 @@ func TestSetupDNS(t *testing.T) {
expectedDNS := strings.Split(string(content), "\n")
assert.Equal(t, dns, expectedDNS)
}

func TestAddARPNeighbors(t *testing.T) {
skipUnlessRoot(t)

tearDown := setupNetworkTest(t)
defer tearDown()

s := sandbox{}

// create a dummy link which we'll play with
macAddr := net.HardwareAddr{0x02, 0x00, 0xCA, 0xFE, 0x00, 0x48}
link := &netlink.Dummy{
LinkAttrs: netlink.LinkAttrs{
MTU: 1500,
TxQLen: -1,
Name: "ifc-name",
HardwareAddr: macAddr,
},
}
netHandle, _ := netlink.NewHandle()
defer netHandle.Delete()

netHandle.LinkAdd(link)
if err := netHandle.LinkSetUp(link); err != nil {
t.Fatal(err)
}

netlinkAddr, _ := netlink.ParseAddr("192.168.0.2/16")
netHandle.AddrAdd(link, netlinkAddr)

mac := "6a:92:3a:59:70:aa"
toIP := "169.254.1.1"
neighbors := []*types.ARPNeighbor{
{
Device: "ifc-name",
Lladdr: mac,
ToIPAddress: &types.IPAddress{Address: toIP},
State: netlink.NUD_PERMANENT,
},
}

testNeighbors := &pb.ARPNeighbors{
ARPNeighbors: neighbors,
}

err := s.addARPNeighbors(netHandle, testNeighbors)
assert.Nil(t, err, "Unexpected add neighbors failure: %v", err)

addedLink, err := netlink.LinkByName(link.Name)
assert.Nil(t, err)

dump, err := netlink.NeighList(addedLink.Attrs().Index, 0)
if err != nil {
t.Errorf("Failed to NeighList: %v", err)
}

neighFound := false
for _, n := range dump {
if n.IP.Equal(net.ParseIP(toIP)) && (n.State&netlink.NUD_INCOMPLETE) == 0 && n.HardwareAddr.String() == mac {
neighFound = true
}
}

if !neighFound {
t.Errorf("Failed to find neighbour after AddARPNeighbor()")
}

}
Loading

0 comments on commit 906f7e2

Please sign in to comment.