[ipxe-devel] [PATCH 4/7] ipv6: Allow manual network configuration

Hannes Reinecke hare at suse.de
Wed Apr 1 07:26:18 UTC 2015


Not on every system IPv6 autoconfiguration is working properly,
so allow for manual network configuration here.
Note: this configures the global route only. Link-local routes
are configured automatically.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 src/include/ipxe/dhcpv6.h   |  4 +++
 src/include/ipxe/ipv6.h     | 42 ++++++++++++++++++++++++++
 src/include/ipxe/settings.h |  9 ++++++
 src/net/ipv6.c              | 72 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 127 insertions(+)

diff --git a/src/include/ipxe/dhcpv6.h b/src/include/ipxe/dhcpv6.h
index a6527c2..a869a4d 100644
--- a/src/include/ipxe/dhcpv6.h
+++ b/src/include/ipxe/dhcpv6.h
@@ -170,6 +170,10 @@ struct dhcpv6_user_class_option {
 /** DHCPv6 bootfile parameters option */
 #define DHCPV6_BOOTFILE_PARAM 60
 
+/** Setting tags */
+#define DHCPV6_EB_GATEWAY 25
+#define DHCPV6_EB_NETMASK 26
+
 /** DHCPv6 syslog server option
  *
  * This option code has not yet been assigned by IANA.  Please update
diff --git a/src/include/ipxe/ipv6.h b/src/include/ipxe/ipv6.h
index a2b4c88..c3d36e2 100644
--- a/src/include/ipxe/ipv6.h
+++ b/src/include/ipxe/ipv6.h
@@ -238,6 +238,48 @@ static inline void ipv6_all_routers ( struct in6_addr *addr ) {
 	addr->s6_addr[15] = 2;
 }
 
+/**
+ * Calculate prefix length from IPv6 netmask
+ *
+ * @v netmask		IPv6 address
+ * @ret prefix_len	Prefix length
+ */
+static inline int ipv6_prefix_len( struct in6_addr *netmask ) {
+	uint8_t *prefix_mask;
+	int prefix_len = 0;
+
+	/* Translate netmask into prefix length */
+	for ( prefix_mask = netmask->s6_addr;
+	      *prefix_mask == 0xff;
+	      prefix_mask++ ) {
+		prefix_len += 8;
+	}
+	switch (*prefix_mask) {
+	case 0xfe:
+		prefix_len += 7;
+		break;
+	case 0xfc:
+		prefix_len += 6;
+		break;
+	case 0xf8:
+		prefix_len += 5;
+		break;
+	case 0xf0:
+		prefix_len += 4;
+		break;
+	case 0xe0:
+		prefix_len += 3;
+		break;
+	case 0xc0:
+		prefix_len += 2;
+		break;
+	case 0x80:
+		prefix_len += 1;
+		break;
+	}
+	return prefix_len;
+}
+
 extern struct list_head ipv6_miniroutes;
 
 extern struct net_protocol ipv6_protocol __net_protocol;
diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h
index 45d600b..2b10781 100644
--- a/src/include/ipxe/settings.h
+++ b/src/include/ipxe/settings.h
@@ -74,6 +74,7 @@ struct setting {
 #define SETTING_AUTH_EXTRA	12 /**< Authentication additional settings */
 #define SETTING_CRYPTO		13 /**< Cryptography settings */
 #define SETTING_MISC		14 /**< Miscellaneous settings */
+#define SETTING_IPV6		15 /**< IPv6 settings */
 
 /** @} */
 
@@ -426,8 +427,16 @@ netmask_setting __setting ( SETTING_IP, netmask );
 extern const struct setting
 gateway_setting __setting ( SETTING_IP, gateway );
 extern const struct setting
+ip6_setting __setting ( SETTING_IPV6, ip6 );
+extern const struct setting
+netmask6_setting __setting ( SETTING_IPV6, netmask6 );
+extern const struct setting
+gateway6_setting __setting ( SETTING_IPV6, gateway6 );
+extern const struct setting
 dns_setting __setting ( SETTING_IP_EXTRA, dns );
 extern const struct setting
+dns6_setting __setting ( SETTING_IP_EXTRA, dns6 );
+extern const struct setting
 hostname_setting __setting ( SETTING_HOST, hostname );
 extern const struct setting
 domain_setting __setting ( SETTING_IP_EXTRA, domain );
diff --git a/src/net/ipv6.c b/src/net/ipv6.c
index 460f7b7..dd0a888 100644
--- a/src/net/ipv6.c
+++ b/src/net/ipv6.c
@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/ipstat.h>
 #include <ipxe/ndp.h>
 #include <ipxe/ipv6.h>
+#include <ipxe/dhcpv6.h>
 
 /** @file
  *
@@ -1083,6 +1084,32 @@ int format_ipv6_setting ( const struct setting_type *type __unused,
 	return snprintf ( buf, len, "%s", inet6_ntoa ( ipv6 ) );
 }
 
+/** IPv6 address setting */
+const struct setting ip6_setting __setting ( SETTING_IPV6, ip6 ) = {
+	.name = "ip6",
+	.description = "IPv6 address",
+	.tag = DHCPV6_IAADDR,
+	.type = &setting_type_ipv6,
+	.scope = &ipv6_scope,
+};
+
+/** IPv6 gateway setting */
+const struct setting gateway6_setting __setting ( SETTING_IPV6, gateway6 ) = {
+	.name = "gateway6",
+	.description = "IPv6 gateway",
+	.tag = DHCPV6_EB_GATEWAY,
+	.type = &setting_type_ipv6,
+	.scope = &ipv6_scope,
+};
+
+/** IPv6 netmask setting */
+const struct setting netmask6_setting __setting ( SETTING_IPV6, netmask6 ) = {
+	.name = "netmask6",
+	.description = "IPv6 netmask",
+	.tag = DHCPV6_EB_NETMASK,
+	.type = &setting_type_ipv6,
+	.scope = &ipv6_scope,
+};
 /**
  * Destroy IPv6 network device
  *
@@ -1108,6 +1135,51 @@ struct net_driver ipv6_driver __net_driver = {
 	.remove = ipv6_remove,
 };
 
+/**
+ * Update IPv6 routing table based on configured settings
+ *
+ * @ret rc		Return status code
+ */
+static int ipv6_update_routes ( void ) {
+	struct net_device *netdev;
+	struct settings *settings;
+	struct in6_addr address, empty;
+	struct in6_addr router, netmask;
+	int prefix_len = 64;
+
+	memset(&empty, 0, sizeof(address));
+	/* Update configured routes for each configured network device */
+	for_each_netdev ( netdev ) {
+		settings = netdev_settings ( netdev );
+		/* Get IPv6 address */
+		memset(&address, 0, sizeof(address));
+		fetch_ipv6_setting ( settings, &ip6_setting, &address );
+		if (!memcmp(&address, &empty, sizeof (address)))
+			continue;
+		/* Update address */
+		ipv6_set_address( netdev, &address );
+		/* Get IPv6 netmask */
+		memset(&netmask, 0, sizeof(netmask));
+		fetch_ipv6_setting( settings, &netmask6_setting, &netmask );
+		if (memcmp(&netmask, &empty, sizeof(netmask)))
+			prefix_len = ipv6_prefix_len( &netmask );
+		/* Get IPv6 router */
+		memset(&router, 0, sizeof(router));
+		fetch_ipv6_setting( settings, &gateway6_setting, &router );
+		if (!memcmp(&router, &empty, sizeof (router)))
+			continue;
+		/* Update routing table */
+		ipv6_set_prefix( netdev, &address, prefix_len, &router );
+	}
+
+	return 0;
+}
+
+/** IPv6 settings applicator */
+struct settings_applicator ipv6_settings_applicator __settings_applicator = {
+	.apply = ipv6_update_routes,
+};
+
 /* Drag in objects via ipv6_protocol */
 REQUIRING_SYMBOL ( ipv6_protocol );
 
-- 
1.8.4.5




More information about the ipxe-devel mailing list