github.com/cilium/cilium@v1.16.2/pkg/socketlb/socketlb.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package socketlb 5 6 import ( 7 "errors" 8 "fmt" 9 "os" 10 "path/filepath" 11 12 "github.com/cilium/ebpf" 13 14 "github.com/cilium/cilium/pkg/bpf" 15 "github.com/cilium/cilium/pkg/cgroups" 16 "github.com/cilium/cilium/pkg/datapath/linux/sysctl" 17 "github.com/cilium/cilium/pkg/logging" 18 "github.com/cilium/cilium/pkg/logging/logfields" 19 "github.com/cilium/cilium/pkg/option" 20 ) 21 22 const ( 23 Subsystem = "socketlb" 24 25 Connect4 = "cil_sock4_connect" 26 SendMsg4 = "cil_sock4_sendmsg" 27 RecvMsg4 = "cil_sock4_recvmsg" 28 GetPeerName4 = "cil_sock4_getpeername" 29 PostBind4 = "cil_sock4_post_bind" 30 PreBind4 = "cil_sock4_pre_bind" 31 Connect6 = "cil_sock6_connect" 32 SendMsg6 = "cil_sock6_sendmsg" 33 RecvMsg6 = "cil_sock6_recvmsg" 34 GetPeerName6 = "cil_sock6_getpeername" 35 PostBind6 = "cil_sock6_post_bind" 36 PreBind6 = "cil_sock6_pre_bind" 37 ) 38 39 var ( 40 log = logging.DefaultLogger.WithField(logfields.LogSubsys, Subsystem) 41 42 cgroupProgs = []string{ 43 Connect4, SendMsg4, RecvMsg4, GetPeerName4, 44 PostBind4, PreBind4, Connect6, SendMsg6, 45 RecvMsg6, GetPeerName6, PostBind6, PreBind6} 46 ) 47 48 // TODO: Clean up bpffs root logic and make this a var. 49 func cgroupLinkPath() string { 50 return filepath.Join(bpf.CiliumPath(), Subsystem, "links/cgroup") 51 } 52 53 // Enable attaches necessary bpf programs for socketlb based on ciliums config. 54 // 55 // On restart, Enable can also detach unnecessary programs if specific configuration 56 // options have changed. 57 // It expects bpf_sock.c to be compiled previously, so that bpf_sock.o is present 58 // in the Runtime dir. 59 func Enable(sysctl sysctl.Sysctl) error { 60 if err := os.MkdirAll(cgroupLinkPath(), 0777); err != nil { 61 return fmt.Errorf("create bpffs link directory: %w", err) 62 } 63 64 spec, err := bpf.LoadCollectionSpec(filepath.Join(option.Config.StateDir, "bpf_sock.o")) 65 if err != nil { 66 return fmt.Errorf("failed to load collection spec for bpf_sock.o: %w", err) 67 } 68 69 coll, commit, err := bpf.LoadCollection(spec, &bpf.CollectionOptions{ 70 CollectionOptions: ebpf.CollectionOptions{ 71 Maps: ebpf.MapOptions{PinPath: bpf.TCGlobalsPath()}, 72 }, 73 }) 74 var ve *ebpf.VerifierError 75 if errors.As(err, &ve) { 76 if _, err := fmt.Fprintf(os.Stderr, "Verifier error: %s\nVerifier log: %+v\n", err, ve); err != nil { 77 return fmt.Errorf("writing verifier log to stderr: %w", err) 78 } 79 } 80 if err != nil { 81 return fmt.Errorf("failed loading eBPF collection into the kernel: %w", err) 82 } 83 defer coll.Close() 84 85 // Map a program name to its enabled status. Programs disabled by default. 86 enabled := make(map[string]bool) 87 for _, p := range cgroupProgs { 88 enabled[p] = false 89 } 90 91 if option.Config.EnableIPv4 { 92 enabled[Connect4] = true 93 enabled[SendMsg4] = true 94 enabled[RecvMsg4] = true 95 96 if option.Config.EnableSocketLBPeer { 97 enabled[GetPeerName4] = true 98 } 99 100 if option.Config.EnableNodePort && option.Config.NodePortBindProtection { 101 enabled[PostBind4] = true 102 } 103 104 if option.Config.EnableHealthDatapath { 105 enabled[PreBind4] = true 106 } 107 } 108 109 // v6 will be non-nil if v6 support is compiled out. 110 _, v6 := sysctl.ReadInt([]string{"net", "ipv6", "conf", "all", "forwarding"}) 111 112 if option.Config.EnableIPv6 || 113 (option.Config.EnableIPv4 && v6 == nil) { 114 enabled[Connect6] = true 115 enabled[SendMsg6] = true 116 enabled[RecvMsg6] = true 117 118 if option.Config.EnableSocketLBPeer { 119 enabled[GetPeerName6] = true 120 } 121 122 if option.Config.EnableNodePort && option.Config.NodePortBindProtection { 123 enabled[PostBind6] = true 124 } 125 126 if option.Config.EnableHealthDatapath { 127 enabled[PreBind6] = true 128 } 129 } 130 131 for p, s := range enabled { 132 if s { 133 if err := attachCgroup(coll, p, cgroups.GetCgroupRoot(), cgroupLinkPath()); err != nil { 134 return fmt.Errorf("cgroup attach: %w", err) 135 } 136 continue 137 } 138 if err := detachCgroup(p, cgroups.GetCgroupRoot(), cgroupLinkPath()); err != nil { 139 return fmt.Errorf("cgroup detach: %w", err) 140 } 141 } 142 143 if err := commit(); err != nil { 144 return fmt.Errorf("committing bpf pins: %w", err) 145 } 146 147 return nil 148 } 149 150 // Disable detaches all bpf programs for socketlb. 151 func Disable() error { 152 for _, p := range cgroupProgs { 153 if err := detachCgroup(p, cgroups.GetCgroupRoot(), cgroupLinkPath()); err != nil { 154 return fmt.Errorf("detach cgroup: %w", err) 155 } 156 } 157 158 return nil 159 }