go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/aclplugin/vppcalls/vpp2106/interfaces_vppcalls.go (about)

     1  //  Copyright (c) 2021 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 vpp2106
    16  
    17  import (
    18  	"fmt"
    19  
    20  	vpp_acl "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/acl"
    21  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/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  }