@@ -404,7 +404,7 @@ func createPacketSnifferDaemonSet(oc *exutil.CLI, namespace string, scheduleOnHo
404
404
}
405
405
406
406
var ds * appsv1.DaemonSet
407
- retries := 12
407
+ retries := 48
408
408
pollInterval := 5
409
409
for i := 0 ; i < retries ; i ++ {
410
410
// Get the DS
@@ -415,7 +415,9 @@ func createPacketSnifferDaemonSet(oc *exutil.CLI, namespace string, scheduleOnHo
415
415
416
416
// Check if NumberReady == DesiredNumberScheduled.
417
417
// In that case, simply return as all went well.
418
- if ds .Status .NumberReady == ds .Status .DesiredNumberScheduled {
418
+ if ds .Status .NumberReady == ds .Status .DesiredNumberScheduled &&
419
+ ds .Status .CurrentNumberScheduled == ds .Status .DesiredNumberScheduled &&
420
+ ds .Status .DesiredNumberScheduled > 0 {
419
421
return ds , nil
420
422
}
421
423
// If no port conflict error was found, simply sleep for pollInterval and then
@@ -426,15 +428,14 @@ func createPacketSnifferDaemonSet(oc *exutil.CLI, namespace string, scheduleOnHo
426
428
// The DaemonSet is not ready, but this is not because of a port conflict.
427
429
// This shouldn't happen and other parts of the code will likely report this error
428
430
// as a CI failure.
429
- return ds , fmt .Errorf ("Daemonset still not ready after %d tries" , retries )
431
+ return ds , fmt .Errorf ("Daemonset still not ready after %d tries: ready=%d, scheduled=%d, desired=%d " , retries , ds . Status . NumberReady , ds . Status . CurrentNumberScheduled , ds . Status . DesiredNumberScheduled )
430
432
}
431
433
432
434
const (
433
435
// The tcpCaptureScript runs tcpdump and extracts all GET request strings from the packets.
434
436
// The resulting lines will be something like:
435
- // 10.128.2.15.36749 /f8f721fa-53c9-444f-bc96-69c7388fcb5a
436
- tcpCaptureScript = `#!/bin/bash
437
- tcpdump -nn -i %s -l -s 0 -A 'tcp and port %d' | awk '/IP / || /IP6 / {ip=$3} /GET \// {print ip, $2}'
437
+ // Parsed 05:38:34.307832 10.128.2.15.36749 /f8f721fa-53c9-444f-bc96-69c7388fcb5a
438
+ tcpCaptureScript = `tcpdump -nn -i %s -l -s 0 -A 'tcp and port %d' | awk 'match($0,/IP6?[[:space:]]+([0-9a-fA-F:\.]+[0-9a-fA-F])/,arr) {ts=$1; ip=arr[1]} $0 !~ /HTTP.*GET/ && match($0,/GET[[:space:]]+([^[:space:]]+)/,arr) {print "Parsed", ts, ip, arr[1]} // {print $0}'
438
439
`
439
440
440
441
// The udpCaptureScript runs tcpdump with option -xx and then decodes the hexadecimal information.
@@ -443,8 +444,8 @@ tcpdump -nn -i %s -l -s 0 -A 'tcp and port %d' | awk '/IP / || /IP6 / {ip=$3} /G
443
444
// that's captured).
444
445
// tshark would definitely be the better tool here, but that would introduce another dependency. Hence,
445
446
// decode the hexadecimal information and look for payload that is marked with 'START(.*)EOF$' and extract
446
- // the '(.*)' part. The resulting lines will be `sourceIP + " " + z.group(1)`, hence something like:
447
- // 10.128.2.15.36749 f8f721fa-53c9-444f-bc96-69c7388fcb5a
447
+ // the '(.*)' part. The resulting lines will be `"Parsed " + timestamp + " " + sourceIP + " " + z.group(1) + "_" + z.group(2 )`, hence something like:
448
+ // Parsed 05:38:34.307832 10.128.2.15.36749 f8f721fa-53c9-444f-bc96-69c7388fcb5a_1
448
449
udpCaptureScript = `#!/bin/bash
449
450
450
451
cat <<'EOF' > capture-python.py
@@ -466,6 +467,7 @@ udpPayloadOffset = 0
466
467
# globals
467
468
fullHex = []
468
469
sourceIP = ""
470
+ timeStamp = ""
469
471
470
472
def decodePayload(hexArray):
471
473
payloadStr = ""
@@ -482,9 +484,9 @@ def printLine():
482
484
global fullHex
483
485
if sourceIP != "" and fullHex != []:
484
486
decodedPayload = decodePayload(fullHex)
485
- z = re.search(r'START(.*)EOF$ ', decodedPayload)
487
+ z = re.search(r'START(.*)EOF_(\d+) ', decodedPayload)
486
488
if z:
487
- print(sourceIP + " " + z.group(1))
489
+ print("Parsed " + timeStamp + " " + sourceIP + " " + z.group(1) + "_" + z.group(2 ))
488
490
fullHex = []
489
491
sourceIP = ""
490
492
@@ -497,6 +499,7 @@ for line in sys.stdin:
497
499
printLine()
498
500
elif not re.match(r'^$', line):
499
501
printLine()
502
+ timeStamp = line.split()[0]
500
503
sourceIP = line.split()[sourceIPOffset]
501
504
502
505
printLine()
@@ -545,16 +548,6 @@ func createHostNetworkedPacketSnifferDaemonSet(clientset kubernetes.Interface, n
545
548
},
546
549
},
547
550
}
548
- readinessProbe := & v1.Probe {
549
- ProbeHandler : v1.ProbeHandler {
550
- Exec : & v1.ExecAction {
551
- Command : []string {
552
- "echo" ,
553
- "ready" ,
554
- },
555
- },
556
- },
557
- }
558
551
runAsUser := int64 (0 )
559
552
securityContext := & v1.SecurityContext {
560
553
RunAsUser : & runAsUser ,
@@ -582,14 +575,19 @@ func createHostNetworkedPacketSnifferDaemonSet(clientset kubernetes.Interface, n
582
575
Labels : podLabels ,
583
576
},
584
577
Spec : corev1.PodSpec {
578
+ Tolerations : []v1.Toleration {
579
+ {
580
+ Key : "node-role.kubernetes.io/master" ,
581
+ Effect : corev1 .TaintEffectNoSchedule ,
582
+ },
583
+ },
585
584
Affinity : & nodeAffinity ,
586
585
HostNetwork : true ,
587
586
Containers : []v1.Container {
588
587
{
589
588
Name : "tcpdump" ,
590
589
Image : networkPacketSnifferImage ,
591
590
Command : podCommand ,
592
- ReadinessProbe : readinessProbe ,
593
591
SecurityContext : securityContext ,
594
592
TTY : true , // needed for immediate log propagation
595
593
Stdin : true , // needed for immediate log propagation
@@ -651,31 +649,33 @@ func scanPacketSnifferDaemonSetPodLogs(oc *exutil.CLI, ds *appsv1.DaemonSet, tar
651
649
scanner := bufio .NewScanner (buf )
652
650
for scanner .Scan () {
653
651
logLine := scanner .Text ()
654
- if strings .Contains (logLine , searchString ) {
655
- // Currently, it is not necessary to discriminate by protocol.
656
- // a log line should look like this for http:
657
- // 10.0.144.5.33226 /bed729aa-4e83-482d-a433-db798e569147
658
- // a log line should look like this for udp:
659
- // 10.0.144.5.33226 bed729aa-4e83-482d-a433-db798e569147
660
- // Should it ever be necessary, the targetProtocol to this method (which is currently
661
- // not used) serves this purpose.
662
- framework .Logf ("Found hit in log line: %s" , logLine )
663
- logLineExploded := strings .Fields (logLine )
664
- if len (logLineExploded ) != 2 {
665
- return nil , fmt .Errorf ("Unexpected logline content: %s" , logLine )
666
- }
667
- ipAddressPortExploded := strings .Split (logLineExploded [0 ], "." )
668
- if len (ipAddressPortExploded ) == 2 {
669
- // ipv6
670
- ip = ipAddressPortExploded [0 ]
671
- } else if len (ipAddressPortExploded ) == 5 {
672
- // ipv4
673
- ip = strings .Join (ipAddressPortExploded [:len (ipAddressPortExploded )- 1 ], "." )
674
- } else {
675
- return nil , fmt .Errorf ("Unexpected logline content, invalid IP/Port: %s" , logLine )
676
- }
677
- matchedIPs [ip ]++
652
+
653
+ if ! strings .HasPrefix (logLine , "Parsed" ) || ! strings .Contains (logLine , searchString ) {
654
+ continue
655
+ }
656
+ // Currently, it is not necessary to discriminate by protocol.
657
+ // a log line should look like this for http:
658
+ // 10.0.144.5.33226 /bed729aa-4e83-482d-a433-db798e569147
659
+ // a log line should look like this for udp:
660
+ // 10.0.144.5.33226 bed729aa-4e83-482d-a433-db798e569147
661
+ // Should it ever be necessary, the targetProtocol to this method (which is currently
662
+ // not used) serves this purpose.
663
+ framework .Logf ("Found hit in log line for node %s: %s" , pod .Spec .NodeName , logLine )
664
+ logLineExploded := strings .Fields (logLine )
665
+ if len (logLineExploded ) != 4 {
666
+ return nil , fmt .Errorf ("Unexpected logline content %s" , logLine )
667
+ }
668
+ ipAddressPortExploded := strings .Split (logLineExploded [2 ], "." )
669
+ if len (ipAddressPortExploded ) == 2 {
670
+ // ipv6
671
+ ip = ipAddressPortExploded [0 ]
672
+ } else if len (ipAddressPortExploded ) == 5 {
673
+ // ipv4
674
+ ip = strings .Join (ipAddressPortExploded [:len (ipAddressPortExploded )- 1 ], "." )
675
+ } else {
676
+ return nil , fmt .Errorf ("Unexpected logline content, invalid IP/Port: %s" , logLine )
678
677
}
678
+ matchedIPs [ip ]++
679
679
}
680
680
}
681
681
return matchedIPs , nil
@@ -1271,26 +1271,28 @@ func sendProbesToHostPort(oc *exutil.CLI, proberPod *v1.Pod, url, targetProtocol
1271
1271
request := fmt .Sprintf ("http://%s/dial?protocol=%s&host=%s&port=%d&request=%s" , url , targetProtocol , targetHost , targetPort , randomIDStr )
1272
1272
var wg sync.WaitGroup
1273
1273
errChan := make (chan error , iterations )
1274
+
1274
1275
for i := 0 ; i < iterations ; i ++ {
1275
1276
// Make sure that we don´t reuse the i variable when passing it to the go func.
1276
- i := i
1277
+ interval := i
1277
1278
// Randomize the start time a little bit per go routine.
1278
1279
// Max of 250 ms * current iteration counter
1279
- n := rand .Intn (250 ) * i
1280
- framework .Logf ("Sleeping for %d ms for iteration %d" , n , i )
1280
+ n := rand .Intn (250 ) * interval
1281
+ framework .Logf ("Sleeping for %d ms for iteration %d" , n , interval )
1281
1282
wg .Add (1 )
1282
1283
go func () {
1283
1284
defer wg .Done ()
1284
1285
time .Sleep (time .Duration (n ) * time .Millisecond )
1285
- output , err := runOcWithRetry (oc .AsAdmin (), "exec" , proberPod .Name , "--" , "curl" , "--max-time" , "15" , "-s" , request )
1286
+ output , err := runOcWithRetry (oc .AsAdmin (), "exec" , proberPod .Name , "--" , "curl" , "--max-time" , "15" , "-s" , fmt .Sprintf ("%s_%d" , request , i ))
1287
+ framework .Logf ("Probed with output: %s" , output )
1286
1288
// Report errors.
1287
1289
if err != nil {
1288
1290
errChan <- fmt .Errorf ("Query failed. Request: %s, Output: %s, Error: %v" , request , output , err )
1289
1291
}
1290
- return
1291
1292
}()
1292
1293
}
1293
1294
wg .Wait ()
1295
+ close (errChan ) // Close the channel after all goroutines finish
1294
1296
1295
1297
// If the above yielded any errors, then append them to a list and report them.
1296
1298
if len (errChan ) > 0 {
@@ -1729,21 +1731,21 @@ func cloudPrivateIpConfigExists(oc *exutil.CLI, cloudNetworkClientset cloudnetwo
1729
1731
}
1730
1732
1731
1733
// egressIPStatusHasIP returns if a given ip was found in a given EgressIP object's status field.
1732
- func egressIPStatusHasIP (oc * exutil.CLI , egressIPObjectName string , ip string ) (bool , error ) {
1734
+ func egressIPStatusHasIP (oc * exutil.CLI , egressIPObjectName string , ip string ) (bool , string , error ) {
1733
1735
eip , err := getEgressIP (oc , egressIPObjectName )
1734
1736
if err != nil {
1735
1737
if errors .IsNotFound (err ) {
1736
- return false , nil
1738
+ return false , "" , nil
1737
1739
}
1738
- return false , fmt .Errorf ("Error looking up EgressIP %s, err: %v" , egressIPObjectName , err )
1740
+ return false , "" , fmt .Errorf ("Error looking up EgressIP %s, err: %v" , egressIPObjectName , err )
1739
1741
}
1740
1742
for _ , egressIPStatusItem := range eip .Status .Items {
1741
1743
if egressIPStatusItem .EgressIP == ip {
1742
- return true , nil
1744
+ return true , egressIPStatusItem . Node , nil
1743
1745
}
1744
1746
}
1745
1747
1746
- return false , nil
1748
+ return false , "" , nil
1747
1749
}
1748
1750
1749
1751
// sdnNamespaceAddEgressIP adds EgressIP <egressip> to netnamespace <namespace>.
0 commit comments