func main()

in ethr.go [27:246]


func main() {
	//
	// If version is not set via ldflags, then default to UNKNOWN
	//
	if gVersion == "" {
		gVersion = "UNKNOWN"
	}

	fmt.Println("\nEthr: Comprehensive Network Performance Measurement Tool (Version: " + gVersion + ")")
	fmt.Println("Maintainer: Pankaj Garg (ipankajg @ LinkedIn | GitHub | Gmail | Twitter)")
	fmt.Println("")

	//
	// Set GOMAXPROCS to 1024 as running large number of goroutines that send
	// data in a tight loop over network is resulting in unfair time allocation
	// across goroutines causing starvation of many TCP connections. Using a
	// higher number of threads via GOMAXPROCS solves this problem.
	//
	runtime.GOMAXPROCS(1024)

	// Common
	flag.Usage = func() { ethrUsage() }
	noOutput := flag.Bool("no", false, "")
	outputFile := flag.String("o", defaultLogFileName, "")
	debug := flag.Bool("debug", false, "")
	use4 := flag.Bool("4", false, "")
	use6 := flag.Bool("6", false, "")
	port := flag.Int("port", 8888, "")
	ip := flag.String("ip", "", "")
	// Server
	isServer := flag.Bool("s", false, "")
	showUI := flag.Bool("ui", false, "")
	// Client & External Client
	clientDest := flag.String("c", "", "")
	bufLenStr := flag.String("l", "", "")
	bwRateStr := flag.String("b", "", "")
	cport := flag.Int("cport", 0, "")
	duration := flag.Duration("d", 10*time.Second, "")
	gap := flag.Duration("g", time.Second, "")
	iterCount := flag.Int("i", 1000, "")
	ncs := flag.Bool("ncs", false, "")
	protocol := flag.String("p", "tcp", "")
	reverse := flag.Bool("r", false, "")
	testTypePtr := flag.String("t", "", "")
	tos := flag.Int("tos", 0, "")
	title := flag.String("T", "", "")
	thCount := flag.Int("n", 1, "")
	wc := flag.Int("w", 1, "")
	xClientDest := flag.String("x", "", "")

	flag.Parse()

	if *isServer {
		if *clientDest != "" {
			printUsageError("Invalid arguments, \"-c\" cannot be used with \"-s\".")
		}
		if *xClientDest != "" {
			printUsageError("Invalid arguments, \"-x\" cannot be used with \"-s\".")
		}
		if *bufLenStr != "" {
			printServerModeArgError("l")
		}
		if *bwRateStr != "" {
			printServerModeArgError("b")
		}
		if *cport != 0 {
			printServerModeArgError("cport")
		}
		if *duration != 10*time.Second {
			printServerModeArgError("d")
		}
		if *gap != time.Second {
			printServerModeArgError("g")
		}
		if *iterCount != 1000 {
			printServerModeArgError("i")
		}
		if *ncs {
			printServerModeArgError("ncs")
		}
		if *protocol != "tcp" {
			printServerModeArgError("p")
		}
		if *reverse {
			printServerModeArgError("r")
		}
		if *testTypePtr != "" {
			printServerModeArgError("t")
		}
		if *tos != 0 {
			printServerModeArgError("tos")
		}
		if *thCount != 1 {
			printServerModeArgError("n")
		}
		if *wc != 1 {
			printServerModeArgError("wc")
		}
		if *title != "" {
			printServerModeArgError("T")
		}
	} else if *clientDest != "" || *xClientDest != "" {
		if *clientDest != "" && *xClientDest != "" {
			printUsageError("Invalid argument, both \"-c\" and \"-x\" cannot be specified at the same time.")
		}
		if *showUI {
			printUsageError(fmt.Sprintf("Invalid argument, \"-%s\" can only be used in server (\"-s\") mode.", "ui"))
		}
	} else {
		printUsageError("Invalid arguments, use either \"-s\" or \"-c\".")
	}

	// Process common parameters.

	if *debug {
		loggingLevel = LogLevelDebug
	}

	if *use4 && !*use6 {
		gIPVersion = ethrIPv4
	} else if *use6 && !*use4 {
		gIPVersion = ethrIPv6
	}

	if *ip != "" {
		gLocalIP = *ip
		ipAddr := net.ParseIP(gLocalIP)
		if ipAddr == nil {
			printUsageError(fmt.Sprintf("Invalid IP address: <%s> specified.", *ip))
		}
		if (gIPVersion == ethrIPv4 && ipAddr.To4() == nil) || (gIPVersion == ethrIPv6 && ipAddr.To16() == nil) {
			printUsageError(fmt.Sprintf("Invalid IP address version: <%s> specified.", *ip))
		}
	}
	gEthrPort = uint16(*port)
	gEthrPortStr = fmt.Sprintf("%d", gEthrPort)

	logFileName := *outputFile
	if !*noOutput {
		if logFileName == defaultLogFileName {
			if *isServer {
				logFileName = "ethrs.log"
			} else {
				logFileName = "ethrc.log"
			}
		}
		logInit(logFileName)
	}

	var testType EthrTestType
	var destination string
	if *isServer {
		// Server side parameter processing.
		testType = All
		serverParam := ethrServerParam{*showUI}
		runServer(serverParam)
	} else {
		gIsExternalClient = false
		destination = *clientDest
		if *xClientDest != "" {
			gIsExternalClient = true
			destination = *xClientDest
		}
		gNoConnectionStats = *ncs
		testType = getTestType(*testTypePtr)
		proto := getProtocol(*protocol)

		// Default latency test to 1B if length is not specified
		switch *bufLenStr {
		case "":
			*bufLenStr = getDefaultBufferLenStr(*testTypePtr)
		}
		bufLen := unitToNumber(*bufLenStr)
		if bufLen == 0 {
			printUsageError(fmt.Sprintf("Invalid length specified: %s" + *bufLenStr))
		}

		// Check specific bwRate if any.
		bwRate := uint64(0)
		if *bwRateStr != "" {
			bwRate = unitToNumber(*bwRateStr)
			bwRate /= 8
		}

		//
		// For Pkt/s, we always override the buffer size to be just 1 byte.
		// TODO: Evaluate in future, if we need to support > 1 byte packets for
		//       Pkt/s testing.
		//
		if testType == Pps {
			bufLen = 1
		}

		if *iterCount <= 0 {
			printUsageError(fmt.Sprintf("Invalid iteration count for latency test: %d", *iterCount))
		}

		if *thCount <= 0 {
			*thCount = runtime.NumCPU()
		}

		gClientPort = uint16(*cport)

		testId := EthrTestID{EthrProtocol(proto), testType}
		clientParam := EthrClientParam{
			uint32(*thCount),
			uint32(bufLen),
			uint32(*iterCount),
			*reverse,
			*duration,
			*gap,
			uint32(*wc),
			uint64(bwRate),
			uint8(*tos)}
		validateClientParams(testId, clientParam)

		rServer := destination
		runClient(testId, *title, clientParam, rServer)
	}
}