diff mbox

[5/5] hotplug/linux: Add IPv6 support to vif-route

Message ID 1485276561-8103-6-git-send-email-s.munaut@whatever-company.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sylvain Munaut Jan. 24, 2017, 4:49 p.m. UTC
Signed-off-by: Sylvain Munaut <s.munaut@whatever-company.com>
---
 docs/man/xl-network-configuration.markdown.5 |  9 ++++++++
 tools/hotplug/Linux/vif-common.sh            | 33 ++++++++++++++++++++++++++++
 tools/hotplug/Linux/vif-route                | 20 ++++++++++++++++-
 tools/libxl/libxl_nic.c                      |  5 +++++
 tools/libxl/libxl_types.idl                  |  1 +
 tools/libxl/xl_cmdimpl.c                     |  7 ++++++
 6 files changed, 74 insertions(+), 1 deletion(-)

Comments

Ian Jackson Jan. 24, 2017, 5:45 p.m. UTC | #1
Sylvain Munaut writes ("[PATCH 5/5] hotplug/linux: Add IPv6 support to vif-route"):
> Signed-off-by: Sylvain Munaut <s.munaut@whatever-company.com>
> ---
>  docs/man/xl-network-configuration.markdown.5 |  9 ++++++++
>  tools/hotplug/Linux/vif-common.sh            | 33 ++++++++++++++++++++++++++++
>  tools/hotplug/Linux/vif-route                | 20 ++++++++++++++++-
>  tools/libxl/libxl_nic.c                      |  5 +++++
>  tools/libxl/libxl_types.idl                  |  1 +
>  tools/libxl/xl_cmdimpl.c                     |  7 ++++++
>  6 files changed, 74 insertions(+), 1 deletion(-)

I'm afraid I don't really understand IPv6 neighbour discovery
etc. well enough to review this.

Can you point me to an explanation ?  (I understand IPv4 quite well.)

> diff --git a/docs/man/xl-network-configuration.markdown.5 b/docs/man/xl-network-configuration.markdown.5
> index 5b86974..ce0da42 100644
> --- a/docs/man/xl-network-configuration.markdown.5
> +++ b/docs/man/xl-network-configuration.markdown.5
> @@ -143,6 +143,15 @@ address globally if necessary. This is of course only usable for the
>  vif-bridge script as the vif-route will require a fully defined address
>  in the 'ip' field.
>  
> +### ipv6_proxy_ndp
> +
> +Enabling this option will cause the Dom0 to answer the IPv6 Neighbor
> +Sollicitation messages it sees on 'gatewaydev' for the VM IPs.

 Solicitation

Thanks,
Ian.
Sylvain Munaut Jan. 24, 2017, 5:57 p.m. UTC | #2
Hi,

> I'm afraid I don't really understand IPv6 neighbour discovery
> etc. well enough to review this.
>
> Can you point me to an explanation ?  (I understand IPv4 quite well.)

It's pretty much that same as IPv4 except instead of being a different
protocol (ARP), it's done over ICMPv6 with special multicast
addresses.

https://en.wikipedia.org/wiki/Neighbor_Discovery_Protocol
http://www.cisco.com/c/dam/en/us/td/i/000001-100000/50001-55000/52501-53000/52673.ps/_jcr_content/renditions/52673.jpg

The kernel has a 'proxy_ndp' mode that's similar to 'proxy_arp' except
you need to manually specify which address you want it to proxy and on
which interface.


Cheers,

   Sylvain Munaut
diff mbox

Patch

diff --git a/docs/man/xl-network-configuration.markdown.5 b/docs/man/xl-network-configuration.markdown.5
index 5b86974..ce0da42 100644
--- a/docs/man/xl-network-configuration.markdown.5
+++ b/docs/man/xl-network-configuration.markdown.5
@@ -143,6 +143,15 @@  address globally if necessary. This is of course only usable for the
 vif-bridge script as the vif-route will require a fully defined address
 in the 'ip' field.
 
+### ipv6_proxy_ndp
+
+Enabling this option will cause the Dom0 to answer the IPv6 Neighbor
+Sollicitation messages it sees on 'gatewaydev' for the VM IPs.
+
+Valid values are 'no' & 'yes'. Defaults to 'no'.
+
+This feature is currently only supported in the linux hotplug script.
+
 ### backend
 
 Specifies the backend domain which this device should attach to. This
diff --git a/tools/hotplug/Linux/vif-common.sh b/tools/hotplug/Linux/vif-common.sh
index b92c36c..d5d98a7 100644
--- a/tools/hotplug/Linux/vif-common.sh
+++ b/tools/hotplug/Linux/vif-common.sh
@@ -346,3 +346,36 @@  dom0_ip()
   fi
   echo "$result"
 }
