[lxc-devel] [lxd/master] network: Allow adding static routes to a bridge

stgraber on Github lxc-bot at linuxcontainers.org
Wed Dec 7 17:00:57 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161207/b94d739f/attachment.bin>
-------------- next part --------------
From 64061fff291ce31912d2e15c47213d2b7e921300 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 7 Dec 2016 17:59:22 +0100
Subject: [PATCH] network: Allow adding static routes to a bridge
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #2701

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 doc/api-extensions.md  |  3 +++
 doc/configuration.md   |  2 ++
 lxd/api_1.0.go         |  1 +
 lxd/networks.go        | 36 ++++++++++++++++++++++++++++++++++--
 lxd/networks_config.go |  2 ++
 5 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index d273d29..32a6e43 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -173,3 +173,6 @@ rules will still be added so long as the matching "ipv4.nat" or
 
 Rules necessary for dnsmasq to work (DHCP/DNS) will always be applied if
 dnsmasq is enabled on the bridge.
+
+## network\_routes
+Introduces "ipv4.routes" and "ipv6.routes" which allow routing additional subnets to a LXD bridge.
diff --git a/doc/configuration.md b/doc/configuration.md
index 3f7abe9..74c4721 100644
--- a/doc/configuration.md
+++ b/doc/configuration.md
@@ -356,6 +356,7 @@ ipv4.nat                        | boolean   | ipv4 address          | false
 ipv4.dhcp                       | boolean   | ipv4 address          | true                      | Whether to allocate addresses using DHCP
 ipv4.dhcp.ranges                | string    | ipv4 dhcp             | all addresses             | Comma separated list of IP ranges to use for DHCP (FIRST-LAST format)
 ipv4.firewall                   | boolean   | ipv4 address          | true                      | Whether to generate filtering firewall rules for this network
+ipv4.routes                     | string    | ipv4 address          | -                         | Comma separated list of additional IPv4 CIDR subnets to route to the bridge
 ipv4.routing                    | boolean   | ipv4 address          | true                      | Whether to route traffic in and out of the bridge
 ipv6.address                    | string    | standard mode         | random unused subnet      | IPv6 address for the bridge (CIDR notation). Use "none" to turn off IPv6 or "auto" to generate a new one
 ipv6.nat                        | boolean   | ipv6 address          | false                     | Whether to NAT (will default to true if unset and a random ipv6.address is generated)
@@ -363,6 +364,7 @@ ipv6.dhcp                       | boolean   | ipv6 address          | true
 ipv6.dhcp.stateful              | boolean   | ipv6 dhcp             | false                     | Whether to allocate addresses using DHCP
 ipv6.dhcp.ranges                | string    | ipv6 stateful dhcp    | all addresses             | Comma separated list of IPv6 ranges to use for DHCP (FIRST-LAST format)
 ipv6.firewall                   | boolean   | ipv6 address          | true                      | Whether to generate filtering firewall rules for this network
+ipv6.routes                     | string    | ipv6 address          | -                         | Comma separated list of additional IPv6 CIDR subnets to route to the bridge
 ipv6.routing                    | boolean   | ipv6 address          | true                      | Whether to route traffic in and out of the bridge
 dns.domain                      | string    | -                     | lxd                       | Domain to advertise to DHCP clients and use for DNS resolution
 dns.mode                        | string    | -                     | managed                   | DNS registration mode ("none" for no DNS record, "managed" for LXD generated static records or "dynamic" for client generated records)
diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index 6ba872a..8ffd973 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -80,6 +80,7 @@ func api10Get(d *Daemon, r *http.Request) Response {
 			"migration_progress",
 			"id_map",
 			"network_firewall_filtering",
+			"network_routes",
 		},
 
 		"api_status":  "stable",
diff --git a/lxd/networks.go b/lxd/networks.go
index fd36c14..208a70b 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -649,12 +649,17 @@ func (n *network) Start() error {
 		return err
 	}
 
-	// Flush all IPv4 addresses
+	// Flush all IPv4 addresses and routes
 	err = shared.RunCommand("ip", "-4", "addr", "flush", "dev", n.name, "scope", "global")
 	if err != nil {
 		return err
 	}
 
+	err = shared.RunCommand("ip", "-4", "route", "flush", "dev", n.name, "proto", "static")
+	if err != nil {
+		return err
+	}
+
 	// Configure IPv4 firewall (includes fan)
 	if n.config["bridge.mode"] == "fan" || !shared.StringInSlice(n.config["ipv4.address"], []string{"", "none"}) {
 		// Setup basic iptables overrides
@@ -756,6 +761,17 @@ func (n *network) Start() error {
 				return err
 			}
 		}
+
+		// Add additional routes
+		if n.config["ipv4.routes"] != "" {
+			for _, route := range strings.Split(n.config["ipv4.routes"], ",") {
+				route = strings.TrimSpace(route)
+				err = shared.RunCommand("ip", "-4", "route", "add", "dev", n.name, route, "proto", "static")
+				if err != nil {
+					return err
+				}
+			}
+		}
 	}
 
 	// Remove any existing IPv6 iptables rules
@@ -769,12 +785,17 @@ func (n *network) Start() error {
 		return err
 	}
 
-	// Flush all IPv6 addresses
+	// Flush all IPv6 addresses and routes
 	err = shared.RunCommand("ip", "-6", "addr", "flush", "dev", n.name, "scope", "global")
 	if err != nil {
 		return err
 	}
 
+	err = shared.RunCommand("ip", "-6", "route", "flush", "dev", n.name, "proto", "static")
+	if err != nil {
+		return err
+	}
+
 	// Configure IPv6
 	if !shared.StringInSlice(n.config["ipv6.address"], []string{"", "none"}) {
 		// Enable IPv6 for the subnet
@@ -895,6 +916,17 @@ func (n *network) Start() error {
 				return err
 			}
 		}
+
+		// Add additional routes
+		if n.config["ipv6.routes"] != "" {
+			for _, route := range strings.Split(n.config["ipv6.routes"], ",") {
+				route = strings.TrimSpace(route)
+				err = shared.RunCommand("ip", "-6", "route", "add", "dev", n.name, route, "proto", "static")
+				if err != nil {
+					return err
+				}
+			}
+		}
 	}
 
 	// Configure the fan
diff --git a/lxd/networks_config.go b/lxd/networks_config.go
index 1ed3b53..0270045 100644
--- a/lxd/networks_config.go
+++ b/lxd/networks_config.go
@@ -63,6 +63,7 @@ var networkConfigKeys = map[string]func(value string) error{
 	"ipv4.nat":         shared.IsBool,
 	"ipv4.dhcp":        shared.IsBool,
 	"ipv4.dhcp.ranges": shared.IsAny,
+	"ipv4.routes":      shared.IsAny,
 	"ipv4.routing":     shared.IsBool,
 
 	"ipv6.address": func(value string) error {
@@ -77,6 +78,7 @@ var networkConfigKeys = map[string]func(value string) error{
 	"ipv6.dhcp":          shared.IsBool,
 	"ipv6.dhcp.stateful": shared.IsBool,
 	"ipv6.dhcp.ranges":   shared.IsAny,
+	"ipv6.routes":        shared.IsAny,
 	"ipv6.routing":       shared.IsBool,
 
 	"dns.domain": shared.IsAny,


More information about the lxc-devel mailing list