go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ifplugin/vppcalls/vpp2106/gtpu_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 "net" 20 21 "github.com/pkg/errors" 22 23 "go.ligato.io/vpp-agent/v3/plugins/vpp" 24 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/gtpu" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/interface_types" 26 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2106/ip_types" 27 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls" 28 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 29 ) 30 31 const defaultDecapNextIndex = 0xFFFFFFFF 32 33 func (h *InterfaceVppHandler) gtpuAddDelTunnel(isAdd bool, gtpuLink *interfaces.GtpuLink, multicastIf uint32) (uint32, error) { 34 var decapNextNode uint32 = defaultDecapNextIndex 35 if gtpuLink.DecapNextNode != 0 { 36 decapNextNode = gtpuLink.DecapNextNode 37 } else { 38 // backwards compatible fallback 39 if gtpuLink.DecapNext != interfaces.GtpuLink_DEFAULT { 40 decapNextNode = uint32(gtpuLink.DecapNext) 41 } 42 } 43 44 req := >pu.GtpuAddDelTunnel{ 45 IsAdd: isAdd, 46 McastSwIfIndex: interface_types.InterfaceIndex(multicastIf), 47 EncapVrfID: gtpuLink.EncapVrfId, 48 Teid: gtpuLink.Teid, 49 Tteid: gtpuLink.RemoteTeid, 50 DecapNextIndex: decapNextNode, 51 } 52 53 srcAddr := net.ParseIP(gtpuLink.SrcAddr) 54 if srcAddr == nil { 55 err := errors.New("bad source address for GTPU tunnel") 56 return 0, err 57 } 58 59 dstAddr := net.ParseIP(gtpuLink.DstAddr) 60 if dstAddr == nil { 61 err := errors.New("bad destination address for GTPU tunnel") 62 return 0, err 63 } 64 65 if gtpuLink.SrcAddr == gtpuLink.DstAddr { 66 err := errors.New("source and destination are the same") 67 return 0, err 68 } 69 70 var isSrcIPv6, isDstIPv6 bool 71 72 if srcAddr.To4() == nil { 73 isSrcIPv6 = true 74 } 75 if dstAddr.To4() == nil { 76 isDstIPv6 = true 77 } 78 79 if !isSrcIPv6 && !isDstIPv6 { 80 var src, dst [4]uint8 81 copy(src[:], srcAddr.To4()) 82 copy(dst[:], dstAddr.To4()) 83 req.SrcAddress = ip_types.Address{ 84 Af: ip_types.ADDRESS_IP4, 85 Un: ip_types.AddressUnionIP4(src), 86 } 87 req.DstAddress = ip_types.Address{ 88 Af: ip_types.ADDRESS_IP4, 89 Un: ip_types.AddressUnionIP4(dst), 90 } 91 } else if isSrcIPv6 && isDstIPv6 { 92 var src, dst [16]uint8 93 copy(src[:], srcAddr.To16()) 94 copy(dst[:], dstAddr.To16()) 95 req.SrcAddress = ip_types.Address{ 96 Af: ip_types.ADDRESS_IP6, 97 Un: ip_types.AddressUnionIP6(src), 98 } 99 req.DstAddress = ip_types.Address{ 100 Af: ip_types.ADDRESS_IP6, 101 Un: ip_types.AddressUnionIP6(dst), 102 } 103 } else { 104 return 0, errors.New("source and destination addresses must be both either IPv4 or IPv6") 105 } 106 107 reply := >pu.GtpuAddDelTunnelReply{} 108 109 if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { 110 return 0, err 111 } 112 return uint32(reply.SwIfIndex), nil 113 } 114 115 // AddGtpuTunnel adds new GTPU interface. 116 func (h *InterfaceVppHandler) AddGtpuTunnel(ifName string, gtpuLink *interfaces.GtpuLink, multicastIf uint32) (uint32, error) { 117 if h.gtpu == nil { 118 return 0, errors.WithMessage(vpp.ErrPluginDisabled, "gtpu") 119 } 120 if gtpuLink == nil { 121 return 0, errors.New("missing GTPU tunnel information") 122 } 123 124 swIfIndex, err := h.gtpuAddDelTunnel(true, gtpuLink, multicastIf) 125 if err != nil { 126 return 0, err 127 } 128 return swIfIndex, h.SetInterfaceTag(ifName, swIfIndex) 129 } 130 131 // DelGtpuTunnel removes GTPU interface. 132 func (h *InterfaceVppHandler) DelGtpuTunnel(ifName string, gtpuLink *interfaces.GtpuLink) error { 133 if h.gtpu == nil { 134 return errors.WithMessage(vpp.ErrPluginDisabled, "gtpu") 135 } 136 if gtpuLink == nil { 137 return errors.New("missing GTPU tunnel information") 138 } 139 140 swIfIndex, err := h.gtpuAddDelTunnel(false, gtpuLink, 0) 141 if err != nil { 142 return err 143 } 144 return h.RemoveInterfaceTag(ifName, swIfIndex) 145 } 146 147 // dumpGtpuDetails dumps GTP-U interface details from VPP and fills them into the provided interface map. 148 func (h *InterfaceVppHandler) dumpGtpuDetails(ifc map[uint32]*vppcalls.InterfaceDetails) error { 149 if h.gtpu == nil { 150 // no-op when disabled 151 return nil 152 } 153 154 reqCtx := h.callsChannel.SendMultiRequest(>pu.GtpuTunnelDump{ 155 SwIfIndex: ^interface_types.InterfaceIndex(0), 156 }) 157 for { 158 gtpuDetails := >pu.GtpuTunnelDetails{} 159 stop, err := reqCtx.ReceiveReply(gtpuDetails) 160 if stop { 161 break // Break from the loop. 162 } 163 if err != nil { 164 return fmt.Errorf("failed to dump GTP-U tunnel interface details: %v", err) 165 } 166 _, ifIdxExists := ifc[uint32(gtpuDetails.SwIfIndex)] 167 if !ifIdxExists { 168 continue 169 } 170 // Multicast interface 171 var multicastIfName string 172 _, exists := ifc[uint32(gtpuDetails.McastSwIfIndex)] 173 if exists { 174 multicastIfName = ifc[uint32(gtpuDetails.McastSwIfIndex)].Interface.Name 175 } 176 177 gtpuLink := &interfaces.GtpuLink{ 178 Multicast: multicastIfName, 179 EncapVrfId: gtpuDetails.EncapVrfID, 180 Teid: gtpuDetails.Teid, 181 RemoteTeid: gtpuDetails.Tteid, 182 DecapNextNode: gtpuDetails.DecapNextIndex, 183 } 184 185 if gtpuDetails.SrcAddress.Af == ip_types.ADDRESS_IP6 { 186 srcAddrArr := gtpuDetails.SrcAddress.Un.GetIP6() 187 gtpuLink.SrcAddr = net.IP(srcAddrArr[:]).To16().String() 188 dstAddrArr := gtpuDetails.DstAddress.Un.GetIP6() 189 gtpuLink.DstAddr = net.IP(dstAddrArr[:]).To16().String() 190 } else { 191 srcAddrArr := gtpuDetails.SrcAddress.Un.GetIP4() 192 gtpuLink.SrcAddr = net.IP(srcAddrArr[:4]).To4().String() 193 dstAddrArr := gtpuDetails.DstAddress.Un.GetIP4() 194 gtpuLink.DstAddr = net.IP(dstAddrArr[:4]).To4().String() 195 } 196 197 ifc[uint32(gtpuDetails.SwIfIndex)].Interface.Link = &interfaces.Interface_Gtpu{Gtpu: gtpuLink} 198 ifc[uint32(gtpuDetails.SwIfIndex)].Interface.Type = interfaces.Interface_GTPU_TUNNEL 199 } 200 201 return nil 202 }