patchpanel: Disable and re-enable IPv6 on IPv6 forwarding update

On Linux IPv6 provisioning is triggered by reception of ICMP6 RA
packets from the IPv6 router. When the interface setup changes,
it is not guaranteed that an RA will arrive immediately so the
namespace needs to poke the router with an RS packet. Without,
this patch IPv6 will not be available right away when there
is a setup change.

One way to fix this is by disabling and re-enabling IPv6. This
will trigger SLAAC in the kernel and an RS will be sent.

BUG=b:182148635
TEST=Connected to ethernet and WiFi;
     Ran:
       - ifconfig eth0 down;
       - ip netns exec connected_netns_0 ping6 <IPV6_ADDR>;
     Without this patch, observe that the ping is failing.
     With this patch, observe that the ping is running.
TEST=units;
TEST=datapath fuzzer;
TEST=make sure that host IPv6 is not restarted;

Change-Id: I171a5670c352299060689b649723d33d40ec0d10
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3081076
Tested-by: Jason Jeremy Iman <jasongustaman@chromium.org>
Commit-Queue: Jason Jeremy Iman <jasongustaman@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/system.cc b/patchpanel/system.cc
index f91f9f7..3970405 100644
--- a/patchpanel/system.cc
+++ b/patchpanel/system.cc
@@ -26,6 +26,9 @@
 // /proc/sys path for controlling connection tracking helper modules
 constexpr const char kSysNetConntrackHelperPath[] =
     "/proc/sys/net/netfilter/nf_conntrack_helper";
+// Enables/Disables IPv6.
+constexpr const char kSysNetDisableIPv6Path[] =
+    "/proc/sys/net/ipv6/conf/all/disable_ipv6";
 // Prefix for IPv4 interface configuration.
 constexpr const char kSysNetIPv4ConfPrefix[] = "/proc/sys/net/ipv4/conf/";
 // Suffix for allowing localhost as a source or destination when routing IPv4.
@@ -89,6 +92,8 @@
                    content);
     case ConntrackHelper:
       return Write(kSysNetConntrackHelperPath, content);
+    case SysNet::IPv6Disable:
+      return Write(kSysNetDisableIPv6Path, content);
     default:
       LOG(ERROR) << "Unknown SysNet value " << target;
       return false;