github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/maps/ctmap/types.go (about) 1 // Copyright 2016-2019 Authors of Cilium 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 ctmap 16 17 import ( 18 "bytes" 19 "fmt" 20 "unsafe" 21 22 "github.com/cilium/cilium/pkg/bpf" 23 "github.com/cilium/cilium/pkg/byteorder" 24 "github.com/cilium/cilium/pkg/tuple" 25 ) 26 27 const ( 28 // MapTypeIPv4TCPLocal and friends are MapTypes which correspond to a 29 // combination of the following attributes: 30 // * IPv4 or IPv6; 31 // * TCP or non-TCP (shortened to Any) 32 // * Local (endpoint-specific) or global (endpoint-oblivious). 33 MapTypeIPv4TCPLocal = iota 34 MapTypeIPv6TCPLocal 35 MapTypeIPv4TCPGlobal 36 MapTypeIPv6TCPGlobal 37 MapTypeIPv4AnyLocal 38 MapTypeIPv6AnyLocal 39 MapTypeIPv4AnyGlobal 40 MapTypeIPv6AnyGlobal 41 MapTypeMax 42 ) 43 44 // MapType is a type of connection tracking map. 45 type MapType int 46 47 // String renders the map type into a user-readable string. 48 func (m MapType) String() string { 49 switch m { 50 case MapTypeIPv4TCPLocal: 51 return "Local IPv4 TCP CT map" 52 case MapTypeIPv6TCPLocal: 53 return "Local IPv6 TCP CT map" 54 case MapTypeIPv4TCPGlobal: 55 return "Global IPv4 TCP CT map" 56 case MapTypeIPv6TCPGlobal: 57 return "Global IPv6 TCP CT map" 58 case MapTypeIPv4AnyLocal: 59 return "Local IPv4 non-TCP CT map" 60 case MapTypeIPv6AnyLocal: 61 return "Local IPv6 non-TCP CT map" 62 case MapTypeIPv4AnyGlobal: 63 return "Global IPv4 non-TCP CT map" 64 case MapTypeIPv6AnyGlobal: 65 return "Global IPv6 non-TCP CT map" 66 } 67 return fmt.Sprintf("Unknown (%d)", int(m)) 68 } 69 70 func (m MapType) isIPv4() bool { 71 switch m { 72 case MapTypeIPv4TCPLocal, MapTypeIPv4TCPGlobal, MapTypeIPv4AnyLocal, MapTypeIPv4AnyGlobal: 73 return true 74 } 75 return false 76 } 77 78 func (m MapType) isIPv6() bool { 79 switch m { 80 case MapTypeIPv6TCPLocal, MapTypeIPv6TCPGlobal, MapTypeIPv6AnyLocal, MapTypeIPv6AnyGlobal: 81 return true 82 } 83 return false 84 } 85 86 func (m MapType) isLocal() bool { 87 switch m { 88 case MapTypeIPv4TCPLocal, MapTypeIPv6TCPLocal, MapTypeIPv4AnyLocal, MapTypeIPv6AnyLocal: 89 return true 90 } 91 return false 92 } 93 94 func (m MapType) isGlobal() bool { 95 switch m { 96 case MapTypeIPv4TCPGlobal, MapTypeIPv6TCPGlobal, MapTypeIPv4AnyGlobal, MapTypeIPv6AnyGlobal: 97 return true 98 } 99 return false 100 } 101 102 func (m MapType) isTCP() bool { 103 switch m { 104 case MapTypeIPv4TCPLocal, MapTypeIPv6TCPLocal, MapTypeIPv4TCPGlobal, MapTypeIPv6TCPGlobal: 105 return true 106 } 107 return false 108 } 109 110 type CtKey interface { 111 bpf.MapKey 112 113 // ToNetwork converts fields to network byte order. 114 ToNetwork() CtKey 115 116 // ToHost converts fields to host byte order. 117 ToHost() CtKey 118 119 // Dump contents of key to buffer. Returns true if successful. 120 Dump(buffer *bytes.Buffer, reverse bool) bool 121 122 // GetFlags flags containing the direction of the CtKey. 123 GetFlags() uint8 124 125 GetTupleKey() tuple.TupleKey 126 } 127 128 // CtKey4 is needed to provide CtEntry type to Lookup values 129 // +k8s:deepcopy-gen=true 130 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 131 type CtKey4 struct { 132 tuple.TupleKey4 133 } 134 135 // NewValue creates a new bpf.MapValue. 136 func (k *CtKey4) NewValue() bpf.MapValue { return &CtEntry{} } 137 138 // ToNetwork converts CtKey4 ports to network byte order. 139 func (k *CtKey4) ToNetwork() CtKey { 140 n := *k 141 n.SourcePort = byteorder.HostToNetwork(n.SourcePort).(uint16) 142 n.DestPort = byteorder.HostToNetwork(n.DestPort).(uint16) 143 return &n 144 } 145 146 // ToHost converts CtKey ports to host byte order. 147 func (k *CtKey4) ToHost() CtKey { 148 n := *k 149 n.SourcePort = byteorder.NetworkToHost(n.SourcePort).(uint16) 150 n.DestPort = byteorder.NetworkToHost(n.DestPort).(uint16) 151 return &n 152 } 153 154 // GetFlags returns the tuple's flags. 155 func (k *CtKey4) GetFlags() uint8 { 156 return k.Flags 157 } 158 159 func (k *CtKey4) String() string { 160 return fmt.Sprintf("%s:%d, %d, %d, %d", k.DestAddr, k.SourcePort, k.DestPort, k.NextHeader, k.Flags) 161 } 162 163 // GetKeyPtr returns the unsafe.Pointer for k. 164 func (k *CtKey4) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 165 166 // Dump writes the contents of key to buffer and returns true if the value for 167 // next header in the key is nonzero. 168 func (k *CtKey4) Dump(buffer *bytes.Buffer, reverse bool) bool { 169 var addrDest string 170 171 if k.NextHeader == 0 { 172 return false 173 } 174 175 // Addresses swapped, see issue #5848 176 if reverse { 177 addrDest = k.SourceAddr.IP().String() 178 } else { 179 addrDest = k.DestAddr.IP().String() 180 } 181 182 if k.Flags&TUPLE_F_IN != 0 { 183 buffer.WriteString(fmt.Sprintf("%s IN %s %d:%d ", 184 k.NextHeader.String(), addrDest, k.SourcePort, 185 k.DestPort), 186 ) 187 } else { 188 buffer.WriteString(fmt.Sprintf("%s OUT %s %d:%d ", 189 k.NextHeader.String(), addrDest, k.DestPort, 190 k.SourcePort), 191 ) 192 } 193 194 if k.Flags&TUPLE_F_RELATED != 0 { 195 buffer.WriteString("related ") 196 } 197 198 if k.Flags&TUPLE_F_SERVICE != 0 { 199 buffer.WriteString("service ") 200 } 201 202 return true 203 } 204 205 func (k *CtKey4) GetTupleKey() tuple.TupleKey { 206 return &k.TupleKey4 207 } 208 209 // CtKey4Global is needed to provide CtEntry type to Lookup values 210 // +k8s:deepcopy-gen=true 211 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 212 type CtKey4Global struct { 213 tuple.TupleKey4Global 214 } 215 216 // NewValue creates a new bpf.MapValue. 217 func (k *CtKey4Global) NewValue() bpf.MapValue { return &CtEntry{} } 218 219 // ToNetwork converts ports to network byte order. 220 // 221 // This is necessary to prevent callers from implicitly converting 222 // the CtKey4Global type here into a local key type in the nested 223 // TupleKey4Global field. 224 func (k *CtKey4Global) ToNetwork() CtKey { 225 return &CtKey4Global{ 226 TupleKey4Global: *k.TupleKey4Global.ToNetwork().(*tuple.TupleKey4Global), 227 } 228 } 229 230 // ToHost converts ports to host byte order. 231 // 232 // This is necessary to prevent callers from implicitly converting 233 // the CtKey4Global type here into a local key type in the nested 234 // TupleKey4Global field. 235 func (k *CtKey4Global) ToHost() CtKey { 236 return &CtKey4Global{ 237 TupleKey4Global: *k.TupleKey4Global.ToHost().(*tuple.TupleKey4Global), 238 } 239 } 240 241 // GetFlags returns the tuple's flags. 242 func (k *CtKey4Global) GetFlags() uint8 { 243 return k.Flags 244 } 245 246 func (k *CtKey4Global) String() string { 247 return fmt.Sprintf("%s:%d --> %s:%d, %d, %d", k.SourceAddr, k.SourcePort, k.DestAddr, k.DestPort, k.NextHeader, k.Flags) 248 } 249 250 // GetKeyPtr returns the unsafe.Pointer for k. 251 func (k *CtKey4Global) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 252 253 // Dump writes the contents of key to buffer and returns true if the 254 // value for next header in the key is nonzero. 255 func (k *CtKey4Global) Dump(buffer *bytes.Buffer, reverse bool) bool { 256 var addrSource, addrDest string 257 258 if k.NextHeader == 0 { 259 return false 260 } 261 262 // Addresses swapped, see issue #5848 263 if reverse { 264 addrSource = k.DestAddr.IP().String() 265 addrDest = k.SourceAddr.IP().String() 266 } else { 267 addrSource = k.SourceAddr.IP().String() 268 addrDest = k.DestAddr.IP().String() 269 } 270 271 if k.Flags&TUPLE_F_IN != 0 { 272 buffer.WriteString(fmt.Sprintf("%s IN %s:%d -> %s:%d ", 273 k.NextHeader.String(), addrSource, k.SourcePort, 274 addrDest, k.DestPort), 275 ) 276 } else { 277 buffer.WriteString(fmt.Sprintf("%s OUT %s:%d -> %s:%d ", 278 k.NextHeader.String(), addrSource, k.SourcePort, 279 addrDest, k.DestPort), 280 ) 281 } 282 283 if k.Flags&TUPLE_F_RELATED != 0 { 284 buffer.WriteString("related ") 285 } 286 287 if k.Flags&TUPLE_F_SERVICE != 0 { 288 buffer.WriteString("service ") 289 } 290 291 return true 292 } 293 294 func (k *CtKey4Global) GetTupleKey() tuple.TupleKey { 295 return &k.TupleKey4Global 296 } 297 298 // CtKey6 is needed to provide CtEntry type to Lookup values 299 // +k8s:deepcopy-gen=true 300 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 301 type CtKey6 struct { 302 tuple.TupleKey6 303 } 304 305 // NewValue creates a new bpf.MapValue. 306 func (k *CtKey6) NewValue() bpf.MapValue { return &CtEntry{} } 307 308 // ToNetwork converts CtKey6 ports to network byte order. 309 func (k *CtKey6) ToNetwork() CtKey { 310 return &CtKey6{ 311 TupleKey6: *k.TupleKey6.ToNetwork().(*tuple.TupleKey6), 312 } 313 } 314 315 // ToHost converts CtKey ports to host byte order. 316 func (k *CtKey6) ToHost() CtKey { 317 return &CtKey6{ 318 TupleKey6: *k.TupleKey6.ToHost().(*tuple.TupleKey6), 319 } 320 } 321 322 // GetFlags returns the tuple's flags. 323 func (k *CtKey6) GetFlags() uint8 { 324 return k.Flags 325 } 326 327 func (k *CtKey6) String() string { 328 return fmt.Sprintf("[%s]:%d, %d, %d, %d", k.DestAddr, k.SourcePort, k.DestPort, k.NextHeader, k.Flags) 329 } 330 331 // GetKeyPtr returns the unsafe.Pointer for k. 332 func (k *CtKey6) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 333 334 // Dump writes the contents of key to buffer and returns true if the value for 335 // next header in the key is nonzero. 336 func (k *CtKey6) Dump(buffer *bytes.Buffer, reverse bool) bool { 337 var addrDest string 338 339 if k.NextHeader == 0 { 340 return false 341 } 342 343 // Addresses swapped, see issue #5848 344 if reverse { 345 addrDest = k.SourceAddr.IP().String() 346 } else { 347 addrDest = k.DestAddr.IP().String() 348 } 349 350 if k.Flags&TUPLE_F_IN != 0 { 351 buffer.WriteString(fmt.Sprintf("%s IN %s %d:%d ", 352 k.NextHeader.String(), addrDest, k.SourcePort, 353 k.DestPort), 354 ) 355 } else { 356 buffer.WriteString(fmt.Sprintf("%s OUT %s %d:%d ", 357 k.NextHeader.String(), addrDest, k.DestPort, 358 k.SourcePort), 359 ) 360 } 361 362 if k.Flags&TUPLE_F_RELATED != 0 { 363 buffer.WriteString("related ") 364 } 365 366 if k.Flags&TUPLE_F_SERVICE != 0 { 367 buffer.WriteString("service ") 368 } 369 370 return true 371 } 372 373 func (k *CtKey6) GetTupleKey() tuple.TupleKey { 374 return &k.TupleKey6 375 } 376 377 // CtKey6Global is needed to provide CtEntry type to Lookup values 378 // +k8s:deepcopy-gen=true 379 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 380 type CtKey6Global struct { 381 tuple.TupleKey6Global 382 } 383 384 // NewValue creates a new bpf.MapValue. 385 func (k *CtKey6Global) NewValue() bpf.MapValue { return &CtEntry{} } 386 387 // ToNetwork converts ports to network byte order. 388 // 389 // This is necessary to prevent callers from implicitly converting 390 // the CtKey6Global type here into a local key type in the nested 391 // TupleKey6Global field. 392 func (k *CtKey6Global) ToNetwork() CtKey { 393 return &CtKey6Global{ 394 TupleKey6Global: *k.TupleKey6Global.ToNetwork().(*tuple.TupleKey6Global), 395 } 396 } 397 398 // ToHost converts ports to host byte order. 399 // 400 // This is necessary to prevent callers from implicitly converting 401 // the CtKey6Global type here into a local key type in the nested 402 // TupleKey6Global field. 403 func (k *CtKey6Global) ToHost() CtKey { 404 return &CtKey6Global{ 405 TupleKey6Global: *k.TupleKey6Global.ToHost().(*tuple.TupleKey6Global), 406 } 407 } 408 409 // GetFlags returns the tuple's flags. 410 func (k *CtKey6Global) GetFlags() uint8 { 411 return k.Flags 412 } 413 414 func (k *CtKey6Global) String() string { 415 return fmt.Sprintf("[%s]:%d --> [%s]:%d, %d, %d", k.SourceAddr, k.SourcePort, k.DestAddr, k.DestPort, k.NextHeader, k.Flags) 416 } 417 418 // GetKeyPtr returns the unsafe.Pointer for k. 419 func (k *CtKey6Global) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 420 421 // Dump writes the contents of key to buffer and returns true if the 422 // value for next header in the key is nonzero. 423 func (k *CtKey6Global) Dump(buffer *bytes.Buffer, reverse bool) bool { 424 var addrSource, addrDest string 425 426 if k.NextHeader == 0 { 427 return false 428 } 429 430 // Addresses swapped, see issue #5848 431 if reverse { 432 addrSource = k.DestAddr.IP().String() 433 addrDest = k.SourceAddr.IP().String() 434 } else { 435 addrSource = k.SourceAddr.IP().String() 436 addrDest = k.DestAddr.IP().String() 437 } 438 439 if k.Flags&TUPLE_F_IN != 0 { 440 buffer.WriteString(fmt.Sprintf("%s IN %s:%d -> %s:%d ", 441 k.NextHeader.String(), addrSource, k.SourcePort, 442 addrDest, k.DestPort), 443 ) 444 } else { 445 buffer.WriteString(fmt.Sprintf("%s OUT %s:%d -> %s:%d ", 446 k.NextHeader.String(), addrSource, k.SourcePort, 447 addrDest, k.DestPort), 448 ) 449 } 450 451 if k.Flags&TUPLE_F_RELATED != 0 { 452 buffer.WriteString("related ") 453 } 454 455 if k.Flags&TUPLE_F_SERVICE != 0 { 456 buffer.WriteString("service ") 457 } 458 459 return true 460 } 461 462 func (k *CtKey6Global) GetTupleKey() tuple.TupleKey { 463 return &k.TupleKey6Global 464 } 465 466 // CtEntry represents an entry in the connection tracking table. 467 // +k8s:deepcopy-gen=true 468 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue 469 type CtEntry struct { 470 RxPackets uint64 `align:"rx_packets"` 471 RxBytes uint64 `align:"rx_bytes"` 472 TxPackets uint64 `align:"tx_packets"` 473 TxBytes uint64 `align:"tx_bytes"` 474 Lifetime uint32 `align:"lifetime"` 475 Flags uint16 `align:"rx_closing"` 476 // RevNAT is in network byte order 477 RevNAT uint16 `align:"rev_nat_index"` 478 _ uint16 `align:"backend_id"` 479 TxFlagsSeen uint8 `align:"tx_flags_seen"` 480 RxFlagsSeen uint8 `align:"rx_flags_seen"` 481 SourceSecurityID uint32 `align:"src_sec_id"` 482 LastTxReport uint32 `align:"last_tx_report"` 483 LastRxReport uint32 `align:"last_rx_report"` 484 } 485 486 // GetValuePtr returns the unsafe.Pointer for s. 487 func (c *CtEntry) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(c) } 488 489 const ( 490 RxClosing = 1 << 0 491 TxClosing = 1 << 1 492 Nat64 = 1 << 2 493 LBLoopback = 1 << 3 494 SeenNonSyn = 1 << 4 495 NodePort = 1 << 5 496 ) 497 498 func (c *CtEntry) flagsString() string { 499 var buffer bytes.Buffer 500 501 buffer.WriteString(fmt.Sprintf("Flags=%#04x [ ", c.Flags)) 502 if (c.Flags & RxClosing) != 0 { 503 buffer.WriteString("RxClosing ") 504 } 505 if (c.Flags & TxClosing) != 0 { 506 buffer.WriteString("TxClosing ") 507 } 508 if (c.Flags & Nat64) != 0 { 509 buffer.WriteString("Nat64 ") 510 } 511 if (c.Flags & LBLoopback) != 0 { 512 buffer.WriteString("LBLoopback ") 513 } 514 if (c.Flags & SeenNonSyn) != 0 { 515 buffer.WriteString("SeenNonSyn ") 516 } 517 if (c.Flags & NodePort) != 0 { 518 buffer.WriteString("NodePort ") 519 } 520 buffer.WriteString("]") 521 return buffer.String() 522 } 523 524 // String returns the readable format 525 func (c *CtEntry) String() string { 526 return fmt.Sprintf("expires=%d RxPackets=%d RxBytes=%d RxFlagsSeen=%#02x LastRxReport=%d TxPackets=%d TxBytes=%d TxFlagsSeen=%#02x LastTxReport=%d %s RevNAT=%d SourceSecurityID=%d \n", 527 c.Lifetime, 528 c.RxPackets, 529 c.RxBytes, 530 c.RxFlagsSeen, 531 c.LastRxReport, 532 c.TxPackets, 533 c.TxBytes, 534 c.TxFlagsSeen, 535 c.LastTxReport, 536 c.flagsString(), 537 byteorder.NetworkToHost(c.RevNAT), 538 c.SourceSecurityID) 539 }