go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/vppcalls/vpp2202/route_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 "context" 19 "net" 20 21 "github.com/pkg/errors" 22 23 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/fib_types" 24 vpp_ip "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/ip" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2202/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 }