github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/network/configure.go (about)

     1  package network
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  
     7  	"code.cloudfoundry.org/lager"
     8  )
     9  
    10  //go:generate counterfeiter . Configurer
    11  type Configurer interface {
    12  	ConfigureContainer(*ContainerConfig) error
    13  	ConfigureHost(*HostConfig) error
    14  }
    15  
    16  //go:generate counterfeiter . Hostname
    17  type Hostname interface {
    18  	SetHostname(hostName string) error
    19  }
    20  
    21  type NetworkConfigurer struct {
    22  	Hostname Hostname
    23  
    24  	Veth interface {
    25  		Create(hostIfcName, containerIfcName string) (*net.Interface, *net.Interface, error)
    26  	}
    27  
    28  	Link interface {
    29  		AddIP(intf *net.Interface, ip net.IP, subnet *net.IPNet) error
    30  		AddDefaultGW(intf *net.Interface, ip net.IP) error
    31  		SetUp(intf *net.Interface) error
    32  		SetMTU(intf *net.Interface, mtu int) error
    33  		SetNs(intf *net.Interface, pid int) error
    34  		InterfaceByName(name string) (*net.Interface, bool, error)
    35  	}
    36  
    37  	Bridge interface {
    38  		Create(bridgeName string, ip net.IP, subnet *net.IPNet) (*net.Interface, error)
    39  		Add(bridge, slave *net.Interface) error
    40  	}
    41  
    42  	Logger lager.Logger
    43  }
    44  
    45  type HostConfig struct {
    46  	HostIntf      string
    47  	BridgeName    string
    48  	BridgeIP      net.IP
    49  	ContainerIntf string
    50  	ContainerPid  int
    51  	Subnet        *net.IPNet
    52  	Mtu           int
    53  }
    54  
    55  func (c *NetworkConfigurer) ConfigureHost(config *HostConfig) error {
    56  	var (
    57  		err       error
    58  		host      *net.Interface
    59  		container *net.Interface
    60  		bridge    *net.Interface
    61  	)
    62  
    63  	cLog := c.Logger.Session("configure-host", lager.Data{
    64  		"bridgeName":     config.BridgeName,
    65  		"bridgeIP":       config.BridgeIP,
    66  		"subnet":         config.Subnet,
    67  		"containerIface": config.ContainerIntf,
    68  		"hostIface":      config.HostIntf,
    69  		"mtu":            config.Mtu,
    70  		"pid":            config.ContainerPid,
    71  	})
    72  
    73  	cLog.Debug("configuring")
    74  
    75  	if bridge, err = c.configureBridgeIntf(cLog, config.BridgeName, config.BridgeIP, config.Subnet); err != nil {
    76  		return err
    77  	}
    78  
    79  	if host, container, err = c.configureVethPair(cLog, config.HostIntf, config.ContainerIntf); err != nil {
    80  		return err
    81  	}
    82  
    83  	if err = c.configureHostIntf(cLog, host, bridge, config.Mtu); err != nil {
    84  		return err
    85  	}
    86  
    87  	// move container end in to container
    88  	if err = c.Link.SetNs(container, config.ContainerPid); err != nil {
    89  		return &SetNsFailedError{err, container, config.ContainerPid}
    90  	}
    91  
    92  	return nil
    93  }
    94  
    95  func (c *NetworkConfigurer) configureBridgeIntf(log lager.Logger, name string, ip net.IP, subnet *net.IPNet) (*net.Interface, error) {
    96  	log = log.Session("bridge-interface")
    97  
    98  	log.Debug("find")
    99  	bridge, bridgeExists, err := c.Link.InterfaceByName(name)
   100  	if err != nil || !bridgeExists {
   101  		log.Error("find", err)
   102  		return nil, &BridgeDetectionError{errors.New("look up existing bridge"), name, ip, subnet}
   103  	}
   104  
   105  	log.Debug("bring-up")
   106  	if err = c.Link.SetUp(bridge); err != nil {
   107  		log.Error("bring-up", err)
   108  		return nil, &LinkUpError{err, bridge, "bridge"}
   109  	}
   110  
   111  	return bridge, nil
   112  }
   113  
   114  func (c *NetworkConfigurer) configureVethPair(log lager.Logger, hostName, containerName string) (*net.Interface, *net.Interface, error) {
   115  	log = log.Session("veth")
   116  
   117  	log.Debug("create")
   118  	if host, container, err := c.Veth.Create(hostName, containerName); err != nil {
   119  		log.Error("create", err)
   120  		return nil, nil, &VethPairCreationError{err, hostName, containerName}
   121  	} else {
   122  		return host, container, err
   123  	}
   124  }
   125  
   126  func (c *NetworkConfigurer) configureHostIntf(log lager.Logger, intf *net.Interface, bridge *net.Interface, mtu int) error {
   127  	log = log.Session("host-interface", lager.Data{
   128  		"bridge-interface": bridge,
   129  		"host-interface":   intf,
   130  	})
   131  
   132  	log.Debug("set-mtu")
   133  	if err := c.Link.SetMTU(intf, mtu); err != nil {
   134  		log.Error("set-mtu", err)
   135  		return &MTUError{err, intf, mtu}
   136  	}
   137  
   138  	log.Debug("add-to-bridge")
   139  	if err := c.Bridge.Add(bridge, intf); err != nil {
   140  		log.Error("add-to-bridge", err)
   141  		return &AddToBridgeError{err, bridge, intf}
   142  	}
   143  
   144  	log.Debug("bring-link-up")
   145  	if err := c.Link.SetUp(intf); err != nil {
   146  		log.Error("bring-link-up", err)
   147  		return &LinkUpError{err, intf, "host"}
   148  	}
   149  
   150  	return nil
   151  }
   152  
   153  type ContainerConfig struct {
   154  	Hostname      string
   155  	ContainerIntf string
   156  	ContainerIP   net.IP
   157  	GatewayIP     net.IP
   158  	Subnet        *net.IPNet
   159  	Mtu           int
   160  }
   161  
   162  func (c *NetworkConfigurer) ConfigureContainer(config *ContainerConfig) error {
   163  	if err := c.configureLoopbackIntf(); err != nil {
   164  		return err
   165  	}
   166  
   167  	if err := c.configureContainerIntf(
   168  		config.ContainerIntf,
   169  		config.ContainerIP,
   170  		config.GatewayIP,
   171  		config.Subnet,
   172  		config.Mtu,
   173  	); err != nil {
   174  		return err
   175  	}
   176  
   177  	return c.Hostname.SetHostname(config.Hostname)
   178  }
   179  
   180  func (c *NetworkConfigurer) configureContainerIntf(name string, ip, gatewayIP net.IP, subnet *net.IPNet, mtu int) (err error) {
   181  	var found bool
   182  	var intf *net.Interface
   183  	if intf, found, err = c.Link.InterfaceByName(name); !found || err != nil {
   184  		return &FindLinkError{err, "container", name}
   185  	}
   186  
   187  	if err := c.Link.AddIP(intf, ip, subnet); err != nil {
   188  		return &ConfigureLinkError{err, "container", intf, ip, subnet}
   189  	}
   190  
   191  	if err := c.Link.SetUp(intf); err != nil {
   192  		return &LinkUpError{err, intf, "container"}
   193  	}
   194  
   195  	if err := c.Link.AddDefaultGW(intf, gatewayIP); err != nil {
   196  		return &ConfigureDefaultGWError{err, intf, gatewayIP}
   197  	}
   198  
   199  	if err := c.Link.SetMTU(intf, mtu); err != nil {
   200  		return &MTUError{err, intf, mtu}
   201  	}
   202  
   203  	return nil
   204  }
   205  
   206  func (c *NetworkConfigurer) configureLoopbackIntf() (err error) {
   207  	var found bool
   208  	var lo *net.Interface
   209  	if lo, found, err = c.Link.InterfaceByName("lo"); !found || err != nil {
   210  		return &FindLinkError{err, "loopback", "lo"}
   211  	}
   212  
   213  	ip, subnet, err := net.ParseCIDR("127.0.0.1/8")
   214  	if err != nil {
   215  		panic("can't parse 127.0.0.1/8 as a CIDR") // cant happen
   216  	}
   217  
   218  	if err := c.Link.AddIP(lo, ip, subnet); err != nil {
   219  		return &ConfigureLinkError{err, "loopback", lo, ip, subnet}
   220  	}
   221  
   222  	if err := c.Link.SetUp(lo); err != nil {
   223  		return &LinkUpError{err, lo, "loopback"}
   224  	}
   225  
   226  	return nil
   227  }