go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/abfplugin/vppcalls/vpp2202/dump_abf_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 vpp2202 16 17 import ( 18 "net" 19 20 "go.ligato.io/vpp-agent/v3/plugins/vpp/abfplugin/vppcalls" 21 vpp_abf "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/abf" 22 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/fib_types" 23 abf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/abf" 24 ) 25 26 // placeholder for unknown names 27 const unknownName = "<unknown>" 28 29 // DumpABFPolicy retrieves VPP ABF configuration. 30 func (h *ABFVppHandler) DumpABFPolicy() ([]*vppcalls.ABFDetails, error) { 31 // retrieve ABF interfaces 32 attachedIfs, err := h.dumpABFInterfaces() 33 if err != nil { 34 return nil, err 35 } 36 37 // retrieve ABF policy 38 abfPolicy, err := h.dumpABFPolicy() 39 if err != nil { 40 return nil, err 41 } 42 43 // merge attached interfaces data to policy 44 for _, policy := range abfPolicy { 45 ifData, ok := attachedIfs[policy.Meta.PolicyID] 46 if ok { 47 policy.ABF.AttachedInterfaces = ifData 48 } 49 } 50 51 return abfPolicy, nil 52 } 53 54 func (h *ABFVppHandler) dumpABFInterfaces() (map[uint32][]*abf.ABF_AttachedInterface, error) { 55 // ABF index <-> attached interfaces 56 abfIfs := make(map[uint32][]*abf.ABF_AttachedInterface) 57 58 req := &vpp_abf.AbfItfAttachDump{} 59 reqCtx := h.callsChannel.SendMultiRequest(req) 60 61 for { 62 reply := &vpp_abf.AbfItfAttachDetails{} 63 last, err := reqCtx.ReceiveReply(reply) 64 if err != nil { 65 return nil, err 66 } 67 if last { 68 break 69 } 70 71 // interface name 72 ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(uint32(reply.Attach.SwIfIndex)) 73 if !exists { 74 ifName = unknownName 75 } 76 77 // attached interface entry 78 attached := &abf.ABF_AttachedInterface{ 79 InputInterface: ifName, 80 Priority: reply.Attach.Priority, 81 IsIpv6: reply.Attach.IsIPv6, 82 } 83 84 _, ok := abfIfs[reply.Attach.PolicyID] 85 if !ok { 86 abfIfs[reply.Attach.PolicyID] = []*abf.ABF_AttachedInterface{} 87 } 88 abfIfs[reply.Attach.PolicyID] = append(abfIfs[reply.Attach.PolicyID], attached) 89 } 90 91 return abfIfs, nil 92 } 93 94 func (h *ABFVppHandler) dumpABFPolicy() ([]*vppcalls.ABFDetails, error) { 95 var abfs []*vppcalls.ABFDetails 96 req := &vpp_abf.AbfPolicyDump{} 97 reqCtx := h.callsChannel.SendMultiRequest(req) 98 99 for { 100 reply := &vpp_abf.AbfPolicyDetails{} 101 last, err := reqCtx.ReceiveReply(reply) 102 if err != nil { 103 return nil, err 104 } 105 if last { 106 break 107 } 108 109 // ACL name 110 aclName, _, exists := h.aclIndexes.LookupByIndex(reply.Policy.ACLIndex) 111 if !exists { 112 aclName = unknownName 113 } 114 115 // paths 116 var fwdPaths []*abf.ABF_ForwardingPath 117 for _, path := range reply.Policy.Paths { 118 // interface name 119 ifName, _, exists := h.ifIndexes.LookupBySwIfIndex(path.SwIfIndex) 120 if !exists { 121 ifName = unknownName 122 } 123 124 // base fields 125 fwdPath := &abf.ABF_ForwardingPath{ 126 NextHopIp: parseNextHopToString(path.Nh, path.Proto), 127 InterfaceName: ifName, 128 Weight: uint32(path.Weight), 129 Preference: uint32(path.Preference), 130 Dvr: path.Type == fib_types.FIB_API_PATH_TYPE_DVR, 131 } 132 fwdPaths = append(fwdPaths, fwdPath) 133 } 134 135 abfData := &vppcalls.ABFDetails{ 136 ABF: &abf.ABF{ 137 Index: reply.Policy.PolicyID, 138 AclName: aclName, 139 ForwardingPaths: fwdPaths, 140 }, 141 Meta: &vppcalls.ABFMeta{ 142 PolicyID: reply.Policy.PolicyID, 143 }, 144 } 145 146 abfs = append(abfs, abfData) 147 } 148 149 return abfs, nil 150 } 151 152 // returns next hop IP address 153 func parseNextHopToString(nh fib_types.FibPathNh, proto fib_types.FibPathNhProto) string { 154 if proto == fib_types.FIB_API_PATH_NH_PROTO_IP4 { 155 addr := nh.Address.GetIP4() 156 return net.IP(addr[:]).To4().String() 157 } 158 if proto == fib_types.FIB_API_PATH_NH_PROTO_IP6 { 159 addr := nh.Address.GetIP6() 160 return net.IP(addr[:]).To16().String() 161 } 162 return "" 163 }