go.ligato.io/vpp-agent/v3@v3.5.0/tests/e2e/011_interface_link_only_test.go (about)

     1  //  Copyright (c) 2019 Cisco and/or its affiliates.
     2  //
     3  //  Licensed under the Apache License, Version 2.0 (the "License");
     4  //  you may not use this file except in compliance with the License.
     5  //  You may obtain a copy of the License at:
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  //  Unless required by applicable law or agreed to in writing, software
    10  //  distributed under the License is distributed on an "AS IS" BASIS,
    11  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //  See the License for the specific language governing permissions and
    13  //  limitations under the License.
    14  
    15  package e2e
    16  
    17  import (
    18  	"context"
    19  	. "net"
    20  	"testing"
    21  
    22  	"github.com/vishvananda/netlink"
    23  
    24  	. "github.com/onsi/gomega"
    25  
    26  	"go.ligato.io/vpp-agent/v3/plugins/netalloc/utils"
    27  	"go.ligato.io/vpp-agent/v3/proto/ligato/kvscheduler"
    28  	linux_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces"
    29  	linux_namespace "go.ligato.io/vpp-agent/v3/proto/ligato/linux/namespace"
    30  	vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    31  	. "go.ligato.io/vpp-agent/v3/tests/e2e/e2etest"
    32  )
    33  
    34  // configure only link on the Linux side of the interface and leave addresses
    35  // untouched during resync.
    36  func TestInterfaceLinkOnlyTap(t *testing.T) {
    37  	ctx := Setup(t)
    38  	defer ctx.Teardown()
    39  
    40  	const (
    41  		vppTapName         = "vpp-tap"
    42  		linuxTapName       = "linux-tap"
    43  		linuxTapHostname   = "tap"
    44  		vppTapIP           = "192.168.1.1"
    45  		linuxTapIPIgnored  = "192.168.1.2"
    46  		linuxTapIPExternal = "192.168.1.3"
    47  		linuxTapHwIgnored  = "22:22:22:33:33:33"
    48  		linuxTapHwExternal = "44:44:44:55:55:55"
    49  		netMask            = "/24"
    50  		msName             = "microservice1"
    51  	)
    52  
    53  	vppTap := &vpp_interfaces.Interface{
    54  		Name:        vppTapName,
    55  		Type:        vpp_interfaces.Interface_TAP,
    56  		Enabled:     true,
    57  		IpAddresses: []string{vppTapIP + netMask},
    58  		Link: &vpp_interfaces.Interface_Tap{
    59  			Tap: &vpp_interfaces.TapLink{
    60  				Version:        2,
    61  				ToMicroservice: MsNamePrefix + msName,
    62  			},
    63  		},
    64  	}
    65  	linuxTap := &linux_interfaces.Interface{
    66  		Name:        linuxTapName,
    67  		LinkOnly:    true, // <--- link only
    68  		Type:        linux_interfaces.Interface_TAP_TO_VPP,
    69  		Enabled:     true,
    70  		IpAddresses: []string{linuxTapIPIgnored + netMask},
    71  		HostIfName:  linuxTapHostname,
    72  		PhysAddress: linuxTapHwIgnored,
    73  		Link: &linux_interfaces.Interface_Tap{
    74  			Tap: &linux_interfaces.TapLink{
    75  				VppTapIfName: vppTapName,
    76  			},
    77  		},
    78  		Namespace: &linux_namespace.NetNamespace{
    79  			Type:      linux_namespace.NetNamespace_MICROSERVICE,
    80  			Reference: MsNamePrefix + msName,
    81  		},
    82  	}
    83  
    84  	ms := ctx.StartMicroservice(msName)
    85  	req := ctx.GenericClient().ChangeRequest()
    86  	err := req.Update(
    87  		vppTap,
    88  		linuxTap,
    89  	).Send(context.Background())
    90  	ctx.Expect(err).ToNot(HaveOccurred())
    91  
    92  	ctx.Eventually(ctx.GetValueStateClb(vppTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED))
    93  	ctx.Expect(ctx.GetValueState(linuxTap)).To(Equal(kvscheduler.ValueState_CONFIGURED))
    94  	ctx.Expect(ctx.PingFromVPP(linuxTapIPIgnored)).NotTo(Succeed()) // IP address was not set
    95  
    96  	hasIP := func(tapLinkName netlink.Link, ipAddr string) bool {
    97  		addrs, err := netlink.AddrList(tapLinkName, netlink.FAMILY_ALL)
    98  		ctx.Expect(err).ToNot(HaveOccurred())
    99  		for _, addr := range addrs {
   100  			if addr.IP.String() == ipAddr {
   101  				return true
   102  			}
   103  		}
   104  		return false
   105  	}
   106  
   107  	leaveMs := ms.EnterNetNs()
   108  	tapLinkName, err := netlink.LinkByName(linuxTapHostname)
   109  	ctx.Expect(err).ToNot(HaveOccurred())
   110  
   111  	// agent didn't set IP address
   112  	ctx.Expect(hasIP(tapLinkName, linuxTapIPIgnored)).To(BeFalse())
   113  
   114  	// set IP and MAC addresses from outside of the agent
   115  	ipAddr, _, err := utils.ParseIPAddr(linuxTapIPExternal+netMask, nil)
   116  	ctx.Expect(err).ToNot(HaveOccurred())
   117  	err = netlink.AddrAdd(tapLinkName, &netlink.Addr{IPNet: ipAddr})
   118  	ctx.Expect(err).ToNot(HaveOccurred())
   119  	hwAddr, err := ParseMAC(linuxTapHwExternal)
   120  	ctx.Expect(err).ToNot(HaveOccurred())
   121  	err = netlink.LinkSetHardwareAddr(tapLinkName, hwAddr)
   122  	ctx.Expect(err).ToNot(HaveOccurred())
   123  	leaveMs()
   124  
   125  	// run downstream resync
   126  	ctx.Expect(ctx.AgentInSync()).To(BeTrue()) // everything in-sync even though the IP addr was added
   127  	leaveMs = ms.EnterNetNs()
   128  	ctx.Expect(hasIP(tapLinkName, linuxTapIPIgnored)).To(BeFalse())
   129  	ctx.Expect(hasIP(tapLinkName, linuxTapIPExternal)).To(BeTrue())
   130  	link, err := netlink.LinkByName(linuxTapHostname)
   131  	ctx.Expect(err).ToNot(HaveOccurred())
   132  	ctx.Expect(link).ToNot(BeNil())
   133  	ctx.Expect(link.Attrs().HardwareAddr.String()).To(Equal(linuxTapHwExternal))
   134  	leaveMs()
   135  
   136  	// test with ping
   137  	ctx.Expect(ctx.PingFromVPP(linuxTapIPExternal)).To(Succeed())
   138  	ctx.Expect(ctx.PingFromMs(msName, vppTapIP)).To(Succeed())
   139  }