go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/vppcalls/vpp2101/route_vppcalls.go (about)

     1  //  Copyright (c) 2019 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 vpp2101
    16  
    17  import (
    18  	"context"
    19  	"net"
    20  
    21  	"github.com/pkg/errors"
    22  
    23  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/fib_types"
    24  	vpp_ip "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/ip"
    25  	"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/ip_types"
    26  	"go.ligato.io/vpp-agent/v3/proto/ligato/netalloc"
    27  	l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3"
    28  )
    29  
    30  const (
    31  	// NextHopViaLabelUnset constant has to be assigned into the field next hop
    32  	// via label in ip_add_del_route binary message if next hop via label is not defined.
    33  	// Equals to MPLS_LABEL_INVALID defined in VPP
    34  	NextHopViaLabelUnset uint32 = 0xfffff + 1
    35  
    36  	// ClassifyTableIndexUnset is a default value for field classify_table_index in ip_add_del_route binary message.
    37  	ClassifyTableIndexUnset = ^uint32(0)
    38  
    39  	// NextHopOutgoingIfUnset constant has to be assigned into the field next_hop_outgoing_interface
    40  	// in ip_add_del_route binary message if outgoing interface for next hop is not defined.
    41  	NextHopOutgoingIfUnset = ^uint32(0)
    42  )
    43  
    44  // vppAddDelRoute adds or removes route, according to provided input. Every route has to contain VRF ID (default is 0).
    45  func (h *RouteHandler) vppAddDelRoute(route *l3.Route, rtIfIdx uint32, delete bool) error {
    46  	req := &vpp_ip.IPRouteAddDel{
    47  		// Multi path is always true
    48  		IsMultipath: true,
    49  		IsAdd:       !delete,
    50  	}
    51  
    52  	// Common route parameters
    53  	fibPath := fib_types.FibPath{
    54  		Weight:     uint8(route.Weight),
    55  		Preference: uint8(route.Preference),
    56  	}
    57  	if route.NextHopAddr != "" {
    58  		nextHop, err := h.addrAlloc.GetOrParseIPAddress(route.NextHopAddr,
    59  			route.OutgoingInterface, netalloc.IPAddressForm_ADDR_ONLY)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		fibPath.Nh, fibPath.Proto = setFibPathNhAndProto(nextHop.IP)
    64  	}
    65  
    66  	// VRF/Other route parameters based on type
    67  	if route.Type == l3.Route_INTER_VRF {
    68  		fibPath.SwIfIndex = rtIfIdx
    69  		fibPath.TableID = route.ViaVrfId
    70  	} else if route.Type == l3.Route_DROP {
    71  		fibPath.Type = fib_types.FIB_API_PATH_TYPE_DROP
    72  	} else {
    73  		fibPath.SwIfIndex = rtIfIdx
    74  		fibPath.TableID = route.VrfId
    75  	}
    76  	// Destination address
    77  	dstNet, err := h.addrAlloc.GetOrParseIPAddress(route.DstNetwork,
    78  		"", netalloc.IPAddressForm_ADDR_NET)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	prefix := networkToPrefix(dstNet)
    83  
    84  	req.Route = vpp_ip.IPRoute{
    85  		TableID: route.VrfId,
    86  		Prefix:  prefix,
    87  		NPaths:  1,
    88  		Paths:   []fib_types.FibPath{fibPath},
    89  	}
    90  
    91  	reply := &vpp_ip.IPRouteAddDelReply{}
    92  	if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
    93  		return err
    94  	}
    95  
    96  	return nil
    97  }
    98  
    99  // VppAddRoute implements route handler.
   100  func (h *RouteHandler) VppAddRoute(ctx context.Context, route *l3.Route) error {
   101  	swIfIdx, err := h.getRouteSwIfIndex(route.OutgoingInterface)
   102  	if err != nil {
   103  		return err
   104  	}
   105  
   106  	return h.vppAddDelRoute(route, swIfIdx, false)
   107  }
   108  
   109  // VppDelRoute implements route handler.
   110  func (h *RouteHandler) VppDelRoute(ctx context.Context, route *l3.Route) error {
   111  	swIfIdx, err := h.getRouteSwIfIndex(route.OutgoingInterface)
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	return h.vppAddDelRoute(route, swIfIdx, true)
   117  }
   118  
   119  func setFibPathNhAndProto(netIP net.IP) (nh fib_types.FibPathNh, proto fib_types.FibPathNhProto) {
   120  	var addrUnion ip_types.AddressUnion
   121  	if netIP.To4() == nil {
   122  		proto = fib_types.FIB_API_PATH_NH_PROTO_IP6
   123  		var ip6addr ip_types.IP6Address
   124  		copy(ip6addr[:], netIP.To16())
   125  		addrUnion.SetIP6(ip6addr)
   126  	} else {
   127  		proto = fib_types.FIB_API_PATH_NH_PROTO_IP4
   128  		var ip4addr ip_types.IP4Address
   129  		copy(ip4addr[:], netIP.To4())
   130  		addrUnion.SetIP4(ip4addr)
   131  	}
   132  
   133  	return fib_types.FibPathNh{
   134  		Address:            addrUnion,
   135  		ViaLabel:           NextHopViaLabelUnset,
   136  		ClassifyTableIndex: ClassifyTableIndexUnset,
   137  	}, proto
   138  }
   139  
   140  func (h *RouteHandler) getRouteSwIfIndex(ifName string) (swIfIdx uint32, err error) {
   141  	swIfIdx = NextHopOutgoingIfUnset
   142  	if ifName != "" {
   143  		meta, found := h.ifIndexes.LookupByName(ifName)
   144  		if !found {
   145  			return 0, errors.Errorf("interface %s not found", ifName)
   146  		}
   147  		swIfIdx = meta.SwIfIndex
   148  	}
   149  	return
   150  }