github.com/fafucoder/cilium@v1.6.11/cilium/cmd/bpf_policy_get.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 "io" 20 "os" 21 "path/filepath" 22 "sort" 23 "strconv" 24 "text/tabwriter" 25 26 "github.com/cilium/cilium/api/v1/models" 27 "github.com/cilium/cilium/common" 28 "github.com/cilium/cilium/pkg/bpf" 29 "github.com/cilium/cilium/pkg/byteorder" 30 "github.com/cilium/cilium/pkg/command" 31 "github.com/cilium/cilium/pkg/identity" 32 "github.com/cilium/cilium/pkg/maps/policymap" 33 "github.com/cilium/cilium/pkg/policy/trafficdirection" 34 "github.com/cilium/cilium/pkg/u8proto" 35 36 "github.com/spf13/cobra" 37 ) 38 39 var ( 40 printIDs bool 41 allList bool 42 ) 43 44 // bpfPolicyListCmd represents the bpf_policy_list command 45 var bpfPolicyListCmd = &cobra.Command{ 46 Use: "get", 47 Short: "List contents of a policy BPF map", 48 Run: func(cmd *cobra.Command, args []string) { 49 common.RequireRootPrivilege("cilium bpf policy get") 50 if allList { 51 listAllMaps() 52 return 53 } 54 requireEndpointID(cmd, args) 55 listMap(args) 56 }, 57 } 58 59 func init() { 60 bpfPolicyCmd.AddCommand(bpfPolicyListCmd) 61 bpfPolicyListCmd.Flags().BoolVarP(&printIDs, "numeric", "n", false, "Do not resolve IDs") 62 bpfPolicyListCmd.Flags().BoolVarP(&allList, "all", "", false, "Dump all policy maps") 63 command.AddJSONOutput(bpfPolicyListCmd) 64 } 65 66 func listAllMaps() { 67 mapRootPrefixPath := bpf.MapPrefixPath() 68 mapMatchExpr := filepath.Join(mapRootPrefixPath, "cilium_policy_*") 69 70 matchFiles, err := filepath.Glob(mapMatchExpr) 71 if err != nil { 72 log.Fatal(err) 73 } 74 75 for _, file := range matchFiles { 76 fmt.Printf("%s:\n", file) 77 fmt.Println() 78 dumpMap(file) 79 fmt.Println() 80 fmt.Println() 81 } 82 } 83 84 func listMap(args []string) { 85 lbl := args[0] 86 87 mapPath, err := endpointToPolicyMapPath(lbl) 88 if err != nil { 89 Fatalf("Failed to parse endpointID %q", lbl) 90 } 91 dumpMap(mapPath) 92 } 93 94 func dumpMap(file string) { 95 m, err := policymap.Open(file) 96 if err != nil { 97 Fatalf("Failed to open map: %s\n", err) 98 } 99 defer m.Close() 100 101 statsMap, err := m.DumpToSlice() 102 if err != nil { 103 Fatalf("Error while opening bpf Map: %s\n", err) 104 } 105 sort.Slice(statsMap, statsMap.Less) 106 107 if command.OutputJSON() { 108 if err := command.PrintOutput(statsMap); err != nil { 109 os.Exit(1) 110 } 111 } else { 112 w := tabwriter.NewWriter(os.Stdout, 5, 0, 3, ' ', 0) 113 formatMap(w, statsMap) 114 w.Flush() 115 if len(statsMap) == 0 { 116 fmt.Printf("Policy stats empty. Perhaps the policy enforcement is disabled?\n") 117 } 118 } 119 120 } 121 122 func formatMap(w io.Writer, statsMap []policymap.PolicyEntryDump) { 123 const ( 124 trafficDirectionTitle = "DIRECTION" 125 labelsIDTitle = "IDENTITY" 126 labelsDesTitle = "LABELS (source:key[=value])" 127 portTitle = "PORT/PROTO" 128 proxyPortTitle = "PROXY PORT" 129 bytesTitle = "BYTES" 130 packetsTitle = "PACKETS" 131 ) 132 133 labelsID := map[identity.NumericIdentity]*identity.Identity{} 134 for _, stat := range statsMap { 135 if !printIDs { 136 id := identity.NumericIdentity(stat.Key.Identity) 137 if lbls, err := client.IdentityGet(id.StringID()); err != nil { 138 fmt.Fprintf(os.Stderr, "Was impossible to retrieve label ID %d: %s\n", 139 id, err) 140 } else { 141 labelsID[id] = identity.NewIdentityFromModel(lbls) 142 } 143 } 144 145 } 146 147 if printIDs { 148 fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", trafficDirectionTitle, labelsIDTitle, portTitle, proxyPortTitle, bytesTitle, packetsTitle) 149 } else { 150 fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t\n", trafficDirectionTitle, labelsDesTitle, portTitle, proxyPortTitle, bytesTitle, packetsTitle) 151 } 152 for _, stat := range statsMap { 153 id := identity.NumericIdentity(stat.Key.Identity) 154 trafficDirection := trafficdirection.TrafficDirection(stat.Key.TrafficDirection) 155 trafficDirectionString := trafficDirection.String() 156 port := models.PortProtocolANY 157 if stat.Key.DestPort != 0 { 158 dport := byteorder.NetworkToHost(stat.Key.DestPort).(uint16) 159 proto := u8proto.U8proto(stat.Key.Nexthdr) 160 port = fmt.Sprintf("%d/%s", dport, proto.String()) 161 } 162 proxyPort := "NONE" 163 if stat.ProxyPort != 0 { 164 proxyPort = strconv.FormatUint(uint64(byteorder.NetworkToHost(stat.ProxyPort).(uint16)), 10) 165 } 166 if printIDs { 167 fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%d\t%d\t\n", trafficDirectionString, id, port, proxyPort, stat.Bytes, stat.Packets) 168 } else if lbls := labelsID[id]; lbls != nil && len(lbls.Labels) > 0 { 169 first := true 170 for _, lbl := range lbls.Labels.GetPrintableModel() { 171 if first { 172 fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%d\t\n", trafficDirectionString, lbl, port, proxyPort, stat.Bytes, stat.Packets) 173 first = false 174 } else { 175 fmt.Fprintf(w, "\t%s\t\t\t\t\t\t\n", lbl) 176 } 177 } 178 } else { 179 fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%d\t%d\t\n", trafficDirectionString, id, port, proxyPort, stat.Bytes, stat.Packets) 180 } 181 } 182 }