package pkg import ( "errors" "strconv" "strings" ) type TCPProfile struct { ProfileCommon ABC string `json:"abc"` ACKOnPush string `json:"ack_on_push:"` CloseWaitTimeout int `json:"close_wait_timeout"` CMetricsCache string `json:"cmetrics_cache"` CMetricsCacheTimeout int `json:"cmetrics_cache_timeout"` CongestionControl string `json:"congestion_control"` DeferredAccept string `json:"deferred_accept"` DelayWindowControl string `json:"delay_window_control"` DelayedACKs string `json:"delayed_acks"` DSACK string `json:"dsack"` EarlyRetransmit string `json:"early_retransmit"` ECN string `json:"ecn"` FastOpen string `json:"fast_open"` FastOpenCookieExp int `json:"fast_open_cookie_expiration"` FINWait2Timeout int `json:"fin_wait_2_timeout"` FINWaitTimeout int `json:"fin_wait_timeout"` HardwareSYNCookie string `json:"hardware_syn_cookie"` IdleTimeout int `json:"idle_timeout"` InitCwnd int `json:"init_cwnd"` InitRwnd int `json:"init_rwnd"` IPDFMode string `json:"ip_df_mode"` IPTOSToClient int `json:"ip_tos_to_client"` IPTTLMode string `json:"ip_ttl_mode"` IPTTLv4 int `json:"ip_ttl_v4"` IPTTLv6 int `json:"ip_ttl_v6"` KeepAliveInterval int `json:"keep_alive_interval"` LimitedTransmit string `json:"limited_transmit"` LinkQOSToClient int `json:"link_qos_to_client"` MaxRetrans int `json:"max_retrans"` MaxSegmentSize int `json:"max_segment_size"` MD5Signature string `json:"md5_signature"` MD5SignaturePassphrase string `json:"md5_signature_passphrase"` MinimumRTO int `json:"minimum_rto"` MPTCP string `json:"mptcp"` MPTCPCSum string `json:"mptcp_csum"` MPTCPCSumVerify string `json:"mptcp_csum_verify"` MPTCPDebug string `json:"mptcp_debug"` MPTCPFallback string `json:"mptcp_fallback"` MPTCPFastjoin string `json:"mptcp_fastjoin"` MPTCPIdleTimeout int `json:"mptcp_idle_timeout"` MPTCPJoinMax int `json:"mptcp_join_max"` MPTCPMakeAfterBreak string `json:"mptcp_makeafterbreak"` MPTCPNojoindssack string `json:"mptcp_nojoindssack"` MPTCPRToMax int `json:"mptcp_rtomax"` MPTCPRXmitMin int `json:"mptcp_rxmitmin"` MPTCPSubFlowMax int `json:"mptcp_subflowmax"` MPTCPTimeout int `json:"mptcp_timeout"` Nagle string `json:"nagle"` PktLossIgnoreBurst int `json:"pkt_loss_ignore_burst"` PktLossIgnoreRate int `json:"pkt_loss_ignore_rate"` ProxyBufferHigh int `json:"proxy_buffer_high"` ProxyBufferLow int `json:"proxy_buffer_low"` ProxyMSS string `json:"proxy_mss"` ProxyOptions string `json:"proxy_options"` RatePace string `json:"rate_pace"` RatePaceMaxRate int `json:"rate_pace_max_rate"` ReceiveWindowSize int `json:"receive_window_size"` ResetOnTimeout string `json:"reset_on_timeout"` RexmtThresh int `json:"rexmt_thresh"` SelectiveACKs string `json:"selective_acks"` SelectiveNACK string `json:"selective_nack"` SendBufferSize int `json:"send_buffer_size"` SlowStart string `json:"slow_start"` SYNCookieWhitelist string `json:"syn_cookie_whitelist"` SYNMaxRetrans int `json:"syn_max_retrans"` SYNRTOBase int `json:"syn_rto_base"` TailLossProbe string `json:"tail_loss_probe"` TCPOptions string `json:"tcp_options"` TimeWaitRecycle string `json:"time_wait_recycle"` TimeWaitTimeout int `json:"time_wait_timeout"` Timestamps string `json:"timestamps"` VerifiedAccept string `json:"verified_accept"` ZeroWindowTimeout int `json:"zero_window_timeout"` } func ParseTCPProfile(raw string) (*TCPProfile, error) { p := new(TCPProfile) split := strings.Split(raw, "\n") if !strings.Contains(split[0], "ltm profile tcp") { return nil, errors.New("not a tcp profile") } p.ProfileCommon = parseCommon(raw) for _, line := range split { f := strings.Fields(line) switch strings.ToLower(f[0]) { case "abc": p.ABC = strings.Join(f[1:], " ") case "ack-on-push": p.ACKOnPush = strings.Join(f[1:], " ") case "close-wait-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.CloseWaitTimeout = i case "cmetrics-cache": p.CMetricsCache = strings.Join(f[1:], " ") case "cmetrics-cache-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.CMetricsCacheTimeout = i case "congestion-control": p.CongestionControl = strings.Join(f[1:], " ") case "deferred-accept": p.DeferredAccept = strings.Join(f[1:], " ") case "delay-window-control": p.DelayWindowControl = strings.Join(f[1:], " ") case "delayed-acks": p.DelayedACKs = strings.Join(f[1:], " ") case "dsack": p.DSACK = strings.Join(f[1:], " ") case "early-retransmit": p.EarlyRetransmit = strings.Join(f[1:], " ") case "ecn": p.ECN = strings.Join(f[1:], " ") case "fast-open": p.FastOpen = strings.Join(f[1:], " ") case "fast-open-cookie-expiration": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.FastOpenCookieExp = i case "fin-wait-2-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.FINWait2Timeout = i case "fin-wait-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.FINWaitTimeout = i case "hardware-syn-cookie": p.HardwareSYNCookie = strings.Join(f[1:], " ") case "idle-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.IdleTimeout = i case "init-cwnd": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.InitCwnd = i case "init-rwnd": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.InitRwnd = i case "ip-df-mode": p.IPDFMode = strings.Join(f[1:], " ") case "ip-tos-to-client": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.IPTOSToClient = i case "ip-ttl-mode": p.IPTTLMode = strings.Join(f[1:], " ") case "ip-ttl-v4": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.IPTTLv4 = i case "ip-ttl-v6": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.IPTTLv6 = i case "keep-alive-interval": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.KeepAliveInterval = i case "limited-transmit": p.LimitedTransmit = strings.Join(f[1:], " ") case "link-qos-to-client": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.LinkQOSToClient = i case "max-retrans": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MaxRetrans = i case "max-segment-size": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MaxSegmentSize = i case "md5-signature": p.MD5Signature = strings.Join(f[1:], " ") case "md5-signature-passphrase": p.MD5SignaturePassphrase = strings.Join(f[1:], " ") case "minimum-rto": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MinimumRTO = i case "mptcp": p.MPTCP = strings.Join(f[1:], " ") case "mptcp-csum": p.MPTCPCSum = strings.Join(f[1:], " ") case "mptcp-csum-verify": p.MPTCPCSumVerify = strings.Join(f[1:], " ") case "mptcp-debug": p.MPTCPDebug = strings.Join(f[1:], " ") case "mptcp-fallback": p.MPTCPFallback = strings.Join(f[1:], " ") case "mptcp-fastjoin": p.MPTCPFastjoin = strings.Join(f[1:], " ") case "mptcp-idle-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MPTCPIdleTimeout = i case "mptcp-join-max": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MPTCPJoinMax = i case "mptcp-makeafterbreak": p.MPTCPMakeAfterBreak = strings.Join(f[1:], " ") case "mptcp-nojoindssack": p.MPTCPNojoindssack = strings.Join(f[1:], " ") case "mptcp-rtomax": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MPTCPRToMax = i case "mptcp-rxmitmin": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MPTCPRXmitMin = i case "mptcp-subflowmax": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MPTCPSubFlowMax = i case "mptcp-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.MPTCPTimeout = i case "nagle": p.Nagle = strings.Join(f[1:], " ") case "pkt-loss-ignore-burst": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.PktLossIgnoreBurst = i case "pkt-loss-ignore-rate": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.PktLossIgnoreRate = i case "proxy-buffer-high": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.ProxyBufferHigh = i case "proxy-buffer-low": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.ProxyBufferLow = i case "proxy-mss": p.ProxyMSS = strings.Join(f[1:], " ") case "proxy-options": p.ProxyOptions = strings.Join(f[1:], " ") case "rate-pace": p.RatePace = strings.Join(f[1:], " ") case "rate-pace-max-rate": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.RatePaceMaxRate = i case "receive-window-size": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.ReceiveWindowSize = i case "reset-on-timeout": p.ResetOnTimeout = strings.Join(f[1:], " ") case "rexmt-thresh": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.RexmtThresh = i case "selective-acks": p.SelectiveACKs = strings.Join(f[1:], " ") case "selective-nack": p.SelectiveNACK = strings.Join(f[1:], " ") case "send-buffer-size": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.SendBufferSize = i case "slow-start": p.SlowStart = strings.Join(f[1:], " ") case "syn-cookie-whitelist": p.SYNCookieWhitelist = strings.Join(f[1:], " ") case "syn-max-retrans": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.SYNMaxRetrans = i case "syn-rto-base": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.SYNRTOBase = i case "tail-loss-probe": p.TailLossProbe = strings.Join(f[1:], " ") case "tcp-options": p.TCPOptions = strings.Join(f[1:], " ") case "time-wait-recycle": p.TimeWaitRecycle = strings.Join(f[1:], " ") case "time-wait-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.TimeWaitTimeout = i case "timestamps": p.Timestamps = strings.Join(f[1:], " ") case "verified-accept": p.VerifiedAccept = strings.Join(f[1:], " ") case "zero-window-timeout": i, err := strconv.Atoi(f[1]) if err != nil { log.WithField("data", f[1]).Error(err.Error()) return nil, err } p.ZeroWindowTimeout = i } } return p, nil }