+
+
+##
+# ip6_of interface
+#
+# Print the first IPv6 address currently in use at the given interface, or nothing if
+# the interface is not up.
+#
+ip6_of()
+{
+  ip -6 -o addr show primary dev "$1" scope global | awk '$3 == "inet6" {split($4,i,"/"); print i[1]; exit}'
+}
+
+
+##
+# dom0_ip6
+#
+# Print the IPv6 address of the interface in dom0 through which we are routing.
+# This is the IP address on the interface specified as "netdev" as a parameter
+# to these scripts, or eth0 by default.  This function will return nothing if no
+# such interface could be found.
+#
+dom0_ip6()
+{
+  local nd=${netdev:-eth0}
+  local result=$(ip6_of "$nd")
+  if [ -z "$result" ]
+  then
+        ""
+  else
+        echo "$result"
+  fi
+}
diff --git a/tools/hotplug/Linux/vif-route b/tools/hotplug/Linux/vif-route
index c149ffc..f07cd75 100644
--- a/tools/hotplug/Linux/vif-route
+++ b/tools/hotplug/Linux/vif-route
@@ -20,11 +20,21 @@  dir=$(dirname "$0")
 . "${dir}/vif-common.sh"
 
 main_ip=$(dom0_ip)
+main_ip6=$(dom0_ip6)
+
+ipv6_proxy_ndp=$(xenstore_read_default "$XENBUS_PATH/ipv6_proxy_ndp" "0")
+
 
 case "${command}" in
     online)
         ifconfig ${dev} ${main_ip} netmask 255.255.255.255 up
         echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp
+        if [ ! -z "${main_ip6}" ]; then
+            ip -6 addr add ${main_ip6} dev ${dev}
+            if [ "${ipv6_proxy_ndp}" != "0" ]; then
+                echo 1 >/proc/sys/net/ipv6/conf/${dev}/proxy_ndp
+            fi
+        fi
         ipcmd='add'
         cmdprefix=''
         ;;
@@ -39,7 +49,15 @@  if [ "${ip}" ] ; then
     # If we've been given a list of IP addresses, then add routes from dom0 to
     # the guest using those addresses.
     for addr in ${ip} ; do
-      ${cmdprefix} ip route ${ipcmd} ${addr} dev ${dev} src ${main_ip}
+        result=$(is_ipv6 "${addr}")
+        if [ -z "${result}" ] ; then
+            ${cmdprefix} ip route ${ipcmd} ${addr} dev ${dev} src ${main_ip}
+        else
+            ${cmdprefix} ip -6 route ${ipcmd} ${addr} dev ${dev} src ${main_ip6}
+            if [ "${ipv6_proxy_ndp}" != "0" ]; then
+                ${cmdprefix} ip -6 neighbor ${ipcmd} proxy ${addr} dev ${netdev:-eth0}
+            fi
+        fi
     done
 fi
 
diff --git a/tools/libxl/libxl_nic.c b/tools/libxl/libxl_nic.c
index 61b55ca..47b0a63 100644
--- a/tools/libxl/libxl_nic.c
+++ b/tools/libxl/libxl_nic.c
@@ -214,6 +214,11 @@  static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
                             nic->rate_interval_usecs));
     }
 
+    if (!libxl_defbool_is_default(nic->ipv6_proxy_ndp)) {
+        flexarray_append_pair(back,"ipv6_proxy_ndp",
+            libxl_defbool_val(nic->ipv6_proxy_ndp) ? "1" : "0");
+    }
+
     flexarray_append(back, "bridge");
     flexarray_append(back, libxl__strdup(gc, nic->bridge));
     flexarray_append(back, "handle");
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index a612d1f..628b102 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -626,6 +626,7 @@  libxl_device_nic = Struct("device_nic", [
     ("rate_bytes_per_interval", uint64),
     ("rate_interval_usecs", uint32),
     ("gatewaydev", string),
+    ("ipv6_proxy_ndp", libxl_defbool),
     # Note that the COLO configuration settings should be considered unstable.
     # They may change incompatibly in future versions of Xen.
     ("coloft_forwarddev", string)
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 7e8a8ae..9996c61 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1059,6 +1059,13 @@  static int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *to
         parse_vif_rate(config, oparg, nic);
     } else if (MATCH_OPTION("forwarddev", token, oparg)) {
         replace_string(&nic->coloft_forwarddev, oparg);
+    } else if (MATCH_OPTION("ipv6_proxy_ndp", token, oparg)) {
+	if (!strcasecmp(oparg, "on") || !strcasecmp(oparg, "1"))
+		libxl_defbool_set(&nic->ipv6_proxy_ndp, true);
+	else if (!strcasecmp(oparg, "off") || !strcasecmp(oparg, "0"))
+		libxl_defbool_set(&nic->ipv6_proxy_ndp, false);
+	else
+		fprintf(stderr, "Invalid value for 'ipv6_proxy_ndp' parameter\n");
     } else if (MATCH_OPTION("accel", token, oparg)) {
         fprintf(stderr, "the accel parameter for vifs is currently not supported\n");
     } else {