Skip to content

Commit

Permalink
feat: Add IPIP & IPSec point-to-multipoint support (#1669)
Browse files Browse the repository at this point in the history
* IPIP & IPSec point-to-multipoint support

Signed-off-by: Rastislav Szabo <[email protected]>

* Add workaround for ipip tunnel mode

Signed-off-by: Rastislav Szabo <[email protected]>

* Add TEIB support

Signed-off-by: Rastislav Szabo <[email protected]>
  • Loading branch information
rastislavs authored Jun 22, 2020
1 parent 60931de commit a52954c
Show file tree
Hide file tree
Showing 28 changed files with 1,656 additions and 303 deletions.
212 changes: 212 additions & 0 deletions plugins/vpp/binapi/vpp2005/teib/teib.ba.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions plugins/vpp/binapi/vpp2005/vpp2005.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/sr"
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/stn"
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/tapv2"
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/teib"
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/vmxnet3"
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/vpe"
"go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2005/vxlan"
Expand All @@ -66,6 +67,7 @@ func init() {
span.AllMessages,
sr.AllMessages,
tapv2.AllMessages,
teib.AllMessages,
vpe.AllMessages,
vxlan.AllMessages,
vxlan_gpe.AllMessages,
Expand Down Expand Up @@ -110,6 +112,7 @@ func init() {
//go:generate binapigen --input-file=$VPP_API_DIR/core/span.api.json
//go:generate binapigen --input-file=$VPP_API_DIR/core/sr.api.json
//go:generate binapigen --input-file=$VPP_API_DIR/core/tapv2.api.json
//go:generate binapigen --input-file=$VPP_API_DIR/core/teib.api.json
//go:generate binapigen --input-file=$VPP_API_DIR/core/vpe.api.json
//go:generate binapigen --input-file=$VPP_API_DIR/core/vxlan.api.json
//go:generate binapigen --input-file=$VPP_API_DIR/core/vxlan_gpe.api.json
Expand Down
12 changes: 7 additions & 5 deletions plugins/vpp/ifplugin/descriptor/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,11 +578,13 @@ func (d *InterfaceDescriptor) Validate(key string, intf *interfaces.Interface) e
return kvs.NewInvalidValueError(ErrIpipSrcAddrBad, "link.ipip.src_addr")
}

if intf.GetIpip().DstAddr == "" {
return kvs.NewInvalidValueError(ErrIpipDstAddrMissing, "link.ipip.dst_addr")
}
if net.ParseIP(intf.GetIpip().DstAddr) == nil {
return kvs.NewInvalidValueError(ErrIpipDstAddrBad, "link.ipip.dst_addr")
if intf.GetIpip().TunnelMode == interfaces.IPIPLink_POINT_TO_POINT {
if intf.GetIpip().DstAddr == "" {
return kvs.NewInvalidValueError(ErrIpipDstAddrMissing, "link.ipip.dst_addr")
}
if net.ParseIP(intf.GetIpip().DstAddr) == nil {
return kvs.NewInvalidValueError(ErrIpipDstAddrBad, "link.ipip.dst_addr")
}
}
}

Expand Down
75 changes: 51 additions & 24 deletions plugins/vpp/ifplugin/vppcalls/vpp2005/ipip_vppcalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,53 +39,65 @@ func (h *InterfaceVppHandler) AddIpipTunnel(ifName string, vrf uint32, ipipLink
if ipipLink == nil {
return 0, errors.New("missing IPIP tunnel information")
}
srcAddr := net.ParseIP(ipipLink.SrcAddr)
var srcAddr, dstAddr net.IP
var isSrcIPv6, isDstIPv6 bool

srcAddr = net.ParseIP(ipipLink.SrcAddr)
if srcAddr == nil {
err := errors.New("bad source address for IPIP tunnel")
return 0, err
}
dstAddr := net.ParseIP(ipipLink.DstAddr)
if dstAddr == nil {
err := errors.New("bad destination address for IPIP tunnel")
return 0, err
}

var isSrcIPv6, isDstIPv6 bool
if srcAddr.To4() == nil {
isSrcIPv6 = true
}
if dstAddr.To4() == nil {
isDstIPv6 = true

if ipipLink.TunnelMode == interfaces.IPIPLink_POINT_TO_POINT {
dstAddr = net.ParseIP(ipipLink.DstAddr)
if dstAddr == nil {
err := errors.New("bad destination address for IPIP tunnel")
return 0, err
}
if dstAddr.To4() == nil {
isDstIPv6 = true
}
}

if !isSrcIPv6 && !isDstIPv6 {
if !isSrcIPv6 && (dstAddr == nil || !isDstIPv6) {
var src, dst [4]uint8
copy(src[:], srcAddr.To4())
copy(dst[:], dstAddr.To4())
req.Tunnel.Src = ip_types.Address{
Af: ip_types.ADDRESS_IP4,
Un: ip_types.AddressUnionIP4(src),
}
req.Tunnel.Dst = ip_types.Address{
Af: ip_types.ADDRESS_IP4,
Un: ip_types.AddressUnionIP4(dst),
if dstAddr != nil {
copy(dst[:], dstAddr.To4())
req.Tunnel.Dst = ip_types.Address{
Af: ip_types.ADDRESS_IP4,
Un: ip_types.AddressUnionIP4(dst),
}
}
} else if isSrcIPv6 && isDstIPv6 {
} else if isSrcIPv6 && (dstAddr == nil || isDstIPv6) {
var src, dst [16]uint8
copy(src[:], srcAddr.To16())
copy(dst[:], dstAddr.To16())
req.Tunnel.Src = ip_types.Address{
Af: ip_types.ADDRESS_IP6,
Un: ip_types.AddressUnionIP6(src),
}
req.Tunnel.Dst = ip_types.Address{
Af: ip_types.ADDRESS_IP6,
Un: ip_types.AddressUnionIP6(dst),
if dstAddr != nil {
copy(dst[:], dstAddr.To16())
req.Tunnel.Dst = ip_types.Address{
Af: ip_types.ADDRESS_IP6,
Un: ip_types.AddressUnionIP6(dst),
}
}
} else {
return 0, errors.New("source and destination addresses must be both either IPv4 or IPv6")
}

if ipipLink.TunnelMode == interfaces.IPIPLink_POINT_TO_MULTIPOINT {
req.Tunnel.Mode = ipip.TUNNEL_API_MODE_MP
}

reply := &ipip.IpipAddTunnelReply{}

if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
Expand Down Expand Up @@ -131,13 +143,28 @@ func (h *InterfaceVppHandler) dumpIpipDetails(ifc map[uint32]*vppcalls.Interface
if ipipDetails.Tunnel.Src.Af == ip_types.ADDRESS_IP6 {
srcAddrArr := ipipDetails.Tunnel.Src.Un.GetIP6()
ipipLink.SrcAddr = net.IP(srcAddrArr[:]).To16().String()
dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP6()
ipipLink.DstAddr = net.IP(dstAddrArr[:]).To16().String()
if ipipDetails.Tunnel.Mode == ipip.TUNNEL_API_MODE_P2P {
dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP6()
ipipLink.DstAddr = net.IP(dstAddrArr[:]).To16().String()
}
} else {
srcAddrArr := ipipDetails.Tunnel.Src.Un.GetIP4()
ipipLink.SrcAddr = net.IP(srcAddrArr[:4]).To4().String()
dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP4()
ipipLink.DstAddr = net.IP(dstAddrArr[:4]).To4().String()
if ipipDetails.Tunnel.Mode == ipip.TUNNEL_API_MODE_P2P {
dstAddrArr := ipipDetails.Tunnel.Dst.Un.GetIP4()
ipipLink.DstAddr = net.IP(dstAddrArr[:4]).To4().String()
}
}

if ipipDetails.Tunnel.Mode == ipip.TUNNEL_API_MODE_MP {
ipipLink.TunnelMode = interfaces.IPIPLink_POINT_TO_MULTIPOINT
}

// TODO: temporary fix since VPP does not dump the tunnel mode properly.
// If dst address is empty, this must be a multipoint tunnel.
if ipipLink.DstAddr == "0.0.0.0" {
ipipLink.TunnelMode = interfaces.IPIPLink_POINT_TO_MULTIPOINT
ipipLink.DstAddr = ""
}

ifc[uint32(ipipDetails.Tunnel.SwIfIndex)].Interface.Link = &interfaces.Interface_Ipip{Ipip: ipipLink}
Expand Down
14 changes: 14 additions & 0 deletions plugins/vpp/ipsecplugin/vppcalls/vpp2005/dump_vppcalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,20 @@ func (h *IPSecVppHandler) DumpTunnelProtections() (tpList []*ipsec.TunnelProtect
}
tp.SaIn = append(tp.SaIn, tpDetails.Tun.SaIn...)
tpList = append(tpList, tp)

if tpDetails.Tun.Nh.Af == ip_types.ADDRESS_IP6 {
nhAddrArr := tpDetails.Tun.Nh.Un.GetIP6()
nhAddr := net.IP(nhAddrArr[:]).To16()
if !nhAddr.IsUnspecified() {
tp.NextHopAddr = nhAddr.String()
}
} else {
nhAddrArr := tpDetails.Tun.Nh.Un.GetIP4()
nhAddr := net.IP(nhAddrArr[:4]).To4()
if !nhAddr.IsUnspecified() {
tp.NextHopAddr = nhAddr.String()
}
}
}
return
}
Expand Down
Loading

0 comments on commit a52954c

Please sign in to comment.