@@ -77,6 +77,9 @@ const (
77
77
encapTypeFOU = "fou"
78
78
encapTypeIPIP = "ipip"
79
79
80
+ ipipModev4 = "ipip"
81
+ ipipModev6 = "ip6ip6"
82
+
80
83
maxPort = uint16 (65535 )
81
84
minPort = uint16 (1024 )
82
85
)
@@ -656,7 +659,7 @@ func (nrc *NetworkRoutingController) injectRoute(path *gobgpapi.Path) error {
656
659
// if the user has disabled overlays, don't create tunnels. If we're not creating a tunnel, check to see if there is
657
660
// any cleanup that needs to happen.
658
661
if shouldCreateTunnel () {
659
- link , err = nrc .setupOverlayTunnel (tunnelName , nextHop )
662
+ link , err = nrc .setupOverlayTunnel (tunnelName , nextHop , dst )
660
663
if err != nil {
661
664
return err
662
665
}
@@ -741,60 +744,104 @@ func (nrc *NetworkRoutingController) cleanupTunnel(destinationSubnet *net.IPNet,
741
744
}
742
745
743
746
// setupOverlayTunnel attempts to create a tunnel link and corresponding routes for IPIP based overlay networks
744
- func (nrc * NetworkRoutingController ) setupOverlayTunnel (tunnelName string , nextHop net.IP ) (netlink.Link , error ) {
747
+ func (nrc * NetworkRoutingController ) setupOverlayTunnel (tunnelName string , nextHop net.IP ,
748
+ nextHopSubnet * net.IPNet ) (netlink.Link , error ) {
745
749
var out []byte
746
750
link , err := netlink .LinkByName (tunnelName )
747
751
748
752
var bestIPForFamily net.IP
749
- var ipipMode string
750
- var ipProto string
753
+ var ipipMode , fouLinkType string
754
+ isIPv6 := false
751
755
ipBase := make ([]string , 0 )
756
+ strFormattedEncapPort := strconv .FormatInt (int64 (nrc .overlayEncapPort ), 10 )
757
+
752
758
if nextHop .To4 () != nil {
753
759
bestIPForFamily = utils .FindBestIPv4NodeAddress (nrc .primaryIP , nrc .nodeIPv4Addrs )
754
- ipipMode = "ipip"
755
- ipProto = "4"
760
+ ipipMode = encapTypeIPIP
761
+ fouLinkType = ipipModev4
756
762
} else {
757
763
// Need to activate the ip command in IPv6 mode
758
764
ipBase = append (ipBase , "-6" )
759
765
bestIPForFamily = utils .FindBestIPv6NodeAddress (nrc .primaryIP , nrc .nodeIPv6Addrs )
760
- ipipMode = "ip6ip6"
761
- ipProto = "6"
766
+ ipipMode = ipipModev6
767
+ fouLinkType = "ip6tnl"
768
+ isIPv6 = true
762
769
}
763
770
if nil == bestIPForFamily {
764
771
return nil , fmt .Errorf ("not able to find an appropriate configured IP address on node for destination " +
765
772
"IP family: %s" , nextHop .String ())
766
773
}
767
774
775
+ // This indicated that the tunnel already exists, so it's possible that there might be nothing more needed. However,
776
+ // it is also possible that the user changed the encap type, so we need to make sure that the encap type matches
777
+ // and if it doesn't, create it
778
+ recreate := false
779
+ if err == nil {
780
+ klog .V (1 ).Infof ("Tunnel interface: %s with encap type %s for the node %s already exists." ,
781
+ tunnelName , link .Attrs ().EncapType , nextHop .String ())
782
+
783
+ switch nrc .overlayEncap {
784
+ case encapTypeIPIP :
785
+ if linkFOUEnabled (tunnelName ) {
786
+ klog .Infof ("Was configured to use ipip tunnels, but found existing fou tunnels in place, cleaning up" )
787
+ recreate = true
788
+
789
+ // Even though we are setup for IPIP tunels we have existing tunnels that are FoU tunnels, remove them
790
+ // so that we can recreate them as IPIP
791
+ nrc .cleanupTunnel (nextHopSubnet , tunnelName )
792
+
793
+ // If we are transitioning from FoU to IPIP we also need to clean up the old FoU port if it exists
794
+ if fouPortAndProtoExist (nrc .overlayEncapPort , isIPv6 ) {
795
+ fouArgs := ipBase
796
+ fouArgs = append (fouArgs , "fou" , "del" , "port" , strFormattedEncapPort )
797
+ out , err := exec .Command ("ip" , fouArgs ... ).CombinedOutput ()
798
+ if err != nil {
799
+ klog .Warningf ("failed to clean up previous FoU tunnel port (this is only a warning because it " +
800
+ "won't stop kube-router from working for now, but still shouldn't have happened) - error: " +
801
+ "%v, output %s" , err , out )
802
+ }
803
+ }
804
+ }
805
+ case encapTypeFOU :
806
+ if ! linkFOUEnabled (tunnelName ) {
807
+ klog .Infof ("Was configured to use fou tunnels, but found existing ipip tunnels in place, cleaning up" )
808
+ recreate = true
809
+ // Even though we are setup for FoU tunels we have existing tunnels that are IPIP tunnels, remove them
810
+ // so that we can recreate them as IPIP
811
+ nrc .cleanupTunnel (nextHopSubnet , tunnelName )
812
+ }
813
+ }
814
+ }
815
+
768
816
// an error here indicates that the tunnel didn't exist, so we need to create it, if it already exists there's
769
817
// nothing to do here
770
- if err != nil {
818
+ if err != nil || recreate {
819
+ klog .Infof ("Creating tunnel %s of type %s with encap %s for destination %s" ,
820
+ tunnelName , fouLinkType , nrc .overlayEncap , nextHop .String ())
771
821
cmdArgs := ipBase
772
822
switch nrc .overlayEncap {
773
- case "ipip" :
823
+ case encapTypeIPIP :
774
824
// Plain IPIP tunnel without any encapsulation
775
825
cmdArgs = append (cmdArgs , "tunnel" , "add" , tunnelName , "mode" , ipipMode , "local" , bestIPForFamily .String (),
776
826
"remote" , nextHop .String ())
777
- case "fou" :
778
- strFormattedEncapPort := strconv .FormatInt (int64 (nrc .overlayEncapPort ), 10 )
779
827
828
+ case encapTypeFOU :
780
829
// Ensure that the FOU tunnel port is set correctly
781
- cmdArgs = append (cmdArgs , "fou" , "show" )
782
- out , err := exec .Command ("ip" , cmdArgs ... ).CombinedOutput ()
783
- if err != nil || ! strings .Contains (string (out ), strFormattedEncapPort ) {
784
- //nolint:gocritic // we understand that we are appending to a new slice
785
- cmdArgs = append (ipBase , "fou" , "add" , "port" , strFormattedEncapPort , "ipproto" , ipProto )
786
- out , err := exec .Command ("ip" , cmdArgs ... ).CombinedOutput ()
830
+ if ! fouPortAndProtoExist (nrc .overlayEncapPort , isIPv6 ) {
831
+ fouArgs := ipBase
832
+ fouArgs = append (fouArgs , "fou" , "add" , "port" , strFormattedEncapPort , "gue" )
833
+ out , err := exec .Command ("ip" , fouArgs ... ).CombinedOutput ()
787
834
if err != nil {
788
835
return nil , fmt .Errorf ("route not injected for the route advertised by the node %s " +
789
836
"Failed to set FoU tunnel port - error: %s, output: %s" , tunnelName , err , string (out ))
790
837
}
791
838
}
792
839
793
840
// Prep IPIP tunnel for FOU encapsulation
794
- //nolint:gocritic // we understand that we are appending to a new slice
795
- cmdArgs = append (ipBase , "link" , "add" , "name" , tunnelName , "type" , "ipip" , "remote" , nextHop .String (),
796
- "local" , bestIPForFamily .String (), "ttl" , "225" , "encap" , "fou" , "encap-sport" , "auto" , "encap-dport" ,
841
+ cmdArgs = append (cmdArgs , "link" , "add" , "name" , tunnelName , "type" , fouLinkType , "remote" , nextHop .String (),
842
+ "local" , bestIPForFamily .String (), "ttl" , "225" , "encap" , "gue" , "encap-sport" , "auto" , "encap-dport" ,
797
843
strFormattedEncapPort , "mode" , ipipMode )
844
+
798
845
default :
799
846
return nil , fmt .Errorf ("unknown tunnel encapsulation was passed: %s, unable to continue with overlay " +
800
847
"setup" , nrc .overlayEncap )
@@ -821,9 +868,6 @@ func (nrc *NetworkRoutingController) setupOverlayTunnel(tunnelName string, nextH
821
868
if err = netlink .LinkSetUp (link ); err != nil {
822
869
return nil , errors .New ("Failed to bring tunnel interface " + tunnelName + " up due to: " + err .Error ())
823
870
}
824
- } else {
825
- klog .V (1 ).Infof (
826
- "Tunnel interface: " + tunnelName + " for the node " + nextHop .String () + " already exists." )
827
871
}
828
872
829
873
// Now that the tunnel link exists, we need to add a route to it, so the node knows where to send traffic bound for
0 commit comments