mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-01 13:14:33 +00:00
network: Detect and add static ARP entries
[ port from runtime commit 67d3e2c5c5d11738c0c0ff46b1228909a6c81ab0 ] Some network plugins add static arp entries in the network namespace. Scan namespace for static entries and pass these on to the agent to be added within the guest. If the grpc api is not implemented by the agent due to a older running agent, check for this and do not error out to maintain backward compatibility. Signed-off-by: Archana Shinde <archana.m.shinde@intel.com> Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
parent
117ce4ac41
commit
520295b938
@ -110,6 +110,7 @@ const (
|
|||||||
grpcUpdateInterfaceRequest = "grpc.UpdateInterfaceRequest"
|
grpcUpdateInterfaceRequest = "grpc.UpdateInterfaceRequest"
|
||||||
grpcListInterfacesRequest = "grpc.ListInterfacesRequest"
|
grpcListInterfacesRequest = "grpc.ListInterfacesRequest"
|
||||||
grpcListRoutesRequest = "grpc.ListRoutesRequest"
|
grpcListRoutesRequest = "grpc.ListRoutesRequest"
|
||||||
|
grpcAddARPNeighborsRequest = "grpc.AddARPNeighborsRequest"
|
||||||
grpcOnlineCPUMemRequest = "grpc.OnlineCPUMemRequest"
|
grpcOnlineCPUMemRequest = "grpc.OnlineCPUMemRequest"
|
||||||
grpcListProcessesRequest = "grpc.ListProcessesRequest"
|
grpcListProcessesRequest = "grpc.ListProcessesRequest"
|
||||||
grpcUpdateContainerRequest = "grpc.UpdateContainerRequest"
|
grpcUpdateContainerRequest = "grpc.UpdateContainerRequest"
|
||||||
@ -638,6 +639,30 @@ func (k *kataAgent) updateRoutes(routes []*vcTypes.Route) ([]*vcTypes.Route, err
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kataAgent) addARPNeighbors(neighs []*vcTypes.ARPNeighbor) error {
|
||||||
|
if neighs != nil {
|
||||||
|
neighsReq := &grpc.AddARPNeighborsRequest{
|
||||||
|
Neighbors: &grpc.ARPNeighbors{
|
||||||
|
ARPNeighbors: k.convertToKataAgentNeighbors(neighs),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := k.sendReq(neighsReq)
|
||||||
|
if err != nil {
|
||||||
|
if grpcStatus.Convert(err).Code() == codes.Unimplemented {
|
||||||
|
k.Logger().WithFields(logrus.Fields{
|
||||||
|
"arpneighbors-requested": fmt.Sprintf("%+v", neighs),
|
||||||
|
}).Warn("add ARP neighbors request failed due to old agent, please upgrade Kata Containers image version")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
k.Logger().WithFields(logrus.Fields{
|
||||||
|
"arpneighbors-requested": fmt.Sprintf("%+v", neighs),
|
||||||
|
}).WithError(err).Error("add ARP neighbors request failed")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kataAgent) listInterfaces() ([]*vcTypes.Interface, error) {
|
func (k *kataAgent) listInterfaces() ([]*vcTypes.Interface, error) {
|
||||||
req := &grpc.ListInterfacesRequest{}
|
req := &grpc.ListInterfacesRequest{}
|
||||||
resultingInterfaces, err := k.sendReq(req)
|
resultingInterfaces, err := k.sendReq(req)
|
||||||
@ -843,7 +868,7 @@ func (k *kataAgent) startSandbox(sandbox *Sandbox) error {
|
|||||||
//
|
//
|
||||||
// Setup network interfaces and routes
|
// Setup network interfaces and routes
|
||||||
//
|
//
|
||||||
interfaces, routes, err := generateInterfacesAndRoutes(sandbox.networkNS)
|
interfaces, routes, neighs, err := generateVCNetworkStructures(sandbox.networkNS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -853,6 +878,9 @@ func (k *kataAgent) startSandbox(sandbox *Sandbox) error {
|
|||||||
if _, err = k.updateRoutes(routes); err != nil {
|
if _, err = k.updateRoutes(routes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err = k.addARPNeighbors(neighs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
storages := setupStorages(sandbox)
|
storages := setupStorages(sandbox)
|
||||||
|
|
||||||
@ -1999,6 +2027,9 @@ func (k *kataAgent) installReqFunc(c *kataclient.AgentClient) {
|
|||||||
k.reqHandlers[grpcListRoutesRequest] = func(ctx context.Context, req interface{}) (interface{}, error) {
|
k.reqHandlers[grpcListRoutesRequest] = func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return k.client.AgentServiceClient.ListRoutes(ctx, req.(*grpc.ListRoutesRequest))
|
return k.client.AgentServiceClient.ListRoutes(ctx, req.(*grpc.ListRoutesRequest))
|
||||||
}
|
}
|
||||||
|
k.reqHandlers[grpcAddARPNeighborsRequest] = func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return k.client.AgentServiceClient.AddARPNeighbors(ctx, req.(*grpc.AddARPNeighborsRequest))
|
||||||
|
}
|
||||||
k.reqHandlers[grpcOnlineCPUMemRequest] = func(ctx context.Context, req interface{}) (interface{}, error) {
|
k.reqHandlers[grpcOnlineCPUMemRequest] = func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return k.client.AgentServiceClient.OnlineCPUMem(ctx, req.(*grpc.OnlineCPUMemRequest))
|
return k.client.AgentServiceClient.OnlineCPUMem(ctx, req.(*grpc.OnlineCPUMemRequest))
|
||||||
}
|
}
|
||||||
@ -2175,18 +2206,27 @@ func (k *kataAgent) convertToIPFamily(ipFamily aTypes.IPFamily) int {
|
|||||||
return netlink.FAMILY_V4
|
return netlink.FAMILY_V4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kataAgent) convertToKataAgentIPAddress(ipAddr *vcTypes.IPAddress) (aIPAddr *aTypes.IPAddress) {
|
||||||
|
if ipAddr == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
aIPAddr = &aTypes.IPAddress{
|
||||||
|
Family: k.convertToKataAgentIPFamily(ipAddr.Family),
|
||||||
|
Address: ipAddr.Address,
|
||||||
|
Mask: ipAddr.Mask,
|
||||||
|
}
|
||||||
|
|
||||||
|
return aIPAddr
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kataAgent) convertToKataAgentIPAddresses(ipAddrs []*vcTypes.IPAddress) (aIPAddrs []*aTypes.IPAddress) {
|
func (k *kataAgent) convertToKataAgentIPAddresses(ipAddrs []*vcTypes.IPAddress) (aIPAddrs []*aTypes.IPAddress) {
|
||||||
for _, ipAddr := range ipAddrs {
|
for _, ipAddr := range ipAddrs {
|
||||||
if ipAddr == nil {
|
if ipAddr == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
aIPAddr := &aTypes.IPAddress{
|
aIPAddr := k.convertToKataAgentIPAddress(ipAddr)
|
||||||
Family: k.convertToKataAgentIPFamily(ipAddr.Family),
|
|
||||||
Address: ipAddr.Address,
|
|
||||||
Mask: ipAddr.Mask,
|
|
||||||
}
|
|
||||||
|
|
||||||
aIPAddrs = append(aIPAddrs, aIPAddr)
|
aIPAddrs = append(aIPAddrs, aIPAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2268,6 +2308,25 @@ func (k *kataAgent) convertToKataAgentRoutes(routes []*vcTypes.Route) (aRoutes [
|
|||||||
return aRoutes
|
return aRoutes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kataAgent) convertToKataAgentNeighbors(neighs []*vcTypes.ARPNeighbor) (aNeighs []*aTypes.ARPNeighbor) {
|
||||||
|
for _, neigh := range neighs {
|
||||||
|
if neigh == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
aNeigh := &aTypes.ARPNeighbor{
|
||||||
|
ToIPAddress: k.convertToKataAgentIPAddress(neigh.ToIPAddress),
|
||||||
|
Device: neigh.Device,
|
||||||
|
State: int32(neigh.State),
|
||||||
|
Lladdr: neigh.LLAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
aNeighs = append(aNeighs, aNeigh)
|
||||||
|
}
|
||||||
|
|
||||||
|
return aNeighs
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kataAgent) convertToRoutes(aRoutes []*aTypes.Route) (routes []*vcTypes.Route) {
|
func (k *kataAgent) convertToRoutes(aRoutes []*aTypes.Route) (routes []*vcTypes.Route) {
|
||||||
for _, aRoute := range aRoutes {
|
for _, aRoute := range aRoutes {
|
||||||
if aRoute == nil {
|
if aRoute == nil {
|
||||||
|
@ -122,6 +122,7 @@ type NetworkInfo struct {
|
|||||||
Addrs []netlink.Addr
|
Addrs []netlink.Addr
|
||||||
Routes []netlink.Route
|
Routes []netlink.Route
|
||||||
DNS DNSInfo
|
DNS DNSInfo
|
||||||
|
Neighbors []netlink.Neigh
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInterface defines a network interface.
|
// NetworkInterface defines a network interface.
|
||||||
@ -942,14 +943,15 @@ func deleteNetNS(netNSPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*vcTypes.Interface, []*vcTypes.Route, error) {
|
func generateVCNetworkStructures(networkNS NetworkNamespace) ([]*vcTypes.Interface, []*vcTypes.Route, []*vcTypes.ARPNeighbor, error) {
|
||||||
|
|
||||||
if networkNS.NetNsPath == "" {
|
if networkNS.NetNsPath == "" {
|
||||||
return nil, nil, nil
|
return nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var routes []*vcTypes.Route
|
var routes []*vcTypes.Route
|
||||||
var ifaces []*vcTypes.Interface
|
var ifaces []*vcTypes.Interface
|
||||||
|
var neighs []*vcTypes.ARPNeighbor
|
||||||
|
|
||||||
for _, endpoint := range networkNS.Endpoints {
|
for _, endpoint := range networkNS.Endpoints {
|
||||||
|
|
||||||
@ -1008,10 +1010,36 @@ func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*vcTypes.Interfa
|
|||||||
r.Device = endpoint.Name()
|
r.Device = endpoint.Name()
|
||||||
r.Scope = uint32(route.Scope)
|
r.Scope = uint32(route.Scope)
|
||||||
routes = append(routes, &r)
|
routes = append(routes, &r)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, neigh := range endpoint.Properties().Neighbors {
|
||||||
|
var n vcTypes.ARPNeighbor
|
||||||
|
|
||||||
|
// We add only static ARP entries
|
||||||
|
if neigh.State != netlink.NUD_PERMANENT {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Device = endpoint.Name()
|
||||||
|
n.State = neigh.State
|
||||||
|
n.Flags = neigh.Flags
|
||||||
|
|
||||||
|
if neigh.HardwareAddr != nil {
|
||||||
|
n.LLAddr = neigh.HardwareAddr.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
n.ToIPAddress = &vcTypes.IPAddress{
|
||||||
|
Family: netlink.FAMILY_V4,
|
||||||
|
Address: neigh.IP.String(),
|
||||||
|
}
|
||||||
|
if neigh.IP.To4() == nil {
|
||||||
|
n.ToIPAddress.Family = netlink.FAMILY_V6
|
||||||
|
}
|
||||||
|
|
||||||
|
neighs = append(neighs, &n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ifaces, routes, nil
|
return ifaces, routes, neighs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNetworkInterfacePair(idx int, ifName string, interworkingModel NetInterworkingModel) (NetworkInterfacePair, error) {
|
func createNetworkInterfacePair(idx int, ifName string, interworkingModel NetInterworkingModel) (NetworkInterfacePair, error) {
|
||||||
@ -1071,6 +1099,11 @@ func networkInfoFromLink(handle *netlink.Handle, link netlink.Link) (NetworkInfo
|
|||||||
return NetworkInfo{}, err
|
return NetworkInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
neighbors, err := handle.NeighList(link.Attrs().Index, netlink.FAMILY_ALL)
|
||||||
|
if err != nil {
|
||||||
|
return NetworkInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return NetworkInfo{
|
return NetworkInfo{
|
||||||
Iface: NetlinkIface{
|
Iface: NetlinkIface{
|
||||||
LinkAttrs: *(link.Attrs()),
|
LinkAttrs: *(link.Attrs()),
|
||||||
@ -1078,6 +1111,7 @@ func networkInfoFromLink(handle *netlink.Handle, link netlink.Link) (NetworkInfo
|
|||||||
},
|
},
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
Routes: routes,
|
Routes: routes,
|
||||||
|
Neighbors: neighbors,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,12 @@ func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
|||||||
{LinkIndex: 329, Dst: nil, Src: nil, Gw: gatewayV6},
|
{LinkIndex: 329, Dst: nil, Src: nil, Gw: gatewayV6},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arpMAC, _ := net.ParseMAC("6a:92:3a:59:70:aa")
|
||||||
|
|
||||||
|
neighs := []netlink.Neigh{
|
||||||
|
{LinkIndex: 329, IP: net.IPv4(192, 168, 0, 101), State: netlink.NUD_PERMANENT, HardwareAddr: arpMAC},
|
||||||
|
}
|
||||||
|
|
||||||
networkInfo := NetworkInfo{
|
networkInfo := NetworkInfo{
|
||||||
Iface: NetlinkIface{
|
Iface: NetlinkIface{
|
||||||
LinkAttrs: netlink.LinkAttrs{MTU: 1500},
|
LinkAttrs: netlink.LinkAttrs{MTU: 1500},
|
||||||
@ -72,6 +78,7 @@ func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
Routes: routes,
|
Routes: routes,
|
||||||
|
Neighbors: neighs,
|
||||||
}
|
}
|
||||||
|
|
||||||
ep0 := &PhysicalEndpoint{
|
ep0 := &PhysicalEndpoint{
|
||||||
@ -84,7 +91,7 @@ func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
|||||||
|
|
||||||
nns := NetworkNamespace{NetNsPath: "foobar", NetNsCreated: true, Endpoints: endpoints}
|
nns := NetworkNamespace{NetNsPath: "foobar", NetNsCreated: true, Endpoints: endpoints}
|
||||||
|
|
||||||
resInterfaces, resRoutes, err := generateInterfacesAndRoutes(nns)
|
resInterfaces, resRoutes, resNeighs, err := generateVCNetworkStructures(nns)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Build expected results:
|
// Build expected results:
|
||||||
@ -106,6 +113,15 @@ func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
|||||||
{Dest: "", Gateway: "2001:db8:1::1", Device: "eth0", Source: ""},
|
{Dest: "", Gateway: "2001:db8:1::1", Device: "eth0", Source: ""},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectedNeighs := []*vcTypes.ARPNeighbor{
|
||||||
|
{
|
||||||
|
Device: "eth0",
|
||||||
|
State: netlink.NUD_PERMANENT,
|
||||||
|
LLAddr: "6a:92:3a:59:70:aa",
|
||||||
|
ToIPAddress: &vcTypes.IPAddress{Address: "192.168.0.101", Family: netlink.FAMILY_V4},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
for _, r := range resRoutes {
|
for _, r := range resRoutes {
|
||||||
fmt.Printf("resRoute: %+v\n", r)
|
fmt.Printf("resRoute: %+v\n", r)
|
||||||
}
|
}
|
||||||
@ -115,7 +131,8 @@ func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
|||||||
"Interfaces returned didn't match: got %+v, expecting %+v", resInterfaces, expectedInterfaces)
|
"Interfaces returned didn't match: got %+v, expecting %+v", resInterfaces, expectedInterfaces)
|
||||||
assert.True(t, reflect.DeepEqual(resRoutes, expectedRoutes),
|
assert.True(t, reflect.DeepEqual(resRoutes, expectedRoutes),
|
||||||
"Routes returned didn't match: got %+v, expecting %+v", resRoutes, expectedRoutes)
|
"Routes returned didn't match: got %+v, expecting %+v", resRoutes, expectedRoutes)
|
||||||
|
assert.True(t, reflect.DeepEqual(resNeighs, expectedNeighs),
|
||||||
|
"ARP Neighbors returned didn't match: got %+v, expecting %+v", resNeighs, expectedNeighs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNetInterworkingModelIsValid(t *testing.T) {
|
func TestNetInterworkingModelIsValid(t *testing.T) {
|
||||||
|
@ -39,3 +39,11 @@ type Route struct {
|
|||||||
Source string
|
Source string
|
||||||
Scope uint32
|
Scope uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ARPNeighbor struct {
|
||||||
|
ToIPAddress *IPAddress
|
||||||
|
Device string
|
||||||
|
LLAddr string
|
||||||
|
State int
|
||||||
|
Flags int
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user