The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7707
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === - Splits host veth helper functions, so that OVN NICs can make selective use of them. - Standardises enrichment of `hwaddr` and `host_name` fields from volatile map. - Adds `Create` function for networks, and defaults to it being a no-op.
From 0cd7e953d6bb9d3e8003befd18326ca7099634fe Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 27 Jul 2020 17:08:37 +0100 Subject: [PATCH 1/9] lxd/network/driver/common: Adds Create function no-op Most network types don't need this. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/network/driver_common.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go index bc26dcaed3..584d90ec7f 100644 --- a/lxd/network/driver_common.go +++ b/lxd/network/driver_common.go @@ -362,6 +362,11 @@ func (n *common) delete(clusterNotification bool) error { return nil } +// Create is a no-op. +func (n *common) Create(clusterNotification bool) error { + return nil +} + // HandleHeartbeat is a no-op. func (n *common) HandleHeartbeat(heartbeatData *cluster.APIHeartbeat) error { return nil From 3972cf6937e9e57568d9b49e838cf0f210792520 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 27 Jul 2020 17:09:00 +0100 Subject: [PATCH 2/9] lxd/network/network/interface: Adds Create function Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/network/network_interface.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lxd/network/network_interface.go b/lxd/network/network_interface.go index cedb68ef31..0bba1fd637 100644 --- a/lxd/network/network_interface.go +++ b/lxd/network/network_interface.go @@ -25,6 +25,7 @@ type Network interface { DHCPv6Ranges() []DHCPRange // Actions. + Create(clusterNotification bool) error Start() error Stop() error Rename(name string) error From 0a784e9bbbd4ce6686c8ec356b18ff63d14866b6 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Mon, 27 Jul 2020 17:09:52 +0100 Subject: [PATCH 3/9] lxd/networks: Adds call to network Create in doNetworksCreate Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/networks.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lxd/networks.go b/lxd/networks.go index c5c25ce106..7f7913e4ec 100644 --- a/lxd/networks.go +++ b/lxd/networks.go @@ -355,6 +355,12 @@ func doNetworksCreate(d *Daemon, req api.NetworksPost, clusterNotification bool) return err } + // Run initial creation setup for the network driver. + err = n.Create(clusterNotification) + if err != nil { + return err + } + err = n.Start() if err != nil { n.Delete(clusterNotification) From ebdd0ae69448260a35e26c45ec70ed92bdcd1519 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 29 Jul 2020 12:36:23 +0100 Subject: [PATCH 4/9] lxd/device/device/utils/network: Adds networkDHCPValidIP For use with multiple NIC types (bridged and ovn). Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/device_utils_network.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lxd/device/device_utils_network.go b/lxd/device/device_utils_network.go index 01306bd716..c88341c5fe 100644 --- a/lxd/device/device_utils_network.go +++ b/lxd/device/device_utils_network.go @@ -1,10 +1,12 @@ package device import ( + "bytes" "crypto/rand" "encoding/hex" "fmt" "io/ioutil" + "net" "strconv" "strings" "sync" @@ -603,3 +605,23 @@ func networkInterfaceBindWait(ifName string) error { return fmt.Errorf("Bind of interface %q took too long", ifName) } + +// networkDHCPValidIP returns whether an IP fits inside one of the supplied DHCP ranges and subnet. +func networkDHCPValidIP(subnet *net.IPNet, ranges []network.DHCPRange, IP net.IP) bool { + inSubnet := subnet.Contains(IP) + if !inSubnet { + return false + } + + if len(ranges) > 0 { + for _, IPRange := range ranges { + if bytes.Compare(IP, IPRange.Start) >= 0 && bytes.Compare(IP, IPRange.End) <= 0 { + return true + } + } + } else if inSubnet { + return true + } + + return false +} From 04495ec8f82b939be9a8e1f0becc5517d6f2bd46 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 29 Jul 2020 12:36:59 +0100 Subject: [PATCH 5/9] lxd/device/nic/bridged: Removes networkDHCPValidIP Updates usage to package level networkDHCPValidIP. Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/nic_bridged.go | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go index aaa375f3af..c509126c75 100644 --- a/lxd/device/nic_bridged.go +++ b/lxd/device/nic_bridged.go @@ -109,7 +109,7 @@ func (d *nicBridged) validateConfig(instConf instance.ConfigReader) error { // Check the static IP supplied is valid for the linked network. It should be part of the // network's subnet, but not necessarily part of the dynamic allocation ranges. - if !d.networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv4.address"])) { + if !networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv4.address"])) { return fmt.Errorf("Device IP address %q not within network %q subnet", d.config["ipv4.address"], d.config["network"]) } } @@ -127,7 +127,7 @@ func (d *nicBridged) validateConfig(instConf instance.ConfigReader) error { // Check the static IP supplied is valid for the linked network. It should be part of the // network's subnet, but not necessarily part of the dynamic allocation ranges. - if !d.networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv6.address"])) { + if !networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv6.address"])) { return fmt.Errorf("Device IP address %q not within network %q subnet", d.config["ipv6.address"], d.config["network"]) } } @@ -208,7 +208,7 @@ func (d *nicBridged) validateEnvironment() error { } if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["parent"])) { - return fmt.Errorf("Parent device '%s' doesn't exist", d.config["parent"]) + return fmt.Errorf("Parent device %q doesn't exist", d.config["parent"]) } return nil @@ -715,7 +715,7 @@ func (d *nicBridged) allocateFilterIPs(n network.Network) (net.IP, net.IP, error // Check the existing static DHCP IP is still valid in the subnet & ranges, if not // then we'll need to generate a new one. ranges := n.DHCPv4Ranges() - if d.networkDHCPValidIP(subnet, ranges, curIPv4.IP.To4()) { + if networkDHCPValidIP(subnet, ranges, curIPv4.IP.To4()) { IPv4 = curIPv4.IP.To4() } } @@ -730,7 +730,7 @@ func (d *nicBridged) allocateFilterIPs(n network.Network) (net.IP, net.IP, error // Check the existing static DHCP IP is still valid in the subnet & ranges, if not // then we'll need to generate a new one. ranges := n.DHCPv6Ranges() - if d.networkDHCPValidIP(subnet, ranges, curIPv6.IP.To16()) { + if networkDHCPValidIP(subnet, ranges, curIPv6.IP.To16()) { IPv6 = curIPv6.IP.To16() } } @@ -787,26 +787,6 @@ func (d *nicBridged) allocateFilterIPs(n network.Network) (net.IP, net.IP, error return IPv4, IPv6, nil } -// networkDHCPValidIP returns whether an IP fits inside one of the supplied DHCP ranges and subnet. -func (d *nicBridged) networkDHCPValidIP(subnet *net.IPNet, ranges []network.DHCPRange, IP net.IP) bool { - inSubnet := subnet.Contains(IP) - if !inSubnet { - return false - } - - if len(ranges) > 0 { - for _, IPRange := range ranges { - if bytes.Compare(IP, IPRange.Start) >= 0 && bytes.Compare(IP, IPRange.End) <= 0 { - return true - } - } - } else if inSubnet { - return true - } - - return false -} - // getDHCPFreeIPv4 attempts to find a free IPv4 address for the device. // It first checks whether there is an existing allocation for the instance. // If no previous allocation, then a free IP is picked from the ranges configured. @@ -826,7 +806,7 @@ func (d *nicBridged) getDHCPFreeIPv4(usedIPs map[[4]byte]dnsmasq.DHCPAllocation, // Lets see if there is already an allocation for our device and that it sits within subnet. // If there are custom DHCP ranges defined, check also that the IP falls within one of the ranges. for _, DHCP := range usedIPs { - if (ctName == DHCP.Name || bytes.Compare(MAC, DHCP.MAC) == 0) && d.networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) { + if (ctName == DHCP.Name || bytes.Compare(MAC, DHCP.MAC) == 0) && networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) { return DHCP.IP, nil } } @@ -898,7 +878,7 @@ func (d *nicBridged) getDHCPFreeIPv6(usedIPs map[[16]byte]dnsmasq.DHCPAllocation // allocations using instance name. If there are custom DHCP ranges defined, check also // that the IP falls within one of the ranges. for _, DHCP := range usedIPs { - if ctName == DHCP.Name && d.networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) { + if ctName == DHCP.Name && networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) { return DHCP.IP, nil } } From 92729611c7cbb827a60489d827233871b499f6d9 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 29 Jul 2020 14:32:47 +0100 Subject: [PATCH 6/9] lxd/device/device/utils/networks: Splits networkSetupHostVethDevice into multiple functions So that each specific host-side veth feature can be used in isolation without having to use all of them. This supports applying host-veth limits for OVN NICs without needing the static routes functionality (that will be in OVN itself). Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/device_utils_network.go | 59 +++++++++++++----------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/lxd/device/device_utils_network.go b/lxd/device/device_utils_network.go index c88341c5fe..71295a098d 100644 --- a/lxd/device/device_utils_network.go +++ b/lxd/device/device_utils_network.go @@ -337,46 +337,23 @@ func networkCreateTap(hostName string, m deviceConfig.Device) error { return nil } -// networkSetupHostVethDevice configures a nic device's host side veth settings. -func networkSetupHostVethDevice(s *state.State, device deviceConfig.Device, oldDevice deviceConfig.Device, v map[string]string) error { - // If not configured, check if volatile data contains the most recently added host_name. - if device["host_name"] == "" { - device["host_name"] = v["host_name"] - } - - // If not configured, check if volatile data contains the most recently added hwaddr. - if device["hwaddr"] == "" { - device["hwaddr"] = v["hwaddr"] - } - +// networkSetupHostVethRoutes configures a nic device's host side veth routes. +// Accepts an optional oldDevice that will have its old host routes removed before adding the new device routes. +// This allows live update of a veth device. +func networkSetupHostVethRoutes(s *state.State, device deviceConfig.Device, oldDevice deviceConfig.Device, v map[string]string) error { // Check whether host device resolution succeeded. if device["host_name"] == "" { - return fmt.Errorf("Failed to find host side veth name for device \"%s\"", device["name"]) - } - - // Refresh tc limits. - err := networkSetVethLimits(device) - if err != nil { - return err + return fmt.Errorf("Failed to find host side veth name for device %q", device["name"]) } // If oldDevice provided, remove old routes if any remain. if oldDevice != nil { - // If not configured, copy the volatile host_name into old device to support live updates. - if oldDevice["host_name"] == "" { - oldDevice["host_name"] = v["host_name"] - } - - // If not configured, copy the volatile hwaddr into old device to support live updates. - if oldDevice["hwaddr"] == "" { - oldDevice["hwaddr"] = v["hwaddr"] - } - + networkVethFillFromVolatile(oldDevice, v) networkRemoveVethRoutes(s, oldDevice) } // Setup static routes to container. - err = networkSetVethRoutes(s, device) + err := networkSetVethRoutes(s, device) if err != nil { return err } @@ -384,6 +361,19 @@ func networkSetupHostVethDevice(s *state.State, device deviceConfig.Device, oldD return nil } +// networkVethFillFromVolatile fills veth host_name and hwaddr fields from volatile if not set in device config. +func networkVethFillFromVolatile(device deviceConfig.Device, volatile map[string]string) { + // If not configured, check if volatile data contains the most recently added host_name. + if device["host_name"] == "" { + device["host_name"] = volatile["host_name"] + } + + // If not configured, check if volatile data contains the most recently added hwaddr. + if device["hwaddr"] == "" { + device["hwaddr"] = volatile["hwaddr"] + } +} + // networkSetVethRoutes applies any static routes configured from the host to the container nic. func networkSetVethRoutes(s *state.State, m deviceConfig.Device) error { // Decide whether the route should point to the veth parent or the bridge parent. @@ -476,13 +466,14 @@ func networkRemoveVethRoutes(s *state.State, m deviceConfig.Device) { } } -// networkSetVethLimits applies any network rate limits to the veth device specified in the config. -func networkSetVethLimits(m deviceConfig.Device) error { +// networkSetupHostVethLimits applies any network rate limits to the veth device specified in the config. +func networkSetupHostVethLimits(m deviceConfig.Device) error { var err error veth := m["host_name"] - if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", veth)) { - return fmt.Errorf("Unknown or missing host side veth: %s", veth) + + if veth == "" || !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", veth)) { + return fmt.Errorf("Unknown or missing host side veth device %q", veth) } // Apply max limit From 292c6df3d7d958f47dcdf9f3d8cbd4c672c9b889 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 29 Jul 2020 14:35:42 +0100 Subject: [PATCH 7/9] lxd/device/nic/bridged: networkVethFillFromVolatile usage and other host-veth functions Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/nic_bridged.go | 40 +++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go index c509126c75..1f77dd13b9 100644 --- a/lxd/device/nic_bridged.go +++ b/lxd/device/nic_bridged.go @@ -266,8 +266,17 @@ func (d *nicBridged) Start() (*deviceConfig.RunConfig, error) { revert.Add(func() { NetworkRemoveInterface(saveData["host_name"]) }) - // Apply and host-side limits and routes. - err = networkSetupHostVethDevice(d.state, d.config, nil, saveData) + // Populate device config with volatile fields if needed. + networkVethFillFromVolatile(d.config, saveData) + + // Apply host-side routes. + err = networkSetupHostVethRoutes(d.state, d.config, nil, saveData) + if err != nil { + return nil, err + } + + // Apply host-side limits. + err = networkSetupHostVethLimits(d.config) if err != nil { return nil, err } @@ -351,6 +360,9 @@ func (d *nicBridged) Update(oldDevices deviceConfig.Devices, isRunning bool) err v := d.volatileGet() + // Populate device config with volatile fields if needed. + networkVethFillFromVolatile(d.config, v) + // If instance is running, apply host side limits and filters first before rebuilding // dnsmasq config below so that existing config can be used as part of the filter removal. if isRunning { @@ -359,8 +371,14 @@ func (d *nicBridged) Update(oldDevices deviceConfig.Devices, isRunning bool) err return err } - // Apply and host-side limits and routes. - err = networkSetupHostVethDevice(d.state, d.config, oldConfig, v) + // Apply host-side routes. + err = networkSetupHostVethRoutes(d.state, d.config, oldConfig, v) + if err != nil { + return err + } + + // Apply host-side limits. + err = networkSetupHostVethLimits(d.config) if err != nil { return err } @@ -381,12 +399,12 @@ func (d *nicBridged) Update(oldDevices deviceConfig.Devices, isRunning bool) err // If an IPv6 address has changed, if the instance is running we should bounce the host-side // veth interface to give the instance a chance to detect the change and re-apply for an // updated lease with new IP address. - if d.config["ipv6.address"] != oldConfig["ipv6.address"] && v["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", v["host_name"])) { - _, err := shared.RunCommand("ip", "link", "set", v["host_name"], "down") + if d.config["ipv6.address"] != oldConfig["ipv6.address"] && d.config["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["host_name"])) { + _, err := shared.RunCommand("ip", "link", "set", d.config["host_name"], "down") if err != nil { return err } - _, err = shared.RunCommand("ip", "link", "set", v["host_name"], "up") + _, err = shared.RunCommand("ip", "link", "set", d.config["host_name"], "up") if err != nil { return err } @@ -412,13 +430,7 @@ func (d *nicBridged) postStop() error { v := d.volatileGet() - if d.config["host_name"] == "" { - d.config["host_name"] = v["host_name"] - } - - if d.config["hwaddr"] == "" { - d.config["hwaddr"] = v["hwaddr"] - } + networkVethFillFromVolatile(d.config, v) if d.config["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["host_name"])) { // Detach host-side end of veth pair from bridge (required for openvswitch particularly). From 90d08afc0fd96355dd30425388caf8be2584705b Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 29 Jul 2020 14:36:54 +0100 Subject: [PATCH 8/9] lxd/device/nic/p2p: networkVethFillFromVolatile usage and other host-veth helper functions Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/nic_p2p.go | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/lxd/device/nic_p2p.go b/lxd/device/nic_p2p.go index 341ae1ea13..5f5b7ef089 100644 --- a/lxd/device/nic_p2p.go +++ b/lxd/device/nic_p2p.go @@ -6,6 +6,7 @@ import ( deviceConfig "github.com/lxc/lxd/lxd/device/config" "github.com/lxc/lxd/lxd/instance" "github.com/lxc/lxd/lxd/instance/instancetype" + "github.com/lxc/lxd/lxd/revert" "github.com/lxc/lxd/shared" ) @@ -61,6 +62,9 @@ func (d *nicP2P) Start() (*deviceConfig.RunConfig, error) { return nil, err } + revert := revert.New() + defer revert.Fail() + saveData := make(map[string]string) saveData["host_name"] = d.config["host_name"] @@ -84,10 +88,20 @@ func (d *nicP2P) Start() (*deviceConfig.RunConfig, error) { return nil, err } - // Apply and host-side limits and routes. - err = networkSetupHostVethDevice(d.state, d.config, nil, saveData) + revert.Add(func() { NetworkRemoveInterface(saveData["host_name"]) }) + + // Populate device config with volatile fields if needed. + networkVethFillFromVolatile(d.config, saveData) + + // Apply host-side routes. + err = networkSetupHostVethRoutes(d.state, d.config, nil, saveData) + if err != nil { + return nil, err + } + + // Apply host-side limits. + err = networkSetupHostVethLimits(d.config) if err != nil { - NetworkRemoveInterface(saveData["host_name"]) return nil, err } @@ -112,6 +126,7 @@ func (d *nicP2P) Start() (*deviceConfig.RunConfig, error) { }...) } + revert.Success() return &runConf, nil } @@ -130,8 +145,17 @@ func (d *nicP2P) Update(oldDevices deviceConfig.Devices, isRunning bool) error { v := d.volatileGet() - // Apply and host-side limits and routes. - err = networkSetupHostVethDevice(d.state, d.config, oldConfig, v) + // Populate device config with volatile fields if needed. + networkVethFillFromVolatile(d.config, v) + + // Apply host-side routes. + err = networkSetupHostVethRoutes(d.state, d.config, oldConfig, v) + if err != nil { + return err + } + + // Apply host-side limits. + err = networkSetupHostVethLimits(d.config) if err != nil { return err } @@ -156,9 +180,7 @@ func (d *nicP2P) postStop() error { v := d.volatileGet() - if d.config["host_name"] == "" { - d.config["host_name"] = v["host_name"] - } + networkVethFillFromVolatile(d.config, v) if d.config["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["host_name"])) { // Removing host-side end of veth pair will delete the peer end too. From 1ea421ead29df66024cb45f52d33a9f3a49ca822 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@canonical.com> Date: Wed, 29 Jul 2020 14:37:56 +0100 Subject: [PATCH 9/9] lxd/device/nic/routed: networkVethFillFromVolatile usage and other host-veth helper functions Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com> --- lxd/device/nic_routed.go | 125 ++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/lxd/device/nic_routed.go b/lxd/device/nic_routed.go index 9eaa638eb3..9a7f963e4c 100644 --- a/lxd/device/nic_routed.go +++ b/lxd/device/nic_routed.go @@ -307,9 +307,11 @@ func (d *nicRouted) Update(oldDevices deviceConfig.Devices, isRunning bool) erro return err } + // Populate device config with volatile fields if needed. + networkVethFillFromVolatile(d.config, v) + // Apply host-side limits. - d.config["host_name"] = v["host_name"] - err = networkSetVethLimits(d.config) + err = networkSetupHostVethLimits(d.config) if err != nil { return err } @@ -322,77 +324,76 @@ func (d *nicRouted) Update(oldDevices deviceConfig.Devices, isRunning bool) erro func (d *nicRouted) postStart() error { v := d.volatileGet() - // If volatile host_name is defined (and it should be), then configure the host-side interface. - if v["host_name"] != "" { - // Apply host-side limits. - d.config["host_name"] = v["host_name"] - err := networkSetVethLimits(d.config) - if err != nil { - return err - } + // Populate device config with volatile fields if needed. + networkVethFillFromVolatile(d.config, v) - // Attempt to disable IPv6 router advertisement acceptance. - err = util.SysctlSet(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", v["host_name"]), "0") - if err != nil && !os.IsNotExist(err) { - return err - } + // Apply host-side limits. + err := networkSetupHostVethLimits(d.config) + if err != nil { + return err + } - // Prevent source address spoofing by requiring a return path. - err = util.SysctlSet(fmt.Sprintf("net/ipv4/conf/%s/rp_filter", v["host_name"]), "1") - if err != nil && !os.IsNotExist(err) { - return err - } + // Attempt to disable IPv6 router advertisement acceptance. + err = util.SysctlSet(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", d.config["host_name"]), "0") + if err != nil && !os.IsNotExist(err) { + return err + } + + // Prevent source address spoofing by requiring a return path. + err = util.SysctlSet(fmt.Sprintf("net/ipv4/conf/%s/rp_filter", d.config["host_name"]), "1") + if err != nil && !os.IsNotExist(err) { + return err + } + + // Apply firewall rules for reverse path filtering of IPv4 and IPv6. + err = d.state.Firewall.InstanceSetupRPFilter(d.inst.Project(), d.inst.Name(), d.name, d.config["host_name"]) + if err != nil { + return errors.Wrapf(err, "Error setting up reverse path filter") + } - // Apply firewall rules for reverse path filtering of IPv4 and IPv6. - err = d.state.Firewall.InstanceSetupRPFilter(d.inst.Project(), d.inst.Name(), d.name, v["host_name"]) + if d.config["ipv4.address"] != "" { + // Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that + // liveness detection of the gateways inside the instance work and ensure that traffic + // doesn't periodically halt whilst ARP is re-detected. + _, err := shared.RunCommand("ip", "-4", "addr", "add", fmt.Sprintf("%s/32", d.ipv4HostAddress()), "dev", d.config["host_name"]) if err != nil { - return errors.Wrapf(err, "Error setting up reverse path filter") + return err } - if d.config["ipv4.address"] != "" { - // Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that - // liveness detection of the gateways inside the instance work and ensure that traffic - // doesn't periodically halt whilst ARP is re-detected. - _, err := shared.RunCommand("ip", "-4", "addr", "add", fmt.Sprintf("%s/32", d.ipv4HostAddress()), "dev", v["host_name"]) - if err != nil { - return err - } - - // Add static routes to instance IPs to custom routing tables if specified. - // This is in addition to the static route added by liblxc to the main routing table, which - // is still critical to ensure that reverse path filtering doesn't kick in blocking traffic - // from the instance. - if d.config["ipv4.host_table"] != "" { - for _, addr := range strings.Split(d.config["ipv4.address"], ",") { - addr = strings.TrimSpace(addr) - _, err := shared.RunCommand("ip", "-4", "route", "add", "table", d.config["ipv4.host_table"], fmt.Sprintf("%s/32", addr), "dev", v["host_name"]) - if err != nil { - return err - } + // Add static routes to instance IPs to custom routing tables if specified. + // This is in addition to the static route added by liblxc to the main routing table, which + // is still critical to ensure that reverse path filtering doesn't kick in blocking traffic + // from the instance. + if d.config["ipv4.host_table"] != "" { + for _, addr := range strings.Split(d.config["ipv4.address"], ",") { + addr = strings.TrimSpace(addr) + _, err := shared.RunCommand("ip", "-4", "route", "add", "table", d.config["ipv4.host_table"], fmt.Sprintf("%s/32", addr), "dev", d.config["host_name"]) + if err != nil { + return err } } } + } - if d.config["ipv6.address"] != "" { - // Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that - // liveness detection of the gateways inside the instance work and ensure that traffic - // doesn't periodically halt whilst NDP is re-detected. - _, err := shared.RunCommand("ip", "-6", "addr", "add", fmt.Sprintf("%s/128", d.ipv6HostAddress()), "dev", v["host_name"]) - if err != nil { - return err - } + if d.config["ipv6.address"] != "" { + // Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that + // liveness detection of the gateways inside the instance work and ensure that traffic + // doesn't periodically halt whilst NDP is re-detected. + _, err := shared.RunCommand("ip", "-6", "addr", "add", fmt.Sprintf("%s/128", d.ipv6HostAddress()), "dev", d.config["host_name"]) + if err != nil { + return err + } - // Add static routes to instance IPs to custom routing tables if specified. - // This is in addition to the static route added by liblxc to the main routing table, which - // is still critical to ensure that reverse path filtering doesn't kick in blocking traffic - // from the instance. - if d.config["ipv6.host_table"] != "" { - for _, addr := range strings.Split(d.config["ipv6.address"], ",") { - addr = strings.TrimSpace(addr) - _, err := shared.RunCommand("ip", "-6", "route", "add", "table", d.config["ipv6.host_table"], fmt.Sprintf("%s/128", addr), "dev", v["host_name"]) - if err != nil { - return err - } + // Add static routes to instance IPs to custom routing tables if specified. + // This is in addition to the static route added by liblxc to the main routing table, which + // is still critical to ensure that reverse path filtering doesn't kick in blocking traffic + // from the instance. + if d.config["ipv6.host_table"] != "" { + for _, addr := range strings.Split(d.config["ipv6.address"], ",") { + addr = strings.TrimSpace(addr) + _, err := shared.RunCommand("ip", "-6", "route", "add", "table", d.config["ipv6.host_table"], fmt.Sprintf("%s/128", addr), "dev", d.config["host_name"]) + if err != nil { + return err } } }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel