go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/aclplugin/vppcalls/vpp2210/interfaces_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 "fmt" 19 20 vpp_acl "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/acl" 21 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2210/interface_types" 22 ) 23 24 // SetACLToInterfacesAsIngress implements ACL handler. 25 func (h *ACLVppHandler) SetACLToInterfacesAsIngress(ACLIndex uint32, ifIndices []uint32) error { 26 return h.requestSetACLToInterfaces(&aclInterfaceLogicalReq{ 27 aclIndex: ACLIndex, 28 ifIndices: ifIndices, 29 ingress: true, 30 }) 31 } 32 33 // RemoveACLFromInterfacesAsIngress implements ACL handler. 34 func (h *ACLVppHandler) RemoveACLFromInterfacesAsIngress(ACLIndex uint32, ifIndices []uint32) error { 35 return h.requestRemoveInterfacesFromACL(&aclInterfaceLogicalReq{ 36 aclIndex: ACLIndex, 37 ifIndices: ifIndices, 38 ingress: true, 39 }) 40 } 41 42 // SetACLToInterfacesAsEgress implements ACL handler. 43 func (h *ACLVppHandler) SetACLToInterfacesAsEgress(ACLIndex uint32, ifIndices []uint32) error { 44 return h.requestSetACLToInterfaces(&aclInterfaceLogicalReq{ 45 aclIndex: ACLIndex, 46 ifIndices: ifIndices, 47 ingress: false, 48 }) 49 } 50 51 // RemoveACLFromInterfacesAsEgress implements ACL handler. 52 func (h *ACLVppHandler) RemoveACLFromInterfacesAsEgress(ACLIndex uint32, ifIndices []uint32) error { 53 return h.requestRemoveInterfacesFromACL(&aclInterfaceLogicalReq{ 54 aclIndex: ACLIndex, 55 ifIndices: ifIndices, 56 ingress: false, 57 }) 58 } 59 60 // AddACLToInterfaceAsIngress implements ACL handler. 61 func (h *ACLVppHandler) AddACLToInterfaceAsIngress(aclIndex uint32, ifName string) error { 62 meta, ok := h.ifIndexes.LookupByName(ifName) 63 if !ok { 64 return fmt.Errorf("metadata for interface %s not found", ifName) 65 } 66 ifIdx := meta.SwIfIndex 67 68 req := &vpp_acl.ACLInterfaceAddDel{ 69 ACLIndex: aclIndex, 70 IsAdd: true, 71 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 72 IsInput: true, 73 } 74 reply := &vpp_acl.ACLInterfaceAddDelReply{} 75 76 err := h.callsChannel.SendRequest(req).ReceiveReply(reply) 77 if err != nil { 78 return fmt.Errorf("failed to add interface %d to ACL (L3/L4) %d as ingress: %v", ifIdx, aclIndex, err) 79 } 80 81 return nil 82 } 83 84 // AddACLToInterfaceAsEgress implements ACL handler. 85 func (h *ACLVppHandler) AddACLToInterfaceAsEgress(aclIndex uint32, ifName string) error { 86 meta, ok := h.ifIndexes.LookupByName(ifName) 87 if !ok { 88 return fmt.Errorf("metadata for interface %s not found", ifName) 89 } 90 ifIdx := meta.SwIfIndex 91 92 req := &vpp_acl.ACLInterfaceAddDel{ 93 ACLIndex: aclIndex, 94 IsAdd: true, 95 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 96 IsInput: false, 97 } 98 reply := &vpp_acl.ACLInterfaceAddDelReply{} 99 100 err := h.callsChannel.SendRequest(req).ReceiveReply(reply) 101 if err != nil { 102 return fmt.Errorf("failed to add interface %d to ACL (L3/L4) %d as egress: %v", ifIdx, aclIndex, err) 103 } 104 105 return nil 106 } 107 108 // DeleteACLFromInterfaceAsIngress implements ACL handler. 109 func (h *ACLVppHandler) DeleteACLFromInterfaceAsIngress(aclIndex uint32, ifName string) error { 110 meta, ok := h.ifIndexes.LookupByName(ifName) 111 if !ok { 112 return fmt.Errorf("metadata for interface %s not found", ifName) 113 } 114 ifIdx := meta.SwIfIndex 115 116 req := &vpp_acl.ACLInterfaceAddDel{ 117 ACLIndex: aclIndex, 118 IsAdd: false, 119 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 120 IsInput: true, 121 } 122 reply := &vpp_acl.ACLInterfaceAddDelReply{} 123 124 if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { 125 return fmt.Errorf("failed to delete interface %d from ACL (L3/L4) %d as ingress: %v", ifIdx, aclIndex, err) 126 } 127 128 return nil 129 } 130 131 // DeleteACLFromInterfaceAsEgress implements ACL handler. 132 func (h *ACLVppHandler) DeleteACLFromInterfaceAsEgress(aclIndex uint32, ifName string) error { 133 meta, ok := h.ifIndexes.LookupByName(ifName) 134 if !ok { 135 return fmt.Errorf("metadata for interface %s not found", ifName) 136 } 137 ifIdx := meta.SwIfIndex 138 139 req := &vpp_acl.ACLInterfaceAddDel{ 140 ACLIndex: aclIndex, 141 IsAdd: false, 142 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 143 IsInput: false, 144 } 145 reply := &vpp_acl.ACLInterfaceAddDelReply{} 146 147 if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { 148 return fmt.Errorf("failed to delete interface %d from ACL (L3/L4) %d as egress: %v", ifIdx, aclIndex, err) 149 } 150 151 return nil 152 } 153 154 // AddMACIPACLToInterface implements ACL handler. 155 func (h *ACLVppHandler) AddMACIPACLToInterface(aclIndex uint32, ifName string) error { 156 meta, ok := h.ifIndexes.LookupByName(ifName) 157 if !ok { 158 return fmt.Errorf("metadata for interface %s not found", ifName) 159 } 160 ifIdx := meta.SwIfIndex 161 162 req := &vpp_acl.MacipACLInterfaceAddDel{ 163 ACLIndex: aclIndex, 164 IsAdd: true, 165 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 166 } 167 reply := &vpp_acl.MacipACLInterfaceAddDelReply{} 168 169 err := h.callsChannel.SendRequest(req).ReceiveReply(reply) 170 if err != nil { 171 return fmt.Errorf("failed to add interface %d to MACIP ACL (L2) %d: %v", ifIdx, aclIndex, err) 172 } 173 174 return nil 175 } 176 177 // DeleteMACIPACLFromInterface implements ACL handler. 178 func (h *ACLVppHandler) DeleteMACIPACLFromInterface(aclIndex uint32, ifName string) error { 179 meta, ok := h.ifIndexes.LookupByName(ifName) 180 if !ok { 181 return fmt.Errorf("metadata for interface %s not found", ifName) 182 } 183 ifIdx := meta.SwIfIndex 184 185 req := &vpp_acl.MacipACLInterfaceAddDel{ 186 ACLIndex: aclIndex, 187 IsAdd: false, 188 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 189 } 190 reply := &vpp_acl.MacipACLInterfaceAddDelReply{} 191 192 err := h.callsChannel.SendRequest(req).ReceiveReply(reply) 193 if err != nil { 194 return fmt.Errorf("failed to delete interface %d from MACIP ACL (L2) %d: %v", ifIdx, aclIndex, err) 195 } 196 197 return nil 198 } 199 200 // SetMACIPACLToInterfaces implements ACL handler. 201 func (h *ACLVppHandler) SetMACIPACLToInterfaces(aclIndex uint32, ifIndices []uint32) error { 202 for _, ifIdx := range ifIndices { 203 req := &vpp_acl.MacipACLInterfaceAddDel{ 204 ACLIndex: aclIndex, 205 IsAdd: true, 206 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 207 } 208 reply := &vpp_acl.MacipACLInterfaceAddDelReply{} 209 210 err := h.callsChannel.SendRequest(req).ReceiveReply(reply) 211 if err != nil { 212 return fmt.Errorf("failed to set interface %d to L2 ACL %d: %v", ifIdx, aclIndex, err) 213 } 214 } 215 216 return nil 217 } 218 219 // RemoveMACIPACLFromInterfaces implements ACL handler. 220 func (h *ACLVppHandler) RemoveMACIPACLFromInterfaces(removedACLIndex uint32, ifIndices []uint32) error { 221 for _, ifIdx := range ifIndices { 222 req := &vpp_acl.MacipACLInterfaceAddDel{ 223 ACLIndex: removedACLIndex, 224 SwIfIndex: interface_types.InterfaceIndex(ifIdx), 225 IsAdd: false, 226 } 227 reply := &vpp_acl.MacipACLInterfaceAddDelReply{} 228 229 if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { 230 return fmt.Errorf("failed to remove L2 ACL %d from interface %d: %v", removedACLIndex, ifIdx, err) 231 } 232 } 233 return nil 234 } 235 236 // aclInterfaceLogicalReq groups multiple fields to not enumerate all of them in one function call 237 type aclInterfaceLogicalReq struct { 238 aclIndex uint32 239 ifIndices []uint32 240 ingress bool 241 } 242 243 func (h *ACLVppHandler) requestSetACLToInterfaces(logicalReq *aclInterfaceLogicalReq) error { 244 for _, aclIfIdx := range logicalReq.ifIndices { 245 // Create acl list with new entry 246 var ACLs []uint32 247 248 // All previously assigned ACLs have to be dumped and added to acl list 249 aclInterfaceDetails, err := h.DumpInterfaceACLList(aclIfIdx) 250 if err != nil { 251 return err 252 } 253 254 var nInput uint8 255 if aclInterfaceDetails != nil { 256 nInput = aclInterfaceDetails.NInput 257 if logicalReq.ingress { 258 // Construct ACL list. ACLs within NInput are defined as ingress, so provided new aclIndex has to be 259 // added to the beginning of the list 260 // TODO it would be nicer to add new acl index to newNInput index 261 ACLs = append(ACLs, logicalReq.aclIndex) 262 ACLs = append(ACLs, aclInterfaceDetails.Acls...) 263 nInput++ // Rise NInput 264 } else { 265 // Construct ACL list. ACLs outside of NInput are defined as egress, so provided new aclIndex has to be 266 // added to the end of the list 267 ACLs = append(ACLs, aclInterfaceDetails.Acls...) 268 ACLs = append(ACLs, logicalReq.aclIndex) 269 // NInput remains the same 270 } 271 } 272 273 msg := &vpp_acl.ACLInterfaceSetACLList{ 274 Acls: ACLs, 275 Count: uint8(len(ACLs)), 276 SwIfIndex: interface_types.InterfaceIndex(aclIfIdx), 277 NInput: nInput, 278 } 279 reply := &vpp_acl.ACLInterfaceSetACLListReply{} 280 281 err = h.callsChannel.SendRequest(msg).ReceiveReply(reply) 282 if err != nil { 283 return err 284 } 285 } 286 287 return nil 288 } 289 290 func (h *ACLVppHandler) requestRemoveInterfacesFromACL(logicalReq *aclInterfaceLogicalReq) error { 291 var wasErr error 292 for _, aclIfIdx := range logicalReq.ifIndices { 293 // Create empty ACL list 294 var ACLs []uint32 295 296 // All assigned ACLs have to be dumped 297 aclInterfaceDetails, err := h.DumpInterfaceACLList(aclIfIdx) 298 if err != nil { 299 return err 300 } 301 302 // Reconstruct ACL list without removed ACL 303 var nInput uint8 304 if aclInterfaceDetails != nil { 305 nInput = aclInterfaceDetails.NInput 306 for idx, aclIndex := range aclInterfaceDetails.Acls { 307 if (aclIndex != logicalReq.aclIndex) || 308 (logicalReq.ingress && idx >= int(aclInterfaceDetails.NInput)) || 309 (!logicalReq.ingress && idx < int(aclInterfaceDetails.NInput)) { 310 ACLs = append(ACLs, aclIndex) 311 } else { 312 // Decrease NInput if ingress, otherwise keep it the same 313 if logicalReq.ingress { 314 nInput-- 315 } 316 } 317 } 318 } 319 320 msg := &vpp_acl.ACLInterfaceSetACLList{ 321 Acls: ACLs, 322 Count: uint8(len(ACLs)), 323 SwIfIndex: interface_types.InterfaceIndex(aclIfIdx), 324 NInput: nInput, 325 } 326 327 reply := &vpp_acl.ACLInterfaceSetACLListReply{} 328 err = h.callsChannel.SendRequest(msg).ReceiveReply(reply) 329 if err != nil { 330 wasErr = err 331 } 332 } 333 334 return wasErr 335 }