github.com/cilium/cilium@v1.16.2/pkg/signal/signal_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package signal 5 6 import ( 7 "bytes" 8 "encoding/binary" 9 "io" 10 "testing" 11 "time" 12 13 "github.com/cilium/ebpf/perf" 14 "github.com/stretchr/testify/require" 15 16 "github.com/cilium/cilium/pkg/byteorder" 17 "github.com/cilium/cilium/pkg/logging" 18 fakesignalmap "github.com/cilium/cilium/pkg/maps/signalmap/fake" 19 ) 20 21 type testReader struct { 22 paused bool 23 closed bool 24 cpu int 25 data []byte 26 lost uint64 27 } 28 29 func (r *testReader) Read() (perf.Record, error) { 30 if r.closed { 31 return perf.Record{}, io.EOF 32 } 33 return perf.Record{CPU: r.cpu, RawSample: r.data, LostSamples: r.lost}, nil 34 } 35 36 func (r *testReader) Pause() error { 37 r.paused = true 38 return nil 39 } 40 41 func (r *testReader) Resume() error { 42 r.paused = false 43 return nil 44 } 45 46 func (r *testReader) Close() error { 47 if r.closed { 48 return io.EOF 49 } 50 r.closed = true 51 return nil 52 } 53 54 func TestSignalSet(t *testing.T) { 55 buf := new(bytes.Buffer) 56 binary.Write(buf, byteorder.Native, SignalNatFillUp) 57 58 events := &testReader{cpu: 1, data: buf.Bytes()} 59 sm := &signalManager{events: events} 60 require.Equal(t, true, sm.isMuted()) 61 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 62 require.Equal(t, true, sm.isSignalMuted(SignalCTFillUp)) 63 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 64 65 // invalid signal, nothing changes 66 err := sm.UnmuteSignals(SignalType(16)) 67 require.Error(t, err) 68 require.ErrorContains(t, err, "signal number not supported: 16") 69 require.Equal(t, true, sm.isMuted()) 70 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 71 require.Equal(t, true, sm.isSignalMuted(SignalCTFillUp)) 72 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 73 74 // 2 active signals 75 err = sm.UnmuteSignals(SignalNatFillUp, SignalCTFillUp) 76 require.Nil(t, err) 77 require.Equal(t, false, sm.isMuted()) 78 require.Equal(t, false, sm.isSignalMuted(SignalNatFillUp)) 79 require.Equal(t, false, sm.isSignalMuted(SignalCTFillUp)) 80 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 81 82 require.Equal(t, false, events.paused) 83 require.Equal(t, false, events.closed) 84 85 // Mute one, one still active 86 err = sm.MuteSignals(SignalNatFillUp) 87 require.Nil(t, err) 88 require.Equal(t, false, sm.isMuted()) 89 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 90 require.Equal(t, false, sm.isSignalMuted(SignalCTFillUp)) 91 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 92 93 require.Equal(t, false, events.paused) 94 require.Equal(t, false, events.closed) 95 96 // Nothing happens if the signal is already muted 97 err = sm.MuteSignals(SignalNatFillUp) 98 require.Nil(t, err) 99 require.Equal(t, false, sm.isMuted()) 100 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 101 require.Equal(t, false, sm.isSignalMuted(SignalCTFillUp)) 102 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 103 104 require.Equal(t, false, events.paused) 105 require.Equal(t, false, events.closed) 106 107 // Unmute one more 108 err = sm.UnmuteSignals(SignalAuthRequired) 109 require.Nil(t, err) 110 require.Equal(t, false, sm.isMuted()) 111 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 112 require.Equal(t, false, sm.isSignalMuted(SignalCTFillUp)) 113 require.Equal(t, false, sm.isSignalMuted(SignalAuthRequired)) 114 115 require.Equal(t, false, events.paused) 116 require.Equal(t, false, events.closed) 117 118 // Last signala are muted 119 err = sm.MuteSignals(SignalCTFillUp, SignalAuthRequired) 120 require.Nil(t, err) 121 require.Equal(t, true, sm.isMuted()) 122 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 123 require.Equal(t, true, sm.isSignalMuted(SignalCTFillUp)) 124 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 125 126 require.Equal(t, true, events.paused) 127 require.Equal(t, false, events.closed) 128 129 // A signal is unmuted again 130 err = sm.UnmuteSignals(SignalCTFillUp) 131 require.Nil(t, err) 132 require.Equal(t, false, sm.isMuted()) 133 require.Equal(t, true, sm.isSignalMuted(SignalNatFillUp)) 134 require.Equal(t, false, sm.isSignalMuted(SignalCTFillUp)) 135 require.Equal(t, true, sm.isSignalMuted(SignalAuthRequired)) 136 137 require.Equal(t, false, events.paused) 138 require.Equal(t, false, events.closed) 139 } 140 141 type SignalData uint32 142 143 const ( 144 // SignalProtoV4 denotes IPv4 protocol 145 SignalProtoV4 SignalData = iota 146 // SignalProtoV6 denotes IPv6 protocol 147 SignalProtoV6 148 SignalProtoMax 149 ) 150 151 var signalProto = [SignalProtoMax]string{ 152 SignalProtoV4: "ipv4", 153 SignalProtoV6: "ipv6", 154 } 155 156 // String implements fmt.Stringer for SignalData 157 func (d SignalData) String() string { 158 return signalProto[d] 159 } 160 161 func TestLifeCycle(t *testing.T) { 162 logging.SetLogLevelToDebug() 163 164 buf1 := new(bytes.Buffer) 165 binary.Write(buf1, byteorder.Native, SignalNatFillUp) 166 binary.Write(buf1, byteorder.Native, SignalProtoV4) 167 168 buf2 := new(bytes.Buffer) 169 binary.Write(buf2, byteorder.Native, SignalCTFillUp) 170 binary.Write(buf2, byteorder.Native, SignalProtoV4) 171 172 messages := [][]byte{buf1.Bytes(), buf2.Bytes()} 173 174 sm := newSignalManager(fakesignalmap.NewFakeSignalMap(messages, time.Second)) 175 require.Equal(t, true, sm.isMuted()) 176 177 wakeup := make(chan SignalData, 1024) 178 err := sm.RegisterHandler(ChannelHandler(wakeup), SignalNatFillUp, SignalCTFillUp) 179 require.Nil(t, err) 180 require.Equal(t, false, sm.isMuted()) 181 182 err = sm.start() 183 require.Nil(t, err) 184 185 select { 186 case x := <-wakeup: 187 sm.MuteSignals(SignalNatFillUp, SignalCTFillUp) 188 require.Equal(t, true, sm.isMuted()) 189 190 ipv4 := false 191 ipv6 := false 192 if x == SignalProtoV4 { 193 ipv4 = true 194 } else if x == SignalProtoV6 { 195 ipv6 = true 196 } 197 198 // Drain current queue since we just woke up anyway. 199 for len(wakeup) > 0 { 200 x := <-wakeup 201 if x == SignalProtoV4 { 202 ipv4 = true 203 } else if x == SignalProtoV6 { 204 ipv6 = true 205 } 206 } 207 208 require.Equal(t, true, ipv4) 209 require.Equal(t, false, ipv6) 210 211 case <-time.After(5 * time.Second): 212 sm.MuteSignals(SignalNatFillUp, SignalCTFillUp) 213 require.Equal(t, true, sm.isMuted()) 214 215 t.Fatal("No signals received on time.") 216 } 217 218 err = sm.stop() 219 require.Nil(t, err) 220 }