github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadget-collection/gadgets/trace/network/gadget.go (about) 1 // Copyright 2019-2022 The Inspektor Gadget authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package networkgraph 16 17 import ( 18 "fmt" 19 20 "sigs.k8s.io/controller-runtime/pkg/client" 21 22 gadgetv1alpha1 "github.com/inspektor-gadget/inspektor-gadget/pkg/apis/gadget/v1alpha1" 23 "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection/networktracer" 24 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-collection/gadgets" 25 netTracer "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/network/tracer" 26 netTypes "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/network/types" 27 "github.com/inspektor-gadget/inspektor-gadget/pkg/operators" 28 "github.com/inspektor-gadget/inspektor-gadget/pkg/operators/kubeipresolver" 29 "github.com/inspektor-gadget/inspektor-gadget/pkg/operators/kubenameresolver" 30 "github.com/inspektor-gadget/inspektor-gadget/pkg/operators/socketenricher" 31 eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types" 32 ) 33 34 type Trace struct { 35 helpers gadgets.GadgetHelpers 36 client client.Client 37 38 started bool 39 40 tracer *netTracer.Tracer 41 conn *networktracer.ConnectionToContainerCollection 42 43 kubeIPInst operators.OperatorInstance 44 kubeNameInst operators.OperatorInstance 45 socketEnricherInst operators.OperatorInstance 46 } 47 48 type TraceFactory struct { 49 gadgets.BaseFactory 50 } 51 52 func NewFactory() gadgets.TraceFactory { 53 return &TraceFactory{ 54 BaseFactory: gadgets.BaseFactory{DeleteTrace: deleteTrace}, 55 } 56 } 57 58 func (f *TraceFactory) Description() string { 59 return `The network-graph gadget monitors the network activity in the specified pods and records the list of TCP connections and UDP streams.` 60 } 61 62 func (f *TraceFactory) OutputModesSupported() map[gadgetv1alpha1.TraceOutputMode]struct{} { 63 return map[gadgetv1alpha1.TraceOutputMode]struct{}{ 64 gadgetv1alpha1.TraceOutputModeStream: {}, 65 } 66 } 67 68 func deleteTrace(name string, t interface{}) { 69 trace := t.(*Trace) 70 if trace.started { 71 trace.stop() 72 } 73 } 74 75 func (f *TraceFactory) Operations() map[gadgetv1alpha1.Operation]gadgets.TraceOperation { 76 n := func() interface{} { 77 return &Trace{ 78 client: f.Client, 79 helpers: f.Helpers, 80 } 81 } 82 83 return map[gadgetv1alpha1.Operation]gadgets.TraceOperation{ 84 gadgetv1alpha1.OperationStart: { 85 Doc: "Start network-graph", 86 Operation: func(name string, trace *gadgetv1alpha1.Trace) { 87 f.LookupOrCreate(name, n).(*Trace).Start(trace) 88 }, 89 }, 90 gadgetv1alpha1.OperationStop: { 91 Doc: "Stop network-graph", 92 Operation: func(name string, trace *gadgetv1alpha1.Trace) { 93 f.LookupOrCreate(name, n).(*Trace).Stop(trace) 94 }, 95 }, 96 } 97 } 98 99 func (t *Trace) publishEvent( 100 trace *gadgetv1alpha1.Trace, 101 event *netTypes.Event, 102 ) { 103 traceName := gadgets.TraceName(trace.ObjectMeta.Namespace, trace.ObjectMeta.Name) 104 t.helpers.PublishEvent( 105 traceName, 106 eventtypes.EventString(event), 107 ) 108 } 109 110 func (t *Trace) Start(trace *gadgetv1alpha1.Trace) { 111 if t.started { 112 trace.Status.State = gadgetv1alpha1.TraceStateStarted 113 return 114 } 115 116 var err error 117 t.tracer, err = netTracer.NewTracer() 118 if err != nil { 119 trace.Status.OperationError = fmt.Sprintf("Failed to start network-graph tracer: %s", err) 120 return 121 } 122 123 // TODO: Don't access the operators directly 124 // - update cmd/kubectl-gadget/advise/network-policy.go to use the gRPC interface instead of the CR one 125 // - delete this file pkg/gadget-collection/gadgets/trace/network/gadget.go 126 kubeIPOp := operators.GetRaw(kubeipresolver.OperatorName).(*kubeipresolver.KubeIPResolver) 127 kubeIPOp.Init(nil) 128 t.kubeIPInst, err = kubeIPOp.Instantiate(nil, nil, nil) 129 if err == nil { 130 t.kubeIPInst.PreGadgetRun() 131 } 132 133 kubeNameOp := operators.GetRaw(kubenameresolver.OperatorName).(*kubenameresolver.KubeNameResolver) 134 kubeNameOp.Init(nil) 135 t.kubeNameInst, err = kubeNameOp.Instantiate(nil, nil, nil) 136 if err == nil { 137 t.kubeNameInst.PreGadgetRun() 138 } 139 140 socketEnricherOp := operators.GetRaw(socketenricher.OperatorName).(*socketenricher.SocketEnricher) 141 socketEnricherOp.Init(nil) 142 t.socketEnricherInst, err = socketEnricherOp.Instantiate(nil, t.tracer, nil) 143 if err == nil { 144 t.socketEnricherInst.PreGadgetRun() 145 } 146 147 eventCallback := func(event *netTypes.Event) { 148 // Enrich event but only with the fields required for the advise network-policy gadget. 149 event.K8s.Node = trace.Spec.Node 150 if t.helpers != nil { 151 t.helpers.EnrichByNetNs(&event.CommonData, event.WithNetNsID.NetNsID) 152 } 153 154 // Use KubeIPResolver and KubeNameResolver to enrich event based on Namespace/Pod and IP. 155 if t.kubeIPInst != nil { 156 t.kubeIPInst.EnrichEvent(event) 157 } 158 if t.kubeNameInst != nil { 159 t.kubeNameInst.EnrichEvent(event) 160 } 161 162 t.publishEvent(trace, event) 163 } 164 t.tracer.SetEventHandler(eventCallback) 165 166 config := &networktracer.ConnectToContainerCollectionConfig[netTypes.Event]{ 167 Tracer: t.tracer, 168 Resolver: t.helpers, 169 Selector: *gadgets.ContainerSelectorFromContainerFilter(trace.Spec.Filter), 170 Base: netTypes.Base, 171 } 172 t.conn, err = networktracer.ConnectToContainerCollection(config) 173 if err != nil { 174 trace.Status.OperationError = fmt.Sprintf("Failed to start network-graph tracer: %s", err) 175 return 176 } 177 178 if err := t.tracer.RunWorkaround(); err != nil { 179 trace.Status.OperationError = fmt.Sprintf("Failed to start network-graph tracer: %s", err) 180 return 181 } 182 183 t.started = true 184 trace.Status.State = gadgetv1alpha1.TraceStateStarted 185 } 186 187 func (t *Trace) Stop(trace *gadgetv1alpha1.Trace) { 188 if !t.started { 189 trace.Status.OperationError = "Not started" 190 return 191 } 192 193 t.stop() 194 trace.Status.State = gadgetv1alpha1.TraceStateStopped 195 } 196 197 func (t *Trace) stop() { 198 if t.conn != nil { 199 t.conn.Close() 200 } 201 if t.kubeIPInst != nil { 202 t.kubeIPInst.PostGadgetRun() 203 t.kubeIPInst = nil 204 } 205 if t.kubeNameInst != nil { 206 t.kubeNameInst.PostGadgetRun() 207 t.kubeNameInst = nil 208 } 209 if t.socketEnricherInst != nil { 210 t.socketEnricherInst.PostGadgetRun() 211 t.socketEnricherInst = nil 212 } 213 214 t.tracer.Close() 215 t.tracer = nil 216 t.started = false 217 }