go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/puntplugin/vppcalls/vpp2210/dump_vppcalls.go (about) 1 // Copyright (c) 2022 Cisco and/or its affiliates. 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 vpp2210 16 17 import ( 18 "net" 19 "strings" 20 21 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/interface_types" 22 vpp_ip "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/ip" 23 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/ip_types" 24 vpp_punt "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/punt" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls" 26 punt "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/punt" 27 ) 28 29 // DumpPuntRedirect dumps ip redirect punts 30 func (h *PuntVppHandler) DumpPuntRedirect() (punts []*punt.IPRedirect, err error) { 31 punt4, err := h.dumpPuntRedirect(false) 32 if err != nil { 33 return nil, err 34 } 35 punts = append(punts, punt4...) 36 37 punt6, err := h.dumpPuntRedirect(true) 38 if err != nil { 39 return nil, err 40 } 41 punts = append(punts, punt6...) 42 43 return punts, nil 44 } 45 46 func (h *PuntVppHandler) dumpPuntRedirect(ipv6 bool) (punts []*punt.IPRedirect, err error) { 47 req := h.callsChannel.SendMultiRequest(&vpp_ip.IPPuntRedirectDump{ 48 SwIfIndex: ^interface_types.InterfaceIndex(0), 49 IsIPv6: ipv6, 50 }) 51 for { 52 d := &vpp_ip.IPPuntRedirectDetails{} 53 stop, err := req.ReceiveReply(d) 54 if stop { 55 break 56 } 57 if err != nil { 58 return nil, err 59 } 60 61 rxIface, _, exists := h.ifIndexes.LookupBySwIfIndex(uint32(d.Punt.RxSwIfIndex)) 62 if !exists { 63 h.log.Warnf("RX interface (%v) not found", d.Punt.RxSwIfIndex) 64 continue 65 } 66 txIface, _, exists := h.ifIndexes.LookupBySwIfIndex(uint32(d.Punt.TxSwIfIndex)) 67 if !exists { 68 h.log.Warnf("TX interface (%v) not found", d.Punt.TxSwIfIndex) 69 continue 70 } 71 72 var l3proto punt.L3Protocol 73 var nextHop string 74 75 if d.Punt.Nh.Af == ip_types.ADDRESS_IP4 { 76 l3proto = punt.L3Protocol_IPV4 77 addr := d.Punt.Nh.Un.GetIP4() 78 nextHop = net.IP(addr[:]).To4().String() 79 } else if d.Punt.Nh.Af == ip_types.ADDRESS_IP6 { 80 l3proto = punt.L3Protocol_IPV6 81 addr := d.Punt.Nh.Un.GetIP6() 82 nextHop = net.IP(addr[:]).To16().String() 83 } else { 84 h.log.Warnf("invalid address family (%v)", d.Punt.Nh.Af) 85 continue 86 } 87 88 punts = append(punts, &punt.IPRedirect{ 89 L3Protocol: l3proto, 90 RxInterface: rxIface, 91 TxInterface: txIface, 92 NextHop: nextHop, 93 }) 94 } 95 96 return punts, nil 97 } 98 99 // DumpExceptions returns dump of registered punt exceptions. 100 func (h *PuntVppHandler) DumpExceptions() (punts []*vppcalls.ExceptionDetails, err error) { 101 reasons, err := h.dumpPuntReasons() 102 if err != nil { 103 return nil, err 104 } 105 reasonMap := make(map[uint32]string, len(reasons)) 106 for _, r := range reasons { 107 reasonMap[r.ID] = r.Reason.Name 108 } 109 110 if punts, err = h.dumpPuntExceptions(reasonMap); err != nil { 111 return nil, err 112 } 113 114 return punts, nil 115 } 116 117 func (h *PuntVppHandler) dumpPuntExceptions(reasons map[uint32]string) (punts []*vppcalls.ExceptionDetails, err error) { 118 req := h.callsChannel.SendMultiRequest(&vpp_punt.PuntSocketDump{ 119 Type: vpp_punt.PUNT_API_TYPE_EXCEPTION, 120 }) 121 for { 122 d := &vpp_punt.PuntSocketDetails{} 123 stop, err := req.ReceiveReply(d) 124 if stop { 125 break 126 } 127 if err != nil { 128 return nil, err 129 } 130 131 if d.Punt.Type != vpp_punt.PUNT_API_TYPE_EXCEPTION { 132 h.log.Warnf("VPP returned invalid punt type in exception punt dump: %v", d.Punt.Type) 133 continue 134 } 135 136 puntData := d.Punt.Punt.GetException() 137 reason := reasons[puntData.ID] 138 socketPath := strings.Trim(d.Pathname, "\x00") 139 140 punts = append(punts, &vppcalls.ExceptionDetails{ 141 Exception: &punt.Exception{ 142 Reason: reason, 143 SocketPath: vppConfigSocketPath, 144 }, 145 SocketPath: socketPath, 146 }) 147 } 148 149 return punts, nil 150 } 151 152 // DumpRegisteredPuntSockets returns punt to host via registered socket entries 153 func (h *PuntVppHandler) DumpRegisteredPuntSockets() (punts []*vppcalls.PuntDetails, err error) { 154 if punts, err = h.dumpPuntL4(); err != nil { 155 return nil, err 156 } 157 158 return punts, nil 159 } 160 161 func (h *PuntVppHandler) dumpPuntL4() (punts []*vppcalls.PuntDetails, err error) { 162 req := h.callsChannel.SendMultiRequest(&vpp_punt.PuntSocketDump{ 163 Type: vpp_punt.PUNT_API_TYPE_L4, 164 }) 165 for { 166 d := &vpp_punt.PuntSocketDetails{} 167 stop, err := req.ReceiveReply(d) 168 if stop { 169 break 170 } 171 if err != nil { 172 return nil, err 173 } 174 175 if d.Punt.Type != vpp_punt.PUNT_API_TYPE_L4 { 176 h.log.Warnf("VPP returned invalid punt type in L4 punt dump: %v", d.Punt.Type) 177 continue 178 } 179 180 puntData := d.Punt.Punt.GetL4() 181 socketPath := strings.Trim(d.Pathname, "\x00") 182 183 punts = append(punts, &vppcalls.PuntDetails{ 184 PuntData: &punt.ToHost{ 185 Port: uint32(puntData.Port), 186 L3Protocol: parseL3Proto(puntData.Af), 187 L4Protocol: parseL4Proto(puntData.Protocol), 188 SocketPath: vppConfigSocketPath, 189 }, 190 SocketPath: socketPath, 191 }) 192 } 193 194 return punts, nil 195 } 196 197 // DumpPuntReasons returns all known punt reasons from VPP 198 func (h *PuntVppHandler) DumpPuntReasons() (reasons []*vppcalls.ReasonDetails, err error) { 199 if reasons, err = h.dumpPuntReasons(); err != nil { 200 return nil, err 201 } 202 203 return reasons, nil 204 } 205 206 func (h *PuntVppHandler) dumpPuntReasons() (reasons []*vppcalls.ReasonDetails, err error) { 207 req := h.callsChannel.SendMultiRequest(&vpp_punt.PuntReasonDump{}) 208 for { 209 d := &vpp_punt.PuntReasonDetails{} 210 stop, err := req.ReceiveReply(d) 211 if stop { 212 break 213 } 214 if err != nil { 215 return nil, err 216 } 217 218 reasons = append(reasons, &vppcalls.ReasonDetails{ 219 Reason: &punt.Reason{ 220 Name: d.Reason.Name, 221 }, 222 ID: d.Reason.ID, 223 }) 224 } 225 226 return reasons, nil 227 } 228 229 func parseL3Proto(p ip_types.AddressFamily) punt.L3Protocol { 230 switch p { 231 case ip_types.ADDRESS_IP4: 232 return punt.L3Protocol_IPV4 233 case ip_types.ADDRESS_IP6: 234 return punt.L3Protocol_IPV6 235 } 236 return punt.L3Protocol_UNDEFINED_L3 237 } 238 239 func parseL4Proto(p ip_types.IPProto) punt.L4Protocol { 240 switch p { 241 case ip_types.IP_API_PROTO_TCP: 242 return punt.L4Protocol_TCP 243 case ip_types.IP_API_PROTO_UDP: 244 return punt.L4Protocol_UDP 245 } 246 return punt.L4Protocol_UNDEFINED_L4 247 }