github.com/cilium/cilium@v1.16.2/pkg/bgpv1/test/links.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package test
     5  
     6  import (
     7  	"net"
     8  	"net/netip"
     9  	"os"
    10  
    11  	"github.com/vishvananda/netlink"
    12  )
    13  
    14  // Note : this will work only in linux environment and requires CAP_NET_ADMIN privilege
    15  
    16  // dummyInterfaces contains IP addresses for the link
    17  type dummyInterfaces struct {
    18  	ipv4 netip.Prefix
    19  	ipv6 netip.Prefix
    20  }
    21  
    22  // default dummy links on which bgp sessions are communicating
    23  var (
    24  	ciliumLink      = "cilium-bgp"
    25  	instance1Link   = "instance1"
    26  	instance2Link   = "instance2"
    27  	ciliumIPEnv     = "CiliumPrefix"
    28  	ciliumIP6Env    = "CiliumPrefix6"
    29  	instance1IPEnv  = "Instance1Prefix"
    30  	instance1IP6Env = "Instance1Prefix6"
    31  	instance2IPEnv  = "Instance2Prefix"
    32  	instance2IP6Env = "Instance2Prefix6"
    33  	dummies         = map[string]dummyInterfaces{
    34  		// link used by BGP Control Plane
    35  		ciliumLink: {
    36  			ipv4: getIP(ciliumIPEnv, "172.16.100.1/32"),
    37  			ipv6: getIP(ciliumIP6Env, "a::1/128"),
    38  		},
    39  		// link used by gobgp instance 1
    40  		instance1Link: {
    41  			ipv4: getIP(instance1IPEnv, "172.16.100.2/32"),
    42  			ipv6: getIP(instance1IP6Env, "a::2/128"),
    43  		},
    44  		// link used by gobgp instance 2
    45  		instance2Link: {
    46  			ipv4: getIP(instance2IPEnv, "172.16.100.3/32"),
    47  			ipv6: getIP(instance2IP6Env, "a::3/128"),
    48  		},
    49  	}
    50  )
    51  
    52  // getIP gets Prefix from env if set, otherwise returns default values.
    53  var getIP = func(envPrefix, defPrefix string) netip.Prefix {
    54  	ip := os.Getenv(envPrefix)
    55  	if ip != "" {
    56  		return netip.MustParsePrefix(ip)
    57  	} else {
    58  		return netip.MustParsePrefix(defPrefix)
    59  	}
    60  }
    61  
    62  // setupLinks creates links defined in dummies
    63  func setupLinks() error {
    64  	log.Info("adding dummy links")
    65  
    66  	for name := range dummies {
    67  		err := netlink.LinkAdd(&netlink.Dummy{
    68  			LinkAttrs: netlink.LinkAttrs{
    69  				Name: name,
    70  			},
    71  		})
    72  		if err != nil {
    73  			return err
    74  		}
    75  	}
    76  	return nil
    77  }
    78  
    79  // teardownLinks deletes links defined in dummies
    80  func teardownLinks() error {
    81  	log.Info("deleting dummy links")
    82  
    83  	for name := range dummies {
    84  		err := netlink.LinkDel(&netlink.Dummy{
    85  			LinkAttrs: netlink.LinkAttrs{
    86  				Name: name,
    87  			},
    88  		})
    89  		if err != nil {
    90  			return err
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  // setupLinkIPs configures IPs and set links up which are defined in setupLinkIPs
    97  func setupLinkIPs() error {
    98  	for name, dummy := range dummies {
    99  		l, err := netlink.LinkByName(name)
   100  		if err != nil {
   101  			return err
   102  		}
   103  
   104  		err = netlink.AddrAdd(l, toNetlinkAddr(dummy.ipv4))
   105  		if err != nil {
   106  			return err
   107  		}
   108  
   109  		err = netlink.AddrAdd(l, toNetlinkAddr(dummy.ipv6))
   110  		if err != nil {
   111  			return err
   112  		}
   113  
   114  		err = netlink.LinkSetUp(l)
   115  		if err != nil {
   116  			return err
   117  		}
   118  	}
   119  
   120  	return nil
   121  }
   122  
   123  // toNetlinkAddr converts netip.Prefix to *netlink.Addr
   124  func toNetlinkAddr(prefix netip.Prefix) *netlink.Addr {
   125  	pLen := 128
   126  	if prefix.Addr().Is4() {
   127  		pLen = 32
   128  	}
   129  	return &netlink.Addr{
   130  		IPNet: &net.IPNet{
   131  			IP:   prefix.Addr().AsSlice(),
   132  			Mask: net.CIDRMask(prefix.Bits(), pLen),
   133  		},
   134  	}
   135  }