[lxc-devel] [lxd/master] Network: Make OVN updates more nuanced and less destructive
tomponline on Github
lxc-bot at linuxcontainers.org
Fri Dec 18 18:15:36 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 428 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201218/c682a49b/attachment-0001.bin>
-------------- next part --------------
From cba9502715754f6ae05cfa8bb4a4dae4e62c8465 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 11:45:16 +0000
Subject: [PATCH 01/16] lxd/network/openvswitch/ovn: Adds mayExist argument to
LogicalRouterAdd
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index d7ad3079ee..86625846c2 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -125,8 +125,14 @@ func (o *OVN) nbctl(args ...string) (string, error) {
}
// LogicalRouterAdd adds a named logical router.
-func (o *OVN) LogicalRouterAdd(routerName OVNRouter) error {
- _, err := o.nbctl("lr-add", string(routerName))
+func (o *OVN) LogicalRouterAdd(routerName OVNRouter, mayExist bool) error {
+ args := []string{}
+
+ if mayExist {
+ args = append(args, "--may-exist")
+ }
+
+ _, err := o.nbctl(append(args, "lr-add", string(routerName))...)
if err != nil {
return err
}
From a67d1ed533580a1e7829ca9afd7a99363eba4ce4 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 11:46:13 +0000
Subject: [PATCH 02/16] lxd/network/openvswitch/ovn: Adds mayExist argument to
LogicalRouterSNATAdd
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index 86625846c2..f529d39394 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -151,8 +151,14 @@ func (o OVN) LogicalRouterDelete(routerName OVNRouter) error {
}
// LogicalRouterSNATAdd adds an SNAT rule to a logical router to translate packets from intNet to extIP.
-func (o *OVN) LogicalRouterSNATAdd(routerName OVNRouter, intNet *net.IPNet, extIP net.IP) error {
- _, err := o.nbctl("lr-nat-add", string(routerName), "snat", extIP.String(), intNet.String())
+func (o *OVN) LogicalRouterSNATAdd(routerName OVNRouter, intNet *net.IPNet, extIP net.IP, mayExist bool) error {
+ args := []string{}
+
+ if mayExist {
+ args = append(args, "--may-exist")
+ }
+
+ _, err := o.nbctl(append(args, "lr-nat-add", string(routerName), "snat", extIP.String(), intNet.String())...)
if err != nil {
return err
}
From 94fdc43a5e424d0a9ec4d35e70f12af2a1a5dd65 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 11:46:41 +0000
Subject: [PATCH 03/16] lxd/network/openvswitch/ovn: Simplifies
LogicalRouterRouteAdd
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index f529d39394..fa6a409b6c 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -204,8 +204,7 @@ func (o *OVN) LogicalRouterRouteAdd(routerName OVNRouter, destination *net.IPNet
args = append(args, "--may-exist")
}
- args = append(args, "lr-route-add", string(routerName), destination.String(), nextHop.String())
- _, err := o.nbctl(args...)
+ _, err := o.nbctl(append(args, "lr-route-add", string(routerName), destination.String(), nextHop.String())...)
if err != nil {
return err
}
From e47204f3c35bc466639591ff1b13d6302e4d6a21 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 11:46:57 +0000
Subject: [PATCH 04/16] lxd/network/openvswitch/ovn: Adds mayExist argument to
LogicalRouterPortAdd
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index fa6a409b6c..f4bd7f186f 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -230,7 +230,29 @@ func (o *OVN) LogicalRouterRouteDelete(routerName OVNRouter, destination *net.IP
}
// LogicalRouterPortAdd adds a named logical router port to a logical router.
-func (o *OVN) LogicalRouterPortAdd(routerName OVNRouter, portName OVNRouterPort, mac net.HardwareAddr, ipAddr ...*net.IPNet) error {
+func (o *OVN) LogicalRouterPortAdd(routerName OVNRouter, portName OVNRouterPort, mac net.HardwareAddr, ipAddr []*net.IPNet, mayExist bool) error {
+ if mayExist {
+ // Check if it exists and update addresses.
+ _, err := o.nbctl("list", "Logical_Router_Port", string(portName))
+ if err == nil {
+ // Router port exists.
+ ips := make([]string, 0, len(ipAddr))
+ for _, ip := range ipAddr {
+ ips = append(ips, ip.String())
+ }
+
+ _, err := o.nbctl("set", "Logical_Router_Port", string(portName),
+ fmt.Sprintf(`networks="%s"`, strings.Join(ips, `","`)),
+ fmt.Sprintf(`mac="%s"`, fmt.Sprintf(mac.String())),
+ )
+ if err != nil {
+ return err
+ }
+
+ return nil
+ }
+ }
+
args := []string{"lrp-add", string(routerName), string(portName), mac.String()}
for _, ipNet := range ipAddr {
args = append(args, ipNet.String())
From 053db5f5a862163d88b494f58a70e61ac3a26cd2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 11:47:14 +0000
Subject: [PATCH 05/16] lxd/network/openvswitch/ovn: Adds
LogicalRouterSNATDeleteAll function
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index f4bd7f186f..47b2bdcceb 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -166,6 +166,16 @@ func (o *OVN) LogicalRouterSNATAdd(routerName OVNRouter, intNet *net.IPNet, extI
return nil
}
+// LogicalRouterSNATDeleteAll deletes all SNAT rules from a logical router.
+func (o *OVN) LogicalRouterSNATDeleteAll(routerName OVNRouter) error {
+ _, err := o.nbctl("--if-exists", "lr-nat-del", string(routerName), "snat")
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
// LogicalRouterDNATSNATAdd adds a DNAT and SNAT rule to a logical router to translate packets from extIP to intIP.
func (o *OVN) LogicalRouterDNATSNATAdd(routerName OVNRouter, extIP net.IP, intIP net.IP, stateless bool, mayExist bool) error {
args := []string{}
From b43527e9d9de2b0ff81d5bfda2fb759be59914e2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 16:30:02 +0000
Subject: [PATCH 06/16] lxd/network/openvswitch/ovn: Clear unused keys in
LogicalSwitchSetIPAllocation
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index 47b2bdcceb..01ba706dc4 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -383,14 +383,19 @@ func (o *OVN) LogicalSwitchDelete(switchName OVNSwitch) error {
// LogicalSwitchSetIPAllocation sets the IP allocation config on the logical switch.
func (o *OVN) LogicalSwitchSetIPAllocation(switchName OVNSwitch, opts *OVNIPAllocationOpts) error {
+ var removeOtherConfigKeys []string
args := []string{"set", "logical_switch", string(switchName)}
if opts.PrefixIPv4 != nil {
args = append(args, fmt.Sprintf("other_config:subnet=%s", opts.PrefixIPv4.String()))
+ } else {
+ removeOtherConfigKeys = append(removeOtherConfigKeys, "subnet")
}
if opts.PrefixIPv6 != nil {
args = append(args, fmt.Sprintf("other_config:ipv6_prefix=%s", opts.PrefixIPv6.String()))
+ } else {
+ removeOtherConfigKeys = append(removeOtherConfigKeys, "ipv6_prefix")
}
if len(opts.ExcludeIPv4) > 0 {
@@ -406,6 +411,17 @@ func (o *OVN) LogicalSwitchSetIPAllocation(switchName OVNSwitch, opts *OVNIPAllo
}
args = append(args, fmt.Sprintf("other_config:exclude_ips=%s", strings.Join(excludeIPs, " ")))
+ } else {
+ removeOtherConfigKeys = append(removeOtherConfigKeys, "exclude_ips")
+ }
+
+ // Clear any unused keys first.
+ if len(removeOtherConfigKeys) > 0 {
+ removeArgs := append([]string{"remove", "logical_switch", string(switchName), "other_config"}, removeOtherConfigKeys...)
+ _, err := o.nbctl(removeArgs...)
+ if err != nil {
+ return err
+ }
}
// Only run command if at least one setting is specified.
From 799ce55e8f6a28d9d3ed09aaaeb93c11003a63f5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:47:47 +0000
Subject: [PATCH 07/16] lxd/network/openvswitch/ovn: Adds support for clearing
unused settings in LogicalRouterPortSetIPv6Advertisements
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index 01ba706dc4..cbdb7e018e 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -290,27 +290,53 @@ func (o *OVN) LogicalRouterPortDelete(portName OVNRouterPort) error {
func (o *OVN) LogicalRouterPortSetIPv6Advertisements(portName OVNRouterPort, opts *OVNIPv6RAOpts) error {
args := []string{"set", "logical_router_port", string(portName),
fmt.Sprintf("ipv6_ra_configs:send_periodic=%t", opts.SendPeriodic),
- fmt.Sprintf("ipv6_ra_configs:address_mode=%s", string(opts.AddressMode)),
+ }
+
+ var removeRAConfigKeys []string
+
+ if opts.AddressMode != "" {
+ args = append(args, fmt.Sprintf("ipv6_ra_configs:address_mode=%s", string(opts.AddressMode)))
+ } else {
+ removeRAConfigKeys = append(removeRAConfigKeys, "address_mode")
}
if opts.MaxInterval > 0 {
args = append(args, fmt.Sprintf("ipv6_ra_configs:max_interval=%d", opts.MaxInterval/time.Second))
+ } else {
+ removeRAConfigKeys = append(removeRAConfigKeys, "max_interval")
}
if opts.MinInterval > 0 {
args = append(args, fmt.Sprintf("ipv6_ra_configs:min_interval=%d", opts.MinInterval/time.Second))
+ } else {
+ removeRAConfigKeys = append(removeRAConfigKeys, "min_interval")
}
if opts.MTU > 0 {
args = append(args, fmt.Sprintf("ipv6_ra_configs:mtu=%d", opts.MTU))
+ } else {
+ removeRAConfigKeys = append(removeRAConfigKeys, "mtu")
}
if len(opts.DNSSearchList) > 0 {
args = append(args, fmt.Sprintf("ipv6_ra_configs:dnssl=%s", strings.Join(opts.DNSSearchList, ",")))
+ } else {
+ removeRAConfigKeys = append(removeRAConfigKeys, "dnssl")
}
if opts.RecursiveDNSServer != nil {
args = append(args, fmt.Sprintf("ipv6_ra_configs:rdnss=%s", opts.RecursiveDNSServer.String()))
+ } else {
+ removeRAConfigKeys = append(removeRAConfigKeys, "rdnss")
+ }
+
+ // Clear any unused keys first.
+ if len(removeRAConfigKeys) > 0 {
+ removeArgs := append([]string{"remove", "logical_router_port", string(portName), "ipv6_ra_configs"}, removeRAConfigKeys...)
+ _, err := o.nbctl(removeArgs...)
+ if err != nil {
+ return err
+ }
}
// Configure IPv6 Router Advertisements.
From 0334dfe8dc8dbde5ff9ae9d78c879e9f064209ce Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:48:18 +0000
Subject: [PATCH 08/16] lxd/network/openvswitch/ovn: Adds
LogicalRouterPortDeleteIPv6Advertisements function
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/openvswitch/ovn.go | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/lxd/network/openvswitch/ovn.go b/lxd/network/openvswitch/ovn.go
index cbdb7e018e..a263bb5ca4 100644
--- a/lxd/network/openvswitch/ovn.go
+++ b/lxd/network/openvswitch/ovn.go
@@ -348,6 +348,17 @@ func (o *OVN) LogicalRouterPortSetIPv6Advertisements(portName OVNRouterPort, opt
return nil
}
+// LogicalRouterPortDeleteIPv6Advertisements removes the IPv6 RA announcement settings from a router port.
+func (o *OVN) LogicalRouterPortDeleteIPv6Advertisements(portName OVNRouterPort) error {
+ // Delete IPv6 Router Advertisements.
+ _, err := o.nbctl("clear", "logical_router_port", string(portName), "ipv6_ra_configs")
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
// LogicalRouterPortLinkChassisGroup links a logical router port to a HA chassis group.
func (o *OVN) LogicalRouterPortLinkChassisGroup(portName OVNRouterPort, haChassisGroupName OVNChassisGroup) error {
chassisGroupID, err := o.nbctl("--format=csv", "--no-headings", "--data=bare", "--colum=_uuid", "find", "ha_chassis_group", fmt.Sprintf("name=%s", haChassisGroupName))
From 271257c7c3dc04495a1abfc1ed080ae08840342c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:52:22 +0000
Subject: [PATCH 09/16] lxd/network/driver/ovn: Enforce that ipv6.address if
specified is at least a /64 subnet
OVN requires at least a /64 for DHCP and SLAAC.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index db9b7366d2..f9df44f31a 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -205,6 +205,16 @@ func (n *ovn) Validate(config map[string]string) error {
return err
}
+ // Check that if IPv6 enabled then the network size must be at least a /64 as both RA and DHCPv6
+ // in OVN (as it generates addresses using EUI64) require at least a /64 subnet to operate.
+ _, ipv6Net, _ := net.ParseCIDR(config["ipv6.address"])
+ if ipv6Net != nil {
+ ones, _ := ipv6Net.Mask.Size()
+ if ones > 64 {
+ return fmt.Errorf("IPv6 subnet must be at least a /64")
+ }
+ }
+
// Load the project to get uplink network restrictions.
p, err := n.state.Cluster.GetProject(n.project)
if err != nil {
From 87218ebf8aef6308a4cfaf11da4a5fd80e725e63 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:55:01 +0000
Subject: [PATCH 10/16] lxd/network/driver/ovn: Pass update flag to mayExist
where possible
And don't delete on failure when updating.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 62 ++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index f9df44f31a..f9b5d47573 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1557,18 +1557,19 @@ func (n *ovn) setup(update bool) error {
return err
}
- revert.Add(func() { client.ChassisGroupDelete(n.getChassisGroupName()) })
-
- // Create logical router.
- if update {
- client.LogicalRouterDelete(n.getRouterName())
+ if !update {
+ revert.Add(func() { client.ChassisGroupDelete(n.getChassisGroupName()) })
}
- err = client.LogicalRouterAdd(n.getRouterName())
+ // Create logical router.
+ err = client.LogicalRouterAdd(n.getRouterName(), update)
if err != nil {
return errors.Wrapf(err, "Failed adding router")
}
- revert.Add(func() { client.LogicalRouterDelete(n.getRouterName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalRouterDelete(n.getRouterName()) })
+ }
// Configure logical router.
@@ -1589,23 +1590,24 @@ func (n *ovn) setup(update bool) error {
}
if len(extRouterIPs) > 0 {
- // Create external logical switch.
- if update {
- client.LogicalSwitchDelete(n.getExtSwitchName())
- }
-
- err = client.LogicalSwitchAdd(n.getExtSwitchName(), false)
+ err = client.LogicalSwitchAdd(n.getExtSwitchName(), update)
if err != nil {
return errors.Wrapf(err, "Failed adding external switch")
}
- revert.Add(func() { client.LogicalSwitchDelete(n.getExtSwitchName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalSwitchDelete(n.getExtSwitchName()) })
+ }
// Create external router port.
- err = client.LogicalRouterPortAdd(n.getRouterName(), n.getRouterExtPortName(), routerMAC, extRouterIPs...)
+ err = client.LogicalRouterPortAdd(n.getRouterName(), n.getRouterExtPortName(), routerMAC, extRouterIPs, update)
if err != nil {
return errors.Wrapf(err, "Failed adding external router port")
}
- revert.Add(func() { client.LogicalRouterPortDelete(n.getRouterExtPortName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalRouterPortDelete(n.getRouterExtPortName()) })
+ }
// Associate external router port to chassis group.
err = client.LogicalRouterPortLinkChassisGroup(n.getRouterExtPortName(), n.getChassisGroupName())
@@ -1614,11 +1616,14 @@ func (n *ovn) setup(update bool) error {
}
// Create external switch port and link to router port.
- err = client.LogicalSwitchPortAdd(n.getExtSwitchName(), n.getExtSwitchRouterPortName(), false)
+ err = client.LogicalSwitchPortAdd(n.getExtSwitchName(), n.getExtSwitchRouterPortName(), update)
if err != nil {
return errors.Wrapf(err, "Failed adding external switch router port")
}
- revert.Add(func() { client.LogicalSwitchPortDelete(n.getExtSwitchRouterPortName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalSwitchPortDelete(n.getExtSwitchRouterPortName()) })
+ }
err = client.LogicalSwitchPortLinkRouter(n.getExtSwitchRouterPortName(), n.getRouterExtPortName())
if err != nil {
@@ -1626,11 +1631,14 @@ func (n *ovn) setup(update bool) error {
}
// Create external switch port and link to external provider network.
- err = client.LogicalSwitchPortAdd(n.getExtSwitchName(), n.getExtSwitchProviderPortName(), false)
+ err = client.LogicalSwitchPortAdd(n.getExtSwitchName(), n.getExtSwitchProviderPortName(), update)
if err != nil {
return errors.Wrapf(err, "Failed adding external switch provider port")
}
- revert.Add(func() { client.LogicalSwitchPortDelete(n.getExtSwitchProviderPortName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalSwitchPortDelete(n.getExtSwitchProviderPortName()) })
+ }
err = client.LogicalSwitchPortLinkProviderNetwork(n.getExtSwitchProviderPortName(), uplinkNet.extSwitchProviderName)
if err != nil {
@@ -1639,14 +1647,14 @@ func (n *ovn) setup(update bool) error {
// Add SNAT rules.
if shared.IsTrue(n.config["ipv4.nat"]) && routerIntPortIPv4Net != nil && routerExtPortIPv4 != nil {
- err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv4Net, routerExtPortIPv4)
+ err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv4Net, routerExtPortIPv4, update)
if err != nil {
return err
}
}
if shared.IsTrue(n.config["ipv6.nat"]) && routerIntPortIPv6Net != nil && routerExtPortIPv6 != nil {
- err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv6Net, routerExtPortIPv6)
+ err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv6Net, routerExtPortIPv6, update)
if err != nil {
return err
}
@@ -1673,7 +1681,10 @@ func (n *ovn) setup(update bool) error {
if err != nil {
return errors.Wrapf(err, "Failed adding internal switch")
}
- revert.Add(func() { client.LogicalSwitchDelete(n.getIntSwitchName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalSwitchDelete(n.getIntSwitchName()) })
+ }
var excludeIPV4 []shared.IPRange
if routerIntPortIPv4 != nil {
@@ -1821,7 +1832,10 @@ func (n *ovn) setup(update bool) error {
if err != nil {
return errors.Wrapf(err, "Failed adding internal switch router port")
}
- revert.Add(func() { client.LogicalSwitchPortDelete(n.getIntSwitchRouterPortName()) })
+
+ if !update {
+ revert.Add(func() { client.LogicalSwitchPortDelete(n.getIntSwitchRouterPortName()) })
+ }
err = client.LogicalSwitchPortLinkRouter(n.getIntSwitchRouterPortName(), n.getRouterIntPortName())
if err != nil {
From c58ccecb18c04fc973a879989dff9b49c77593ef Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:55:51 +0000
Subject: [PATCH 11/16] lxd/network/driver/ovn: Delete SNAT rules from route
before adding new ones
This ensures that during an update, old SNAT rules are removed.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index f9b5d47573..e4a39b519b 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1645,6 +1645,15 @@ func (n *ovn) setup(update bool) error {
return errors.Wrapf(err, "Failed linking external switch provider port to external provider network")
}
+ // Remove any existing SNAT rules on update. As currently these are only defined from the network
+ // config rather than from any instance NIC config, so we can re-create the active config below.
+ if update {
+ err = client.LogicalRouterSNATDeleteAll(n.getRouterName())
+ if err != nil {
+ return errors.Wrapf(err, "Failed removing existing router SNAT rules")
+ }
+ }
+
// Add SNAT rules.
if shared.IsTrue(n.config["ipv4.nat"]) && routerIntPortIPv4Net != nil && routerExtPortIPv4 != nil {
err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv4Net, routerExtPortIPv4, update)
From cb9db30dbd7848b2f4c14ce636ab4bbb9c5e2f51 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:56:24 +0000
Subject: [PATCH 12/16] lxd/network/driver/ovn: Improve SNAT failure errors
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index e4a39b519b..1c0439f3a1 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1658,14 +1658,14 @@ func (n *ovn) setup(update bool) error {
if shared.IsTrue(n.config["ipv4.nat"]) && routerIntPortIPv4Net != nil && routerExtPortIPv4 != nil {
err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv4Net, routerExtPortIPv4, update)
if err != nil {
- return err
+ return errors.Wrapf(err, "Failed adding router IPv4 SNAT rule")
}
}
if shared.IsTrue(n.config["ipv6.nat"]) && routerIntPortIPv6Net != nil && routerExtPortIPv6 != nil {
err = client.LogicalRouterSNATAdd(n.getRouterName(), routerIntPortIPv6Net, routerExtPortIPv6, update)
if err != nil {
- return err
+ return errors.Wrapf(err, "Failed adding router IPv6 SNAT rule")
}
}
From 0455da20308446fa359d010aee1b301f58e6f14d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:57:00 +0000
Subject: [PATCH 13/16] lxd/network/driver/ovn: Pass update to mayExists when
setting up default routes
And remove default routes when IP protocol address isn't enabled.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 1c0439f3a1..f386d3a6c9 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1669,19 +1669,31 @@ func (n *ovn) setup(update bool) error {
}
}
- // Add default routes.
+ // Add or remove default routes as config dictates.
+ defaultIPv4Route := &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)}
if uplinkNet.routerExtGwIPv4 != nil {
- err = client.LogicalRouterRouteAdd(n.getRouterName(), &net.IPNet{IP: net.IPv4zero, Mask: net.CIDRMask(0, 32)}, uplinkNet.routerExtGwIPv4, false)
+ err = client.LogicalRouterRouteAdd(n.getRouterName(), defaultIPv4Route, uplinkNet.routerExtGwIPv4, update)
if err != nil {
return errors.Wrapf(err, "Failed adding IPv4 default route")
}
+ } else if update {
+ err = client.LogicalRouterRouteDelete(n.getRouterName(), defaultIPv4Route, nil)
+ if err != nil {
+ return errors.Wrapf(err, "Failed removing IPv4 default route")
+ }
}
+ defaultIPv6Route := &net.IPNet{IP: net.IPv6zero, Mask: net.CIDRMask(0, 128)}
if uplinkNet.routerExtGwIPv6 != nil {
- err = client.LogicalRouterRouteAdd(n.getRouterName(), &net.IPNet{IP: net.IPv6zero, Mask: net.CIDRMask(0, 128)}, uplinkNet.routerExtGwIPv6, false)
+ err = client.LogicalRouterRouteAdd(n.getRouterName(), defaultIPv6Route, uplinkNet.routerExtGwIPv6, update)
if err != nil {
return errors.Wrapf(err, "Failed adding IPv6 default route")
}
+ } else if update {
+ err = client.LogicalRouterRouteDelete(n.getRouterName(), defaultIPv6Route, nil)
+ if err != nil {
+ return errors.Wrapf(err, "Failed removing IPv6 default route")
+ }
}
}
From acf0f3da29e98fb94c67636786a1e395c35b454a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 17:58:20 +0000
Subject: [PATCH 14/16] lxd/network/driver/ovn: Create internal router port
before DHCP option setup
Keeps DHCP setup steps together.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 60 +++++++++++++++++++++------------------
1 file changed, 32 insertions(+), 28 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index f386d3a6c9..6ce441e752 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1722,6 +1722,38 @@ func (n *ovn) setup(update bool) error {
return errors.Wrapf(err, "Failed setting IP allocation settings on internal switch")
}
+ // Gather internal router port IPs (in CIDR format).
+ intRouterIPs := []*net.IPNet{}
+
+ if routerIntPortIPv4Net != nil {
+ intRouterIPs = append(intRouterIPs, &net.IPNet{
+ IP: routerIntPortIPv4,
+ Mask: routerIntPortIPv4Net.Mask,
+ })
+ }
+
+ if routerIntPortIPv6Net != nil {
+ intRouterIPs = append(intRouterIPs, &net.IPNet{
+ IP: routerIntPortIPv6,
+ Mask: routerIntPortIPv6Net.Mask,
+ })
+ }
+
+ if len(intRouterIPs) <= 0 {
+ return fmt.Errorf("No internal IPs defined for network router")
+ }
+
+ // Create internal router port.
+ err = client.LogicalRouterPortAdd(n.getRouterName(), n.getRouterIntPortName(), routerMAC, intRouterIPs, update)
+ if err != nil {
+ return errors.Wrapf(err, "Failed adding internal router port")
+ }
+
+ if !update {
+ revert.Add(func() { client.LogicalRouterPortDelete(n.getRouterIntPortName()) })
+ }
+
+ // Configure DHCP option sets.
var dhcpv4UUID, dhcpv6UUID string
dhcpV4Subnet := n.DHCPv4Subnet()
dhcpV6Subnet := n.DHCPv6Subnet()
@@ -1763,27 +1795,6 @@ func (n *ovn) setup(update bool) error {
}
}
- // Internal router port IPs (in CIDR format).
- intRouterIPs := []*net.IPNet{}
-
- if routerIntPortIPv4Net != nil {
- intRouterIPs = append(intRouterIPs, &net.IPNet{
- IP: routerIntPortIPv4,
- Mask: routerIntPortIPv4Net.Mask,
- })
- }
-
- if routerIntPortIPv6Net != nil {
- intRouterIPs = append(intRouterIPs, &net.IPNet{
- IP: routerIntPortIPv6,
- Mask: routerIntPortIPv6Net.Mask,
- })
- }
-
- if len(intRouterIPs) <= 0 {
- return fmt.Errorf("No IPs defined for network router")
- }
-
// Create DHCPv4 options for internal switch.
if dhcpV4Subnet != nil {
err = client.LogicalSwitchDHCPv4OptionsSet(n.getIntSwitchName(), dhcpv4UUID, dhcpV4Subnet, &openvswitch.OVNDHCPv4Opts{
@@ -1812,13 +1823,6 @@ func (n *ovn) setup(update bool) error {
}
}
- // Create internal router port.
- err = client.LogicalRouterPortAdd(n.getRouterName(), n.getRouterIntPortName(), routerMAC, intRouterIPs...)
- if err != nil {
- return errors.Wrapf(err, "Failed adding internal router port")
- }
- revert.Add(func() { client.LogicalRouterPortDelete(n.getRouterIntPortName()) })
-
// Set IPv6 router advertisement settings.
if dhcpV6Subnet != nil {
adressMode := openvswitch.OVNIPv6AddressModeSLAAC
From 2b3cf479b84ce250ea8b90890fb5ade64e3ff1db Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 18:12:33 +0000
Subject: [PATCH 15/16] lxd/network/driver/ovn: Modifies IPv6 RA settings and
removes them entirely when IPv6 disabled
Settings change to:
- ipv6.dhcp = false
RA with slaac
- ipv6.dhcp = true
RA with stateless DHCP
- ipv6.dhcp = true and ipv6.dhcp.stateful = true
RA with stateful DHCP
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 6ce441e752..630ae3c914 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -1824,10 +1824,13 @@ func (n *ovn) setup(update bool) error {
}
// Set IPv6 router advertisement settings.
- if dhcpV6Subnet != nil {
+ if routerIntPortIPv6Net != nil {
adressMode := openvswitch.OVNIPv6AddressModeSLAAC
- if shared.IsTrue(n.config["ipv6.dhcp.stateful"]) {
- adressMode = openvswitch.OVNIPv6AddressModeDHCPStateful
+ if dhcpV6Subnet != nil {
+ adressMode = openvswitch.OVNIPv6AddressModeDHCPStateless
+ if shared.IsTrue(n.config["ipv6.dhcp.stateful"]) {
+ adressMode = openvswitch.OVNIPv6AddressModeDHCPStateful
+ }
}
var recursiveDNSServer net.IP
@@ -1850,6 +1853,11 @@ func (n *ovn) setup(update bool) error {
if err != nil {
return errors.Wrapf(err, "Failed setting internal router port IPv6 advertisement settings")
}
+ } else {
+ err = client.LogicalRouterPortDeleteIPv6Advertisements(n.getRouterIntPortName())
+ if err != nil {
+ return errors.Wrapf(err, "Failed removing internal router port IPv6 advertisement settings")
+ }
}
// Create internal switch port and link to router port.
From f486c839c6f9cc884ba40d3cc67031aab69dbe0f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 18 Dec 2020 18:14:07 +0000
Subject: [PATCH 16/16] lxd/network/driver/ovn: Don't return DHCPv6 subnet if
IPv6 prefix smaller than /64
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/network/driver_ovn.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go
index 630ae3c914..6f2d9d7d39 100644
--- a/lxd/network/driver_ovn.go
+++ b/lxd/network/driver_ovn.go
@@ -2585,6 +2585,11 @@ func (n *ovn) DHCPv6Subnet() *net.IPNet {
return nil
}
+ ones, _ := subnet.Mask.Size()
+ if ones > 64 {
+ return nil // OVN only supports DHCPv6 allocated using EUI64 (which requires at least a /64).
+ }
+
return subnet
}
More information about the lxc-devel
mailing list