github.com/fafucoder/cilium@v1.6.11/cilium/cmd/bpf_lb_list.go (about)

     1  // Copyright 2017-2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cmd
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/cilium/cilium/common"
    21  	"github.com/cilium/cilium/pkg/bpf"
    22  	"github.com/cilium/cilium/pkg/command"
    23  	"github.com/cilium/cilium/pkg/loadbalancer"
    24  	"github.com/cilium/cilium/pkg/maps/lbmap"
    25  
    26  	"github.com/spf13/cobra"
    27  )
    28  
    29  const (
    30  	idTitle             = "ID"
    31  	serviceAddressTitle = "SERVICE ADDRESS"
    32  	backendAddressTitle = "BACKEND ADDRESS"
    33  )
    34  
    35  var (
    36  	listRevNAT bool
    37  )
    38  
    39  func dumpRevNat(serviceList map[string][]string) {
    40  	if err := lbmap.RevNat4Map.DumpIfExists(serviceList); err != nil {
    41  		Fatalf("Unable to dump IPv4 reverse NAT table: %s", err)
    42  	}
    43  	if err := lbmap.RevNat6Map.DumpIfExists(serviceList); err != nil {
    44  		Fatalf("Unable to dump IPv6 reverse NAT table: %s", err)
    45  	}
    46  }
    47  
    48  func dumpSVC(serviceList map[string][]string) {
    49  	// It's safe to use the same map for both IPv4 and IPv6, as backend
    50  	// IDs are allocated from the same pool regardless the protocol
    51  	backendMap := make(map[loadbalancer.BackendID]lbmap.BackendValue)
    52  
    53  	parseBackendEntry := func(key bpf.MapKey, value bpf.MapValue) {
    54  		id := key.(lbmap.BackendKey).GetID()
    55  		backendMap[id] = value.DeepCopyMapValue().(lbmap.BackendValue)
    56  	}
    57  	if err := lbmap.Backend4Map.DumpWithCallbackIfExists(parseBackendEntry); err != nil {
    58  		Fatalf("Unable to dump IPv4 backends table: %s", err)
    59  	}
    60  	if err := lbmap.Backend6Map.DumpWithCallbackIfExists(parseBackendEntry); err != nil {
    61  		Fatalf("Unable to dump IPv6 backends table: %s", err)
    62  	}
    63  
    64  	parseSVCEntry := func(key bpf.MapKey, value bpf.MapValue) {
    65  		var entry string
    66  
    67  		svcKey := key.(lbmap.ServiceKeyV2)
    68  		svcVal := value.(lbmap.ServiceValueV2)
    69  		svc := svcKey.String()
    70  		revNATID := svcVal.GetRevNat()
    71  		backendID := svcVal.GetBackendID()
    72  
    73  		if backendID == 0 {
    74  			ip := "0.0.0.0"
    75  			if svcKey.IsIPv6() {
    76  				ip = "[::]"
    77  			}
    78  			entry = fmt.Sprintf("%s:%d (%d)", ip, 0, revNATID)
    79  		} else if backend, found := backendMap[backendID]; !found {
    80  			entry = fmt.Sprintf("backend %d not found", backendID)
    81  		} else {
    82  			fmtStr := "%s:%d (%d)"
    83  			if svcKey.IsIPv6() {
    84  				fmtStr = "[%s]:%d (%d)"
    85  			}
    86  			entry = fmt.Sprintf(fmtStr, backend.GetAddress(),
    87  				backend.GetPort(), revNATID)
    88  		}
    89  
    90  		serviceList[svc] = append(serviceList[svc], entry)
    91  	}
    92  
    93  	if err := lbmap.Service4MapV2.DumpWithCallbackIfExists(parseSVCEntry); err != nil {
    94  		Fatalf("Unable to dump IPv4 services table: %s", err)
    95  	}
    96  	if err := lbmap.Service6MapV2.DumpWithCallbackIfExists(parseSVCEntry); err != nil {
    97  		Fatalf("Unable to dump IPv6 services table: %s", err)
    98  	}
    99  }
   100  
   101  // bpfCtListCmd represents the bpf_ct_list command
   102  var bpfLBListCmd = &cobra.Command{
   103  	Use:     "list",
   104  	Aliases: []string{"ls"},
   105  	Short:   "List load-balancing configuration",
   106  	Run: func(cmd *cobra.Command, args []string) {
   107  		common.RequireRootPrivilege("cilium bpf lb list")
   108  
   109  		var firstTitle string
   110  		serviceList := make(map[string][]string)
   111  		switch {
   112  		case listRevNAT:
   113  			firstTitle = idTitle
   114  			dumpRevNat(serviceList)
   115  		default:
   116  			firstTitle = serviceAddressTitle
   117  			dumpSVC(serviceList)
   118  		}
   119  
   120  		if command.OutputJSON() {
   121  			if err := command.PrintOutput(serviceList); err != nil {
   122  				Fatalf("Unable to generate JSON output: %s", err)
   123  			}
   124  			return
   125  		}
   126  
   127  		TablePrinter(firstTitle, backendAddressTitle, serviceList)
   128  	},
   129  }
   130  
   131  func init() {
   132  	bpfLBCmd.AddCommand(bpfLBListCmd)
   133  	bpfLBListCmd.Flags().BoolVarP(&listRevNAT, "revnat", "", false, "List reverse NAT entries")
   134  	command.AddJSONOutput(bpfLBListCmd)
   135  }