go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/vppcalls/vpp2202/gre_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  	"errors"
    19  	"net"
    20  
    21  	vpp_gre "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/gre"
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/ip_types"
    23  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/tunnel_types"
    24  	ifs "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    25  )
    26  
    27  func (h *InterfaceVppHandler) greAddDelTunnel(isAdd bool, greLink *ifs.GreLink) (uint32, error) {
    28  	if greLink.TunnelType == ifs.GreLink_UNKNOWN {
    29  		err := errors.New("bad GRE tunnel type")
    30  		return 0, err
    31  	}
    32  
    33  	greSource := net.ParseIP(greLink.SrcAddr)
    34  	if greSource == nil {
    35  		err := errors.New("bad source address for GRE tunnel")
    36  		return 0, err
    37  	}
    38  	greDestination := net.ParseIP(greLink.DstAddr)
    39  	if greDestination == nil {
    40  		err := errors.New("bad destination address for GRE tunnel")
    41  		return 0, err
    42  	}
    43  
    44  	if greLink.SrcAddr == greLink.DstAddr {
    45  		err := errors.New("source and destination are the same")
    46  		return 0, err
    47  	}
    48  
    49  	if greLink.TunnelType == ifs.GreLink_ERSPAN && greLink.SessionId > 1023 {
    50  		err := errors.New("set session id for ERSPAN tunnel type")
    51  		return 0, err
    52  	}
    53  
    54  	var tt vpp_gre.GreTunnelType
    55  	switch greLink.TunnelType {
    56  	case ifs.GreLink_L3:
    57  		tt = vpp_gre.GRE_API_TUNNEL_TYPE_L3
    58  	case ifs.GreLink_TEB:
    59  		tt = vpp_gre.GRE_API_TUNNEL_TYPE_TEB
    60  	case ifs.GreLink_ERSPAN:
    61  		tt = vpp_gre.GRE_API_TUNNEL_TYPE_ERSPAN
    62  	default:
    63  		return 0, errors.New("bad GRE tunnel type")
    64  	}
    65  
    66  	tunnel := vpp_gre.GreTunnel{
    67  		Type:         tt,
    68  		Mode:         tunnel_types.TUNNEL_API_MODE_P2P, // TODO: add mode to proto model
    69  		Instance:     ^uint32(0),
    70  		OuterTableID: greLink.OuterFibId,
    71  		SessionID:    uint16(greLink.SessionId),
    72  	}
    73  
    74  	var isSrcIPv6, isDstIPv6 bool
    75  
    76  	if greSource.To4() == nil {
    77  		isSrcIPv6 = true
    78  	}
    79  	if greDestination.To4() == nil {
    80  		isDstIPv6 = true
    81  	}
    82  	if isSrcIPv6 != isDstIPv6 {
    83  		return 0, errors.New("source and destination addresses must be both either in IPv4 or IPv6")
    84  	}
    85  
    86  	if isSrcIPv6 {
    87  		var src, dst [16]uint8
    88  		copy(src[:], greSource.To16())
    89  		copy(dst[:], greDestination.To16())
    90  		tunnel.Src = ip_types.Address{
    91  			Af: ip_types.ADDRESS_IP6,
    92  			Un: ip_types.AddressUnionIP6(src),
    93  		}
    94  		tunnel.Dst = ip_types.Address{
    95  			Af: ip_types.ADDRESS_IP6,
    96  			Un: ip_types.AddressUnionIP6(dst),
    97  		}
    98  	} else {
    99  		var src, dst [4]uint8
   100  		copy(src[:], greSource.To4())
   101  		copy(dst[:], greDestination.To4())
   102  		tunnel.Src = ip_types.Address{
   103  			Af: ip_types.ADDRESS_IP4,
   104  			Un: ip_types.AddressUnionIP4(src),
   105  		}
   106  		tunnel.Dst = ip_types.Address{
   107  			Af: ip_types.ADDRESS_IP4,
   108  			Un: ip_types.AddressUnionIP4(dst),
   109  		}
   110  	}
   111  
   112  	req := &vpp_gre.GreTunnelAddDel{
   113  		IsAdd:  isAdd,
   114  		Tunnel: tunnel,
   115  	}
   116  	reply := &vpp_gre.GreTunnelAddDelReply{}
   117  
   118  	if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
   119  		return 0, err
   120  	}
   121  	return uint32(reply.SwIfIndex), nil
   122  }
   123  
   124  // AddGreTunnel adds new GRE interface.
   125  func (h *InterfaceVppHandler) AddGreTunnel(ifName string, greLink *ifs.GreLink) (uint32, error) {
   126  	swIfIndex, err := h.greAddDelTunnel(true, greLink)
   127  	if err != nil {
   128  		return 0, err
   129  	}
   130  	return swIfIndex, h.SetInterfaceTag(ifName, swIfIndex)
   131  }
   132  
   133  // DelGreTunnel removes GRE interface.
   134  func (h *InterfaceVppHandler) DelGreTunnel(ifName string, greLink *ifs.GreLink) (uint32, error) {
   135  	swIfIndex, err := h.greAddDelTunnel(false, greLink)
   136  	if err != nil {
   137  		return 0, err
   138  	}
   139  	return swIfIndex, h.RemoveInterfaceTag(ifName, swIfIndex)
   140  }