mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Read Iptables-save output in a more-memory-efficient way
This commit is contained in:
		@@ -765,33 +765,84 @@ func makeChainLine(chain utiliptables.Chain) string {
 | 
				
			|||||||
// getChainLines parses a table's iptables-save data to find chains in the table.
 | 
					// getChainLines parses a table's iptables-save data to find chains in the table.
 | 
				
			||||||
// It returns a map of iptables.Chain to string where the string is the chain line from the save (with counters etc).
 | 
					// It returns a map of iptables.Chain to string where the string is the chain line from the save (with counters etc).
 | 
				
			||||||
func getChainLines(table utiliptables.Table, save []byte) map[utiliptables.Chain]string {
 | 
					func getChainLines(table utiliptables.Table, save []byte) map[utiliptables.Chain]string {
 | 
				
			||||||
	// get lines
 | 
					 | 
				
			||||||
	lines := strings.Split(string(save), "\n")
 | 
					 | 
				
			||||||
	chainsMap := make(map[utiliptables.Chain]string)
 | 
						chainsMap := make(map[utiliptables.Chain]string)
 | 
				
			||||||
	tablePrefix := "*" + string(table)
 | 
						tablePrefix := "*" + string(table)
 | 
				
			||||||
	lineNum := 0
 | 
						readIndex := 0
 | 
				
			||||||
	// find beginning of table
 | 
						// find beginning of table
 | 
				
			||||||
	for ; lineNum < len(lines); lineNum++ {
 | 
						for readIndex < len(save) {
 | 
				
			||||||
		if strings.HasPrefix(strings.TrimSpace(lines[lineNum]), tablePrefix) {
 | 
							line, n := readLine(readIndex, save)
 | 
				
			||||||
			lineNum++
 | 
							readIndex = n
 | 
				
			||||||
 | 
							if strings.HasPrefix(line, tablePrefix) {
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// parse table lines
 | 
						// parse table lines
 | 
				
			||||||
	for ; lineNum < len(lines); lineNum++ {
 | 
						for readIndex < len(save) {
 | 
				
			||||||
		line := strings.TrimSpace(lines[lineNum])
 | 
							line, n := readLine(readIndex, save)
 | 
				
			||||||
 | 
							readIndex = n
 | 
				
			||||||
 | 
							if len(line) == 0 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if strings.HasPrefix(line, "COMMIT") || strings.HasPrefix(line, "*") {
 | 
							if strings.HasPrefix(line, "COMMIT") || strings.HasPrefix(line, "*") {
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		} else if len(line) == 0 || strings.HasPrefix(line, "#") {
 | 
							} else if strings.HasPrefix(line, "#") {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		} else if strings.HasPrefix(line, ":") && len(line) > 1 {
 | 
							} else if strings.HasPrefix(line, ":") && len(line) > 1 {
 | 
				
			||||||
			chain := utiliptables.Chain(strings.SplitN(line[1:], " ", 2)[0])
 | 
								chain := utiliptables.Chain(strings.SplitN(line[1:], " ", 2)[0])
 | 
				
			||||||
			chainsMap[chain] = lines[lineNum]
 | 
								chainsMap[chain] = line
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return chainsMap
 | 
						return chainsMap
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readLine(readIndex int, byteArray []byte) (string, int) {
 | 
				
			||||||
 | 
						currentReadIndex := readIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// consume left spaces
 | 
				
			||||||
 | 
						for currentReadIndex < len(byteArray) {
 | 
				
			||||||
 | 
							if byteArray[currentReadIndex] == ' ' {
 | 
				
			||||||
 | 
								currentReadIndex++
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// leftTrimIndex stores the left index of the line after the line is left-trimmed
 | 
				
			||||||
 | 
						leftTrimIndex := currentReadIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// rightTrimIndex stores the right index of the line after the line is right-trimmed
 | 
				
			||||||
 | 
						// it is set to -1 since the correct value has not yet been determined.
 | 
				
			||||||
 | 
						rightTrimIndex := -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ; currentReadIndex < len(byteArray); currentReadIndex++ {
 | 
				
			||||||
 | 
							if byteArray[currentReadIndex] == ' ' {
 | 
				
			||||||
 | 
								// set rightTrimIndex
 | 
				
			||||||
 | 
								if rightTrimIndex == -1 {
 | 
				
			||||||
 | 
									rightTrimIndex = currentReadIndex
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (byteArray[currentReadIndex] == '\n') || (currentReadIndex == (len(byteArray) - 1)) {
 | 
				
			||||||
 | 
								// end of line or byte buffer is reached
 | 
				
			||||||
 | 
								if currentReadIndex <= leftTrimIndex {
 | 
				
			||||||
 | 
									return "", currentReadIndex + 1
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// set the rightTrimIndex
 | 
				
			||||||
 | 
								if rightTrimIndex == -1 {
 | 
				
			||||||
 | 
									rightTrimIndex = currentReadIndex
 | 
				
			||||||
 | 
									if currentReadIndex == (len(byteArray)-1) && (byteArray[currentReadIndex] != '\n') {
 | 
				
			||||||
 | 
										// ensure that the last character is part of the returned string,
 | 
				
			||||||
 | 
										// unless the last character is '\n'
 | 
				
			||||||
 | 
										rightTrimIndex = currentReadIndex + 1
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return string(byteArray[leftTrimIndex:rightTrimIndex]), currentReadIndex + 1
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// unset rightTrimIndex
 | 
				
			||||||
 | 
								rightTrimIndex = -1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return "", currentReadIndex
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func isLocalIP(ip string) (bool, error) {
 | 
					func isLocalIP(ip string) (bool, error) {
 | 
				
			||||||
	addrs, err := net.InterfaceAddrs()
 | 
						addrs, err := net.InterfaceAddrs()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,39 @@ func checkAllLines(t *testing.T, table utiliptables.Table, save []byte, expected
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestReadLinesFromByteBuffer(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testFn := func(byteArray []byte, expected []string) {
 | 
				
			||||||
 | 
							index := 0
 | 
				
			||||||
 | 
							readIndex := 0
 | 
				
			||||||
 | 
							for ; readIndex < len(byteArray); index++ {
 | 
				
			||||||
 | 
								line, n := readLine(readIndex, byteArray)
 | 
				
			||||||
 | 
								readIndex = n
 | 
				
			||||||
 | 
								if expected[index] != line {
 | 
				
			||||||
 | 
									t.Errorf("expected:%q, actual:%q", expected[index], line)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} // for
 | 
				
			||||||
 | 
							if readIndex < len(byteArray) {
 | 
				
			||||||
 | 
								t.Errorf("Byte buffer was only partially read. Buffer length is:%d, readIndex is:%d", len(byteArray), readIndex)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if index < len(expected) {
 | 
				
			||||||
 | 
								t.Errorf("All expected strings were not compared. expected arr length:%d, matched count:%d", len(expected), index-1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						byteArray1 := []byte("\n  Line 1  \n\n\n L ine4  \nLine 5 \n \n")
 | 
				
			||||||
 | 
						expected1 := []string{"", "Line 1", "", "", "L ine4", "Line 5", ""}
 | 
				
			||||||
 | 
						testFn(byteArray1, expected1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						byteArray1 = []byte("")
 | 
				
			||||||
 | 
						expected1 = []string{}
 | 
				
			||||||
 | 
						testFn(byteArray1, expected1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						byteArray1 = []byte("\n\n")
 | 
				
			||||||
 | 
						expected1 = []string{"", ""}
 | 
				
			||||||
 | 
						testFn(byteArray1, expected1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestgetChainLines(t *testing.T) {
 | 
					func TestgetChainLines(t *testing.T) {
 | 
				
			||||||
	iptables_save := `# Generated by iptables-save v1.4.7 on Wed Oct 29 14:56:01 2014
 | 
						iptables_save := `# Generated by iptables-save v1.4.7 on Wed Oct 29 14:56:01 2014
 | 
				
			||||||
	*nat
 | 
						*nat
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user