diff --git a/client/cmd/debug.go b/client/cmd/debug.go index 4036bb8f6..3f13a0c3a 100644 --- a/client/cmd/debug.go +++ b/client/cmd/debug.go @@ -307,7 +307,7 @@ func getStatusOutput(cmd *cobra.Command, anon bool) string { cmd.PrintErrf("Failed to get status: %v\n", err) } else { statusOutputString = nbstatus.ParseToFullDetailSummary( - nbstatus.ConvertToStatusOutputOverview(statusResp, anon, "", nil, nil, nil), + nbstatus.ConvertToStatusOutputOverview(statusResp, anon, "", nil, nil, nil, ""), ) } return statusOutputString diff --git a/client/cmd/status.go b/client/cmd/status.go index b108ca57a..2d6e41bc2 100644 --- a/client/cmd/status.go +++ b/client/cmd/status.go @@ -26,6 +26,7 @@ var ( statusFilter string ipsFilterMap map[string]struct{} prefixNamesFilterMap map[string]struct{} + connectionTypeFilter string ) var statusCmd = &cobra.Command{ @@ -45,6 +46,7 @@ func init() { statusCmd.PersistentFlags().StringSliceVar(&ipsFilter, "filter-by-ips", []string{}, "filters the detailed output by a list of one or more IPs, e.g., --filter-by-ips 100.64.0.100,100.64.0.200") statusCmd.PersistentFlags().StringSliceVar(&prefixNamesFilter, "filter-by-names", []string{}, "filters the detailed output by a list of one or more peer FQDN or hostnames, e.g., --filter-by-names peer-a,peer-b.netbird.cloud") statusCmd.PersistentFlags().StringVar(&statusFilter, "filter-by-status", "", "filters the detailed output by connection status(idle|connecting|connected), e.g., --filter-by-status connected") + statusCmd.PersistentFlags().StringVar(&connectionTypeFilter, "filter-by-connection-type", "", "filters the detailed output by connection type (P2P|Relayed), e.g., --filter-by-connection-type P2P") } func statusFunc(cmd *cobra.Command, args []string) error { @@ -89,7 +91,7 @@ func statusFunc(cmd *cobra.Command, args []string) error { return nil } - var outputInformationHolder = nbstatus.ConvertToStatusOutputOverview(resp, anonymizeFlag, statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilterMap) + var outputInformationHolder = nbstatus.ConvertToStatusOutputOverview(resp, anonymizeFlag, statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilterMap, connectionTypeFilter) var statusOutputString string switch { case detailFlag: @@ -156,6 +158,15 @@ func parseFilters() error { enableDetailFlagWhenFilterFlag() } + switch strings.ToLower(connectionTypeFilter) { + case "", "p2p", "relayed": + if strings.ToLower(connectionTypeFilter) != "" { + enableDetailFlagWhenFilterFlag() + } + default: + return fmt.Errorf("wrong connection-type filter, should be one of P2P|Relayed, got: %s", connectionTypeFilter) + } + return nil } diff --git a/client/proto/daemon.pb.go b/client/proto/daemon.pb.go index 26e58d183..753aa62d1 100644 --- a/client/proto/daemon.pb.go +++ b/client/proto/daemon.pb.go @@ -1330,6 +1330,13 @@ func (x *PeerState) GetRelayAddress() string { return "" } +func (x *PeerState) GetConnectionType() string { + if x.Relayed { + return "Relayed" + } + return "P2P" +} + // LocalPeerState contains the latest state of the local peer type LocalPeerState struct { state protoimpl.MessageState `protogen:"open.v1"` diff --git a/client/status/status.go b/client/status/status.go index 18056e363..507c7ea80 100644 --- a/client/status/status.go +++ b/client/status/status.go @@ -100,7 +100,7 @@ type OutputOverview struct { LazyConnectionEnabled bool `json:"lazyConnectionEnabled" yaml:"lazyConnectionEnabled"` } -func ConvertToStatusOutputOverview(resp *proto.StatusResponse, anon bool, statusFilter string, prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}) OutputOverview { +func ConvertToStatusOutputOverview(resp *proto.StatusResponse, anon bool, statusFilter string, prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}, connectionTypeFilter string) OutputOverview { pbFullStatus := resp.GetFullStatus() managementState := pbFullStatus.GetManagementState() @@ -118,7 +118,7 @@ func ConvertToStatusOutputOverview(resp *proto.StatusResponse, anon bool, status } relayOverview := mapRelays(pbFullStatus.GetRelays()) - peersOverview := mapPeers(resp.GetFullStatus().GetPeers(), statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilter) + peersOverview := mapPeers(resp.GetFullStatus().GetPeers(), statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilter, connectionTypeFilter) overview := OutputOverview{ Peers: peersOverview, @@ -193,6 +193,7 @@ func mapPeers( prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}, + connectionTypeFilter string, ) PeersStateOutput { var peersStateDetail []PeerStateDetailOutput peersConnected := 0 @@ -208,7 +209,7 @@ func mapPeers( transferSent := int64(0) isPeerConnected := pbPeerState.ConnStatus == peer.StatusConnected.String() - if skipDetailByFilters(pbPeerState, pbPeerState.ConnStatus, statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilter) { + if skipDetailByFilters(pbPeerState, pbPeerState.ConnStatus, statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilter, connectionTypeFilter) { continue } if isPeerConnected { @@ -218,10 +219,7 @@ func mapPeers( remoteICE = pbPeerState.GetRemoteIceCandidateType() localICEEndpoint = pbPeerState.GetLocalIceCandidateEndpoint() remoteICEEndpoint = pbPeerState.GetRemoteIceCandidateEndpoint() - connType = "P2P" - if pbPeerState.Relayed { - connType = "Relayed" - } + connType = pbPeerState.GetConnectionType() relayServerAddress = pbPeerState.GetRelayAddress() lastHandshake = pbPeerState.GetLastWireguardHandshake().AsTime().Local() transferReceived = pbPeerState.GetBytesRx() @@ -542,10 +540,11 @@ func parsePeers(peers PeersStateOutput, rosenpassEnabled, rosenpassPermissive bo return peersString } -func skipDetailByFilters(peerState *proto.PeerState, peerStatus string, statusFilter string, prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}) bool { +func skipDetailByFilters(peerState *proto.PeerState, peerStatus string, statusFilter string, prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}, connectionTypeFilter string) bool { statusEval := false ipEval := false nameEval := true + connectionTypeEval := false if statusFilter != "" { if !strings.EqualFold(peerStatus, statusFilter) { @@ -570,8 +569,11 @@ func skipDetailByFilters(peerState *proto.PeerState, peerStatus string, statusFi } else { nameEval = false } + if connectionTypeFilter != "" && !strings.EqualFold(peerState.GetConnectionType(), connectionTypeFilter) { + connectionTypeEval = true + } - return statusEval || ipEval || nameEval + return statusEval || ipEval || nameEval || connectionTypeEval } func toIEC(b int64) string { diff --git a/client/status/status_test.go b/client/status/status_test.go index 33eda4b9e..5b5d23efd 100644 --- a/client/status/status_test.go +++ b/client/status/status_test.go @@ -234,7 +234,7 @@ var overview = OutputOverview{ } func TestConversionFromFullStatusToOutputOverview(t *testing.T) { - convertedResult := ConvertToStatusOutputOverview(resp, false, "", nil, nil, nil) + convertedResult := ConvertToStatusOutputOverview(resp, false, "", nil, nil, nil, "") assert.Equal(t, overview, convertedResult) } diff --git a/client/ui/debug.go b/client/ui/debug.go index ab7dba37a..55829de1e 100644 --- a/client/ui/debug.go +++ b/client/ui/debug.go @@ -433,7 +433,7 @@ func (s *serviceClient) collectDebugData( var postUpStatusOutput string if postUpStatus != nil { - overview := nbstatus.ConvertToStatusOutputOverview(postUpStatus, params.anonymize, "", nil, nil, nil) + overview := nbstatus.ConvertToStatusOutputOverview(postUpStatus, params.anonymize, "", nil, nil, nil, "") postUpStatusOutput = nbstatus.ParseToFullDetailSummary(overview) } headerPostUp := fmt.Sprintf("----- NetBird post-up - Timestamp: %s", time.Now().Format(time.RFC3339)) @@ -450,7 +450,7 @@ func (s *serviceClient) collectDebugData( var preDownStatusOutput string if preDownStatus != nil { - overview := nbstatus.ConvertToStatusOutputOverview(preDownStatus, params.anonymize, "", nil, nil, nil) + overview := nbstatus.ConvertToStatusOutputOverview(preDownStatus, params.anonymize, "", nil, nil, nil, "") preDownStatusOutput = nbstatus.ParseToFullDetailSummary(overview) } headerPreDown := fmt.Sprintf("----- NetBird pre-down - Timestamp: %s - Duration: %s", @@ -581,7 +581,7 @@ func (s *serviceClient) createDebugBundle(anonymize bool, systemInfo bool, uploa var statusOutput string if statusResp != nil { - overview := nbstatus.ConvertToStatusOutputOverview(statusResp, anonymize, "", nil, nil, nil) + overview := nbstatus.ConvertToStatusOutputOverview(statusResp, anonymize, "", nil, nil, nil, "") statusOutput = nbstatus.ParseToFullDetailSummary(overview) }