go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/abfplugin/vppcalls/vpp2202/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 "fmt" 19 "net" 20 21 "github.com/go-errors/errors" 22 23 vpp_abf "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/abf" 24 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/fib_types" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/interface_types" 26 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/ip_types" 27 abf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/abf" 28 ) 29 30 const ( 31 // NextHopViaLabelUnset constant has to be assigned into the field next hop via label 32 // in abf_policy_add_del binary message if next hop via label is not defined. 33 NextHopViaLabelUnset uint32 = 0xfffff + 1 34 35 // ClassifyTableIndexUnset is a default value for field classify_table_index 36 // in abf_policy_add_del binary message. 37 ClassifyTableIndexUnset = ^uint32(0) 38 ) 39 40 // GetAbfVersion retrieves version of the VPP ABF plugin 41 func (h *ABFVppHandler) GetAbfVersion() (ver string, err error) { 42 req := &vpp_abf.AbfPluginGetVersion{} 43 reply := &vpp_abf.AbfPluginGetVersionReply{} 44 45 if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { 46 return "", err 47 } 48 49 return fmt.Sprintf("%d.%d", reply.Major, reply.Minor), nil 50 } 51 52 // AddAbfPolicy creates new ABF entry together with a list of forwarding paths 53 func (h *ABFVppHandler) AddAbfPolicy(policyID, aclID uint32, abfPaths []*abf.ABF_ForwardingPath) error { 54 if err := h.abfAddDelPolicy(policyID, aclID, abfPaths, true); err != nil { 55 return errors.Errorf("failed to add ABF policy %d (ACL: %v): %v", policyID, aclID, err) 56 } 57 return nil 58 } 59 60 // DeleteAbfPolicy removes existing ABF entry 61 func (h *ABFVppHandler) DeleteAbfPolicy(policyID uint32, abfPaths []*abf.ABF_ForwardingPath) error { 62 if err := h.abfAddDelPolicy(policyID, 0, abfPaths, false); err != nil { 63 return errors.Errorf("failed to delete ABF policy %d: %v", policyID, err) 64 } 65 return nil 66 } 67 68 // AbfAttachInterfaceIPv4 attaches IPv4 interface to the ABF 69 func (h *ABFVppHandler) AbfAttachInterfaceIPv4(policyID, ifIdx, priority uint32) error { 70 if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, true, false); err != nil { 71 return errors.Errorf("failed to attach IPv4 interface %d to ABF policy %d: %v", ifIdx, policyID, err) 72 } 73 return nil 74 } 75 76 // AbfDetachInterfaceIPv4 detaches IPV4 interface from the ABF 77 func (h *ABFVppHandler) AbfDetachInterfaceIPv4(policyID, ifIdx, priority uint32) error { 78 if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, false, false); err != nil { 79 return errors.Errorf("failed to detach IPv4 interface %d from ABF policy %d: %v", ifIdx, policyID, err) 80 } 81 return nil 82 } 83 84 // AbfAttachInterfaceIPv6 attaches IPv6 interface to the ABF 85 func (h *ABFVppHandler) AbfAttachInterfaceIPv6(policyID, ifIdx, priority uint32) error { 86 if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, true, true); err != nil { 87 return errors.Errorf("failed to attach IPv6 interface %d to ABF policy %d: %v", ifIdx, policyID, err) 88 } 89 return nil 90 } 91 92 // AbfDetachInterfaceIPv6 detaches IPv6 interface from the ABF 93 func (h *ABFVppHandler) AbfDetachInterfaceIPv6(policyID, ifIdx, priority uint32) error { 94 if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, false, true); err != nil { 95 return errors.Errorf("failed to detach IPv6 interface %d from ABF policy %d: %v", ifIdx, policyID, err) 96 } 97 return nil 98 } 99 100 func (h *ABFVppHandler) abfAttachDetachInterface(policyID, ifIdx, priority uint32, isAdd, isIPv6 bool) error { 101 req := &vpp_abf.AbfItfAttachAddDel{ 102 IsAdd: isAdd, 103 Attach: vpp_abf.AbfItfAttach{ 104 PolicyID: policyID, 105 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 106 Priority: priority, 107 IsIPv6: isIPv6, 108 }, 109 } 110 reply := &vpp_abf.AbfItfAttachAddDelReply{} 111 112 return h.callsChannel.SendRequest(req).ReceiveReply(reply) 113 } 114 115 func (h *ABFVppHandler) abfAddDelPolicy(policyID, aclID uint32, abfPaths []*abf.ABF_ForwardingPath, isAdd bool) error { 116 req := &vpp_abf.AbfPolicyAddDel{ 117 IsAdd: isAdd, 118 Policy: vpp_abf.AbfPolicy{ 119 PolicyID: policyID, 120 ACLIndex: aclID, 121 Paths: h.toFibPaths(abfPaths), 122 NPaths: uint8(len(abfPaths)), 123 }, 124 } 125 reply := &vpp_abf.AbfPolicyAddDelReply{} 126 127 return h.callsChannel.SendRequest(req).ReceiveReply(reply) 128 } 129 130 func (h *ABFVppHandler) toFibPaths(abfPaths []*abf.ABF_ForwardingPath) (fibPaths []fib_types.FibPath) { 131 var err error 132 for _, abfPath := range abfPaths { 133 // fib path interface 134 ifData, exists := h.ifIndexes.LookupByName(abfPath.InterfaceName) 135 if !exists { 136 continue 137 } 138 139 fibPath := fib_types.FibPath{ 140 SwIfIndex: ifData.SwIfIndex, 141 Weight: uint8(abfPath.Weight), 142 Preference: uint8(abfPath.Preference), 143 Type: setFibPathType(abfPath.Dvr), 144 } 145 if fibPath.Nh, fibPath.Proto, err = setFibPathNhAndProto(abfPath.NextHopIp); err != nil { 146 h.log.Errorf("ABF path next hop error: %v", err) 147 } 148 fibPaths = append(fibPaths, fibPath) 149 } 150 151 return fibPaths 152 } 153 154 // supported cases are DVR and normal 155 func setFibPathType(isDvr bool) fib_types.FibPathType { 156 if isDvr { 157 return fib_types.FIB_API_PATH_TYPE_DVR 158 } 159 return fib_types.FIB_API_PATH_TYPE_NORMAL 160 } 161 162 // resolve IP address and return FIB path next hop (IP address) and IPv4/IPv6 version 163 func setFibPathNhAndProto(ipStr string) (nh fib_types.FibPathNh, proto fib_types.FibPathNhProto, err error) { 164 netIP := net.ParseIP(ipStr) 165 if netIP == nil { 166 return nh, proto, errors.Errorf("failed to parse next hop IP address %s", ipStr) 167 } 168 var au ip_types.AddressUnion 169 if ipv4 := netIP.To4(); ipv4 == nil { 170 var address ip_types.IP6Address 171 proto = fib_types.FIB_API_PATH_NH_PROTO_IP6 172 copy(address[:], netIP[:]) 173 au.SetIP6(address) 174 } else { 175 var address ip_types.IP4Address 176 proto = fib_types.FIB_API_PATH_NH_PROTO_IP4 177 copy(address[:], netIP[12:]) 178 au.SetIP4(address) 179 } 180 return fib_types.FibPathNh{ 181 Address: au, 182 ViaLabel: NextHopViaLabelUnset, 183 ClassifyTableIndex: ClassifyTableIndexUnset, 184 }, proto, nil 185 }